Nginx 防止IP扫描

日志里经常会出现访问/phpmyadmin类似后台路径的请求,经查是由僵尸网络发起的网络扫描,如果找到有相应程序的主机,则进行攻击。这些连接的特点是通过IP进行请求,请求头Host字段为IP地址,UA也不是正常浏览器,而是特定的扫描程序名称。这些探测请求一次可能有几百条路径同时发起,浪费后端服务资源。

通过Nginx listen 80 default_serverserver_name _ 将没有正确Host的请求引入受限的虚拟主机,并且限制请求的频率,可以达到欺骗扫描程序,并且减轻后端压力的效果。

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

    # fake vhost
    server {
        listen 80 default_server;
        listen 443 ssl default_server;
        server_name _;

        ssl_certificate /etc/nginx/certs/certificate.pem;
        ssl_certificate_key /etc/nginx/certs/certificate.key;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

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

        index index.html;
        root /usr/share/nginx/html;

        location = / {
            try_files /index.html =404;
            # empty_gif;
            limit_req zone=one burst=5;
            limit_req_status 444;
        }

        location / {
            return 444;
        }
    }
    
    # real server
    server {
        listen 80;
        listen 443 ssl;
        server_name  example.net;
        
        ssl_certificate /etc/nginx/certs/certificate.pem;
        ssl_certificate_key /etc/nginx/certs/certificate.key;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        access_log  /var/log/nginx/example.access.log  main;
        
        index index.html;
        root /usr/share/nginx/html;
        
        location / {
            try_files /index.html =404;
        }
    }
}

上面的配置包含了Certbot申请Let's Encrypt证书自动添加的一些配置。异常的请求会记录在/var/log/nginx/access.log,正常的请求在/var/log/nginx/example.access.log

其中 location =/ 如果不想返回index.html可以使用empty_gif,这只是保证服务器根目录能返回一个正确的页面,其他任何地址都会断开连接。

原文链接:https://marskid.net/2018/02/04/nginx-deny-web-scanner/