Linux conntrack 未将多播响应视为同一流的一部分

Linux conntrack 未将多播响应视为同一流的一部分

我的电视(192.168.1.48)正在多播 SSDP 数据包(到 239.255.255.250:1900),并且在我的服务器(192.168.1.17)上,通过运行 smcroute 并进行一些数据包处理来增加此多播数据包的 IP TTL,我可以将其路由到通过桥接网络连接的容器(Podman / Docker):

ISP                LAN              bridge network @ server
 |           (192.168.1.0/24)            (10.1.1.0/24)
 |                  |                         |
 +--[router]--(.1)--+                         |
 |                  |                         |
 |                  +--(.48)--[tv]            +--(.2)--[container_A]
 |                  |                         |
 :                  |                         +--(.3)--[container_B]
                    |                         |
                    +--(.17)--[server]--(.1)--+
                    |                         |
                    :                         :

容器甚至可以回复此 SSDP 数据包,并且容器中的媒体服务器发现正在运行,所有路由均无需代理或 NAT。(LAN 上的路由器(192.168.1.1)通过 192.168.1.17 具有 10.1.1.0/24 网络的静态路由,这也有所帮助。)

我的问题是,当我nft在服务器上的 FORWARD 链中创建一条规则以允许往返于容器的 SSDP 流量时,conntrack 系统似乎没有意识到响应是从 192.168.1.48 到 10.1.1.2 和 10.1.1.3 的已建立流的一部分,因此它将响应数据包(来自 10.1.1.2:1900 和 10.1.1.3:1900)视为新流,这意味着我必须添加另一条规则以允许从桥接网络到 LAN 的 udp/1900 数据包。

这些是相关的防火墙规则:

table inet fw {
    chain FORWARD {
        type filter hook forward priority filter; policy drop;
        ct state invalid drop
        ct state established accept
        ct state related accept
        ct state untracked counter packets 0 bytes 0
        ip daddr 239.255.255.250 udp dport 1900 accept comment "forward SSDP"
        log prefix "CHAIN=FORWARD " accept # TODO: remove temporary rule
    }

    chain MANGLE {
        type nat hook prerouting priority mangle; policy accept;
        meta pkttype multicast ip ttl set 2
    }
}

显示的内容如下conntrack -L conntrack,请注意第一行,它期待来自 239.255.255.250:1900 的回复数据包,而实际上应该是 10.1.1.2:1900 和 10.1.1.3:1900:

udp      17 3 src=192.168.1.48 dst=239.255.255.250 sport=49155 dport=1900 [UNREPLIED] src=239.255.255.250 dst=192.168.1.48 sport=1900 dport=49155 use=1
udp      17 3 src=10.1.1.2 dst=192.168.1.48 sport=1900 dport=49155 [UNREPLIED] src=192.168.1.48 dst=10.1.1.2 sport=49155 dport=1900 use=1
udp      17 3 src=10.1.1.3 dst=192.168.1.48 sport=1900 dport=49155 [UNREPLIED] src=192.168.1.48 dst=10.1.1.3 sport=49155 dport=1900 use=1

conntrack 系统是否应该足够智能,能够识别出多播数据包和两个响应是同一流的一部分?或者是否应该由助手设置一个期望,以便将这些数据包视为 RELATED 而不是 ESTABLISHED?

答案1

如上所述,conntrack 基础设施本身不会将对多播请求的响应识别为同一流的一部分。

一个选择是使用 conntrack 助手。对于我的具体情况 (SSDP),conntrack-tools 包中有一个 ssdp 助手。

暗示了另一种选择在这个答案中,但对于 iptables 和 ipset,它们有(或曾经有)一个专用的hash:ip4,port类型。使用 nftables连接,我能够使其适应 nftables 并使其适用于所有多播请求,如下所示:

table inet filter {
    set mc4_out {
        type ipv4_addr . inet_service
        timeout 5s
    }
    set mc6_out {
        type ipv6_addr . inet_service
        timeout 5s
    }
    chain OUTPUT {
        type filter  hook output  priority filter
        policy accept
        meta nfproto ipv4  fib daddr type multicast  counter  add @mc4_out { ip saddr . udp sport }
        meta nfproto ipv6  fib daddr type multicast  counter  add @mc6_out { ip6 saddr . udp sport }
    }
    chain INPUT {
       type filter  hook input  priority filter
       policy drop
       meta nfproto ipv4  ip daddr . udp dport @mc4_out  counter  accept
       meta nfproto ipv6  ip6 daddr . udp dport @mc6_out  counter  accept
    }
}

一个小问题是meta pkttype multicast在我的 OUTPUT 链中不起作用,这在这个答案meta pkttype查看链路级数据包类型,并且当数据包遍历 OUTPUT 链时,还没有链路级报头,解决方案是使用 查询 FIB fib daddr type multicast

相关内容