我正在尝试创建静态 NAT,但是当我运行该命令时ip route add nat 172.31.19.02 via 10.0.2.2
,它给出了错误Error: Invalid scope.
,并且在指定全局范围时给出了相同的错误。我正在尝试复制上面描述的内容使用 iproute2 进行无状态 NAT页。
我的网络设置由同一子网上的两个物理接口(ens5、ens6)和一个用于我的 tinc vpn (vpn) 的虚拟接口组成。可以从 tinc 接口访问地址 10.0.2.2。目标是将流量从 转发172.31.19.02
到10.0.2.2
。
据我了解IP地址文档页面global
应为“在任何地方有效”。这是否不正确?
的相关部分ip a
:
2: ens5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether [...]
inet 172.31.19.01/20 brd 172.31.31.255 scope global ens5
valid_lft forever preferred_lft forever
[...]
3: ens6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether [...]
inet 172.31.19.02/20 brd 172.31.31.255 scope global ens6
valid_lft forever preferred_lft forever
[...]
4: vpn: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
link/none
inet 10.0.2.1/24 scope global homeforward
valid_lft forever preferred_lft forever
[...]
我的路由表:
$ ip r
default via 172.31.16.1 dev ens5 proto static
10.0.2.0/24 dev homeforward proto kernel scope link src 10.0.2.1
172.31.16.0/20 dev ens6 proto kernel scope link src 172.31.19.02
172.31.16.0/20 dev ens5 proto kernel scope link src 172.31.19.01
$ ip r ls table 1000
default via 172.31.16.1 dev ens5 proto static
172.31.19.01 dev ens5 proto static scope link
$ ip r ls table 1001
default via 172.31.16.1 dev ens6 proto static
172.31.19.02 dev ens6 proto static scope link
答案1
Linux 的路由无状态 NAT 又名“IP NAT 哑”不再起作用,原因很简单:手册页告诉:
警告:Linux 2.6 不再支持路由 NAT。
所以像这样的例子这个:
[root@masq-gw]# ip route add nat 205.254.211.17 via 192.168.100.17 [root@masq-gw]# ip rule add nat 205.254.211.17 from 192.168.100.17 [root@masq-gw]# ip route flush cache [root@masq-gw]# ip route show table all | grep ^nat nat 205.254.211.17 via 192.168.100.17 table local scope host [root@masq-gw]# ip rule show 0: from all lookup local 32765: from 192.168.100.17 lookup main map-to 205.254.211.17 32766: from all lookup main 32767: from all lookup 253
将不再工作了。
该功能已添加到内核中2.1.15(1996)和在内核 2.6.9 中删除(2004)(但可能之前有一些内核):
<[email protected]> [IPV4]: Kill remnant of ip_nat_dumb This line in net/ipv4/Makefile was left behind when the rest of the dumb NAT option was taken out. Signed-off-by: Herbert Xu <[email protected]> Signed-off-by: David S. Miller <[email protected]>
这解释在备用无状态 NAT 中给出,使用tc nat
在内核 2.6.24 中重新添加:
以前我们有无状态 NAT 功能,该功能已集成到 IPv4 路由子系统中。只要 NAT 在子网到子网的基础上工作,这样 NAT 规则的数量相对较少,这就是一个很好的解决方案。原因是对于 SNAT,基于路由的系统必须通过规则执行线性扫描。
如果规则数量很大,则需要对路由子系统进行重大改造才能使其切实可行。
TC
这是一个基本的我制作的 DNAT 示例。进行无状态NAT的接口是ens5
(我不会将您的设置与同一 LAN 中的两个网卡一起使用:如果没有额外的设置,将会出现与以下相关的其他问题ARP通量和反向路径过滤。看来您已经意识到这一点,因为您有额外的路由表,但让我们保持这个示例简单),其上的本地地址是 172.31.19.1 和 172.31.19.2。任何入口到 172.31.19.2 的流量被 DNAT 到目的地 10.0.2.2,任何出口来自 10.0.2.2 的流量被 SNAT 到源 172.31.19.2。正如通常所做的那样,普里奥队列盘使用它是因为它的简单性,而不是因为它的优先特性。
tc qdisc add dev ens5 ingress
tc filter add dev ens5 ingress protocol ip matchall \
action nat ingress 172.31.19.2/32 10.0.2.2/32
tc qdisc add dev ens5 root handle 1: prio
tc filter add dev ens5 parent 1: protocol ip matchall \
action nat egress 10.0.2.2/32 172.31.19.2/32
可能会与 netfilter 的状态连接跟踪发生不可预见的交互。
nftables
也可以使用 nftables 执行相同的操作,如中所述nftables 维基。
nft add table ip natdumb
nft add chain ip natdumb prerouting '{ type filter hook prerouting priority -350; policy accept; }'
nft add rule ip natdumb prerouting ip daddr 172.31.19.2 ip daddr set 10.0.2.2
nft add chain ip natdumb postrouting '{ type filter hook postrouting priority 350; policy accept; }'
nft add rule ip natdumb postrouting ip saddr 10.0.2.2 ip saddr set 172.31.19.2
同样,可能会与 netfilter 的 conntrack 进行交互。notrack
如果没有加载或至少在当前名称空间中激活 netfilter NAT 内核模块,我删除了任何可能使其仍然工作的内容(同时notrack
将所有回复数据包视为NEW
流而不是ESTABLISHED
)。请随意尝试。
答案2
添加路由时,内核会检查它是否可以通过较低范围访问新范围,因为路由网关必须在同一 L2(数据链路层)连接上直接可达。
这个答案(https://superuser.com/a/1389304)对这个范围概念以及为什么/何时需要设置它有一个很好的快速澄清:
这些路由是您告诉 Linux 内核您所在的子网的方式。
当您添加 IP 地址时,此信息不会存储在隐藏的“我当前的子网”字段中;而是存储在隐藏的“我当前的子网”字段中。相反,它总是转换为没有指定网关的“范围链接”路由(也称为“设备路由”或“接口路由”),并且每当内核需要确定某个地址是否可直接访问时,它只执行路由表检查。
通常,一旦您配置了 IP 地址,这些路由就会自动添加 - 例如,运行 ip addr add 192.168.1.5/24 会分配 IP 地址 192.168.1.5 并为 192.168.1.0/24 创建子网路由。所以正常使用时不需要添加这些路由。
但是当你盲目地“删除所有路由”时,你最终也会删除这些自动创建的路由,并且内核的“这个地址是否在我的子网中”检查不再起作用。这就是为什么您最终必须手动重新添加路由。
(内核需要在 ip Route add 期间执行此检查,因为路由网关(下一跳)必须在同一 L2 连接上直接可达 - 它们不能位于另一个网关后面。也就是说,网关必须位于您的子网中。
路由范围是表达此限制的通用机制:新路由的下一跳需要通过具有较低范围的现有路由可达。换句话说,您必须先经过本地主机(链接范围),然后才能到达远程主机(全局范围)。)
编辑:
但这还不够:我一直在尝试让它在测试环境中运行,但到目前为止还没有成功。Error: Invalid scope.
也不断发生。