iptables: drop incoming UDP packets, destination port 1900
I am trying to use iptables to drop UDP packets that have destination port 1900. This shall affect both directions, so I added one rule each for the INPUT and the OUTPUT chain of the filter table.
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
This is what the incoming packets look like:
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
Usually iptables works very well, I had other filter rules that worked as expected. This OUTPUT rule also works as expected. The following output shows that this OUTPUT rule caught (and dropped) a few packets.
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
But the INPUT rule does not work. I have now tried several rule variants to catch the incoming packets, no success.
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
For me it looks like the rules are correct but the incoming packets aren't even visible to the INPUT chain. The counter displayed per chain policy doesn't match the count of packets I see in tcpdump. In one case I saw like 20 UDP packets in tcpdump, but the counter showed only 1 packet: Chain INPUT (policy ACCEPT 1 packets, 52 bytes)
.
The incoming packets are also not visible in the log file, when I add a rule that logs every packet in the INPUT chain:
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] "
The only packets in the log are HTTPS and DNS.
My questions are:
- Why is the INPUT rule not effective? Maybe iptables doesn't handle the incoming packets because they are addressed to some sort of broadcast address?
- How can I drop the packets (UDP, destination port 1900) with iptables?
This is all about IPv4, I am not worried about IPv6.
Linux kernel version: 5.8.0-44-generic #50~20.04.1-Ubuntu SMP
Update (2021-05-26): I tried a few older kernels, read some changelogs and known bugs. No success. I ended up with buying a dedicated firewall.
This is less of an answer and more of supporting your conclusions.
For me it looks like the rules are correct but the incoming packets aren't even visible to the INPUT chain. The counter displayed per chain policy doesn't match the count of packets I see in tcpdump. In one case I saw like 20 UDP packets in tcpdump, but the counter showed only 1 packet: Chain INPUT (policy ACCEPT 1 packets, 52 bytes).
I get the same. Here is my rules set script:
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
In my case, I have a Samsung T.V. at 192.168.111.123 constantly spewing packets to port 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
And I agree they simply do not get to the INPUT chain:
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
And we see nothing related in the syslog file:
doug@rpi2:~ $ grep -a "DPT=8001" /var/log/syslog
doug@rpi2:~ $