无需 resolv.conf 即可使用 iptables 正确重新路由 DNS 查询

无需 resolv.conf 即可使用 iptables 正确重新路由 DNS 查询

我在 127.0.0.1:53 上运行自定义 DNS 服务,我不仅希望所有查询都通过它,还希望只有该服务才能响应。这就是问题出现的地方。我的 NAT iptables 设置:

iptables -t nat -A OUTPUT -p tcp --dport 53 -j DNAT --to-destination 127.0.0.1:53
iptables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:53

这里是我的 tcpdump,正在 ping ya.ru

[root@localhost ~]# tcpdump -nnSXvv -i any udp
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
18:34:15.974227 IP (tos 0x0, ttl 64, id 20601, offset 0, flags [DF], proto UDP (17), length 51)
    192.168.0.6.54387 > 127.0.0.1.53: [bad udp cksum 0x3fe0 -> 0x2c11!] 58964+ A? ya.ru. (23)
    <data here>
18:34:15.974457 IP (tos 0x0, ttl 64, id 26083, offset 0, flags [DF], proto UDP (17), length 604)
    192.168.0.6.56172 > 77.66.84.233.443: [bad udp cksum 0x6533 -> 0x48f0!] UDP, length 576
    <data here>
18:34:16.028783 IP (tos 0x0, ttl 57, id 7923, offset 0, flags [none], proto UDP (17), length 204)
    77.66.84.233.443 > 192.168.0.6.56172: [udp sum ok] UDP, length 176
    <data here>
18:34:16.029127 IP (tos 0x0, ttl 64, id 12032, offset 0, flags [DF], proto UDP (17), length 78)
    1.1.1.1.53 > 192.168.0.6.54387: [bad udp cksum 0xc2fb -> 0xc42e!] 58964 q: A? ya.ru. 1/0/1 ya.ru. A 87.250.250.242 ar: . OPT UDPsize=1252 (50)
    <data here>
18:34:16.075993 IP (tos 0x0, ttl 64, id 20662, offset 0, flags [DF], proto UDP (17), length 73)
    192.168.0.6.38972 > 127.0.0.1.53: [bad udp cksum 0x3ff6 -> 0x7be2!] 32011+ PTR? 242.250.250.87.in-addr.arpa. (45)
    <data here>
18:34:16.076448 IP (tos 0x0, ttl 64, id 26142, offset 0, flags [DF], proto UDP (17), length 604)
    192.168.0.6.53415 > 77.66.84.233.443: [bad udp cksum 0x6533 -> 0xf1ca!] UDP, length 576
    <data here>
18:34:16.186718 IP (tos 0x0, ttl 57, id 7930, offset 0, flags [none], proto UDP (17), length 268)
    77.66.84.233.443 > 192.168.0.6.53415: [udp sum ok] UDP, length 240
    <data here>
18:34:16.187096 IP (tos 0x0, ttl 64, id 12081, offset 0, flags [DF], proto UDP (17), length 103)
    1.1.1.1.53 > 192.168.0.6.38972: [bad udp cksum 0xc314 -> 0xfa7e!] 32011 q: PTR? 242.250.250.87.in-addr.arpa. 1/0/1 242.250.250.87.in-addr.arpa. PTR ya.ru. ar: . OPT UDPsize=1252 (75)
    <data here>

1) 本地端口 54387 的进程发送请求,并按预期重定向到 127.0.0.1:53
2) 本地自定义 DNS 服务向远程 DNS 服务器发送请求
3) 远程服务器回复
4) ??? 本地端口 54387 的原始进程收到来自 1.1.1.1:53 的响应 ???
5+) 对 PTR 重复上述操作

这里发生了什么?为什么会发生?如何在不编辑解析的情况下避免这种情况?总的来说这不是一个大问题,但来自自定义服务的 DNS 查询是加密的,而来自 1.1.1.1:53 的响应不是。

作为参考,当前 resolv.conf 通过 DHCP 租约更新:

1.1.1.1
8.8.8.8

我无法编辑它,因为最初的问题是针对 Android 9+ 的,它只是没有一个地方可以让你只设置 DNS 就可以了。我设法在我的CentOS8设置,所以问题应该适用的

答案1

上述第 1 点中的请求是在其中一个预路由链中发生 DNAT 之后看到的。这就是为什么您看到的目标地址是 127.0.0.1,而不是原始目标地址 1.1.1.1。此数据包在您的解析器上传输,然后您似乎继续通过 HTTPS 进行 DNS。

当本地解析器将响应发送回请求者时,它也会经过 NAT。此 NAT 将确保响应的源地址是请求的原始目标地址。这就是为什么您会在上面第 4 点中看到 1.1.1.1 作为源地址。

基本上,NAT 发生在两个地方:

  1. 它根据您提供的规则修改 OUTGOING 数据包。
  2. 它还修改了 INCOMING 数据包以恢复上述修改,并确保返回数据包与“原始”节点上的正确套接字正确匹配。

相关内容