Re: tcpsvd - Allow only x connections from somebody/hour

Ketil Froyn <[email protected]>
Newsgroups gmane.comp.misc.pape.general
Message-ID <1101999588.23254.393.camel@ketil>
On Wed, 2004-12-01 at 22:45, Clemens Fischer wrote:

> so for the database i want a fixed size hash table.  the algorithm is
> neccessarily humble in its goals, because it only knows about IPs trying to
> connect, not how any connections get to be handled by the server program.
> 
> please criticize the following (rough outline):
> 
> *  data kept per IP:
>    +  IP (a long number)
>    +  last_seen (timestamp, long int)
>    +  n (number of connections during monitored time period)

How will you know when to decrease n?

Consider the following thinking out loud...:)

Writing to an on-disk database on every connect() would probably give
you trouble quite fast if you have a busy site. If you want to write
this securely to disk, you are limited to the number of fdatasync()s you
can do per second. Something like this would probably need another
running process that keeps the DB in memory, if you don't just put this
functionality into tcpserver.

I'd actually probably argue that the DB never needs to be on disk. If
you restart the service keeping the database, you wipe that database.
That's ok, it should stop any ongoing DoS soon enough.

How about keeping a constant sized database, with X slots available for
(IP, timestamp) tuples (not necessarily unique). When there's no more
space, you just discard the entry with the oldest timestamp. Then you
can presumably keep track of the last 1 million connections in 8 million
bytes + overhead for structure (size should be configurable). The number
of slots in your database must be larger if you are running a busy site,
but if you get 40 connections per second, 1 million entries should keep
enough stats for almost 7 hours.

The database should only keep track of the last LIMITIPTO connections
from each IP. That way, if someone tries a DoS from one IP, they won't
use all the slots and discard all the other IPs from your database.
Without this it would be quite easy to do a DoS if the attacker has two
or more source IPs to attack from.

Data structures aren't my specialty, but I'm sure it'd be possible to
get the right structure for fast inserts and lookups (note: you'd never
need to delete, just don't count old entries on lookups). This actually
sounds a bit similar to how dnscache works, doesn't it?

A possible algorithm for max LIMITIPTO connections per LIMITIPTIME
seconds (accept connection on DB error):

0) if LIMITIPTO == 0  or LIMITIPTIME == 0 goto 5
1) connect to LIMITIPDB
2) add (REMOTEIP,now)
3) N = count(REMOTEIP, LIMITIPTIME) counts tuples (REMOTEIP, ts)
   where ts > now - LIMITIPTIME
4) if (N > LIMITIPTO) die
5) exec argv

You could move 2 after 4, but if someone would be killing your server
with lots of requests, it's probably better never to let them in, rather
than accept some connections every LIMITIPTIME seconds.

Ketil Froyn
[email protected]
http://ketil.froyn.name/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.