I was asked recently to check how UDP packets could be filtered which don't
have any contents. The reason was that these packets were used as a Denial of
Service against a specific game server. This bug had been acknowledged by the
developers of the server, but had been fixed in a later version and wouldn't
be fixed in the older one.
iptables can filter on this as follows:
$ sudo iptables -A INPUT -p udp --dport 6500 -m length --length 28 -j REJECT
Why the length is 28, I can't really say. It's of course UDP over IPv4. UDP
has a fixed header size, but IPv4 has a variable header size. Anyway, I've
tested the above using netcat:
Start service listening to port 6500 on machine 1:
$ nc -l -u -p 6500
Open a new terminal on machine 1 and start a traffic dump:
$ sudo tcpdump -X -vv "port 6500"
Set up a client on machine 2, which sends all input from stdin to machine 1:
$ nc -u machine1 6500
Now type some text, then press enter. The server will output whatever you
typed. Now just press enter. You're sending a UDP packet with as a content the
enter \n. tcpdump should display:
16:20:43.898341 IP (tos 0x0, ttl 64, id 65431, offset 0, flags [DF], proto: UDP (17), length: 29) machine1.6500 > machine2.36237: [bad udp cksum 26d!] UDP, length 1 0x0000: 4500 001d ff97 4000 4011 ca51 ac10 8cb7 E.....@.@..Q.... 0x0010: ac10 8c0e 1964 8d8d 0009 7101 0a .....d....q..
Lengte 29 thus means: subtract one and get an empty UDP packet.
If that length doesn't work, you can play with ranges. For example "--length
20:30" means: reject everything between 20 and 30 bytes length.