Homemade DDoS Protection Using IPTables SYNPROXY
First off, if you want the real deal and get your service DDoS protected from even the most complex types of DDoS attacks by security specialists today, don’t bother reading about SYNPROXY and instead check out our Anti DDoS Hosting and Remote DDoS Protection. If you feel confident that you can use SYNPROXY as an addition to your current DDoS mitigation strategy and are an experienced system or network admin, continue reading.
It’s nothing new that DDoS attacks are increasing constantly in size and quantity over the years, making them more likely to affect you personally every month passing by. Apart of DNS Amplifictation Attacks, SYN Floods are one of the most common DDoS attack types today. Until recently Linux systems were very bad at handling SYN Floods properly compared to *BSD, which has a SYN Proxy feature built into its default firewall « PF » for quite a while now, which is a good approach for SYN Flood DDoS mitigation. The Linux default firewall « IPTables » hasn’t had a similar feature for a long time and the only approach to mitigate SYN Floods was the Kernel’s « syncookie » feature, which isn’t by far as performant as one would wish when under SYN Flood.
Finally, after years of lacking appropiate SYN Flood mitigation options under Linux, the new « SYNPROXY » target was introduced with the 3.12 kernel and IPTables version 1.4.21 trying to fill that gap quite successfully. Although it’s not a cure for every SYN Flood, because most ISPs are likely to nullroute your IP before the attack clogs your TCP/IP stack and probably your NIC will cause interrupts before your kernel, but tests have shown that there is a major increase of performance when under SYN Flood, SYN-ACK Flood or ACK Flood.
While a Linux kernel with default settings usually starts to cause software interrupts and starts dropping packets at as little as 200.000 packets per second (PPS), it can handle multiple millions of packets per second with the strategy explained in this tutorial. The number of SYN packets it can handle per second increases by a factor of 10 and the number of ACK packets it can handle per second even increases by a factor of 20, which can be a major advantage when you have to handle large amounts of packets (read: you’re under SYN or ACK Flood).
IPTables « SYNPROXY » on Debian Wheezy
In this example we’ll use a Debian Wheezy system for our setup. I can imagine this being used on Vyatta boxes in the future to effectively protect whole network segments with very cheap hardware. The first things we’ll have to do is to upgrade our kernel and iptables version.
Upgrading the Kernel
First we have to add the Backports repository to fetch a recent kernel from, as well as the « testing » repository to get the latest iptables version from.
cat >> /etc/apt/sources.list << EOF deb http://ftp.debian.org/debian testing main contrib non-free deb http://ftp.debian.org/debian/ wheezy-backports main EOF
Then, before continuing, we should use APT pinning to make sure that we don’t install any packages from these repositories that we don’t want to install.
cat >> /etc/apt/preferences << EOF Package: * Pin: release a=stable Pin-Priority: 700 Package: * Pin: release a=wheezy-backports Pin-Priority: 650 Package: * Pin: release a=testing Pin-Priority: 600 EOF
Only then we can run «
apt-get update » to fetch the list of packages inside the newly added repositories and install/upgrade the kernel and iptables.
apt-get update apt-get -t wheezy-backports install linux-image-amd64 apt-get -t testing install iptables
After that you should reboot your system with «
shutdown -r now » to boot into the new kernel. Once done, run «
iptables --version » to verify that your iptables version is 1.4.21 or newer and «
uname -a » to verify that your kernel is 3.12 or newer. After your box fulfills these requirements, we can continue with the interesting stuff.
Adjusting Your Kernel Settings
Because the « SYNPROXY » feature uses syncookies and syncookies use timestamps, we have to enable both in our kernel settings. You can either edit your /etc/sysctl.conf to reflect these settings or apply them directly with:
sysctl -w net/ipv4/tcp_syncookies=1 sysctl -w net/ipv4/tcp_timestamps=1
Furthermore we have to adjust the conntrack settings, because a major part of the « SYNPROXY » feature is to not track TCP connections that aren’t fully established, because that needs a lot of resources. The following setting will exclude ACK packets from connection tracking and mark them as INVALID and, amongst other things, make your server absorb ACK Floods.
sysctl -w net/netfilter/nf_conntrack_tcp_loose=0
If that command returns an error, try to apply it later when the conntrack kernel module is actually active. Furthermore it makes sense to increase conntrack’s hash size and the conntrack_max setting:
echo 2500000 > /sys/module/nf_conntrack/parameters/hashsize sysctl -w net/netfilter/nf_conntrack_max=2000000
These are only the most important settings, there are lots of other kernel settings that can be tweaked in order to increase the network performance with many connections/packets, but covering all of them wouldn’t be possible with this small tutorial. So lets continue with the actual iptables rules.
« SYNPROXY » Against SYN Floods & Other DDoS Attacks
Now our Debian box is fully prepared and we can add the iptables rules. We’ll start with a rule that applies to all NICs and all IPs that are up on them. Please keep in mind that these example rules will cause issues with NAT, so make sure you don’t use NAT or read ahead to learn how to protect single IPs/ports only.
The first rule we insert, excludes SYN packets from connection tracking, because that would use a lot of resources and obviously we don’t want that:
iptables -t raw -I PREROUTING -p tcp -m tcp --syn -j CT --notrack
The „raw“ table handles untracked connections, the « CT » target stands for «
conntrack » and the «
--notrack » option excludes them from tracking. This rule should pretty much explain itself.
iptables -I INPUT -p tcp -m tcp -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
This rule matches the SYN packets (UNTRACKED as per previous rule) and ACK packets (INVALID as per « nf_conntrack_tcp_loose=0 ») and forwards them to the SYNPROXY target, which then verifies the syncookies (parallel, which wasn’t possible previously) and establishes the full TCP connections. At last we add a rule that drops every packet that the previous rule didn’t catch, read bad packets/DDoS:
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
That’s it already. If you want to protect a specific IP which is under DDoS attack, you can adjust the rules like this:
iptables -t raw -I PREROUTING -p tcp -m tcp -d 192.168.0.50 --syn -j CT --notrack iptables -I INPUT -p tcp -m tcp -d 192.168.0.50 -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460 iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
And of course you can also add
--dport 80 for example, to protect only port 80 if that’s the destination of the SYN flood.
To verify that everything’s working, access one of the services you protected with these rules and then have a look inside «
/proc/net/stat/synproxy« . It should look like this or similar:
Congratulations, your server is now able to handle multiple millions of packets per second, as long as your NIC doesn’t crumble and your ISP doesn’t nullroute your IP. I can imagine this being used not only on Vyatta routers/firewalls, but also on OpenVZ nodes and other virtualization hosts directly, to prevent trouble if one of the VMs is under SYN flood. It’s all very new (at least for the Linux community, not really for the *BSD one) and the downside is that it adds a small delay to each TCP connection, although that shouldn’t be noticable as long as it’s being used on localhost, but it’s really promising and a huge step forward.
At last I’d like to thank Jesper Brouer from Red Hat for introducing this on DevConf.cz 2014.