我有一台既充当路由器又充当服务器的机器。我在这台机器上有几个 lxc 容器,并且希望将它们暴露给 LAN 和 WAN。下列的https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/sec-configuring_port_forwarding_using_nftables我能够成功地从 WAN 和 LAN 计算机访问服务器,但不能从本地主机/路由器服务器本身访问!
这是部分有效的配置:
# Created from lxc-net in debian
table inet lxc {
chain input {
type filter hook input priority filter; policy accept;
iifname "lxcbr0" udp dport { 53, 67 } accept
iifname "lxcbr0" tcp dport { 53, 67 } accept
}
chain forward {
type filter hook forward priority filter; policy accept;
iifname "lxcbr0" accept
oifname "lxcbr0" accept
}
}
# Created from lxc-net in debian
table ip lxc {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 10.0.3.0/24 ip daddr != 10.0.3.0/24 counter packets 51 bytes 3745 masquerade
}
}
# This is what I added
table ip myportforwarding {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
tcp dport 8088 dnat to 10.0.3.230
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip daddr 10.0.3.230 masquerade
}
}
我从这个答案中尝试了几个选项:如何使用 nftables 为 Raspberry Pi 上的 Minecraft 服务器配置端口转发?
似乎没有任何方法可以实现对 8088 上的服务的本地访问。
查看wireshark,从局域网访问如下:
192.168.1.105 -> 192.168.1.1 SYN
10.0.3.1 -> 10.0.3.230 SYN
...
从同一台机器访问:
192.168.1.1 -> 192.168.1.1 SYN
192.168.1.1 <- 192.168.1.1 FIN!
我不太熟悉 nft 或 iptables,所以我确信我缺少一些东西
答案1
让我们看一下其中的一部分Netfilter 和通用网络中的数据包流示意图。它是为iptables但大部分都适用于nftables:
据记载,纳特仅针对处于 conntrack 状态的数据包查阅表 新:数据包开始新的流动。
路由/转发的流量来自NAT/预路由hook:这就是新流有机会进行 NAT 的地方。 OP处理了这个案子。
本地发起的数据包(创建于本地进程气泡在中心)首先遍历自然/输出钩子,然后他们的答案将像往常一样通过NAT/预路由钩。撇开查询的目的地尚未更改这一事实不谈,因为答案与之前创建的流相匹配,所以它不再是处于 NEW 状态的数据包:NAT/预路由hook 永远不会被咨询此类流量,因为为时已晚:唯一进行 NAT 的地方是自然/输出。
因此,对于这种情况,路由数据包和本地启动的数据包都应收到相同的更改,规则为NAT/预路由必须复制到自然/输出并且通常会稍微调整以匹配不同的情况。
这里的适配是关于主机到达自身,因此对于接口是环回(lo
)接口的路由情况,从而添加oif lo
到它。如果没有此过滤器,使用端口 8088 从主机到任何地方的任何查询都将被重定向到容器,而只有主机对其自身的情况才是预期的。
将这条链添加到已经存在的链中ip 我的端口转发表将处理它:
chain output {
type nat hook output priority dstnat; policy accept;
tcp dport 8088 oif "lo" dnat to 10.0.3.230
}
对于小细节:从自然/输出触发重新路由检查部分,其中路由堆栈被告知重新考虑之前的路由决策(输出接口lo
)。后重新路由检查输出接口变为lxcbr0
。