#!/bin/bash #Copyright 2003 William Stearns #Released under the GPL. #FIXME - sort by flag frequency #FIXME - organize by state so we're not constantly checking state tables #FIXME - state invalid, untracked Me='tcpchk' MyVersion='0.4.1' DefaultActions='DROP' [ -r /etc/modwall/modwall.conf ] && . /etc/modwall/modwall.conf [ -r /etc/modwall/$Me.conf ] && . /etc/modwall/$Me.conf [ -r ${MWLibDir:-'/usr/lib/modwall/'}/modwalllib ] && . ${MWLibDir:-'/usr/lib/modwall/'}/modwalllib if [ -z "$MWLibVer" ]; then echo 'It looks like modwalllib was not loaded, why? Exiting' >&2 exit 1 fi for OneTask in $Tasks ; do case "$OneTask" in link) $IptablesBin -N $Me >/dev/null 2>&1 $IptablesBin $AppIn INPUT -i \! lo -p tcp -j $Me $IptablesBin $AppIn FORWARD -p tcp -j $Me $IptablesBin $AppIn OUTPUT -p tcp -j $Me ;; unlink) $IptablesBin -D INPUT -i \! lo -p tcp -j $Me $IptablesBin -D FORWARD -p tcp -j $Me $IptablesBin -D OUTPUT -p tcp -j $Me $IptablesBin -X $Me >/dev/null 2>&1 ;; create) echo "Starting $Me" >&2 FlushOrNewChain $Me LogAs='tcp-lowport' $Ipt -A $Me -p tcp --sport 0:19 $Tail LogAs='tcp-lowport' $Ipt -A $Me -p tcp --dport 0:19 $Tail #UAPRSF #We put in no rules for these as they're legal for flags, but might get #chucked later for a different reason (invalid source/dest address, etc.) #010000 A legal $IptablesBin -A $Me -p tcp --tcp-flags ALL ACK -m state --state ESTABLISHED -j RETURN LogAs='tcpflag-a-nr' $Ipt -A $Me -p tcp --tcp-flags ALL ACK -m state --state NEW,RELATED $Tail #011000 PA legal $IptablesBin -A $Me -p tcp --tcp-flags ALL PSH,ACK -m state --state ESTABLISHED -j RETURN $IptablesBin -A $Me -p tcp --tcp-flags ALL PSH,ACK -m state --state NEW -j RETURN #Occasionally iptables misclassifies as new LogAs='tcpflag-pa-r' $Ipt -A $Me -p tcp --tcp-flags ALL PSH,ACK -m state --state RELATED $Tail #000000 NULL block (confirmed) LogAs='tcpflag-null' $Ipt -A $Me -p tcp --tcp-flags ALL NONE $Tail #111111 XMAS block LogAs='tcpflag-xmas' $Ipt -A $Me -p tcp --tcp-flags ALL ALL $Tail #????11 SF block (confirmed) LogAs='tcpflag-sf' $Ipt -A $Me -p tcp --tcp-flags SYN,FIN SYN,FIN $Tail #???11? SR block (confirmed) LogAs='tcpflag-sr' $Ipt -A $Me -p tcp --tcp-flags SYN,RST SYN,RST $Tail #???1?1 RF block (confirmed) LogAs='tcpflag-rf' $Ipt -A $Me -p tcp --tcp-flags RST,FIN RST,FIN $Tail #1???1? SU block (no payload on syn, cannot have urg data) LogAs='tcpflag-su' $Ipt -A $Me -p tcp --tcp-flags SYN,URG SYN,URG $Tail #001010 SP block (no payload on syn) LogAs='tcpflag-sp' $Ipt -A $Me -p tcp --tcp-flags ALL SYN,PSH $Tail #011010 SAP block (no payload on syn/ack) LogAs='tcpflag-sap' $Ipt -A $Me -p tcp --tcp-flags ALL SYN,ACK,PSH $Tail #?0???1 F, no A block LogAs='tcpflag-f' $Ipt -A $Me -p tcp --tcp-flags ACK,FIN FIN $Tail #??0??1 P, no A block LogAs='tcpflag-p' $Ipt -A $Me -p tcp --tcp-flags ACK,PSH PSH $Tail #0????1 U, no A block LogAs='tcpflag-u' $Ipt -A $Me -p tcp --tcp-flags ACK,URG URG $Tail #RST only? I get them from the razor servers, and gkrellm shipped a few back to noaa.gov after getting weather. $IptablesBin -A $Me -p tcp --tcp-flags ALL RST -m state --state ESTABLISHED -j RETURN LogAs='tcpflag-r-nr' $Ipt -A $Me -p tcp --tcp-flags ALL RST -m state --state NEW,RELATED $Tail #?0??0? neither S nor A block LogAs='tcpflag-nosa' $Ipt -A $Me -p tcp --tcp-flags SYN,ACK NONE $Tail #000010 S legal $IptablesBin -A $Me -p tcp --tcp-flags ALL SYN -m state --state NEW -j RETURN #Normal syn's $IptablesBin -A $Me -p tcp --tcp-flags ALL SYN -m state --state RELATED -j RETURN #Opening syn of ftp data LogAs='tcpflag-s-est' $Ipt -A $Me -p tcp --tcp-flags ALL SYN -m state --state ESTABLISHED $Tail #010010 SA legal $IptablesBin -A $Me -p tcp --tcp-flags ALL SYN,ACK -m state --state ESTABLISHED -j RETURN LogAs='tcpflag-sa-nr' $Ipt -A $Me -p tcp --tcp-flags ALL SYN,ACK -m state --state NEW,RELATED $Tail #Common backscatter #010001 FA legal $IptablesBin -A $Me -p tcp --tcp-flags ALL FIN,ACK -m state --state ESTABLISHED -j RETURN LogAs='tcpflag-fa-nr' $Ipt -A $Me -p tcp --tcp-flags ALL FIN,ACK -m state --state NEW,RELATED $Tail #010100 RA legal $IptablesBin -A $Me -p tcp --tcp-flags ALL RST,ACK -m state --state ESTABLISHED -j RETURN $IptablesBin -A $Me -p tcp --tcp-flags ALL RST,ACK -m state --state NEW -j RETURN #Common backscatter. Occasionally iptables misclassifies as new LogAs='tcpflag-ra-r' $Ipt -A $Me -p tcp --tcp-flags ALL RST,ACK -m state --state RELATED $Tail #111000 APU (legal, ctrl-c on telnet) $IptablesBin -A $Me -p tcp --tcp-flags ALL ACK,PSH,RST -m state --state ESTABLISHED -j RETURN LogAs='tcpflag-apu-nr' $Ipt -A $Me -p tcp --tcp-flags ALL ACK,PSH,RST -m state --state NEW,RELATED $Tail #011001 FPA RETURN (FIN implies a push, but we're seeing this on legit traffic) $IptablesBin -A $Me -p tcp --tcp-flags ALL FIN,PSH,ACK -m state --state ESTABLISHED -j RETURN LogAs='tcpflag-fpa-nr' $Ipt -A $Me -p tcp --tcp-flags ALL FIN,PSH,ACK -m state --state NEW,RELATED $Tail #For the following, I want to be conservative; I'm not sure if they're bad or good. #Leaving them as counter rules for the moment. #011100 RAP block? $IptablesBin -A $Me -p tcp --tcp-flags ALL RST,ACK,PSH #-j DROP #110100 RAU block? $IptablesBin -A $Me -p tcp --tcp-flags ALL RST,ACK,URG #-j DROP #111100 RAPU block? $IptablesBin -A $Me -p tcp --tcp-flags ALL RST,ACK,PSH,URG #-j DROP #111001 FPAU block? (FIN implies a push) $IptablesBin -A $Me -p tcp --tcp-flags ALL FIN,PSH,ACK,URG #-j DROP #110000 AU? (APU more likely) $IptablesBin -A $Me -p tcp --tcp-flags ALL ACK,URG #-j DROP #110001 AUF? $IptablesBin -A $Me -p tcp --tcp-flags ALL ACK,URG,FIN #-j DROP ;; destroy) echo "Stopping $Me" >&2 DestroyChain $Me ;; renamechain) TempChain="$Me-$RANDOM" echo "Replacing existing rules in $Me with new rules" >&2 $IptablesBin -E $Me $TempChain ;; replacelinks) if [ -z "$TempChain" ]; then echo "No temporary chain to relink in $Me replacelinks, replace operation incomplete." >&2 elif ! $IptablesBin -L $Me -n >/dev/null 2>&1 ; then echo "No $Me chain in $Me, replace operation incomplete." >&2 elif ! $IptablesBin -L $TempChain -n >/dev/null 2>&1 ; then echo "No $TempChain chain in $Me, replace operation incomplete." >&2 elif [ "`$IptablesBin -L INPUT -n --line-numbers | grep $TempChain | wc -l`" -ne 1 ]; then echo "Too few/many references to $TempChain in INPUT in $Me replacelinks, replace operation incomplete." >&2 elif [ "`$IptablesBin -L FORWARD -n --line-numbers | grep $TempChain | wc -l`" -ne 1 ]; then echo "Too few/many references to $TempChain in FORWARD in $Me replacelinks, replace operation incomplete." >&2 elif [ "`$IptablesBin -L OUTPUT -n --line-numbers | grep $TempChain | wc -l`" -ne 1 ]; then echo "Too few/many references to $TempChain in OUTPUT in $Me replacelinks, replace operation incomplete." >&2 else $IptablesBin -R INPUT `$IptablesBin -L INPUT -n --line-numbers | grep $TempChain | awk '{print $1}'` -i \! lo -p tcp -j $Me $IptablesBin -R FORWARD `$IptablesBin -L FORWARD -n --line-numbers | grep $TempChain | awk '{print $1}'` -p tcp -j $Me $IptablesBin -R OUTPUT `$IptablesBin -L OUTPUT -n --line-numbers | grep $TempChain | awk '{print $1}'` -p tcp -j $Me DestroyChain $TempChain unset TempChain fi ;; status) if $IptablesBin -L $Me -n >/dev/null 2>&1 ; then echo "$Me created" >&2 else echo "$Me destroyed" >&2 fi ;; version) echo "$Me $MyVersion, modwalllib $MWLibVer" >&2 ;; help) DefaultHelp cat <&2 The $Me module checks characteristics of tcp traffic. It handles low port (ports 0-19) and illegal tcp flag combinations. The flag rules tend to be conservative, so it should be safe to use these in any environment (unless you know you are using small services). EOTEXT ;; *) echo "Unknown action $Action in $Me, no action taken." >&2 ;; esac done