Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This question already has an answer here:

I have a 1GB-VPS-hosted site running on Ubuntu 10.04 LTS. I am using nginx as the web server. The site has been running in a relatively stable configuration for three years, and handles about 4 million pageviews a month.

For the past 16 hours, I've been seeing what I believe is a "mild" DDoS attack. Outgoing traffic has multiplied by 5, and CPU usage has roughly tripled. I am seeing in my nginx logs a one or two IPs each second sending multiple requests simultaneously (1-10 each). These requests seem not to be going to my URL, but my IP address directly. Since I am somewhat comfortable with the nginx.conf, I set up a separate "default" server block there to catch this traffic and log it. I have it set to log that traffic and return error code 444 to it. I also set up limit_req_zone and limit_conn_zone for this traffic, though since these are different IPs sending requests, that has little impact. Here is the relevant section of nginx.conf:

limit_req_zone  $binary_remote_addr  zone=ddos:25m   rate=1r/m;
limit_conn_zone $binary_remote_addr zone=blockedfuckers:20m;    
server {
    listen 80 default_server;
    server_name _;
    access_log /var/log/nginx/a2.log hackers;
    limit_req zone=ddos nodelay;
    limit_conn blockedfrakers 1;
    return 444;

This knocked CPU usage down by about 30%, but outgoing traffic is still high, and the CPU is still over double normal. For some reason, the log shows the requests being sent a 400 response, not the 444 I am trying to send. For example: [12/Mar/2013:22:49:24 -0400], REQLENGTH: 0, STATUS: 400, HTTPHEADER: - [12/Mar/2013:22:49:36 -0400], REQLENGTH: 0, STATUS: 400, HTTPHEADER: - [12/Mar/2013:22:49:36 -0400], REQLENGTH: 0, STATUS: 400, HTTPHEADER: - [12/Mar/2013:22:49:36 -0400], REQLENGTH: 0, STATUS: 400, HTTPHEADER: - [12/Mar/2013:22:49:36 -0400], REQLENGTH: 0, STATUS: 400, HTTPHEADER: - [12/Mar/2013:22:49:36 -0400], REQLENGTH: 0, STATUS: 400, HTTPHEADER: -

These look like "empty" requests to me, so I am trying to configure iptables to just drop those, but the few things I've tried haven't worked. Any ideas on how I can target & drop this traffic?

share|improve this question

marked as duplicate by Tom O'Connor Aug 25 '13 at 22:20

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

up vote 1 down vote accepted

If you are sure that TCP payload is 0, you can try with the --length options of iptables. This options matches the layer 3 payload. This rule should work:

iptables -I INPUT -p tcp --dport 80 -m length --length 20 -j DROP

The size of a TCP header is usually 20 (could be bigger, but try with 20 and see the results). So, that rule drop packets that only contains a packet with a TCP header and no payload.

share|improve this answer
Having TSval and TSecr in the options seems quite common to me. With padding they make 12 byte, so he should give --length 32 a try as well. – Karma Fusebox Mar 13 '13 at 14:28
Thanks, I had to add both length 20 and 32 to catch all of them. – Josh K Mar 19 '13 at 1:54

Not the answer you're looking for? Browse other questions tagged or ask your own question.