[oclug] Apache anti-abuse

Tim Hosking tim at trhosking.com
Fri Aug 23 08:49:41 EDT 2002


Cool. Also take a look at the iptables pathc-o-matic stuff:

Forgive the amount of pasted docs, but this really is interesting shit :)

----

The base/iplimit patch:
   Author: Gerd Knorr <kraxel at bytesex.org>
   Status: ItWorksForMe[tm]
   
   This adds CONFIG_IP_NF_MATCH_IPLIMIT match allows you to restrict the
   number of parallel TCP connections to a server per client IP address
   (or address block).
   
   Examples:
   
   # allow 2 telnet connections per client host
   iptables -p tcp --syn --dport 23 -m iplimit --iplimit-above 2 -j REJECT
   
   # you can also match the other way around:
   iptables -p tcp --syn --dport 23 -m iplimit ! --iplimit-above 2 -j ACCEPT
   
   # limit the nr of parallel http requests to 16 per class C sized
   # network (24 bit netmask)
   iptables -p tcp --syn --dport 80 -m iplimit --iplimit-above 16
--iplimit-mask 24 -j REJECT


----

The extra/recent patch:
   Author: Stephen Frost <sfrost at snowman.net>
   Status: Tested locally, no problems so far.
   
   This module is used for creating one or many list(s) of recently seen IP
   addresses and then matching against that/those list(s).
   
   --name     Specify the list to use for the commands.  If no name is given
   then 'DEFAULT' will be used.
   
   --set      followed by an optional `!'
   This will add the source address of the packet to the list.
   If the source address is already in the list, this will update
   the existing entry.  This will always return success.
   
   --rcheck   followed by an optional `!'
   This will check if the source address of the packet is currently
   in the list and return true if it is, and false otherwise.
   
   --update   followed by an optional `!'
   This will check if the source address of the packet is currently
   in the list.  If it is then that entry will be updated and the
   rule will return true.  If the source address is not in the list
   then the rule will return false.
   
   --remove   followed by an optional `!'
   This will check if the source address of the packet is currently
   in the list and if so that address will be removed from the list.
   
   --seconds  followed by an optional `!', then the value
   This option must be used in conjunction with one of 'rcheck' or
   'update'.  When used, this will narrow the match to only happen
   when the address is in the list and was seen within the last
   given number of seconds.
   
   --hitcount followed by an optional `!', then the value
   This option must be used in conjunction with one of 'rcheck' or
   'update'.  When used, this will narrow the match to only happen
   when the address is in the list and packets had been received
   greater than or equal to the given value.  This option may be
   used along with 'seconds' to create an even narrower match
   requiring a certain number of hits within a specific time frame.
   
   --rttl     This option must be used in conjunction with one of 'rcheck'
or
   'update'.  When used, this will narrow the match to only happen
   when the address is in the list and the TTL of the current packet
   matches that of the packet which hit the --set rule.  This may be
   useful if you have problems with people faking their source
   address in order to DoS you via this module by disallowing others
   access to your site by sending bogus packets to you.
   
   /proc/net/ipt_recent is a directory which contains the currently active
