#!/bin/bash #Copyright 2003 William Stearns #Released under the GPL. Me='mapssh' MyVersion='0.4.0' #DefaultActions='' [ -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 \! -f -m connbytes --connbytes 0:255 -m state --state ESTABLISHED -m length --length 46:375 -j $Me $IptablesBin $AppIn FORWARD -p tcp \! -f -m connbytes --connbytes 0:255 -m state --state ESTABLISHED -m length --length 46:375 -j $Me $IptablesBin $AppIn OUTPUT -p tcp \! -f -m connbytes --connbytes 0:255 -m state --state ESTABLISHED -m length --length 46:375 -j $Me ;; unlink) $IptablesBin -D INPUT -i \! lo -p tcp \! -f -m connbytes --connbytes 0:255 -m state --state ESTABLISHED -m length --length 46:375 -j $Me $IptablesBin -D FORWARD -p tcp \! -f -m connbytes --connbytes 0:255 -m state --state ESTABLISHED -m length --length 46:375 -j $Me $IptablesBin -D OUTPUT -p tcp \! -f -m connbytes --connbytes 0:255 -m state --state ESTABLISHED -m length --length 46:375 -j $Me $IptablesBin -X $Me >/dev/null 2>&1 ;; create) echo "Starting $Me" >&2 FlushOrNewChain $Me #Check for first 255 bytes of tcp connection, hex #0x5353482d ("SSH-") as first 4 payload octets, #established, <192 bytes (mine was 77, even with 12 #bytes of tcp options. #The entire command is as follows, but we've already checked most of this #in IOF. The shorter version follows this long one. #LogAs='sshserver' $Ipt -A $Me -p tcp \! -f -m connbytes --connbytes 0:255 \ # -m state --state ESTABLISHED -m length --length 46:375 -m u32 \ # --u32 "0>>22&0x3C@ 12>>26&0x3C@ 0=0x5353482D" $Tail #FIXME - put in tests for specific ssh versions here with -m string LogAs='sshserver' $Ipt -A $Me -m u32 --u32 '"0>>22&0x3C@ 12>>26&0x3C@ 0=0x5353482D"' $Tail ;; 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 \! -f -m connbytes --connbytes 0:255 -m state --state ESTABLISHED -m length --length 46:375 -j $Me $IptablesBin -R FORWARD `$IptablesBin -L FORWARD -n --line-numbers | grep $TempChain | awk '{print $1}'` -p tcp \! -f -m connbytes --connbytes 0:255 -m state --state ESTABLISHED -m length --length 46:375 -j $Me $IptablesBin -R OUTPUT `$IptablesBin -L OUTPUT -n --line-numbers | grep $TempChain | awk '{print $1}'` -p tcp \! -f -m connbytes --connbytes 0:255 -m state --state ESTABLISHED -m length --length 46:375 -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 uses some very tight checks to identify the SSH protocol string found at the beginning of a connection. Because it strictly limits how many packets it inspects, it _should_ not produce high load on the system, even when inspecting every tcp connection. There is a small chance of false positives and/or false negatives. EOTEXT ;; *) echo "Unknown action $Action in $Me, no action taken." >&2 ;; esac done