Limit connections doens't work

olli hauer ohauer at gmx.de
Sun Dec 6 13:18:25 UTC 2009


Nico De Dobbeleer wrote:
> Hello, 
> 
> As most of the public ip's my servers are constantly under bruteforce attack see example: 
> 
> Dec 5 13:56:36 hosting sshd[18621]: Failed password for invalid user tim from 173.10.126.226 port 47871 ssh2 
> Dec 5 13:56:37 hosting sshd[18623]: Invalid user support123 from 173.10.126.226 
> Dec 5 13:56:39 hosting sshd[18623]: Failed password for invalid user support123 from 173.10.126.226 port 48289 ssh2 

...

> 
> Now I want to limit the connection over ssh to a specific ipaddress and I added the rules below for that. 
> ------------------------------------------------------------------------------------------------------------------ 
> #Tables 
> table <abusive_ips> persist file "/etc/pf.abusive_ips.block.list" 
> table <brute> persist 
> 
> # Rules 
> 
> block quick from <abusive_ips> 
> block quick from <brute> 
> 
> 
> # Limit connections per IP 
> 
> pass in quick on { $ext_if, $int_if, $mng_if } inet proto tcp from any to xx.xx.xx.xx port ssh flags S/SA keep state 
> (max-src-conn 10, max-src-conn-rate 3/15, overload <abusive_ips> flush) 
> pass in quick on { $ext_if, $int_if, $mng_if } inet proto tcp from any to xx.xx.xx.xx port ssh flags S/SA keep state 
> (max-src-conn 10, max-src-conn-rate 3/15, overload <brute> flush) 
> pass in quick on { $ext_if, $int_if, $mng_if } inet proto tcp from any to xx.xx.xx.xx port ssh flags S/SA keep state 
> (max-src-conn 10, max-src-conn-rate 3/15, overload <abusive_ips> flush) 
> -------------------------------------------------------------------------------------------------------------------- 
> 
> The only problem is that it doesn't work. These rules don't write the abusive ip in the abusif list file or in the <brute> table. 
> 
> Anyone an idea why it doesn't overload the ip's when the connections per ip are more then 10 of more then 3/15? 

- which FreeBSD version is this 6.x 7.x/8.x?

- avoid the quick keyword in the rules with overload

- pf can preload IP's from file specified in
   "table <tablename> ... file "/filename" but does not write IP's into
   the file. I use the script below to do this on a OpenBSD machine.

- rewrite your rule and avoid the any keyword
pass in on { $ext_if, $int_if, $mng_if } inet proto tcp \
   from !<brute> to xx.xx.xx.xx port ssh flags S/SA keep state \
   (max-src-conn 10, max-src-conn-rate 3/15, overload <brute> flush)

hint:
- look for the additional keyword global (flush global)
- If the IP in your rule is your base IP on $ext_if write it with as 
$ext_if:0



this script writes IP's from the bf_* tables into a file so you can
preload them next time pf rules are installed or the machine reboots.
additional it can send you a mail with IP's added to the table and if
GeoIP is installed you get the GeoIP info.

With a little modification of the script/rules It will work for you


#!/bin/sh
##################################################################
# $Source: RCS/pftable_to_file.sh,v $
# OS: OpenBSD
#
# olli hauer
#
##################################################################

# sample rule for pf
# ---------------------------
# block in log quick proto { tcp, udp } from <bf_ssh>  \
#   to any port ssh label BRUTFORCE-SSH    # table for overload connections
#
# pass in log on $if_ext inet proto tcp from ! <bf_ssh> to $if_ext \
#     port = ssh flags S/SA keep state \
#     (source-track rule, max-src-conn 10, \
#      max-src-conn-rate 3/90, overload <bf_ssh> \
#      flush global, if-bound, src.track 90) \
#     label "SSH"


umask 077

PF_TABLES="bf_mail bf_ssh bf_web"
OUTDIR="/etc/pf"
GEOIP=/usr/local/bin/geoiplookup

# hold the output from pfctl -tx -Ts
TMP_PFCTL=`mktemp /tmp/.tmp_pf_table.XXXXXXXXXX` || exit 1

# hold the diff between old and new
TMP_DIFF=`mktemp /tmp/.tmp_diff.XXXXXXXXXX` || exit 1

trap 'rm -f ${TMP_PFCTL} ${TMP_DIFF}' 0 1 2 3 13 15

[ -d ${OUTDIR} ] || mkdir -p ${OUTDIR}

for TABLE in ${PF_TABLES}; do
     # make sure the output file exists
     [ -f ${OUTDIR}/${TABLE} ] || /usr/bin/touch ${OUTDIR}/${TABLE}

     # extraxt IP's from table
     /sbin/pfctl -t${TABLE} -Ts | awk '{print $1}' > ${TMP_PFCTL}

     # we need only the '+diff' to grep for this later
     /usr/bin/diff -bu ${OUTDIR}/${TABLE} ${TMP_PFCTL} > ${TMP_DIFF}
     RETVAL=$?

     case ${RETVAL} in
         0) continue ;;
         1)
            # save the old file
            if [ -f ${OUTDIR}/${TABLE} ]; then
                cp ${OUTDIR}/${TABLE} ${OUTDIR}/${TABLE}.old
            fi

            # mail message header
            date
            echo "change in table: ${TABLE}"
            echo "------------------------------------"

            # lookup the IP in the GeoIP database
            if [ -x ${GEOIP} ]; then
                for IP in `egrep "^\+[0-9]" ${TMP_DIFF} | tr -d \+`; do

                    # print the IP wo. linefeed
                    printf "%-20s # " ${IP}

                    # strip netmask if we add NET by hand
                    IPT=`echo ${IP} | sed 's/\/[[:digit:]]*//g'`

                    # make a short GeoIP output
                    ${GEOIP} ${IPT} | sed 's/ Country Edition//g'
                done
            else
                egrep "^\+[0-9]" ${TMP_DIFF} | tr -d \+
            fi

            mv ${TMP_PFCTL} ${OUTDIR}/${TABLE}
            ;;

         *) echo "error in diff" ;;
     esac
done




small snippet from my bf_ssh file (places with IP rangees I don't visit 
in near time)

snippet from file:/etc/pf/bf_ssh
12.0.0.0/8
21.0.0.0/8
24.0.0.0/8
25.0.0.0/8
26.0.0.0/8
28.0.0.0/8
29.0.0.0/8
30.0.0.0/8
32.0.0.0/8
33.0.0.0/8
38.0.0.0/8
58.0.0.0/8
59.0.0.0/8
60.0.0.0/8
61.0.0.0/8
62.0.0.0/8
63.0.0.0/8
64.0.0.0/8
...
216.0.0.0/8
217.0.0.0/8
218.0.0.0/8
219.0.0.0/8
220.0.0.0/8
221.0.0.0/8
222.0.0.0/8





More information about the freebsd-pf mailing list