我正在尝试使用 iptables 删除目标端口为 1900 的 UDP 数据包。这将影响两个方向,因此我为过滤表的 INPUT 和 OUTPUT 链各添加了一条规则。
root@hostname:~# iptables --table filter --list --numeric --verbose
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:1900
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:1900
传入数据包如下所示:
root@hostname:~# tcpdump -i enp2s0 -n "udp and port 1900"
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp2s0, link-type EN10MB (Ethernet), capture size 262144 bytes
11:17:35.845252 IP 192.168.0.1.56189 > 239.255.255.250.1900: UDP, length 123
11:17:36.285268 IP 192.168.0.1.36900 > 239.255.255.250.1900: UDP, length 133
11:17:36.285758 IP 192.168.0.1.36900 > 239.255.255.250.1900: UDP, length 127
11:17:36.286157 IP 192.168.0.1.36900 > 239.255.255.250.1900: UDP, length 127
11:17:36.286566 IP 192.168.0.1.36900 > 239.255.255.250.1900: UDP, length 129
11:17:36.286971 IP 192.168.0.1.36900 > 239.255.255.250.1900: UDP, length 129
11:17:36.287390 IP 192.168.0.1.36900 > 239.255.255.250.1900: UDP, length 124
11:17:40.845707 IP 192.168.0.1.56189 > 239.255.255.250.1900: UDP, length 123
11:17:41.285393 IP 192.168.0.1.36900 > 239.255.255.250.1900: UDP, length 133
11:17:41.285810 IP 192.168.0.1.36900 > 239.255.255.250.1900: UDP, length 127
11:17:41.286220 IP 192.168.0.1.36900 > 239.255.255.250.1900: UDP, length 127
11:17:41.286613 IP 192.168.0.1.36900 > 239.255.255.250.1900: UDP, length 129
11:17:41.287029 IP 192.168.0.1.36900 > 239.255.255.250.1900: UDP, length 129
11:17:41.287405 IP 192.168.0.1.36900 > 239.255.255.250.1900: UDP, length 124
^C
14 packets captured
14 packets received by filter
0 packets dropped by kernel
通常 iptables 工作得很好,我有其他按预期工作的过滤规则。此 OUTPUT 规则也按预期工作。以下输出显示此 OUTPUT 规则捕获(并丢弃)了一些数据包。
root@hostname:~# iptables --table filter --list OUTPUT --numeric --verbose
Chain OUTPUT (policy ACCEPT 412 packets, 87079 bytes)
pkts bytes target prot opt in out source destination
6 1128 DROP udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:1900
但是 INPUT 规则不起作用。我现在已经尝试了几种规则变体来捕获传入的数据包,但没有成功。
root@hostname:~# iptables --table filter --list INPUT --numeric --verbose
Chain INPUT (policy ACCEPT 385 packets, 138K bytes)
pkts bytes target prot opt in out source destination
0 0 DROP udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:1900
0 0 DROP udp -- enp0s2 * 0.0.0.0/0 0.0.0.0/0 udp dpt:1900
0 0 DROP all -- * * 0.0.0.0/0 239.255.255.250
0 0 DROP all -- enp0s2 * 0.0.0.0/0 239.255.255.250
0 0 DROP udp -- * * 0.0.0.0/0 239.255.255.250
0 0 DROP udp -- enp0s2 * 0.0.0.0/0 239.255.255.250
0 0 DROP all -- enp0s2 * 0.0.0.0/0 224.0.0.0/4
在我看来,规则似乎是正确的,但传入的数据包甚至对 INPUT 链不可见。每个链策略显示的计数器与我在 tcpdump 中看到的数据包数量不匹配。有一次我在 tcpdump 中看到了 20 个 UDP 数据包,但计数器只显示 1 个数据包:Chain INPUT (policy ACCEPT 1 packets, 52 bytes)
。
当我添加一条记录 INPUT 链中每个数据包的规则时,传入的数据包在日志文件中也不可见:
Chain INPUT (policy ACCEPT 655 packets, 573K bytes)
pkts bytes target prot opt in out source destination
0 0 DROP udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:1900
46 5527 LOG udp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "[INPUT UDP] "
657 573K LOG all -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "[INPUT all] "
日志中唯一的数据包是 HTTPS 和 DNS。
我的问题是:
- 为什么 INPUT 规则无效?也许 iptables 不处理传入的数据包,因为它们被发送到某种广播地址?
- 如何使用 iptables 丢弃数据包(UDP,目标端口 1900)?
这都是关于 IPv4 的,我并不担心 IPv6。
Linux内核版本:5.8.0-44-generic#50~20.04.1-Ubuntu SMP
更新(2021-05-26):我尝试了几个较旧的内核,阅读了一些更新日志和已知错误。没有成功。最后我买了一个专用防火墙。
答案1
这不是一个答案,而是一个支持你的结论的东西。
在我看来,规则似乎是正确的,但传入的数据包甚至对 INPUT 链不可见。每个链策略显示的计数器与我在 tcpdump 中看到的数据包数量不匹配。有一次我在 tcpdump 中看到了 20 个 UDP 数据包,但计数器只显示 1 个数据包:Chain INPUT(策略接受 1 个数据包,52 字节)。
我得到了同样的结果。这是我的规则集脚本:
doug@rpi2:~ $ cat test-iptables
#!/bin/sh
FWVER=0.01
#
# test_firewall 2021.03.05 Ver:0.01
# Just some simple rules for a test.
# Currently for this question:
# https://askubuntu.com/questions/1321344/iptables-drop-incoming-udp-packets-destination-port-1900
#
echo "Loading test_firewall version $FWVER..\n"
# The location of the iptables program
#
IPTABLES=/usr/sbin/iptables
#Set some stuff
#
EXTIF="eth0"
UNIVERSE="0.0.0.0/0"
#Clearing any previous configuration
#
#echo " Clearing any existing rules and setting default policies.."
$IPTABLES -P INPUT ACCEPT
$IPTABLES -F INPUT
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -F OUTPUT
# Otherwise, I can not seem to delete it later on
$IPTABLES -F
# Delete user defined chains
$IPTABLES -X
# Reset all IPTABLES counters
$IPTABLES -Z
$IPTABLES -t nat -Z
# try to prevent accidental loss of my SSH connection.
# added after I did exactly that.
#
$IPTABLES -A INPUT -i $EXTIF -p tcp --dport 22 -j ACCEPT
# loopback interfaces are valid.
#
$IPTABLES -A INPUT -i lo -s $UNIVERSE -d $UNIVERSE -j ACCEPT
$IPTABLES -A INPUT -i $EXTIF -p udp --dport 1900 -j LOG --log-prefix "U1900:" --log-level info
$IPTABLES -A INPUT -i $EXTIF -p udp --dport 1900 -j DROP
$IPTABLES -A INPUT -d 224.0.0.7 -j LOG --log-prefix "IP224:" --log-level info
$IPTABLES -A INPUT -d 224.0.0.7 -j DROP
$IPTABLES -A INPUT -p udp --dport 8001 -j LOG --log-prefix "U8001:" --log-level info
$IPTABLES -A INPUT -p udp --dport 8001 -j DROP
$IPTABLES -A INPUT -m pkttype --pkt-type broadcast -j LOG --log-prefix "BROAD:" --log-level info
$IPTABLES -A INPUT -m pkttype --pkt-type broadcast -j DROP
$IPTABLES -A INPUT -m pkttype --pkt-type multicast -j LOG --log-prefix "MULTI:" --log-level info
$IPTABLES -A INPUT -m pkttype --pkt-type multicast -j DROP
$IPTABLES -A INPUT -m pkttype --pkt-type UNICAST -j LOG --log-prefix "UNI:" --log-level info
$IPTABLES -A INPUT -m pkttype --pkt-type UNICAST -j DROP
#$IPTABLES -A INPUT -m pkttype --pkt-type ANYCAST -j LOG --log-prefix "ANY:" --log-level info
#$IPTABLES -A INPUT -m pkttype --pkt-type ANYCAST -j DROP
$IPTABLES -A INPUT -s 192.168.111.123 -p udp --sport 8001 -j DROP
$IPTABLES -A INPUT -s 192.168.111.122 -j DROP
$IPTABLES -A INPUT -d 224.0.0.0/4 -j LOG --log-prefix "IP224B:" --log-level info
$IPTABLES -A INPUT -d 224.0.0.0/4 -j DROP
# $IPTABLES -A FORWARD -p udp -i $EXTIF --dport 8001 -j DROP
$IPTABLES -A INPUT -j LOG --log-prefix "CATCH:" --log-level info
echo test_iptables $FWVER done.
echo "test_iptables $FWVER done..." >> /dev/kmsg
就我的情况来说,我有一台地址为 192.168.111.123 的三星电视,它不断向端口 8001 发送数据包:
doug@rpi2:~ $ sudo tcpdump -n -tttt -vvv host 192.168.111.123
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
2021-03-06 13:26:24.073438 IP (tos 0x0, ttl 64, id 57376, offset 0, flags [DF], proto UDP (17), length 63)
192.168.111.123.36088 > 192.168.111.255.15600: [udp sum ok] UDP, length 35
2021-03-06 13:26:24.840570 IP (tos 0x0, ttl 1, id 35446, offset 0, flags [DF], proto UDP (17), length 232)
192.168.111.123.8001 > 224.0.0.7.8001: [udp sum ok] UDP, length 204
2021-03-06 13:26:26.849469 IP (tos 0x0, ttl 1, id 35532, offset 0, flags [DF], proto UDP (17), length 232)
192.168.111.123.8001 > 224.0.0.7.8001: [udp sum ok] UDP, length 204
^C
我也同意他们根本就没有进入 INPUT 链:
doug@rpi2:~ $ sudo iptables -xvnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
194 15856 ACCEPT tcp -- eth0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
0 0 LOG udp -- eth0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:1900 LOG flags 0 level 6 prefix "U1900:"
0 0 DROP udp -- eth0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:1900
0 0 LOG all -- * * 0.0.0.0/0 224.0.0.7 LOG flags 0 level 6 prefix "IP224:"
0 0 DROP all -- * * 0.0.0.0/0 224.0.0.7
0 0 LOG udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:8001 LOG flags 0 level 6 prefix "U8001:"
0 0 DROP udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:8001
1612 173750 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 PKTTYPE = broadcast LOG flags 0 level 6 prefix "BROAD:"
1612 173750 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 PKTTYPE = broadcast
460 69304 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 PKTTYPE = multicast LOG flags 0 level 6 prefix "MULTI:"
460 69304 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 PKTTYPE = multicast
96 13068 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 PKTTYPE = unicast LOG flags 0 level 6 prefix "UNI:"
96 13068 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 PKTTYPE = unicast
0 0 DROP udp -- * * 192.168.111.123 0.0.0.0/0 udp spt:8001
0 0 DROP all -- * * 192.168.111.122 0.0.0.0/0
0 0 LOG all -- * * 0.0.0.0/0 224.0.0.0/4 LOG flags 0 level 6 prefix "IP224B:"
0 0 DROP all -- * * 0.0.0.0/0 224.0.0.0/4
0 0 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 6 prefix "CATCH:"
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 264 packets, 39247 bytes)
pkts bytes target prot opt in out source destination
我们在 syslog 文件中没有看到任何相关内容:
doug@rpi2:~ $ grep -a "DPT=8001" /var/log/syslog
doug@rpi2:~ $