Can ipfw be used to limit concurrent requests from an IP?

Ian Smith smithi at nimnet.asn.au
Sat May 28 14:28:12 UTC 2016


In freebsd-questions Digest, Vol 625, Issue 7, Message: 3
On Fri, 27 May 2016 20:34:56 +0100 Will Squire <will_squire at hotmail.co.uk> wrote:

(please wrap lines < 80 columns if possible)

 > Can ipfw limit the number requests in a given amount of time from a 
 > specific IP?
 > 
 > To contextualise, if an IP sends requests in high concurrency (let's 
 > say 50 a second) can ipfw either block requests the exceed a 
 > threshold for that second (lets say the threshold is 20, 30 would be 
 > blocked), or ban/deny the given IP for exceeding a threshold?

Not as such.  If you know the specific IP address (or range, or subnet) 
you can use stateful rules with 'limit' instead of 'keep-state' to limit 
the maximum number of concurrent connections to the port/s configured in 
a given rule; see ipfw(8).  You cauld use a table of addresses to block
or limit rather than hard-coding them into rule/s.

While this is very useful for avoiding DoS of any particular service, it 
does not allow you to specify a rate, nor time limit, nor (directly) to 
block an IP address that's exceeding the given number of connections.

 > The aim is to lessen strain under DoS attacks, specifically for HTTP. 
 > The system is using Apache and mod_evasive has been added and tested, 
 > but it is not functioning correctly.

I haven't used (nor heard of) mod_evasive so can't comment on that, but 
limiting the total number of connections open to a given service can 
certainly mitigate the effect of such DoS attacks.

You could of course use /etc/inetd.conf (aka TCPwrappers) to limit 
connections in just the ways you want, though I'm not sure starting HTTP 
connections in that way is recommended these days.  I use if for FTP and 
POP3 connections, which works very well, thus:

sola# grep -v '#' /etc/inetd.conf
ftp     stream  tcp     nowait/7/3 root /usr/libexec/ftpd  ftpd -dll -S
pop3    stream  tcp     nowait/7/4 root /usr/local/libexec/qpopper qpopper -s -T 120

See inetd(1), particularly re the inetd.conf setting:
{wait|nowait}[/max-child[/max-connections-per-ip-per-minute[/max-child-per-ip]]]

The above example limits pop3 connections to 7 children and 4 
connections per IP per minute.  Excess connections are logged to 
/var/log/messages (and console.log if enabled) thus:

May 21 12:31:59 sola inetd[9671]: pop3 from 182.118.103.211 exceeded counts/min (limit 4/min)
May 21 14:21:51 sola inetd[9671]: pop3 from 182.118.99.168 exceeded counts/min (limit 4/min)
May 21 14:21:52 sola inetd[9671]: pop3 from 182.118.99.168 exceeded counts/min (limit 4/min)
May 21 14:26:40 sola inetd[9671]: pop3 from 182.117.230.117 exceeded counts/min (limit 4/min)
May 21 15:34:53 sola inetd[9671]: pop3 from 182.117.207.48 exceeded counts/min (limit 4/min)
May 21 16:26:56 sola inetd[9671]: pop3 from 182.117.226.184 exceeded counts/min (limit 4/min)

You could run a script to tail messages hunting for such lines, then add 
the IP to a table if you want; for example I run a script that instantly 
bans GET requests for certain strings to any of a number of webservers. 
I also tend to check logs and hand-add naughty nets such as the above to 
a block table, never to be seen again ..

I also use not dissimilar connection limits to sendmail's MTA, but 
that's done in sendmail's own configuration.

Others may know better ways to deal specifically with HTTP connections?

 > (P.S. The freebsd-ipfw list seems to be for development of the 
 > technology only, so asking this here. Please let me know if this 
 > isn?t the case)

It's usually fairly low volume and noone seems to mind usage questions, 
though the developers usually tend to let these go by.

cheers, Ian


More information about the freebsd-questions mailing list