a (linux) webserver I administer (on a VPS) for a low volume website has just been subjected to about 5 SYN requests/second on port 80, with no other traffic coming from the remote host.
It was more of a drip than a flood, but it went on for something like an hour after I first noticed it. I don't know if this was an amplification attack or not.
I have no desire to be part of that sort of thing, and in any case, all those half-opened connections clogging up netstat were annoying, even if there was no real harm done. (SYN-cookies are enabled, the link was a long way from saturated, and apache was coping, though I think memory usage was up and responses a bit slower than normal.)
So, this one, I 'mitigated' by manually blocking the spoofed / actual
originating IP address, and then kept an eye on it with tcpdump, which is how
I knew they'd given up. I'd like an automatic solution...
As it's a public-facing webserver, there are SUPPOSED to be connections! And
some pages have a lot of pictures/CSS files, etc. on them. I therefore fully expect that genuine users will far exceeding the 5 'attack' requests per second, and that therefore things like
iptables -A INPUT -m state --state NEW -m limit --limit 4/second --limit-burst 20 ....
will just catch out genuine users but barely catch the attack, if at all.
Other than something crude like a script counting SYN_RCVD entries in the output of netstat every so often and then feeding the results into a log for fail2ban to respond to, is there an effective solution to drop packets if the cumulative total of half-open connections from a given IP exceeds some number? I can't see anything in iptables, but maybe I'm missing something.
EDIT: Forgot to say, the VPS is openVZ-based (built on RHEL6), so the kernel I'm stick with is 2.6.32 at the moment. Answers that work on kernels that ancient would be great!
EDIT2: Conntrack timeouts, as requested:
net.netfilter.nf_conntrack_generic_timeout = 120
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 30
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 15
net.netfilter.nf_conntrack_tcp_timeout_established = 86400
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 30
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 15
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 10
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30
net.netfilter.nf_conntrack_tcp_timeout_close = 5
net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 60
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 60
net.netfilter.nf_conntrack_udp_timeout = 10
net.netfilter.nf_conntrack_udp_timeout_stream = 60
net.netfilter.nf_conntrack_icmpv6_timeout = 30
net.netfilter.nf_conntrack_icmp_timeout = 10
net.netfilter.nf_conntrack_events_retry_timeout = 15
net.ipv6.nf_conntrack_frag6_timeout = 4194
But as I wrote above, I'm not so much interested in impact on the server (so far it's been minimal) as blocking script-kiddies and the like, just
like when they try to see if I've got phpmyAdmin, a dlink-router, (etc) that's about the last packet of theirs I get.
Answer
Yes, you can do that Kernel settings (e.g. setting timeouts via conntrack module) in combination with iptables limits and SYNPROXY.
Basically what synproxy does is to check if a full TLS connection is established and if not drop the request. It has a much better performance than other solutions that came before (hashlimits etc.).
And you're right, a limit of 4 connections/second will block a lot of legitimate connections, around 60-80/s is more realistic. For your use case synproxy is definitely the way to go.
When playing around with DDoS protection with built in Linux tools earlier this year myself I found a great anti-DoS guide here: https://javapipe.com/ddos/blog/iptables-ddos-protection/
This guide basically is a how-to to all of the things I mentioned above.
It explains what every rule does, why you should or shouldn't implement it, how it works, how it affects performance and tells you if it's optional, a really great guide.
No comments:
Post a Comment