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