#!/bin/bash #FIXME check syn/ack's too Me='plength' MyVersion='0.2.1' Action="$1" case "$Action" in start) echo "Starting $Me" iptables -N $Me #Drop fragmented syn or syn/ack packets: iptables -A $Me -p tcp --tcp-flags SYN SYN -m u32 --u32 "4&0x3FFF=1:0x3FFF" -j LOG --log-prefix "FragmentedSyn " #Check for payload on a syn/syn+ack. To do so, we use u32 #to jump over the ip and tcp headers, and simply test the first #payload byte for 0:255. If there is any payload at all, this #will return true; if there is no payload, u32 will realize it's #being asked to test a non-existant byte and return false. #Marvelously elegant; thanks to Don Cohen for this. iptables -A $Me -p tcp --tcp-flags SYN SYN -m u32 --u32 "0>>22&0x3C@12>>26&0x3C@-3&0xFF=0:255" -j LOG --log-prefix "PayloadOnSyn " #rfc791: #Every internet module must be able to forward a datagram of 68 octets #without further fragmentation. This is because an internet header may #be up to 60 octets, and the minimum fragment is 8 octets. #So, any fragment except the last that is less than 68 bytes was #artificially fragmented. #We can't have MF set and have a packet smaller than 68 bytes. iptables -A $Me -m u32 --u32 "3&0x20>>5=1" -m length --length 0:67 -j LOG --log-prefix "TooSmallNonTerminalFrag " #MF set, 68-511 bytes, technically legal, but _way_ unlikely. iptables -A $Me -m u32 --u32 "3&0x20>>5=1" -m length --length 68:511 -j LOG --log-prefix "SmallNonTerminalFrag " #Last fragment (MF clear, non-zero frag offset) must be >=21 bytes iptables -A $Me -m u32 --u32 "3&0x20>>5=0 && 4&0x1FFF=1:65535" -m length --length 0:20 -j LOG --log-prefix "TooSmallTerminalFrag " #OK, we're done testing fragments, so we go back if MF is set #iptables -A $Me -m u32 --u32 "3&0x20>>5=1" -j RETURN #...or the Frag offset is >0 #iptables -A $Me -m u32 --u32 "4&0x1FFF=1:65535" -j RETURN #Actually, check for set MF or non-zero offset all at once: iptables -A $Me -m u32 --u32 "4&0x3FFF=1:65535" -j RETURN #Now we're left with unfragmented packets #Complete UDP >=28 bytes iptables -A $Me -p udp -m length --length 0:27 -j LOG --log-prefix "Toosmalludp " #Complete TCP >=40 bytes iptables -A $Me -p tcp -m length --length 0:39 -j LOG --log-prefix "Toosmalltcp " #Complete ICMP; 28 bytes for no payload ping or chargen request; smaller ones? iptables -A $Me -p icmp -m length --length 0:27 -j LOG --log-prefix "Toosmallicmp " #protocol 30, should be >=32 bytes iptables -A $Me -p 30 -m length --length 0:31 -j LOG --log-prefix "Toosmallproto30 " #protocol 47 GRE, >=40 iptables -A $Me -p 47 -m length --length 0:39 -j LOG --log-prefix "Toosmallproto47 " #protocol 50 ESP, >=50 iptables -A $Me -p 50 -m length --length 0:49 -j LOG --log-prefix "Toosmallproto50 " #protocol 51 AH, >=36 iptables -A $Me -p 51 -m length --length 0:35 -j LOG --log-prefix "Toosmallproto51 " #IP packets, >=20 iptables -A $Me -m length --length 0:19 -j LOG --log-prefix "ToosmallIP " iptables -A INPUT -i \! lo -m length --length 512: -j $Me iptables -A FORWARD -m length --length 512: -j $Me iptables -A OUTPUT -m length --length 512: -j $Me ;; stop) echo "Stopping $Me" iptables -D INPUT -i \! lo -m length --length 512: -j $Me iptables -D FORWARD -m length --length 512: -j $Me iptables -D OUTPUT -m length --length 512: -j $Me iptables -D $Me -p tcp --tcp-flags SYN SYN -m u32 --u32 "4&0x3FFF=1:0x3FFF" -j LOG --log-prefix "FragmentedSyn " iptables -D $Me -p tcp --tcp-flags SYN SYN -m u32 --u32 "0>>22&0x3C@12>>26&0x3C@-3=0:255" -j LOG --log-prefix "PayloadOnSyn " iptables -D $Me -m u32 --u32 "3&0x20>>5=1" -m length --length 0:67 -j LOG --log-prefix "TooSmallNonTerminalFrag " iptables -D $Me -m u32 --u32 "3&0x20>>5=1" -m length --length 68:511 -j LOG --log-prefix "SmallNonTerminalFrag " iptables -D $Me -m u32 --u32 "3&0x20>>5=0 && 4&0x1FFF=1:65535" -m length --length 0:20 -j LOG --log-prefix "TooSmallTerminalFrag " #iptables -D $Me -m u32 --u32 "3&0x20>>5=1" -j RETURN #iptables -D $Me -m u32 --u32 "4&0x1FFF=1:65535" -j RETURN iptables -D $Me -m u32 --u32 "4&0x3FFF=1:65535" -j RETURN iptables -D $Me -p udp -m length --length 0:27 -j LOG --log-prefix "Toosmalludp " iptables -D $Me -p tcp -m length --length 0:39 -j LOG --log-prefix "Toosmalltcp " iptables -D $Me -p icmp -m length --length 0:27 -j LOG --log-prefix "Toosmallicmp " iptables -D $Me -p 30 -m length --length 0:31 -j LOG --log-prefix "Toosmallproto30 " iptables -D $Me -p 47 -m length --length 0:39 -j LOG --log-prefix "Toosmallproto47 " iptables -D $Me -p 50 -m length --length 0:49 -j LOG --log-prefix "Toosmallproto50 " iptables -D $Me -p 51 -m length --length 0:35 -j LOG --log-prefix "Toosmallproto51 " iptables -D $Me -m length --length 0:19 -j LOG --log-prefix "ToosmallIP " iptables -F $Me iptables -X $Me ;; esac