Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I'm running a couple of web hosting servers with Directadmin. I'm running Apache as main web server with Nginx working as a proxy in front of it.

In order to keep Nginx "invisible" to Directadmin, I run Nginx on port 81 and forward all connections arriving port 80 to port 81, and then let Nginx work as a proxy (I based my setup on this post). This has been working perfectly for over a year.

The thing is that yesterday we started to notice an attack in a couple of our servers. We receive requests like this (taken from Apache's mod_status):

11-2    29087   0/17/17 W   1.88    19  0   0.0 0.07    0.07    31.7.58.56  www.somedomain.com  GET http://124.108.121.178/?.src=pop&.intl=e1&.help=1&.v=0&.u=c
12-2    29105   0/5/5   W   0.02    42  0   0.0 0.06    0.06    95.79.20.72 www.somedomain.com  GET http://chek.zennolab.com/proxy.php HTTP/1.1
13-2    29111   0/14/14 W   0.29    26  0   0.0 0.07    0.07    87.227.9.151    www.somedomain.com  POST http://arhack.net/vb/index.php HTTP/1.1
14-2    29113   0/5/5   W   0.80    35  0   0.0 0.00    0.00    94.153.69.101   www.somedomain.com  GET http://72.14.203.105/search?as_q=%22/yybbs53a/yybbs.cgi%22+
15-2    29117   0/12/12 W   1.16    19  0   0.0 0.06    0.06    27.159.254.158  www.somedomain.com  GET http://search.sky.com/web?term=chiropractic+seattle+%22Rece
16-2    29118   0/5/5   W   0.61    36  0   0.0 0.30    0.30    31.7.58.56  www.somedomain.com  GET http://217.146.187.123/?.src=pop&.intl=e1&.help=1&.v=0&.u=c
17-2    29119   0/3/3   W   0.71    38  0   0.0 3.95    3.95    203.116.85.147  www.somedomain.com  GET http://119.160.247.158/?.src=pop&.intl=e1&.help=1&.v=0&.u=c
18-2    29120   0/4/4   W   0.52    36  0   0.0 0.06    0.06    176.9.25.25 www.somedomain.com  GET http://www.bing.com/search?q=link%3Arapidvisa.com&setplang=
19-2    29132   0/12/12 W   1.75    25  0   0.0 0.08    0.08    176.31.122.7    www.somedomain.com  GET http://www.baidu.com/%22>Inicio</a>+|+<a+href=%22/webmail%2
20-2    29142   0/11/11 W   1.48    20  0   0.0 0.58    0.58    87.245.203.22   www.somedomain.com  GET http://www.baidu.com/ HTTP/1.1

The thing is that if I let the requests get to Apache, the load average starts rising. If I suspend the domain (which makes Apache just return an error page, without much processing) it get's much better. So what I would like to do is have Nginx deny those sort of requests so that they don't even get to Apache.

How should I do this?

I tried adding this but it didn't work (maybe the regexp is wrong).

location ~* ^http.* {
            deny all;
        }

Here's my nginx.conf (X.X.X.X is my server's public IP):

user  apache;
worker_processes  4;


events {
    worker_connections  4096;
}

http {

    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  /var/log/nginx/access.log  main;

    ## Size Limits
    client_body_buffer_size     128K;
    client_header_buffer_size   128K;
    client_max_body_size          1M;
    large_client_header_buffers 1 1k;

    ## Timeouts
    client_body_timeout   60;
    client_header_timeout 60;
    keepalive_timeout     60 60;
    send_timeout          60;

    ## General Options
    ignore_invalid_headers   on;
    keepalive_requests      100;
    limit_zone gulag $binary_remote_addr 5m;
    limit_rate              512k;
    recursive_error_pages    on;
    sendfile                 on;
    server_name_in_redirect off;
    server_tokens           off;

    ## TCP options
    tcp_nodelay on;
    tcp_nopush  on;

    ## Compression
    gzip              on;
    gzip_buffers      16 8k;
    gzip_comp_level   6;
    gzip_http_version 1.0;
    gzip_min_length   0;
    gzip_types        text/plain text/css image/x-icon application/x-perl application/x-httpd-cgi;
    gzip_vary         on;

    server_names_hash_bucket_size 64;
    reset_timedout_connection on;

        server {
        listen       0.0.0.0:81;
        server_name  myserver.fqdn.com _;

        charset off;

        access_log off;

        limit_conn  gulag 20;

        # Main reverse proxy for most requests
        location / {
                    proxy_set_header Host $host;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

                    proxy_pass              http://X.X.X.X;    # apache here

                    client_max_body_size       16m;
                    client_body_buffer_size    128k;

                    proxy_buffering     on;  

                    proxy_connect_timeout      90;
                    proxy_send_timeout         90;
                    proxy_read_timeout         120;
                    proxy_buffer_size          8k;
                    proxy_buffers              32 32k;
                    proxy_busy_buffers_size    64k;
                    proxy_temp_file_write_size 64k;

                    error_page              502 503 /50x.html;
        }

        location /nginx_status {
            stub_status on;
            access_log   off;
            allow 127.0.0.1;
            deny all;
        }

        location ~* ^http.* {
                deny all;
        }        

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /var/www/html;
    }

}
share|improve this question

1 Answer 1

up vote 4 down vote accepted

There's no way to match those requests with a location, since that style of request uri will be processed by nginx to strip out the scheme://host part.

if ($request ~* https?://) { return 444; }

In the server will match any request lines that contain http:// or https://. 444 is a special code to nginx, it will drop the connection without sending any sort of response. You can change that to a return 403 if you'd prefer.

share|improve this answer
    
Great answer, really helpful, thanks! –  El Barto Aug 2 '12 at 20:52
    
I just realized there's a domain which is on a different IP where Nginx isn't setup as a proxy. Do you know how to do the same in Apache? –  El Barto Aug 2 '12 at 21:09
1  
I don't know apache at all anymore, sorry –  kolbyjack Aug 2 '12 at 21:30
    
haha that's ok, thanks for your help –  El Barto Aug 2 '12 at 21:45
    
Just a minor change: I had to change the regexp to: ^https?://, because I had problems with other legitimate requests where an URL was passed as a parameter. –  El Barto Aug 6 '12 at 18:58

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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