load_filter() { # $1 .. filter status # $2 .. compress flag; i.e. compress it not empty local funtag="[${FUNCNAME[0]}]" unset -f filter [[ -f filter ]] && mv filter filter.old [[ -f filter.compress ]] && rm -f filter.compress ./mkfilter $1 if [ -f filter.old ] then diff -c filter filter.old > filter-diffs else [[ -f filter-diffs ]] && rm -f filter-diffs fi # If the 'compress filter' flag is set compress filter; # i.e. remove comments and empty lines for runtime if [ ! -z "$2" ] then trace "$funtag Using filter compressed" compress_filter . filter.compress else trace "$funtag Using filter plain" . filter fi # Create/refresh superflous_map as well SUPERFLOUS=`mk_superflous` } # OpenVPN log lines come in as # TLS Error: cannot locate HMAC in incoming packet from [AF_INET]45.79.111.6:33325 # So, the universal 'get_bandit' function fails and must be overwritten here # The IP address is hidden in the last field on the line get_bandit() { awk ' /TLS Error:/ { lastfield=$NF split(lastfield,parts, /[\]:]/ ) IP=parts[2] print IP } ' <<< "$REPLY" } # # - inject - # ... is directly called by a 'rule' and the global variable $RULE is set though. # The log line is in the global variable $REPLY. So nothing must get passed. # All the dirty work is done here. # inject() { local funtag="[${FUNCNAME[0]}]" local penalty=${1:-1} local retcode=0 local affairs local haveit local isdropped trace "$funtag Triggered by rule ['$RULE'] '$Pattern'" BANDIT=`get_bandit` if ipset -q test whitelist "$BANDIT" then return 3 # Flag whitelisted IP address fi validate_IP "$BANDIT" if [ $? -ne 0 ] then trace "$funtag: Junk IP address for bandit '$BANDIT' ... bailing out" return 255 fi # See if we have an NXDOMAIN or FAKEHOST here # CLASS=`get_class $BANDIT` PORT=`echo "$REPLY" | grep -o 'port [0-9]*' |grep -o '[0-9]*'` trace "$funtag $CLASS $BANDIT Port: $PORT" # # OK ... 'observed candidate' ... or ... 'new candidate' ?? # haveit=`$SQL "select IP from $TABLE where IP='$BANDIT'"` if [ -z "$haveit" ] then # # Introduce the bandit (insert in to database) # # Note: # NXDOMAINs & FAKEHOSTS are killed on 2nd attempt; i.e. they get 'MAX_AFFAIRS - 1' # on 1st attempt. The first attempt is needed to detect and identify the bandit # if [[ "NXDOMAIN FAKEHOST" =~ $CLASS ]] then penalty=$((MAX_AFFAIRS - 1)) fi AFFAIRS=$penalty STATE=INTRO ACTION="Initial $AFFAIRS/$MAX_AFFAIRS, Penalty: $penalty" if [ ! -z "$GEOTRACK" ]; then do_geotrack; fi $SQL "insert into $TABLE (affairs,IP,type,state,date_intro,date_event,class,comment) values ($AFFAIRS,'$BANDIT','$THIS_TYPE','$STATE', datetime(current_timestamp, 'localtime'), datetime(current_timestamp, 'localtime'), '$CLASS', '$THIS_TYPE,$CLASS');" $IPSET -exist add tarpit $BANDIT timeout $((2**AFFAIRS * TIME_SLICE)) comment "$THIS_TYPE,$AFFAIRS" retcode=1 else # Already got a DROP? # If so kick to bin permanently isdropped=`$SQL "select state from $TABLE where IP='$BANDIT' and state='DROP';"` if [ ! -z "$isdropped" ] then trace "$funtag DROPed culprit $BANDIT re-occured ... taken into custody" $IPSET -exist add custody $BANDIT comment "$THIS_TYPE,$CLASS" # Take the short way out ... return 1 fi # # ... A known bandit (UPDATE) # AFFAIRS=`$SQL "select affairs from $TABLE where IP='$BANDIT';"` ((AFFAIRS++)) if [ $AFFAIRS -lt $MAX_AFFAIRS ] then STATE=COUNT ACTION="Count $AFFAIRS/$MAX_AFFAIRS" $SQL "update $TABLE set affairs=$AFFAIRS, class='$CLASS', state='$STATE', comment='Login,$ACTION', date_event=datetime(current_timestamp, 'localtime') where IP='$BANDIT';" $IPSET -exist add tarpit $BANDIT timeout $((2**AFFAIRS * TIME_SLICE)) comment "$THIS_TYPE,$AFFAIRS" retcode=1 else # Mark a DROP in the database drop if MAX_AFFAIRS is reached ... STATE=DROP ACTION="Dropped @ $AFFAIRS" $SQL "update $TABLE set affairs=$AFFAIRS, state='$STATE', date_event=datetime(current_timestamp, 'localtime'), class='$CLASS', comment='$THIS_TYPE,$CLASS' where IP='$BANDIT';" $IPSET -exist add tarpit $BANDIT timeout $((2**AFFAIRS * TIME_SLICE)) comment "$THIS_TYPE,$AFFAIRS" retcode=1 fi fi write_affairs $BANDIT $AFFAIRS $RULE clog "$funtag" "$CLASS" "$BANDIT" "'$ACTION'" #log "$funtag $CLASS $BANDIT '$ACTION'" trace "$funtag $CLASS $BANDIT '$ACTION'" return $retcode }