Starting on 4.9.0, I’ve been experiencing DNS issues when a VPN client is activated on the router, where DNS lookups that originate from a client which fall back to TCP fail, if the client’s DNS is configured as the router’s IP. It reproduces regardless of the VPN settings:
- Allow Non-VPN Traffic or Enhanced Kill Switch are globally enabled
- Kill Switch is enabled or not at the individual tunnel level
- Allow Remote Access to the LAN Subnet is enabled or not
- IP Masquerading is enabled or not
It also doesn’t seem to matter whether DNS mode is automatic or manual, and whether “Allow Custom DNS to Override VPN DNS” is toggled on or not. Assuming the router’s IP is 192.168.8.1, the following command executed on a Linux client consistently fails:
dig +tcp @192.168.8.1 probe-$RANDOM.google.com
;; communications error to 192.168.8.1#53: timed out
Using dig +notcp @192.168.8.1 probe-$RANDOM.google.com will work without issues.
google.com can be replaced with something else. The $RANDOM is there to avoid possible caching mechanisms. Note that the following do succeed:
- Running the above dig command from the router itself on an SSH session, or
- Running the above using any other upstream DNS (whether they’re on the LAN or not).
After trying many things, it seems the root cause is a firewall rule that only gets applied on the OUTPUT chain when a VPN client is connected:
4 24 1472 DROP tcp -- \* \* 0.0.0.0/0 0.0.0.0/0 mark match 0x0/0xf000 owner UID match 453 /\* !fw3: tcp_dns_leak_drop \*/
453 is dnsmasq’s user. This rule essentially says “Drop all TCP packets that the dnsmasq process emits, if that connection isn't marked to go through the VPN”. 0x0/0xf000 are essentially unmarked packets. From that, and the comment tcp_dns_leak_drop, it’s clear this rule is meant to protect DNS leaks from happening on TCP. The main issue is that this is applying to all clients - even ones that do go through the router's VPN, regardless of kill-switch options, and even though “Allow Non-VPN Traffic” is selected.
I can confirm that dropping that rule temporarily resolved all issues.
While most DNS traffic is UDP, there are certainly many cases where it can happen through TCP.
- Responses over a certain size (the EDNS UDP buffer size) get truncated, and fallback to TCP. Example:
dig @192.168.8.1 +bufsize=512 dnskey orgresults in;; Truncated, retrying in TCP mode., which then hangs. Any client hitting this is affected. - UDP fails to be delivered due to whatever reason
- A client prefers or forces TCP for whatever reason
One natural case where this was happening for me: I have a client that’s connected to its own Proton VPN tunnel (and does not go through the router’s), while setting Proton’s DNS resolver to the router’s IP. journalctl shows Using degraded feature set TCP instead of UDP for DNS server 192.168.8.1.Not exactly sure why that triggers it as I’m not an expert in this area - something about systemd-resolved, tunnel MTU’s, or something else.
Regardless, I did not experience this behavior prior to 4.9.0. I reproduced this on on Arch Linux desktop with systemd-resolved, as well as a few other Linux clients connected to the router.






