我家里有一个 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。eth1
to eth7
pluswlan0
是名为 的桥的一部分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/PREROUTING
和nat/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
我的具体设置是使用
pimd
PIMv2,我不知道是否始终使用该协议,但当源 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 -