nftables:段之间重复的广播数据包

nftables:段之间重复的广播数据包

我们有一个 Debian Buster 盒子(nftables 0.9.0,内核 4.19)连接到四个不同的网段。其中三个网段是运行 Syncthing 的设备的所在地,Syncthing 通过向 UDP 端口 21027 广播来运行自己的本地发现。因此,由于广播不跨网段,因此这些设备不能全部“看到”彼此; Buster 盒本身不参与同步集群。

虽然我们可以通过在 Buster 盒子上运行 Syncthing 的发现或中继服务器来解决这个问题,但我们被要求不要使用它们(由于配置和漫游到其他站点的设备的原因)。因此,我们正在寻找基于 nftables 的解决方案;我的理解是,通常不会这样做,但为了使这项工作有效,我们必须:

  • 匹配 UDP 21027 上的传入数据包
  • 将这些数据包复制到需要查看的其他网段接口
  • 更改新数据包的目标 IP 以匹配新网段的广播地址(同时保留源 IP,因为发现协议可以依赖它)
  • 发出新的广播而不会再次重复

只有三个附加段参与设备;所有子网掩码均为/24。

  • 段 A (eth0, 192.168.0.1) 不应转发
  • 网段 B(eth1、192.168.1.1)应仅转发到网段 A
  • 段 C (eth2, 192.168.2.1) 应转发到 A 和 B

到目前为止,我们最接近的工作规则是(为简洁起见,省略了其他 DNAT/MASQ 和本地过滤规则):

table ip mangle {
    chain repeater {
        type filter hook prerouting priority -152; policy accept;
        ip protocol tcp return
        udp dport != 21027 return
        iifname "eth1" ip saddr 192.168.2.0/24 counter ip daddr set 192.168.1.255 return
        iifname "eth0" ip saddr 192.168.2.0/24 counter ip daddr set 192.168.0.255 return
        iifname "eth0" ip saddr 192.168.1.0/24 counter ip daddr set 192.168.0.255 return
        iifname "eth2" ip saddr 192.168.2.0/24 counter dup to 192.168.0.255 device "eth0" nftrace set 1
        iifname "eth2" ip saddr 192.168.2.0/24 counter dup to 192.168.1.255 device "eth1" nftrace set 1
        iifname "eth1" ip saddr 192.168.1.0/24 counter dup to 192.168.0.255 device "eth0" nftrace set 1
    }
}

计数器显示规则已被满足,但如果没有规则,daddr set广播地址仍与始发段上的相同。nft monitor trace至少显示一些数据包正在到达具有正确目标 IP 的预期接口,但随后落在盒子本身的输入挂钩中,并且不会被网段上的其他设备看到。

我们在这里寻求的结果在实践中是否可以实现?如果可以,遵循哪些规则?

答案1

仍然可以在中使用 nftables网络开发者家庭(而不是ip家庭)对于这种情况,因为只有入口需要(nftables 还没有出口可用的)。dupfwd中的行为入口钩子与TC-镜像'mirrorredirect

我还讨论了一个小细节:将以太网源地址重写为新的以太网传出接口的 MAC 地址,就像对真正路由的数据包所做的那样,即使没有它也适用。因此必须事先知道接口的 MAC 地址。我把所需的两个(以太网0'沙以太网1's)在变量/宏定义中,应使用正确的值进行编辑。

define eth0mac = 02:0a:00:00:00:01
define eth1mac = 02:0b:00:00:00:01

table netdev statelessnat
delete table netdev statelessnat

table netdev statelessnat {
    chain b { type filter hook ingress device eth1 priority 0;
        pkttype broadcast ether type ip ip daddr 192.168.1.255 udp dport 21027 jump b-to-a
        
    }

    chain c { type filter hook ingress device eth2 priority 0;
        pkttype broadcast ether type ip ip daddr 192.168.2.255 udp dport 21027 counter jump c-to-b-a
    }

    chain b-to-a {
        ether saddr set $eth0mac ip daddr set 192.168.0.255 fwd to eth0
    }

    chain c-to-b-a {
        ether saddr set $eth1mac ip daddr set 192.168.1.255 dup to eth1 goto b-to-a
    }
}

答案2

编辑:对于后来发现这个问题的人来说,AB 接受的答案给出了一个纯粹的 nft 解决方案。

感谢 AB 的建议,现在可以使用 tc 而不是纯粹的 nftables 规则来工作:

tc qdisc add dev eth2 ingress
tc filter add dev eth2 ingress \
    protocol ip u32 \
    match ip dst 192.168.2.255 \
    match ip protocol 17 0xff \
    match ip dport 21027 0xffff \
    action nat ingress 192.168.2.255/32 192.168.0.255 \
    pipe action mirred egress mirror dev eth0 \
    pipe action nat ingress 192.168.0.255/32 192.168.1.255 \
    pipe action mirred egress redirect dev eth1

tc qdisc add dev eth1 ingress
tc filter add dev eth1 ingress \
    protocol ip u32 \
    match ip dst 192.168.1.255 \
    match ip protocol 17 0xff \
    match ip dport 21027 0xffff \
    action nat ingress 192.168.1.255/32 192.168.0.255 \
    pipe action mirred egress redirect dev eth0

我对这些过滤器的理解是,它们匹配 UDP 端口 21027 的传入广播数据包,将它们 NAT 到每个其他预期子网的广播地址(ingress更改目标 IP,而不是nat egress会更改的源 IP),然后复制/重定向将经过 NAT 处理的数据包发送到其他接口的输出队列。

作为 tc 的新手,这可能不是解决问题的最佳方法,但它可以让公告广播跨段传播(Syncthing 很高兴发现新节点)。

相关内容