lists.
   
   /proc/net/ipt_recent/* are the current lists of addresses and information
   about each entry of each list.
   
   Each file in /proc/net/ipt_recent/ can be read from to see the current
list
   or written two using the following commands to modify the list:
   'echo xx.xx.xx.xx > /proc/net/ipt_recent/DEFAULT' to Add to the DEFAULT
list
   or 'echo +xx.xx.xx.xx > /proc/net/ipt_recent/DEFAULT' for the same
result.
   'echo -xx.xx.xx.xx > /proc/net/ipt_recent/DEFAULT' to Remove from the
DEFAULT list
   'echo -0.0.0.0 > /proc/net/ipt_recent/DEFAULT' to empty the DEFAULT list.
   
   The module itself accepts two parameters:
   ip_list_tot=40
   ip_pkt_list_tot=10
   
   Shown are the defaults.
   ip_list_tot is the total number of addresses which will be remembered,
note
   that the list is searched in-order for every attempted match and so you
do
   not want to increase this value too much or alot of time will be spent
   traversing the list.
   
   ip_pkt_list_tot is the total number of packets which will be remembered
for
   each address.  This list is only used by '--hitcount' and so the default
   will probably suffice unless you make extensive use of that option.
   
   Example #1:
   
   # iptables -A FORWARD -m recent --rcheck --seconds 60 -j DROP
   # iptables -A FORWARD -i eth0 -d 127.0.0.0/8 -m recent --set -j DROP
   
   Here we are making a 'bad guy' out of anyone who tries to send data to
   127.0.0.0/8 on our eth0 interface (which should never legitimately
   happen).  The first packet will make it past the first rule and then
   be caught by the second rule and that address will be put into the
   recent list and the packet dropped.
   
   Any subsequent packets for the next 60 seconds that show up from that
   address will be dropped, regardless of destination address, destiation
   port, etc.
   
   Example #2:
   
   # iptables -A FORWARD -m recent --update --seconds 60 -j DROP
   # iptables -A FORWARD -i eth0 -d 127.0.0.0/8 -m recent --set -j DROP
   
   (The author's favorite method)
   
   This is identical to example #1 except that for every subsequent packet
   received from this source address the 'last seen' status will be updated
   in the table.  Therefore there must be a 'quiet time' of 60 seconds
   before another packet from this address will even be considered.
   
   It is the author's intent that all 'DROP' rules be replaced by:
   
   '-m recent --set -j DROP'
   
   and that a:
   
   '-m recent --update --seconds 60 -j DROP'
   
   rule be added very early on in the rule set, though following any:
   
   '--match state --state ! NEW,INVALID -j ACCEPT'
   
   rules.  If the '--update' rule is before this check for ! NEW,INVALID
   packets then ESTABLISHED connection or those in the process of becoming
   ESTABLISHED could be disrupted by a malicious person who can modify
   his/her source address.

----

There are some other really nice iptables patches available too. The PSD
Match (port scan detection) is a beaut.

-- 
Tim Hosking


On 8/23/02 8:20 AM, "David F. Skoll" <dfs at roaringpenguin.com> wrote:

> Hi,
> 
> My Web server was attacked on the 21st and 22nd August, with some
> bozo at Ottawa-HSE-ppp262070.sympatico.ca hitting me over 480,000
> times with ApacheBench.
> 
> This is the second time something like this has happened, so I wrote
> this little protection script.  Run it every 5 minutes from cron, feeding
> it your Apache log file as input.  It firewalls off hosts who hit you
> too often (default is if 250 hits of the last 1000 are from the same host,
> you're out.)
> 
> Invoke:  watch-apache-abuse < /path/to/access_log
> 
> It creates an iptables chain called web_abusers which you should call
> from INPUT like this:
> 
> iptables -A INPUT --proto tcp --dport 80 -j web_abusers
> 
> You also need a web_abusers_log chain, which you can create
> as follows:
> 
> iptables -N web_abusers_log > /dev/null 2>&1
> iptables -A web_abusers_log -j LOG --log-prefix "FW: Web Abuser "
> iptables -A web_abusers_log -j DROP
> 
> Regards,
> 
> David.
> 
> #!/bin/sh
> #
> # Usage:  watch-apache-abuse < LOGFILE
> #
> # Copyright 2002 Roaring Penguin Software Inc.
> # This file may be distributed under the terms of the GNU General
> # Public License, version 2.
> 
> # Sample size
> SAMPLE=1000
> 
> # Number of samples from same host to be considered abuse
> ABUSE=250
> 
> # Output firewall file
> FWFILE=/root/web-abusers
> 
> # Back up firewall file
> mv -f $FWFILE $FWFILE.ORIG > /dev/null 2>&1 || touch $FWFILE.ORIG
> 
> # Create firewall file
> cat <<EOF > $FWFILE
> #!/bin/sh
> 
> iptables -F web_abusers > /dev/null 2>&1
> EOF
> # Get list of abusive hosts
> 
> 
> ABUSERS=""
> tail -$SAMPLE | awk '{print $1}' | sort | uniq -c | awk "{if (\$1 > $ABUSE) {
> print \$0 }}" | while read count host ; do
>   fgrep $host $FWFILE.ORIG > /dev/null || echo "`date`: Host $host marked as
> abusive ($count hits)"
>   echo "iptables -A web_abusers --source $host -j web_abusers_log" >> $FWFILE
> done
> 
> . $FWFILE
> 
> 
> 
> 
> 
> _______________________________________________
> oclug mailing list
> oclug at lists.oclug.on.ca
> http://www.oclug.on.ca/mailman/listinfo/oclug
> 




More information about the OCLUG mailing list