$ resolvectl status
...
Link 2 (enp1s0)
Current Scopes: DNS
Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 192.168.8.1
DNS Servers: 192.168.8.1
DNS Domain: lan
...
After much digging, it appears that 127.0.0.3 is the local stub resolver for systemd-resolved. To my understanding, it performs local caching of DNS results. If not found in cache, resolved will query upstream. We can check which is upstream with resolvectl status. (In my case this is pointing to the router)
For other's references:
I turn off resolved's caching by adding Cache=no (case sensitive) to /etc/systemd/resolved.conf.
Then, sudo systemctl restart systemd-resolved to apply changes.
Confirm that cache is off with sudo resolvectl statistics.
I also noticed that it's easier to remove a domain from whitelist than to add it. In many lucky cases:
$ # Already in whitelist
$ curl ifconfig.co
(real IP)
$ curl ifconfig.me
(real IP)
$ # Remove from whitelist
$ curl ifconfig.co
[VPN IP]
$ curl ifconfig.me
[VPN IP]
$ # Add to whitelist, did not take effect
$ curl ifconfig.co
[VPN IP]
$ curl ifconfig.me
[VPN IP]
I tried turning off/on the VPN, I still obtain the VPN IP despite having added to whitelist.
I wonder if it was using the wrong resolver, perhaps the VPN's resolver?
I also tried curl ifconfig.me on the router but I'm not certain this result is not heavily cached. I have seen it giving a different answer than on my Ubuntu (with caching turned off).
When you use encrypted DNS (including AdguardHome), the DNS query cannot be splited, meaning it goes to either vpn or non-vpn.
So in the above test, the DNS resolving surely goes to vpn, even you use it in vpn policy.
But after it resolves to IP, it will split.
For DNS leaks, we decided to faover the VPN connection so all encrypted dns goes to VPN.
If you want "domain-based vpn policy" has the highest priority, using it with encrypted dns will be a difficult. Two encrypted dns streams need to created. And we need to decide which stream to use at the very early stage.
I am using AGH + encrypted upstream servers using QUIC/DoH + VPN split policies and everything is totally working!
The only thing I don't use is encrypted DNS from my device to the AGH instance. But I doubt that @Fox uses it because configuration of encrypted DNS to AGH is really pain.
I had great success following @teleney's suggestions.
ifconfig.me not in VPN whitelist. Curl result shows VPN IP as expected. ifconfig.me is then added to whitelist and applied.
ipset list on router returns 5 sets, all without any members.
curl ifconfig.me still returns VPN IP (wrong, but as you expected)
nslookup ifconfig.me on router.
ipset list now shows the IPs as member under bypass_vpn_domain set.
curl ifconfig.me on Ubuntu is now correctly returning my residential IP.
In your original comment where you said it is an issue, do you mean it is a known bug that will be fixed in the future? My concerns are as follows:
As you mentioned, this is temporary (and manual). I tried clicking Apply on the policy editor without making any changes, and found out that all domains I whitelisted disappeared from ipset list, while all IPs that I whitelisted remains.
This approach doesn't work with services where the domain is stable but the IP of the backend is load balanced / rotated frequently. (Unless I manually run nslookup again)
Implications:
At least for the workaround now, since matching is based on IP and not domain, it appears that having a stub resolver with caching on local PC is still fine for the cases where the IP is static.
Automatic subdomain matching will be broken for now unless manually processed.
The config is written to /etc/config/vpnpolicy. I am tempted to run nslookup on the entries daily, but of course, running realtime checks is preferred, which handles subdomains as well.
Is there anything else I can help with to get this bug resolved?
I did some tests to confirm that DNS traffic from the subnet would successfully update the ipset. I think it may be that your Ubuntu is not successfully sending DNS messages. You can try capturing packets on the router to ensure that DNS packets are being sent from Ubuntu (tcpdump -i br-lan port 53).
I think as long as it can trigger IP updates, it can be used normally.