How to route subdomains with PBR (utilize dnsmasq’s nft sets support)?

Initial goal: I want only certain third-level domains (e.g., *.myip.com) to be routed through the VPN, while all other traffic should continue be routed through the regular WAN connection.

Current state: I can successfully route specified third-level domains only when the exact subdomain name is explicitly specified in the PBR configuration (e.g., api.myip.com), and when option resolver_set is set to 'none' in the PBR config.

config pbr 'config'
	option enabled '1'
	...
	option resolver_set 'none'

config policy
	option name 'curl http://api.myip.com'
	option dest_addr 'api.myip.com'
	option interface 'vpn'

Issue description: PBR does not route traffic through the VPN when option resolver_set is set to 'dnsmasq.nftset' in the PBR config. It seems the reason of that is because dnsmasq's nft set does NOT automatically add third-level domain IPs to the set when I open a subdomain URL on PC connected to OpenWrt router (why?).

Details:
According to the official PBR documentation, to resolve subdomains correctly, I need to uninstall dnsmasq and install the dnsmasq-full, libnettle8, and libnetfilter-conntrack3 packages. I have installed all of them.

Here is my current PBR configuration:

config pbr 'config'
	option enabled '1'
	option verbosity '2'
	option strict_enforcement '1'
	option resolver_set 'dnsmasq.nftset'
	list resolver_instance '*'
	option ipv6_enabled '0'
	list ignored_interface 'vpnserver'
	option boot_timeout '30'
	option rule_create_option 'add'
	option procd_reload_delay '1'
	option webui_show_ignore_target '0'
	option nft_rule_counter '0'
	option nft_set_auto_merge '1'
	option nft_set_counter '0'
	option nft_set_flags_interval '1'
	option nft_set_flags_timeout '0'
	option nft_set_policy 'performance'
	list webui_supported_protocol 'all'
	list webui_supported_protocol 'tcp'
	list webui_supported_protocol 'udp'
	list webui_supported_protocol 'tcp udp'
	list webui_supported_protocol 'icmp'
	list supported_interface 'vpn'

config policy
	option name 'curl ip-api.com'
	option dest_addr 'ip-api.com'
	option interface 'vpn'

config policy
	option name 'curl api.myip.com'
	option dest_addr 'myip.com'
	option interface 'vpn'

As I mentioned, with this configuration, traffic is not routed through the VPN when I run curl http://api.myip.com or curl ip-api.com on a PC connected to the OpenWrt router. It seems that the root cause of issue is that nft list sets does not contain the corresponding IP addresses of subdomain, which should be automatically added/populated by dnsmasq-full.

nft list sets without IP populated
root@OpenWrt:~# nft list sets
table inet fw4 {
        set pbr_vpn_4_dst_ip_cfg026ff5 {
                type ipv4_addr
                flags interval
                auto-merge
                comment "curl ip-api.com"
        }
        set pbr_vpn_4_dst_ip_cfg036ff5 {
                type ipv4_addr
                flags interval
                auto-merge
                comment "curl api.myip.com"
        }
}

Only when I manually run nslookup ip-api.com and nslookup api.myip.com in the OpenWrt router's console, the IP addresses appear in the nft sets and routing via VPN starts working as expected.

nft list sets with IP populated
root@OpenWrt:~# nft list sets
table inet fw4 {
        set pbr_vpn_4_dst_ip_cfg026ff5 {
                type ipv4_addr
                flags interval
                auto-merge
                comment "curl ip-api.com"
                elements = { 208.95.112.1 }
        }
        set pbr_vpn_4_dst_ip_cfg036ff5 {
                type ipv4_addr
                flags interval
                auto-merge
                comment "curl http://api.myip.com"
                elements = { 104.26.8.59, 104.26.9.59,
                             172.67.75.163 }
        }
}

Question: How can I make dnsmasq-full populate the nft list sets with IP addresses automatically, without needing to run nslookup manually?
Maybe I missed something in configuration, or maybe some additional configuration should be added into dnsmasq.conf? Please advice.
Thank you!

Is that PC using the OpenWRT router as its DNS server?

1 Like

No, PC has been configured with Cloudflare dns for its DNS server.

DNSmasq will only populate a set when it resolves the address. If it's not resolving any addresses then it won't populate anything.

2 Likes

Thank you for this clarification!
Are there any options for OpenWrt router to force clients to use the router's Dnsmasq for resolving addresses regardless of the clients' configurations?

I reconfigured the PC and set the PC's DNS server = router's IP address.

If I open http://api.myip.com or https://ip-api.com/ on the PC, nft list sets on the router still returns an array without IP addresses.

So, I'm curious what I have missed and how to tell dnsmasq to add IP addresses automatically, similar to when I run nslookup ip-api.com and nslookup api.myip.com manually.

Make sure you use pbr 1.1.8.
As already said your clients must use dnsmasq some browsers use private dns.

Note dns is cached by client and on the router so either flush dns or restart

1 Like

Many thanks @egc , @krazeh ! You were absolutely right. The issue is solved.

Once I rebooted my PC (cleared the DNS cache), my PC began using the router's IP as its DNS server.

I ran curl http://api.myip.com or curl ip-api.com on PC again, and right after that, the nft list sets entries with IP started to populate automatically on router, and the VPN routing began working as expected automatically as well.

So, sub-domains can be correctly routed by PBR, but it's essential that clients must use the OpenWRT router as their DNS server. DNSmasq will only add subdomain IPs to the nft set if the router itself resolves them.
Thanks!

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.