无状态nat中如何根据端口号进行nat?

无状态nat中如何根据端口号进行nat?

我只想将从一个 IP:端口对收到的 RTP 数据包转发到另一个 IP:端口对。我已经用 iptables 做到了。 iptables 使用 conntrack 模块。但我的应用程序中不需要 conntrack。所以我想用无状态NAT来做到这一点。我发现无状态 NAT 规则可以使用“ip route add nat”命令执行,例如

ip route add nat 205.254.211.17 via 192.168.100.17

该命令告诉内核对任何发往 205.254.211.17 的数据包执行网络地址转换。参数via告诉NAT代码用新的目标地址192.168.100.17重写绑定到205.254.211.17的数据包。

据我了解,问题是这会将所有发往 205.254.211.17 的数据包转发到 192.168.100.17。是否有任何选项可以将 205.254.211.17 特定端口上收到的 RTP 数据包转发到另一个 IP:端口?

答案1

经过修改数据包标头字段nftables这是可能的,甚至不使用ip route add nat它,作为一个简单的路由器功能,仅限于第 3 层 (IP),而不是第 4 层(TCP、UDP,...)。

警告:需要 nftables >= 0.6(如果使用 notrack,则此处 >= 0.7)并且内核 >= 4.10。此处使用 nftables 0.8.3 和内核 4.15.x 进行测试。

它非常紧凑,因为 nftables 可以组合多个目标(这里有 3 个目标):

# nft add table raw
# nft 'add chain raw prerouting {type filter hook prerouting priority -300;}'
# nft add rule raw prerouting ip daddr 205.254.211.17 udp dport 5004 notrack ip daddr set 192.168.100.17 udp dport set 5006

第 2 行引号以避免 shell 解释。如果进行测试,删除所有 nft 的最快方法是nft flush ruleset

因此,只要大声读出它,规则就会告诉您仅选择目标为 205.254.211.17 的 IP 数据包,即目标端口为 5004 的 UDP,然后将其标记为不可追踪(通过 conntrack,如果已加载),将其目标 IP 设置为 192.168.100.17,并将其目标端口设置为 5006。

只要您不同时在两者上使用表(好吧,无论如何您都不想使用它),您就可以毫无问题地混合nftables使用规则。能够明确表达iptablesnat链优先级raw甚至允许选择 nftables 钩子是否在相应的 iptables 钩子之前或之后运行,例如,如果有这样的需要,这里通过选择 -301 或 -299 来确保在 iptables 表之前或之后运行。

答案2

Linux 似乎并未提供对无状态 NAT 的支持,从而允许您通过特定端口或端口组来限制行为。

来自iproute2 文档:

无状态 NAT(有时被称为哑 NAT)是最简单的 NAT 形式。它涉及重写通过路由设备的地址:入站数据包将进行目标地址重写,出站数据包将进行源地址重写。

看起来这种类型的 NAT 仅限于 IP 地址。看看目前的情况主流内核实现在这里,看来负责完成这项工作的功能不接受端口号,只接受 IP 地址和网络掩码。

答案3

您需要使用 tcpedit munge 编辑数据包。匹配传入端口,将数据包目的地重写为 LAN 地址,并反转为传出数据包。 https://www.man7.org/linux/man-pages/man8/tc-pedit.8.html

tc 的好处是它很快,非常快。不好的一面是学习曲线。

相关内容