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.