多播流量能够在 netfilter 连接跟踪系统中戳出一个漏洞

多播流量能够在 netfilter 连接跟踪系统中戳出一个漏洞

我家里有一个 IPTV 解决方案,ISP 每秒从一个10.4.4.5端口10到另一个239.3.5.3端口向我发送数百个大型 UDP 数据报10,即它使用多播。我当前的iptables入口流量配置非常简单:

~# iptables -L INPUT -v -n --line-numbers
Chain INPUT (policy DROP 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1       19   845 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
2     1146  275K ACCEPT     all  --  eth0   *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED /* established/related connections */
# 

规则iptables-save格式:

# iptables-save -c
# Generated by iptables-save v1.6.0 on Sun Aug 26 12:51:11 2018
*nat
:PREROUTING ACCEPT [44137:4586148]
:INPUT ACCEPT [6290:1120016]
:OUTPUT ACCEPT [419:75595]
:POSTROUTING ACCEPT [98:8415]
[26464:2006874] -A POSTROUTING -o eth0 -m comment --comment SNAT -j MASQUERADE
COMMIT
# Completed on Sun Aug 26 12:51:11 2018
# Generated by iptables-save v1.6.0 on Sun Aug 26 12:51:11 2018
*filter
:INPUT DROP [72447:97366152]
:FORWARD ACCEPT [77426:101131642]
:OUTPUT ACCEPT [148:17652]
[17:787] -A INPUT -i lo -j ACCEPT
[333:78556] -A INPUT -i eth0 -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "established/related connections" -j ACCEPT
COMMIT
# Completed on Sun Aug 26 12:51:11 2018
# 

eth0上图是面向 ISP 的 NIC。现在奇怪的部分是,虽然这个多播流量根据计数器被丢弃(链默认策略计数器增加了几 MB/s),但实际上我确实在mplayer.其原因是多播流量似乎在 netfilter 连接跟踪系统中造成了漏洞。我可以用 来验证这一点conntrack -L。例子:

# conntrack -L | grep --color 239.3.
udp      17 29 src=10.4.4.5 dst=239.3.5.3 sport=10 dport=10 [UNREPLIED] src=239.3.5.3 dst=10.4.4.5 sport=10 dport=10 mark=0 use=1
conntrack v1.4.4 (conntrack-tools): 130 flow entries have been shown.
# 

即使我执行conntrack -F,上面的条目也会重新出现,并且我可以在 中看到视频流mplayer。然而,最终(大约 5 分钟后)该条目消失,并且流也立即停止。

仅供参考,这款基于 Linux 的路由器有 9 个物理接口:

# ip -br link
lo               UNKNOWN        00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP> 
eth2             DOWN           00:a0:c9:77:96:bd <NO-CARRIER,BROADCAST,MULTICAST,UP> 
eth1             UP             00:14:bf:5f:de:71 <BROADCAST,MULTICAST,UP,LOWER_UP> 
eth0             UNKNOWN        00:50:8d:d1:4f:ee <BROADCAST,MULTICAST,UP,LOWER_UP> 
eth3             DOWN           00:a0:c9:4b:21:a0 <NO-CARRIER,BROADCAST,MULTICAST,UP> 
eth4             UP             00:20:e2:1e:2e:64 <BROADCAST,MULTICAST,UP,LOWER_UP> 
eth5             DOWN           00:20:fc:1e:2e:65 <NO-CARRIER,BROADCAST,MULTICAST,UP> 
eth6             DOWN           00:20:fc:1e:2e:8e <NO-CARRIER,BROADCAST,MULTICAST,UP> 
eth7             UP             00:20:fc:1e:2f:67 <BROADCAST,MULTICAST,UP,LOWER_UP> 
wlan0            UP             00:21:91:e3:20:20 <BROADCAST,MULTICAST,UP,LOWER_UP> 
br0              UP             00:14:bf:5e:da:71 <BROADCAST,MULTICAST,UP,LOWER_UP> 
# ip -br address
lo               UNKNOWN        127.0.0.1/8 
eth2             DOWN           
eth1             UP             
eth0             UNKNOWN        192.0.2.79/24
eth3             DOWN           
eth4             UP             
eth5             DOWN           
eth6             DOWN           
eth7             UP             
wlan0            UP             
br0              UP             192.168.0.1/24
# 

正如我所说,eth0已连接到 ISP。eth1to eth7pluswlan0是名为 的桥的一部分br0。路由表如下所示:

# ip -4 r
default via 192.0.2.1 dev eth0 
192.0.2.0/24 dev eth0 proto kernel scope link src 192.0.2.79 
192.168.0.0/24 dev br0 proto kernel scope link src 192.168.0.1 
# 

可以在此处查看所有接口的各种网络参数:

# ip -4 netconf 
ipv4 dev lo forwarding on rp_filter off mc_forwarding off proxy_neigh off ignore_routes_with_linkdown off 
ipv4 dev eth2 forwarding on rp_filter off mc_forwarding off proxy_neigh off ignore_routes_with_linkdown off 
ipv4 dev eth1 forwarding on rp_filter off mc_forwarding off proxy_neigh off ignore_routes_with_linkdown off 
ipv4 dev eth0 forwarding on rp_filter off mc_forwarding on proxy_neigh off ignore_routes_with_linkdown off 
ipv4 dev eth3 forwarding on rp_filter off mc_forwarding off proxy_neigh off ignore_routes_with_linkdown off 
ipv4 dev eth4 forwarding on rp_filter off mc_forwarding off proxy_neigh off ignore_routes_with_linkdown off 
ipv4 dev eth5 forwarding on rp_filter off mc_forwarding off proxy_neigh off ignore_routes_with_linkdown off 
ipv4 dev eth6 forwarding on rp_filter off mc_forwarding off proxy_neigh off ignore_routes_with_linkdown off 
ipv4 dev eth7 forwarding on rp_filter off mc_forwarding off proxy_neigh off ignore_routes_with_linkdown off 
ipv4 dev wlan0 forwarding on rp_filter off mc_forwarding off proxy_neigh off ignore_routes_with_linkdown off 
ipv4 dev br0 forwarding on rp_filter off mc_forwarding on proxy_neigh off ignore_routes_with_linkdown off 
ipv4 all forwarding on rp_filter off mc_forwarding on proxy_neigh off ignore_routes_with_linkdown off 
ipv4 default forwarding on rp_filter off mc_forwarding off proxy_neigh off ignore_routes_with_linkdown off 
# 

这是预期的行为吗?我的第一个想法是 conntrack 模块能够检查 IGMP“成员报告”消息,从而允许流量到达239.3.5.3,但这并不能解释即使在 之后如何允许流量conntrack -F

答案1

使用类似的设置后pimd,我只能得出这样的结论:

  • filter/FORWARD只要为此流启用了多播路由,就会转发普通(数据)多播数据包。 conntrack 条目udp 17 29 src=10.4.4.5 dst=239.3.5.3 sport=10 dport=10 [UNREPLIED] src=239.3.5.3 dst=10.4.4.5 sport=10 dport=10 mark=0 use=1就是这样一个转发流,并且还会将nat/PREROUTINGnat/POSTROUTING计数器递增(仅)1:触发此 contrack 条目的新数据包。
  • 链路本地多播数据包(发送至 224.0.0.{1,22} 的 IGMP 数据包和发送至 224.0.0.13 的 PIMv2)由 停止filter/INPUT
  • 如果该流之前已启用,则组播路由器将激活该特定组播目的地的转发一段时间。一旦发生配置的超时,由于防火墙的原因,它没有从 LAN 收到任何 IGMP 报告或从 WAN 收到 PIMv2,它将认为不再有客户端侦听或不再有有效流,并将停止转发相应的组播流。

最后,您应该允许 linux 路由器接收:

  • 来自 LAN 的 IGMP 数据包,使路由器能够了解哪些多播客户端正在侦听:

    iptables -A INPUT -i br0 -p igmp -j ACCEPT
    
  • 我的具体设置是使用pimdPIMv2,我不知道是否始终使用该协议,但当源 IP 不只是 192.0.0.1 时,我必须允许 PIM 协议在保持 DROP 策略的同时工作。 2.1(但 10.4.4.5):

    iptables -A INPUT -s 192.0.2.1 -i eth0 -p pim -j ACCEPT
    
  • 可能需要允许来自 ISP 路由器的 IGMP 数据包,但我的特定设置不需要它们:

    iptables -A INPUT -s 192.0.2.1 -i eth0 -p igmp -j ACCEPT
    

更新:

请注意,filter/INPUT链的 DROP 策略仍会显示命中:Linux 路由器自己的 IGMP 和 PIMv2 数据包(多播)在发送到外部时会环回到本地系统,因此会被(无害地)丢弃,因为上述规则未启用。添加相应的规则后,我遇到了 PIMv2 的奇怪行为,最后我不得不标记数据包filter/OUTPUT以允许它们在filter/INPUT.同时我也限制了 na 规则。最终,通过以下规则,filter/INPUT在转发组播流量时, 的 DROP 策略计数器始终保持在 [0:0]:

# Generated by iptables-save v1.6.2 on Mon Aug 27 01:01:48 2018
*nat
:PREROUTING ACCEPT [1:56]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [1:56]
[0:0] -A POSTROUTING -s 192.168.0.0/24 -o eth0 -m comment --comment SNAT -j MASQUERADE
COMMIT
# Completed on Mon Aug 27 01:01:48 2018
# Generated by iptables-save v1.6.2 on Mon Aug 27 01:01:48 2018
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [1533311:325676232]
:OUTPUT ACCEPT [75:3724]
[0:0] -A INPUT -i lo -j ACCEPT
[1:56] -A INPUT -i eth0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
[40:1800] -A INPUT -i br0 -p igmp -j ACCEPT
[14:774] -A INPUT -s 192.0.2.1/32 -i eth0 -p pim -j ACCEPT
[28:1288] -A INPUT -s 192.0.2.1/32 -i eth0 -p igmp -j ACCEPT
[17:932] -A INPUT -s 192.0.2.79/32 -i eth0 -p igmp -j ACCEPT
[28:1392] -A INPUT -m mark --mark 0x1 -j ACCEPT
[28:1392] -A OUTPUT -p pim -j MARK --set-xmark 0x1/0xffffffff
COMMIT
# Completed on Mon Aug 27 01:01:48 2018

您可以模拟多播客户端并转储到标准输出socat(如果有多个接口,请指定本地IP):

socat -u UDP4-RECV:10,ip-add-membership=239.3.5.3:0.0.0.0 -

相关内容