如何使用 nftables 为 Raspberry Pi 上的 Minecraft 服务器配置端口转发?

如何使用 nftables 为 Raspberry Pi 上的 Minecraft 服务器配置端口转发?

由于我使用透明代理服务,因此我使用树莓派作为我的家庭路由器。它的操作系统是普通的 Raspbian。现在我正在 上设置 Minecraft 服务器192.168.2.28,并使用 NAT 将其暴露到 WAN。这是我的/etc/nftables.conf

#!/sbin/nft -f

flush ruleset

table ip filter {
    chain output {
        type filter hook output priority 0; policy accept;
        tcp sport 25565 drop
    }
}

table ip nat {
    chain prerouting {
        type nat hook prerouting priority 0; policy accept;
        tcp dport 25565 dnat 192.168.2.28
    }

    chain postrouting {
        type nat hook postrouting priority 0; policy accept;
        tcp sport 25565 ip saddr 192.168.2.28 masquerade
    }
}

但是,我有以下问题: On 192.168.2.28,我运行 nc -l -p 25565 On 192.168.2.27,我运行 echo "Hello, world!" | nc wan_ip 25565

想要的行为是我得到“Hello, world!”留言于192.168.2.28.

然而,当第一个 SYN 数据包通过路由器时,它仅将其 baddr 进行了 NAT,保持其 Saddr 等于192.168.2.27

192.168.2.28收到数据包时,它会回复192.168.2.27。由于它们位于同一 L2 网络中,因此数据包不会通过路由器,因此不会经过 NAT。

然后192.168.2.27收到来自 的数据包192.168.2.28,但它不知道这是来自 的回复wan_ip

如何解决此问题并使端口转发在任何地方(包括 LAN 主机)都可以工作?

答案1

提醒一句,nftables(就像iptables)仅看到要进行 NAT 处理的流的第一个数据包。当进行 NAT 时,同一流中的所有其他数据包将直接由网络过滤器/连线没有看到nftables不再:因此返回流量会自动取消 NAT,无需进一步帮助。

唯一重要的部分是第一个数据包发生了什么(因此对于 TCP 来说,它是一个 SYN 数据包)。此流的进一步流量(包括回复数据包)会自动处理并绕过 NAT 挂钩。

这意味着不应该有特殊的后路由规则来处理从 192.168.2.28 发出的流量。应该只有一个通用的伪装规则全部与互联网通信时为 192.168.2.0/24。无论如何,这个规则本身不是问题:当发出的流量是回复流量时,它不会像人们想象的那样频繁使用:它是预先存在的流量的一部分,因此如上所述,此类数据包不会遍历nftables不再了。

重要的是要有合适的NAT 发夹支持:客户端与服务器位于同一 LAN 中的情况,如果不小心,可能会发生不对称流量。

这里:

  • 当路由器发现任何内容(来自任何地方)发往 tcp 目标端口 25565 时,将目标地址重定向到 192.168.2.28

    由于重定向不区分外部和内部,因此当与整个 LAN 的适当通用伪装规则关联时,该规则本身就足够了。但OP并没有使用这样的规则。

  • 而不是后路由中的通用伪装,

    使用OPtcp sport 25565 ip saddr 192.168.2.28与之前规则的过滤部分无关第一的tcp dport 25565(并且还收到了新的目的地192.168.2.28):未实现 NAT 发夹。

什么需要被完成而是以下之一:

  1. 对整个 LAN 使用通用伪装(适应 NAT 发夹用例且缺乏附加信息)

        chain postrouting {
            type nat hook postrouting priority 0; policy accept;
            ip saddr 192.168.2.0/24 ip daddr != 192.168.2.0/24 masquerade
        }
    
  2. 仅当服务器是目标时才对目标端口为 25565 的数据包使用伪装

        chain postrouting {
            type nat hook postrouting priority 0; policy accept;
            tcp dport 25565 ip daddr 192.168.2.28 masquerade
        }
    

    这意味着只有流向服务器的流量(包括用于正确 NAT 发夹的 LAN 到 LAN 的流量)才会被伪装(LAN 系统将无法访问 Internet)。

  3. 而不是 2. 选择仅对首先获得 DNAT 的流量应用伪装

        chain postrouting {
            type nat hook postrouting priority 0; policy accept;
            ct status dnat masquerade
        }
    

    与 2. 效果相同,但更通用。

  4. 仅在需要时结合 1 和 3 进行伪装

    项目符号 2. 或 3. 具有隐藏 Internet 源地址的副作用,因此最好仅将其应用于 LAN:

        chain postrouting {
            type nat hook postrouting priority 0; policy accept;
            ip saddr 192.168.2.0/24 ip daddr != 192.168.2.0/24 ct status dnat masquerade
        }
    

因此,要么使用 1. 要么使用 4.(限制 LAN 访问 Internet) 还有其他可能的选择。

注意:1. 有一个极端情况:如果客户端使用路由器的内部 IP 地址作为目标,如果没有针对这种情况的附加规则,它将无法工作,但我怀疑客户端会这样做,而且我没有足够的规则来自OP的信息:路由器的内部IP地址。

相关内容