我一直在搜索,但似乎找不到我的具体问题的答案。我今天在预路由下有以下规则:
iifname "br0" udp dport 53 counter dnat to 192.168.22.5:53
但是,我有一个问题,IP 地址 192.168.22.5 也在“br0”上。所以手头的问题是,我如何让 nftables 忽略这个 IP 并允许它访问网络上的端口 53(这是我的 pihole),但将所有其他端口 53 udp 数据重定向到它?
感谢您的回复!
答案1
您只需添加一个附加条件即可不匹配此 IP 地址,从而最终不执行 NAT:
iifname "br0" ip saddr != 192.168.22.5 udp dport 53 counter dnat to 192.168.22.5:53
但...如果客户端和 DNS 服务器都在同一个 LAN 中,那么回复将直接从 DNS 服务器发送到客户端。例如,如果客户端 192.168.22.101 设置为使用 google 的公共解析器(涉及所有隐私问题),您将得到以下信息:
查询:192.168.22.101 到 8.8.8.8 -> 路由和 dnat-ed -> 192.168.22.5
回复:192.168.22.5 -> 桥接(或两种情况下路由器都看不到)ip 家族规则 -> 192.168.22.101
但是由于 192.168.22.101 期望的应答来自 8.8.8.8,而不是来自 192.168.22.5,因此它将失败。
因此你也必须斯奈特查询。任何使数据包使用路由器的 IP 地址都可以:路由器的内部 IP(masquerade
),因为路由器拥有此 IP,或任何 Internet IP(使用snat
),因为它们是通过路由器路由的。您甚至可以想象为此使用一些 TEST-NET IP(例如:192.0.2.2):无论如何,IP 地址永远不会在本地网络之外看到。缺点是 DNS 服务器无法识别哪个 IP 发出了查询。较新的内核(即将推出的 5.7 或 5.8)将具有相当于 iptables 的 NETMAP如果这确实很重要,则可用。
masquerade
为了简单起见,我们就在这里使用。
因此,在等效的后路由链中可以使用类似以下内容创建(请适应您自己的命名约定):
nft add chain ip nat postrouting '{ type nat hook postrouting priority 100; policy accept; }'
规则如下:
ip daddr 192.168.22.5 udp dport 53 counter masquerade
这不会影响从 DNS 服务器发起的任何返回流量,因为它的 conntrack 条目将不再处于 NEW 状态,并且这纳特规则不会被遍历。
如果你只想影响来自br0而不是来自其他地方,有以下几种选择:
检查源 IP 来自 192.168.22.0/24 并且经过 dnat-ed
ip saddr 192.168.22.0/24 ip daddr 192.168.22.5 udp dport 53 ct status dnat counter masquerade
使用足够新的内核(>= 5.6)匹配传入接口(仍然在后路由中)就足够了:
iifname "br0" ip daddr 192.168.22.5 udp dport 53 ct status dnat counter masquerade
或者,如果它们不与其他用途冲突,您可以在预布线和后布线中使用标记:
预路由:
iifname "br0" ip saddr != 192.168.22.5 udp dport 53 counter set mark 1 dnat to 192.168.22.5:53
后路由:
mark 1 counter masquerade
最后,由于 DNS 使用 TCP 和 UDP,您可能也应该使用相同的方法tcp dport 53
。
答案2
来自主机本身的流量不会被匹配iifname $outgoing_interface
(但是iifname lo
),所以您的担心不存在。