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

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

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

我的 Debian 服务器上有 bind9 在监听端口 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

我使用 netcat 验证了我在 127.0.0.2:53 收到了 DNS 请求的副本。到目前为止一切顺利。

现在,我需要更改目标 IP。我尝试使用以下方法实现此目的:

iptables -t nat -A PREROUTING -p udp -d 127.0.0.2 --dport 53 -j DNAT --to 8.8.8.8

我使用 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

tcpdump 仍然没有显示任何内容。

我已开启 IP 转发:

$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

我几乎没有主意了,希望得到任何帮助。谢谢。

答案1

有了 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

我使用 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

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

iptables -t nat -I PREROUTING 2 -i docker0 -p udp --dst 172.17.0.1 --dport 53 -j TEE --gateway 127.1.2.3

但也可以这样 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

因此,除了在 mangle 表中使用 TEE 之外,您的做法基本正确,这里我在 nat 表上同时使用了 TEE 和 DNAT,除了便于调试和处理规则更改外,不需要 MARK。您犯的另一个错误是让 DNAT 规则作用于您认为 TEE 应该去往的目标,但实际上 TEE 和 DNAT 应该作用于相同的条件。但我将保留 mark 规则,只是为了和货物崇拜者开个玩笑。

简短形式为:

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

答案2

文档说

球座目标将克隆一个数据包并将此克隆重定向到另一台机器当地的网络段。换句话说,下一跳必须是目标,否则您将必须配置下一跳以根据需要进一步转发它。

我不知道这个限制的原因,但似乎无法用 iptables NAT 克服,这很有道理,因为如果底层实现支持外部目标,那么为什么要限制 TEE 的目标范围。我怀疑 TEE 是在 NAT 级别以下完成的。

无论如何它都无法工作因为响应会带有错误的源地址。

答案3

由于 TEE 只能在同一子网中使用,因此您可以使用 守护进程记录器, 也提供在 github 上 (哪里看起来更新鲜?)。

Daemonlogger 是 Martin Roesch 开发的数据包记录器和软分接器。基于 libpcap 的程序有两种运行模式:

  1. 它嗅探数据包并直接将它们缓存到磁盘,并且可以将自身作为后台数据包日志记录的守护进程。默认情况下,当记录了 2 GB 的数据时,文件就会滚动更新。
  2. 它嗅探数据包并将其重写到第二个接口,本质上充当软水龙头。它也可以在守护进程模式下执行此操作。这两种运行时模式是互斥的,如果将程序置于水龙头模式(使用 -I 开关),则禁用记录到磁盘。

一些文字说明:

相关内容