使用 nftables 进行多宿主入站 natting

使用 nftables 进行多宿主入站 natting

我有一个具有两个外部 IP 的多宿主路由器。我想将来自两个 IP 的传入连接 NAT 到同一个内部 IP。

我目前拥有的

$ ip rule show
0:      from all lookup local
32761:  from 192.168.220.129 lookup ftto
32764:  from 192.168.220.128 lookup vdsl
32766:  from all lookup main
32767:  from all lookup default
$ ip route show default table ftto
default via fttogw dev ftto
support@qbs01:~$ ip route show default table vdsl
default via vdslgw dev vdsl
$ cat nftables.conf
...
table ip nat {
        chain prerouting {
                type nat hook prerouting priority 100; policy accept;
                iifname "vdsl" tcp dport { smtp } dnat 192.168.220.128;
                iifname "ftto" tcp dport { smtp } dnat 192.168.220.129;

        }
        chain postrouting {
                type nat hook postrouting priority 100; policy accept;
                # masquerade internal networks
                ip saddr 192.168.220.0/23 oifname "vdsl" masquerade;
                ip saddr 192.168.220.0/23 oifname "ftto" masquerade;
...
}

并且成功了。如何才能做到这一点,而不必为每台需要进行此类设置的内部机器分配两个内部 IP 地址?

答案1

补充OP中没有的信息:

  • 192.168.220.0/23 是路由器接口上可用的 LAN,名称为局域网0

  • OP 的设置中没有其他 LAN。


让我们看看从外部发起的流程需要什么:

  • 原始传入

    显然没什么特别的:只是基因全部送达单一目的地

  • 回复

    连接跟踪存储了一个连接跟踪上一个项目中的流的查找条目。但缺少的是它来自的接口。因为同一个公共 IP 地址可以选择一次通过甚高数字用户线还有一次光纤到户这是针对每个流程的,而不是针对远程客户端的。因此连接跟踪需要帮助来保留这一缺失的信息。对于这个角色,连接跟踪标记可以使用。在此设置中,每个标记值将相当于一个接口名称。

    本博客中举例描述了它的用法:Netfilter 连接标记。这允许在前一步(传入)为流(而不仅仅是数据包)分配特定标记,并将其用作传出的选择器。

    此选择无法在邮政路由:这是在需要选择接口之后。它必须发生在路由并影响路由堆栈。ip 规则s 也必须改变才能使用标记

最后,完成了以下工作:

  • 仅保留 192.168.220.128 作为示例服务器

  • 添加类型过滤器钩子预路由链来处理标记。由于这是仅路由器的情况(OP 对由路由器本身发起或到达路由器本身的流量不感兴趣),因此不需要输出钩子。下面是它的工作原理:

    • 如果连接跟踪标记已设置,这意味着此流程之前已经处理过:设置数据包标记并跳过下一步设置
    • 否则,如果是新流,则在数据包的传入接口上设置一个标记,并在连接跟踪入口。
  • 更改 IP 规则以使用标记而不是地址,并完成路由表

  • 无需为不同的钩子类型使用多个表,这是 iptables 的限制,限制了可用的功能。例如,集合和映射的范围仅限于单个表。要使用集合分解规则,使用此集合的所有链都必须位于同一个表中。

  • 我将使用一个映射来存储从端口到后端服务器的关联,以简化管理。

  • 吹毛求疵:nat/prerouting 的传统优先级是 -100 而不是 100,这其实并不重要,除非还与iptables的自然。

首先,改变ip 规则改为使用下面的规则和路由:使用标记作为选择器,而不是任何 IP 地址。它将通过以下方式为每个新流设置nftables连接跟踪标记用于状态机制并检索属于此流的每个数据包。

ip rule add fwmark 101 lookup vdsl
ip rule add fwmark 102 lookup ftto

如果严格反向路径转发已启用,每个表中都应该有所有路由(因此下面为每个路由表添加了重复的 LAN 路由):

ip route add table vdsl 192.168.220.0/23 dev lan0
ip route add table vdsl default via vdslgw dev vdsl onlink
ip route add table ftto 192.168.220.0/23 dev lan0
ip route add table ftto default via fttogw dev ftto onlink

尽管如此,如果在 SRPF 的情况下,11岁最近才有记录src_valid_mark必须启用 sysctl toggle:

sysctl -w net.ipv4.conf.lan0.src_valid_mark=1
sysctl -w net.ipv4.conf.vdsl.src_valid_mark=1
sysctl -w net.ipv4.conf.ftto.src_valid_mark=1

新的规则集取代了 OP 的规则集:

table ip multihomed {

    map port2ip {
        type inet_service : ipv4_addr
        elements = {
            25 : 192.168.220.128
        }
    }

    chain handlemarks {
        type filter hook prerouting priority -150; policy accept;
        ct mark != 0 meta mark set ct mark accept
        ct state new meta mark set iifname map { "vdsl" : 101, "ftto" : 102 } ct mark set meta mark accept
    }

    chain prenat {
        type nat hook prerouting priority -100; policy accept;
        iifname { "vdsl", "ftto" } dnat to tcp dport map @port2ip;
    }

    chain postnat {
        type nat hook postrouting priority 100; policy accept;
        ip saddr 192.168.220.0/23 oifname { "vdsl", "ftto" } masquerade;
    }
}

为了轻松添加可从两个公共地址访问的(单个)服务,可以在端口2ip映射。例如映射到服务器 192.168.220.130 的 http 端口:

nft add element ip multihomed port2ip '{ 80: 192.168.220.130 }'

注意:最后一个伪装规则,针对流量发起来自 LAN 或路由器的路由将不受策略路由约束。通常的路由将始终使用相同的单一接口。

相关内容