#!/bin/bash #Copyright 2003 William Stearns #Released under the GPL. Me='catchmapper' MyVersion='0.3.2' DefaultActions='DROP' [ -r /etc/firebricks/firebricks.conf ] && . /etc/firebricks/firebricks.conf [ -r /etc/firebricks/$Me.conf ] && . /etc/firebricks/$Me.conf [ -r ${FBLibDir:-'/usr/lib/firebricks/'}/firebrickslib ] && . ${FBLibDir:-'/usr/lib/firebricks/'}/firebrickslib if [ -z "$FBLibVer" ]; then echo 'It looks like firebrickslib 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 -j $Me $IptablesBin $AppIn FORWARD -j $Me $IptablesBin $AppIn OUTPUT -o \! lo -j $Me ;; unlink) $IptablesBin -D INPUT -i \! lo -j $Me $IptablesBin -D FORWARD -j $Me $IptablesBin -D OUTPUT -o \! lo -j $Me $IptablesBin -X $Me >/dev/null 2>&1 ;; create) echo "Starting $Me" >&2 FlushOrNewChain $Me #Here we log the _destination_ address of any proto, host, network, or port unreachable, or #time exceeded packets. Note these have to be RELATED packets, meaning that there #had to be a packet that elicited the error. The original packet might still have had #a spoofed source, so a) we can't ban forever, and b) this may still affect normal operation. #For this reason, the punishmapper script should follow the "allow ESTABLISHED,RELATED" rule. LogAs='mapper-proto' $Ipt -A $Me -p icmp --icmp-type protocol-unreachable -m state --state RELATED -m recent --name mapper --rdest --set $Tail LogAs='mapper-host' $Ipt -A $Me -p icmp --icmp-type host-unreachable -m state --state RELATED -m recent --name mapper --rdest --set $Tail LogAs='mapper-network' $Ipt -A $Me -p icmp --icmp-type network-unreachable -m state --state RELATED -m recent --name mapper --rdest --set $Tail LogAs='mapper-hostt' $Ipt -A $Me -p icmp --icmp-type TOS-host-unreachable -m state --state RELATED -m recent --name mapper --rdest --set $Tail LogAs='mapper-networkt' $Ipt -A $Me -p icmp --icmp-type TOS-network-unreachable -m state --state RELATED -m recent --name mapper --rdest --set $Tail LogAs='mapper-hostp' $Ipt -A $Me -p icmp --icmp-type host-prohibited -m state --state RELATED -m recent --name mapper --rdest --set $Tail LogAs='mapper-networkp' $Ipt -A $Me -p icmp --icmp-type network-prohibited -m state --state RELATED -m recent --name mapper --rdest --set $Tail LogAs='mapper-commp' $Ipt -A $Me -p icmp --icmp-type communication-prohibited -m state --state RELATED -m recent --name mapper --rdest --set $Tail LogAs='mapper-hostu' $Ipt -A $Me -p icmp --icmp-type host-unknown -m state --state RELATED -m recent --name mapper --rdest --set $Tail LogAs='mapper-networku' $Ipt -A $Me -p icmp --icmp-type network-unknown -m state --state RELATED -m recent --name mapper --rdest --set $Tail LogAs='mapper-port' $Ipt -A $Me -p icmp --icmp-type port-unreachable -m state --state RELATED -m recent --name mapper --rdest --set $Tail LogAs='mapper-timeex' $Ipt -A $Me -p icmp --icmp-type time-exceeded -m state --state RELATED -m recent --name mapper --rdest --set $Tail LogAs='mapper-srcrt' $Ipt -A $Me -p icmp --icmp-type source-route-failed -m state --state RELATED -m recent --name mapper --rdest --set $Tail LogAs='mapper-param' $Ipt -A $Me -p icmp --icmp-type parameter-problem -m state --state RELATED -m recent --name mapper --rdest --set $Tail #I would _like_ to tag the recipients of rst's as mappers too, but I can't tell between an #IP getting a reset because they're mapping tcp ports, and an IP getting a reset because #the server to which they were connected was shut down. Instead, we'll depend on the psd #(port scan detector) module: #FIXME - customize psd params later? LogAs='mapper-param' $Ipt -A $Me -m psd -m state --state RELATED -m recent --name mapper --set $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 >/dev/null 2>&1 ; then echo "No $Me chain in $Me, replace operation incomplete." >&2 elif ! $IptablesBin -L $TempChain >/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 -j $Me $IptablesBin -R FORWARD `$IptablesBin -L FORWARD -n --line-numbers | grep $TempChain | awk '{print $1}'` -j $Me $IptablesBin -R OUTPUT `$IptablesBin -L OUTPUT -n --line-numbers | grep $TempChain | awk '{print $1}'` -o \! lo -j $Me DestroyChain $TempChain unset TempChain fi ;; status) if $IptablesBin -L $Me >/dev/null 2>&1 ; then echo "$Me created" >&2 else echo "$Me destroyed" >&2 fi ;; version) echo "$Me $MyVersion, firebrickslib $FBLibVer" >&2 ;; help) DefaultHelp cat <&2 The $Me module identifies people trying to map our network. It looks for icmp errors such as proto, host, network, or port unreachables, as well as time exceeded in transit errors, and remembers the _destination_ ip address of those packets - the IP that sent the probe packet. Because of the potential for a spoofed source address in a probe packet, this is a potentially dangerous module. EOTEXT ;; *) echo "Unknown action $Action in $Me, no action taken." >&2 ;; esac done