From f733ec81c355da2ae4c40779fef52ebdbcad7fbc Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Sun, 30 Sep 2012 01:01:17 -0400 Subject: [PATCH] DoS hardening. --- Makefile | 2 +- NEWS | 4 ++-- irkerd | 21 +++++++++++++++++++++ security.txt | 11 ++++------- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 722724d..c1ef880 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ clean: rm -f irkerd.1 irker-*.tar.gz *~ rm -f SHIPPER.* *.html -PYLINTOPTS = --rcfile=/dev/null --reports=n --include-ids=y --disable="C0103,C0111,C0301,R0201,R0902,R0903,E1101,W0201,W0621,W0702" +PYLINTOPTS = --rcfile=/dev/null --reports=n --include-ids=y --disable="C0103,C0111,C0301,R0201,R0902,R0903,R0912,E1101,W0201,W0621,W0702" pylint: @pylint --output-format=parseable $(PYLINTOPTS) irkerd @pylint --output-format=parseable $(PYLINTOPTS) irkerhook.py diff --git a/NEWS b/NEWS index d17cbfd..c6f3170 100644 --- a/NEWS +++ b/NEWS @@ -9,8 +9,8 @@ 1.2 @ All segments of a message with embedded newlines are now transmitted. - Message reduction - irkerhook driops the filelist on execessively long ones. - Shell quote hardening in irkerhook.py. + Message reduction - irkerhook drips the filelist on execessively long ones. + Shell quote hardening in irkerhook.py and some anti-DoS logic. diff --git a/irkerd b/irkerd index bdcd54e..bc53d5e 100755 --- a/irkerd +++ b/irkerd @@ -35,6 +35,7 @@ UNSEEN_TTL = 60 # Time to live, seconds since first request CHANNEL_MAX = 18 # Max channels open per socket (default) ANTI_FLOOD_DELAY = 0.125 # Anti-flood delay after transmissions, seconds ANTI_BUZZ_DELAY = 0.09 # Anti-buzz delay after queue-empty check +CONNECTION_MAX = 200 # Avoid pushing per-process thread or fd limits # No user-serviceable parts below this line @@ -340,6 +341,26 @@ class Irker: for servername in servernames: if not self.servers[servername].live(): del self.servers[servername] + # If we might be pushing a resource limit + # even after garbage collection, remove a + # session. The goal here is to head off + # DoS attacks that aim at exhausting + # thread space or file descriptors. The + # cost is that attempts to DoS this + # service will cause lots of join/leave + # spam as we scavenge old channels after + # connecting to new ones. The particular + # method used for selecting a session to + # be terminated doesn't matter much; we + # choose the one longest idle on the + # assumption that message activity is likely + # to be clumpy. + oldest = None + if len(self.servers) >= CONNECTION_MAX: + for (name, server) in self.servers.items(): + if not oldest or server.last_xmit < self.servers[oldest].last_xmit: + oldest = name + del self.servers[oldest] except ValueError: self.logerr("can't recognize JSON on input: %s" % repr(line)) diff --git a/security.txt b/security.txt index 1dd53a3..9a72daf 100644 --- a/security.txt +++ b/security.txt @@ -152,13 +152,10 @@ with legitimate high-volume use by a very active repo site. After this we appear to have run out of easy options, as source IP address is the only thing irkerd can see that an attacker can't spoof. -=== Future directions === - -One way we could mitigate some availability risks is by reaping old -sessions when we're near resource limits. An ordinary DoS attack -would then be prevented from completely blocking all message traffic; -the cost would be a whole lot of join/leave spam due to connection -churn. +We mitigate some availability risks by reaping old sessions when we're +near resource limits. An ordinary DoS attack would then be prevented +from completely blocking all message traffic; the cost would be a +whole lot of join/leave spam due to connection churn. = Authentication/Integrity = -- 2.26.2