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/