Hello everyone,
After updating to Core 203 I ran into a DNS problem that also seems to affect other users with OpenVPN, so I want to document it properly here with the analysis and a working fix.
Setup
My Green network is 192.168.99.0/28 and the firewall itself is 192.168.99.1. Clients connecting over WireGuard use 192.168.99.1 as their DNS server. This worked perfectly before Core 203.
Symptom
After the update, name resolution over the tunnel stopped working. Resolving raw IP addresses was fine, but DNS queries failed. On the client I saw this:
nslookup google.de 192.168.99.1
;; reply from unexpected source: 192.168.4.250#53, expected 192.168.99.1#53
;; connection timed out; no servers could be reached
So the query goes to 192.168.99.1, but the answer comes back from 192.168.4.250, which is my Red (WAN) interface. The client rejects the reply because the source does not match, and the lookup times out.
Analysis
The new Knot Resolver configuration in /etc/knot-resolver/config.yaml only binds to the wildcard address:
network:
listen:
- interface: 0.0.0.0@53
When a socket is bound to 0.0.0.0, the kernel decides which source address to use for outgoing replies based on the routing table. For traffic leaving through the tunnel interface, it picks the Red interface IP instead of the Green IP the query was originally sent to. That is why the client sees the answer coming from an unexpected source and discards it.
Fix
Adding an explicit listen socket for the Green interface address solves the problem completely:
network:
listen:
- interface: 0.0.0.0@53
- interface: 192.168.99.1@53
After restarting the service, both workers open dedicated sockets on the Green IP in addition to the wildcard, and there is no address conflict:
ss -tulpn | grep :53
udp UNCONN 192.168.99.1:53 users:(("kresd",...))
udp UNCONN 0.0.0.0:53 users:(("kresd",...))
tcp LISTEN 192.168.99.1:53 users:(("kresd",...))
tcp LISTEN 0.0.0.0:53 users:(("kresd",...))
Local resolution on the firewall still works, and queries through the tunnel now return correct answers with the correct source address.
The problem with this fix
The file starts with a clear warning:
# DO NOT EDIT as any changes will be overwritten
So this manual change does not survive a DNS settings change or a core update, because the configuration file gets regenerated. This means it is only a temporary workaround, not a real solution.
Suggestion
Would it be possible to have the configuration generator include the configured interface addresses as explicit listen sockets in addition to 0.0.0.0? Alternatively the resolver could be told to reply from the same address the query was received on. Either approach would restore tunnel DNS behaviour for WireGuard and OpenVPN users.
Can anyone confirm this on their own system?
Thanks a lot.