提升 Nginx 自身防御能力的一些方法

1. 设置合理的 client_max_body_size

这个指令限制客户端请求体(如文件上传)的最大大小。设置过小影响正常使用,设置过大则可能被攻击者利用,发送超大请求体来消耗服务器资源。

配置方法:

通常,这个指令可以在 httpserverlocation 块中设置。

http {
    # 在http块中设置为全局默认值,例如限制为10M
    client_max_body_size 10m;
}

server {
    listen 80;
    server_name your_domain.com;

    # 针对这个server,可以覆盖全局设置,例如限制为20M
    client_max_body_size 20m;

    location / {
        # ... 其他配置 ...
    }

    location /upload {
        # 对于专门的上传接口,可以设置得更大一些
        client_max_body_size 50m;
        # ... 其他上传配置 ...
    }

    location /api {
        # 对于API,可能不需要太大的请求体
        client_max_body_size 1m;
    }
}
  • 单位:k (千字节), m (兆字节), g (千兆字节)
  • 建议:根据您的业务需求设置。如果网站没有文件上传功能,可以设置一个较小的值(如1M)。对于上传功能,设置一个合理的上限。

2. 限制单个 IP 的连接数和请求速率

这是应对CC攻击和扫描非常有效的手段。

A. 限制请求速率

使用 limit_req_zonelimit_req 指令。

http {
    # 定义限制参数
    # $binary_remote_addr 是客户端的二进制IP地址,占用空间更小
    # zone=req_per_ip:10m 定义一个名为req_per_ip的共享内存区,用来存储KEY的状态,10MB可以处理约16万个IP的状态
    # rate=10r/s 表示每秒允许10个请求
    limit_req_zone $binary_remote_addr zone=req_per_ip:10m rate=10r/s;

    server {
        listen 80;
        server_name your_domain.com;

        location / {
            # 应用限制
            # zone=req_per_ip 使用上面定义的zone
            # burst=20 允许超过速率限制后最多有20个请求被放入队列延迟处理
            # nodelay 对于burst队列中的请求,不延迟处理,立即按速率处理;如果没有nodelay,则会延迟处理,导致用户等待。
            limit_req zone=req_per_ip burst=20 nodelay;

            # ... 其他配置(例如 proxy_pass, root等) ...
        }

        # 对于静态文件,通常可以放宽或不做限制
        location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
            # 不应用请求频率限制
            expires 1y;
            add_header Cache-Control "public, immutable";
        }

        # 对于登录页面或API,可以设置更严格的限制以防爆破
        location /login {
            limit_req zone=req_per_ip burst=5 nodelay;
            # ... 其他配置 ...
        }
    }
}

B. 限制连接数

使用 limit_conn_zonelimit_conn 指令。这对于防止单个IP占用过多连接(如下载)特别有用。

http {
    # 定义连接限制参数
    # zone=conn_per_ip:10m 定义一个名为conn_per_ip的共享内存区
    limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m;

    server {
        listen 80;
        server_name your_domain.com;

        # 全局限制每个IP最多保持10个连接
        limit_conn conn_per_ip 10;

        location / {
            # ... 其他配置 ...
        }

        # 对于下载区域,可以单独限制更严格的连接数
        location /downloads {
            limit_conn conn_per_ip 2; # 每个IP同时只能下载2个文件
            # ... 其他配置 ...
        }
    }
}

3. 对某些敏感的 URL 路径实施严格的访问控制

通过 location 块对管理后台、API接口等敏感路径进行加固。

A. IP 白名单(最安全)

只允许受信任的IP访问。

server {
    listen 80;
    server_name your_domain.com;

    # 正常网站内容
    location / {
        # ... 其他配置 ...
    }

    # 保护 WordPress 后台
    location /wp-admin {
        allow 192.168.1.100; # 替换为您的办公室或家庭IP
        allow 203.0.113.50;  # 替换为另一个信任的IP
        deny all;            # 拒绝所有其他IP

        # 同时可以加上请求速率限制
        limit_req zone=req_per_ip burst=5 nodelay;

        # ... 其他配置(例如 try_files 或 proxy_pass)...
    }

    # 保护 PHPMyAdmin 或其他数据库管理工具
    location /phpmyadmin {
        allow 192.168.1.100;
        deny all;
        auth_basic "Admin Login"; # 额外增加一层HTTP基础认证
        auth_basic_user_file /etc/nginx/.htpasswd;
    }

    # 保护 API 接口
    location /api/v1/admin {
        allow 192.168.1.0/24; # 允许整个内网网段
        deny all;
        limit_req zone=req_per_ip burst=10 nodelay;
    }
}

B. 密码认证

即使IP泄露,也多一层防护。

生成密码文件:

# 首次创建,-c 参数表示创建文件,后续添加用户不要再使用 -c,否则会覆盖
sudo sh -c "echo -n 'username:' >> /etc/nginx/.htpasswd"
sudo sh -c "openssl passwd -apr1 >> /etc/nginx/.htpasswd"
# 然后输入密码

# 或者使用 apache2-utils 包中的 htpasswd 命令
sudo apt-get install apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd username

Nginx 配置:

location /secret-area {
    auth_basic "Restricted Area";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

综合配置示例

一个结合了以上多种措施的 server 块可能看起来像这样:

http {
    limit_req_zone $binary_remote_addr zone=req_per_ip:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m;
    client_max_body_size 10m;
}

server {
    listen 80;
    server_name your_domain.com;

    # 全局连接限制
    limit_conn conn_per_ip 10;

    # 根目录,应用请求频率限制
    location / {
        limit_req zone=req_per_ip burst=20 nodelay;
        try_files $uri $uri/ /index.php?$query_string;
    }

    # 静态资源,不限制频率,利用缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # 严格保护后台
    location /admin {
        allow 192.168.1.100; # 你的IP
        deny all;
        limit_req zone=req_per_ip burst=5 nodelay;
        auth_basic "Admin Panel";
        auth_basic_user_file /etc/nginx/.htpasswd;
        try_files $uri $uri/ /index.php?$query_string;
    }

    # 保护上传接口,限制文件大小
    location /api/upload {
        client_max_body_size 20m;
        limit_req zone=req_per_ip burst=5 nodelay;
        # ... 处理上传的逻辑 ...
    }
}

重要提醒:

  1. 测试:在应用这些配置到生产环境之前,请在测试环境中充分验证,确保不会误伤正常用户。
  2. 重载配置:每次修改 Nginx 配置后,使用 sudo nginx -t 测试配置语法是否正确,然后使用 sudo systemctl reload nginx 重载配置使其生效。
  3. 根据业务调整:所有数字(如速率、连接数、文件大小)都需要根据您网站的实际流量和业务需求进行调整。

通过这些 Nginx 层面的防护,您可以大大降低被恶意扫描和攻击的风险,与 Fail2ban 形成互补的防御体系。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部
×
问题求助