如何复制传入的 DNS 数据包并使用 iptables 将它们发送到不同的名称服务器?

ret*_*eax 5 networking domain-name-system linux router iptables

编辑:tldr:我想使用 TEE 和 NAT 来克隆 UDP 流量。我不担心处理响应。理想情况下,我不想安装新软件。我正在使用 TEE 成功发送到本地网段 (127.0.0.2),然后我想将该流量通过 NAT 传输到 WAN。

我有 bind9 在我的 Debian 服务器上侦听端口 53。我有一个外部客户端向所述服务器发出 DNS 请求。所有这些都运行良好。我想在端口 53 上复制传入的 DNS 请求并将它们发送到 8.8.8.8。注意复制这个词。

通过对 SU 的大量搜索和阅读,我发现最常用的方法是使用 iptables TEE 和 NAT。我的 TEE 工作得很好,这是我的命令:

iptables -t mangle -A POSTROUTING -p udp -d 127.0.0.1 --dport 53 -j TEE --gateway 127.0.0.2
Run Code Online (Sandbox Code Playgroud)

我确认我在 127.0.0.2:53 收到了一份带有 netcat 的 DNS 请求的副本。到现在为止还挺好。

现在,我需要更改目标 IP。我尝试通过以下方式完成此操作:

iptables -t nat -A PREROUTING -p udp -d 127.0.0.2 --dport 53 -j DNAT --to 8.8.8.8
Run Code Online (Sandbox Code Playgroud)

我使用 tcpdump 来监控到 8.8.8.8 的传出流量。没有。我想知道:也许我需要更改源 IP 地址,以便内核不会丢弃此数据包,因为它到达 127.0.0.2,但源 IP 设置为我的外部 DNS 客户端的 IP。为什么不?

iptables -t nat -A POSTROUTING -p udp -d 127.0.0.2 --dport 53 -j SNAT --to DNS_SERVERS_PUBLIC_IP
Run Code Online (Sandbox Code Playgroud)

尽管如此,tcpdump 什么也没显示。

我有 IP 转发:

$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
Run Code Online (Sandbox Code Playgroud)

我几乎没有想法,希望得到任何帮助。谢谢你。

小智 2

有了 iptables,没有什么是不可能的。

# iptables -t nat -L -v --line-numbers -n
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        5   281 MARK       udp  --  docker0 *       0.0.0.0/0            172.17.0.1           udp dpt:53 MARK set 0xc0fe
2        5   281 TEE        udp  --  docker0 *       0.0.0.0/0            172.17.0.1           udp dpt:53 TEE gw:127.1.2.3
3        3   167 DNAT       udp  --  *      *       0.0.0.0/0            0.0.0.0/0            mark match 0xc0fe to:1.1.1.1:53
Run Code Online (Sandbox Code Playgroud)

我正在使用 docker 进行测试,因为它的界面更容易使用。请注意,我将这些规则放在 nat 预路由表中的任何其他规则之前。

您要做的就是标记您感兴趣的数据包,然后 TEE(复制)该数据包,现在您可以将该数据包 DNAT 到 1.1.1.1。

标记它们,这里你应该使用你的 eth0 或 eno1,而不是 docker0。

iptables -t nat -I PREROUTING 1 -i docker0 -p udp -d 172.17.0.1 --dport 53 -j MARK --set-mark 0xc0fe
Run Code Online (Sandbox Code Playgroud)

复制/发球,到本地主机,规则可以是这样的

iptables -t nat -I PREROUTING 2 -i docker0 -p udp --dst 172.17.0.1 --dport 53 -j TEE --gateway 127.1.2.3
Run Code Online (Sandbox Code Playgroud)

但也可以像这样 iptables -t nat -I PREROUTING 3 -p udp -m mark --mark 0xc0fe -j TEE --gateway 127.1.2.3

最后

iptables -t nat -I PREROUTING 3 -p udp  -m mark --mark 0xc0fe -j DNAT --to-destination 1.1.1.1:53
Run Code Online (Sandbox Code Playgroud)

所以你走在正确的道路上,除了在 mangle 表中使用 TEE 之外,这里我在 nat 表上使用 TEE 和 DNAT,并且除了更容易调试和处理规则更改之外不需要 MARK。您还犯的另一个错误是让 DNAT 规则在您认为 TEE 应该去的目标上起作用,但 TEE 和 DNAT 应该在相同的条件下起作用。但我将把标​​记规则留在这里,只是为了与货物崇拜者一起玩。

更简短的形式:

iptables -t nat -I PREROUTING 1 -i eth0 -p udp --dst 172.17.0.1 --dport 53 -j TEE --gateway 127.3.3.3
iptables -t nat -I PREROUTING 2 -i eth0 -p udp --dst 172.17.0.1 --dport 53 -j DNAT --to-destination 1.1.1.1:53
Run Code Online (Sandbox Code Playgroud)