I ran dnscrypt-proxy or tor on Linux listning on [::]:1053 to server DNS. I wanted to make all my Linux host's DNS queries transparently use that proxy.
This is what I found from Internet how we transparent proxy UDP traffic:
iptables -t nat -I OUTPUT -p udp --dport 53 -j REDIRECT--to-ports 1053
or
iptables -t nat -I OUTPUT -p udp --dport 53 -j DNAT --to 127.0.0.1:1053
(-j REDIRECT is equal to -j DNAT --to 127.0.0.1:)
Didn't work. My browser can't open URLs, and nslookup and dig say:
;; reply from unexpected source: 192.168.3.60#1053, expected 192.168.3.1#53
(192.168.3.1 is in my /etc/resolv.conf)
I saw on wireshark that the reply packet from DNS proxy wasn't SNATed, but it should be SNATed.
And this is conntrack -E:
[NEW] udp 17 30 src=127.0.0.1 dst=127.0.0.1 sport=35954 dport=35954 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=35954 dport=35954
[NEW] udp 17 30 src=::1 dst=::1 sport=59799 dport=59799 [UNREPLIED] src=::1 dst=::1 sport=59799 dport=59799
[NEW] udp 17 30 src=192.168.3.60 dst=192.168.3.1 sport=34825 dport=53 [UNREPLIED] src=127.0.0.1 dst=192.168.3.60 sport=1053 dport=34825
[NEW] udp 17 30 src=192.168.3.60 dst=192.168.3.60 sport=1053 dport=34825 [UNREPLIED] src=192.168.3.60 dst=192.168.3.60 sport=34825 dport=1053
But then strangely, if I make proxy listen on 127.0.0.1 instead of [::], it works. I saw on wireshark the reply packet correctly SNATed. And dig and nslookup can get reply from transparent DNS proxy.
This is conntract -E when proxy listen on 127.0.0.1:
[NEW] udp 17 30 src=127.0.0.1 dst=127.0.0.1 sport=58584 dport=58584 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=58584 dport=58584
[NEW] udp 17 30 src=::1 dst=::1 sport=39482 dport=39482 [UNREPLIED] src=::1 dst=::1 sport=39482 dport=39482
[NEW] udp 17 30 src=192.168.3.60 dst=192.168.3.1 sport=38165 dport=53 [UNREPLIED] src=127.0.0.1 dst=192.168.3.60 sport=1053 dport=38165
[UPDATE] udp 17 30 src=192.168.3.60 dst=192.168.3.1 sport=38165 dport=53 src=127.0.0.1 dst=192.168.3.60 sport=1053 dport=38165
While TCP doesn't encounter such issue (dnscrypt-proxy also serves TCP). TCP reply packet always correctly SNATed.
So what is going on? Am I doing something wrong with UDP NAT? I want DNS proxy listen on 0.0.0.0 or [::] and transparently proxy my Linux host's DNS queries.