4

I'm running fail2ban on a Raspberry Pi at 950MHz which I cannot overclock further.

The Pi is occasionally subject to SYN floods on particular ports. I've set up iptables to throttle the rate of SYNs on the port of interest; when the throttle limits are exceeded, hosts which send SYNs are dropped into the REJECT chain and the particular SYN packet which exceeded the limit is logged.

fail2ban then watches for these logged SYNs and, after seeing a few, temporarily bans the host for a short time (this is a transient issue in the app I'm working with).

The problem is that the SYN floods can occasionally reach rates which are too fast for fail2ban to keep up with; I'll see 20-40 log messages per second, and eventually fail2ban falls behind and becomes ineffective. To add insult to injury, it continues consuming a LOT of CPU as it tries to catch up.

I have verified that DROP chained packets from hosts already banned by fail2ban are not logged, and thus do not add to its load.

What are my options here? I have a few ideas, but no clear path forward.

  1. Could I make the log-parse regex "easier" so it takes fewer cycles? Would using iptables --log-prefix to put a token near the start of the log message, and/or otherwise simplifying/altering the fail2ban regex help? Here is the current fail2ban config line containing a regex:
    failregex = kernel:.*?SRC=(?:::f{4,6}:)?(?P<host>[\w\-.^_]+) DST.*?SYN

  2. Is there a faster way for fail2ban to watch for the packets exceeding the limits than parsing kern.log?

  3. Could fail2ban be run under PyPy instead of CPython with minimal nonstandard wizardry (the OS is Raspbian 7, so, mostly Debian 7)?

  4. Is there something better than fail2ban that I could use to watch for the packets which exceed the SYN limits, and after N exceeds in X seconds, temporarily put the offending IP into the iptables DROP bucket, and take it out when the ban timer expires? Again, I'd vastly prefer a solution that uses as much software available in Debian as possible, though I can build Debian packages in a pinch.

4
  • Have you tried using CSF? It is a lot more robust than fail2ban, and is a little bit more resource consuming, but since fail2ban hogs your resources on SYN attack, maybe it would be a better option.
    – SeeBeen
    Commented Oct 28, 2013 at 0:13
  • Great question. Should be migrated over to Unix & Linux, though.
    – EEAA
    Commented Oct 28, 2013 at 0:21
  • @SeeBeen I'll look into CSF - RAM is really at a premium on the Pi, as is CPU, but maybe it'll be a better candidate. Commented Oct 28, 2013 at 0:40
  • 1
    Everything is premium for PI. I know because I am also using it as a server( nginx/php-fpm, CI). My advice would be to to move the webserver to nonstandard port (eg. 8032) and use iptables rules do deny all other incoming traffic. Pi should not be used as a webserver, IMO.
    – SeeBeen
    Commented Oct 28, 2013 at 1:00

2 Answers 2

1

Slightly off-topic to your question, but SYN cookies might be a suitable and simple mitigation when confronted with moderate SYN flooding.

# echo 1 > /proc/sys/net/ipv4/tcp_syncookies

Google some for reasons why this might be a good or bad idea.

Alternatively, since you already have a kernel firewall configured, you could use the "recent" iptables module as limiter circumventing fail2ban entirely:

# iptables -A INPUT -p tcp -m state --state NEW -m recent --name ftp_limit --update --seconds 60 --hitcount 20 -j DROP
# iptables -A INPUT -p tcp -m state --state NEW -m recent --set --name ftp_limit -m tcp --dport 21 -j ACCEPT

These rules limit the rate of SYN requests (new connections) from one IP to 20 per minute (line 1) for IP-addresses in the list named ftp_limit and DROP any additional requests. Line 2 will add the source IP-address to the ftp_limit list whenever a new connection is being established on port 21 (ftp).

You run the risk you block legitimate traffic originating from networks behind NAT, since those appear to originate from a single ip-address. And you might want to whitelist some trusted networks as well.

0

Like I said in my comments.

Switch to CSF, it has a larger memory footprint, but if I had to choose between high ARM-CPU usage and high overall memory usage, I would choose the latter.

Other alternative would be to drop using any firewall software and switch to iptables rules. Move the server to nonstandard port (8030, 24544, etc.) and use iptables to drop connections on all other ports.

If you're behind NAT, you could use your router to disable portforwarding on all ports except the one for the webserver (assuming you set it up to listen on other port).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .