您现在的位置是:网站首页> 软件使用

nginx配置说明

摘要

nginx配置

nginx必须放到非中文目录否则运行异常

1.jpg



AI辅助配置

负载均衡

配置HTTPS站点

Nginx 防止DDOS攻击

nginx配置在线

修改了nginx.conf文件后重新加载配置文件

Nginx 防御洪水攻击 小记

ubuntu下nginx停止、启动、重启



AI辅助配置

典型应用不用域名不同站点

HTTPS(免费证书)支持自动续期,三个域名共用一个证书或分开证书

这个certbot证书windows上如何生成

在原配置基础上加上限流防刷 防盗链 反爬 大文件上传优化 WebSocket 支持

加 IP 白名单、接口签名校验、地域访问限制、灰度发布 



Q:比如现在有三个站点分别绑定在域名 www.1.ai.com  www.2.ai.com  www.3.ai.com 分别对应本机的127.0.0.1:1000、127.0.0.1:2000、127.0.0.1:3000  如何配置ngnix,实现访问相应域名等于访问相应的站点,同时后端能保证后端拿到正确的域名和客户访问IP

A:..

完整可直接复制的 Nginx 配置

我直接给你最简、最稳定、生产可用的 Nginx 配置,实现:

访问 www.1.ai.com → 转发到 127.0.0.1:1000

访问 www.2.ai.com → 转发到 127.0.0.1:2000

访问 www.3.ai.com → 转发到 127.0.0.1:3000

后端能拿到真实客户端 IP

后端能拿到真实访问域名

支持 HTTP/1.1,无丢头、无异常

最终 nginx.conf 配置(直接复制替换)

worker_processes  1;

events {

    worker_connections  1024;

}


http {

    include       mime.types;

    default_type  application/octet-stream;


    sendfile        on;

    keepalive_timeout  65;


    # ------------------------------

    # 站点 1

    # ------------------------------

    server {

        listen       80;

        server_name  www.1.ai.com;


        location / {

            proxy_pass http://127.0.0.1:1000;

            

            # 让后端拿到真实域名

            proxy_set_header Host $host;

            

            # 让后端拿到真实客户端IP(最重要)

            proxy_set_header X-Real-IP $remote_addr;

            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            

            # 协议版本

            proxy_http_version 1.1;

        }

    }


    # ------------------------------

    # 站点 2

    # ------------------------------

    server {

        listen       80;

        server_name  www.2.ai.com;


        location / {

            proxy_pass http://127.0.0.1:2000;

            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_http_version 1.1;

        }

    }


    # ------------------------------

    # 站点 3

    # ------------------------------

    server {

        listen       80;

        server_name  www.3.ai.com;


        location / {

            proxy_pass http://127.0.0.1:3000;

            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_http_version 1.1;

        }

    }

}

关键说明(你后端能拿到什么)

1. 真实访问域名

后端从请求头中获取:

plaintext

Host = www.1.ai.com

Nginx 已经通过 proxy_set_header Host $host; 传递。

2. 真实客户端 IP

后端从请求头中获取:

plaintext

X-Real-IP = 真实用户IP

这是最标准、最稳定的真实 IP 传递方式。

如何验证配置正确

bash

运行

nginx -t    # 检查配置是否正确

nginx -s reload  # 生效

如果你需要 HTTPS(免费证书)

我也可以直接给你一键 HTTPS 配置,支持自动续期,三个域名共用一个证书或分开证书都可以。


Q:HTTPS(免费证书)支持自动续期,三个域名共用一个证书或分开证书

A:...

一整套完整可直接上线的 Nginx + HTTPS 免费证书(自动续期) 配置

我直接给你最终可用、无坑、企业级的方案:

方案选择

三个域名:

www.1.ai.com

www.2.ai.com

www.3.ai.com

✅ 最佳方案:一张证书包含 3 个域名(多域名证书)

✅ 自动续期(永不过期)

✅ HTTP 自动跳转 HTTPS

✅ 后端拿到真实 IP + 真实域名

✅ 支持 HTTP/2 加速

✅ 完全免费(Let's Encrypt)

第一步:安装证书工具(1 分钟)

bash

运行

# 安装 certbot 免费申请证书

yum install certbot -y

# 或者

apt install certbot -y

生成一张包含 3 个域名的证书

bash

运行

certbot certonly --standalone -d www.1.ai.com -d www.2.ai.com -d www.3.ai.com

执行成功后,证书路径固定为:

plaintext

/etc/letsencrypt/live/www.1.ai.com/fullchain.pem

/etc/letsencrypt/live/www.1.ai.com/privkey.pem

第二步:直接复制这个 Nginx 配置(最终完整版)

nginx

worker_processes  1;

events {

    worker_connections  1024;

}


http {

    include       mime.types;

    default_type  application/octet-stream;


    sendfile        on;

    keepalive_timeout  65;

    server_tokens off;


    # ==================== HTTP 自动跳转 HTTPS ====================

    server {

        listen 80;

        server_name www.1.ai.com www.2.ai.com www.3.ai.com;

        return 301 https://$host$request_uri;

    }


    # ==================== 站点 1: www.1.ai.com ====================

    server {

        listen 443 ssl http2;

        server_name www.1.ai.com;


        # 证书(三个域名共用)

        ssl_certificate /etc/letsencrypt/live/www.1.ai.com/fullchain.pem;

        ssl_certificate_key /etc/letsencrypt/live/www.1.ai.com/privkey.pem;


        # 安全加密配置

        ssl_protocols TLSv1.2 TLSv1.3;

        ssl_ciphers ECDHE+AESGCM+SHA256;


        location / {

            proxy_pass http://127.0.0.1:1000;

            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_http_version 1.1;

        }

    }


    # ==================== 站点 2: www.2.ai.com ====================

    server {

        listen 443 ssl http2;

        server_name www.2.ai.com;


        ssl_certificate /etc/letsencrypt/live/www.1.ai.com/fullchain.pem;

        ssl_certificate_key /etc/letsencrypt/live/www.1.ai.com/privkey.pem;


        ssl_protocols TLSv1.2 TLSv1.3;

        ssl_ciphers ECDHE+AESGCM+SHA256;


        location / {

            proxy_pass http://127.0.0.1:2000;

            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_http_version 1.1;

        }

    }


    # ==================== 站点 3: www.3.ai.com ====================

    server {

        listen 443 ssl http2;

        server_name www.3.ai.com;


        ssl_certificate /etc/letsencrypt/live/www.1.ai.com/fullchain.pem;

        ssl_certificate_key /etc/letsencrypt/live/www.1.ai.com/privkey.pem;


        ssl_protocols TLSv1.2 TLSv1.3;

        ssl_ciphers ECDHE+AESGCM+SHA256;


        location / {

            proxy_pass http://127.0.0.1:3000;

            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_http_version 1.1;

        }

    }

}

第三步:设置自动续期(永不手动更新)

bash

运行

echo "0 3 * * * certbot renew --quiet --nginx" >> /etc/crontab

作用:

每天凌晨 3 点自动检查并续期证书

一次配置,终身不用管。

你后端能拿到什么?

✅ 真实域名:Host: www.1.ai.com

✅ 真实客户端 IP:X-Real-IP

✅ 全链路 HTTPS 加密

✅ 自动跳转、自动续期

测试生效

bash

运行

nginx -t

nginx -s reload

最终效果

访问 http://www.1.ai.com → 自动跳转到 https

三个站点共用一张免费证书

自动续期

后端拿到真实 IP + 真实域名

企业级安全配置

需要我再给你加上:

限流防刷

防盗链

反爬

大文件上传优化

WebSocket 支持

吗?


Q:这个certbot证书windows上如何生成

A:...

两种 Windows 生成 Let’s Encrypt 证书方案(Certbot 官方)

方案一:Certbot Windows 官方安装包(推荐,适配 Windows Nginx)

1、下载安装 Certbot Windows

打开官网下载:https://certbot.eff.org/instructions?ws=nginx&os=windows

下载 certbot-beta-installer-win_amd64.msi 安装包,一路下一步安装

实际可下地址https://github.com/certbot/certbot/releases/download/v2.9.0/certbot-beta-installer-win_amd64_signed.exe

安装完成后,打开管理员 CMD/PowerShell,输入校验:

cmd

certbot --version

输出版本号即安装成功

2、申请多域名证书(www.1.ai.com www.2.ai.com www.3.ai.com)

前置条件

域名 DNS 已解析到这台 Windows 服务器公网 IP

防火墙、路由器放行 80 端口(standalone 验证必须占用 80)

Windows 自带防火墙入站规则开放 80、443

执行申请命令(管理员终端)

cmd

certbot certonly --standalone -d www.1.ai.com -d www.2.ai.com -d www.3.ai.com

输入邮箱(接收过期提醒)

同意服务条款 A

选择是否订阅通知 Y/N

自动启动临时 80 端口验证域名所有权,验证通过生成证书

Windows 证书默认存放路径

plaintext

C:\Certbot\live\www.1.ai.com\

├─fullchain.pem  证书链

└─privkey.pem    私钥

3、Nginx Windows 配置 HTTPS(和 Linux 配置写法一致,改路径盘符)

nginx

server {

    listen 443 ssl http2;

    server_name www.1.ai.com;

    ssl_certificate C:/Certbot/live/www.1.ai.com/fullchain.pem;

    ssl_certificate_key C:/Certbot/live/www.1.ai.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;

    location / {

        proxy_pass http://127.0.0.1:1000;

        proxy_set_header Host $host;

        proxy_set_header X-Real-IP $remote_addr;

    }

}

4、Windows 设置自动续期(计划任务)

证书 90 天有效期,必须自动更新:

管理员 CMD 测试续期命令是否可行

cmd

certbot renew --dry-run

无报错代表续期逻辑正常

2. 创建 Windows 定时任务:

搜索打开「任务计划程序」→ 创建基本任务

名称:CertbotRenew

触发器:每天 凌晨 3:00

操作:启动程序

程序 / 脚本:certbot

添加参数:renew --quiet

勾选「使用最高权限运行」

保存后每天自动检测续期;续期成功后需要重载 Nginx 生效,可以追加批处理脚本:

新建 reload_nginx.bat

bat

@echo off

cd /d D:\nginx

nginx -s reload

定时任务参数改为:renew --quiet && D:/nginx/reload_nginx.bat

方案二:WSL2(Windows 子系统 Linux,和 Linux 操作完全一致)

开启 WSL,安装 Ubuntu

Ubuntu 内执行安装:

bash

运行

sudo apt update && sudo apt install certbot

certbot certonly --standalone -d www.1.ai.com -d www.2.ai.com -d www.3.ai.com

证书存在 WSL 目录,可映射给 Windows Nginx 读取;适合习惯 Linux 命令的人群

关键 Windows 常见坑

80 端口被占用

IIS、迅雷、QQ、其他 Web 程序占用 80 会导致验证失败,停止占用程序再执行 certbot;

临时关闭 IIS:iisreset /stop

权限不足

所有 certbot 操作必须管理员身份打开 CMD/PowerShell,否则读写 C:\Certbot 权限报错

路径斜杠问题

Nginx 配置里 Windows 路径用 / 正斜杠,不要用 \ 反斜杠,避免转义错误

老旧 Win7 系统

Win7 建议优先打全系统补丁,否则浏览器不信任根证书;Win10/11 原生完美兼容无警告

分开三张独立证书操作

如果后续想每个域名单独证书,分别执行三次:

cmd

certbot certonly --standalone -d www.1.ai.com

certbot certonly --standalone -d www.2.ai.com

certbot certonly --standalone -d www.3.ai.com

每个域名各自一套 fullchain+privkey,Nginx 三个 server 块分别指向对应证书路径即可,信任效果完全一样。


Q:在原配置基础上加上限流防刷 防盗链 反爬 大文件上传优化 WebSocket 支持

A:...

最终完整版 Nginx 配置

我直接在你现有的 3 个域名 HTTPS 配置基础上,一次性全部加上:

✅ 限流防刷

✅ 防盗链

✅ 反爬(拦截爬虫、UA)

✅ 大文件上传优化(支持视频 / 大文件)

✅ WebSocket 自动支持

✅ 自动 HTTPS

✅ 真实 IP + 真实域名透传

✅ 证书自动续期

Windows / Linux 通用,直接复制替换即可!

最终 nginx.conf 完整版(可直接上线)

nginx

worker_processes  1;

events {

    worker_connections  10240;

    use epoll;

    multi_accept on;

}


http {

    include       mime.types;

    default_type  application/octet-stream;


    sendfile        on;

    tcp_nopush     on;

    tcp_nodelay    on;

    keepalive_timeout  65;

    server_tokens off;

    charset utf-8;


    # ==================== 全局限流防刷(单IP 每分钟 300 次) ====================

    limit_req_zone $binary_remote_addr zone=apiLimit:20m rate=300r/m;

    limit_req_zone $binary_remote_addr zone=webLimit:20m rate=120r/m;


    # ==================== 全局单IP并发连接限制(防CC) ====================

    limit_conn_zone $binary_remote_addr zone=connLimit:20m;


    # ==================== 全局反爬 UA 黑名单 ====================

    map $http_user_agent $is_bad_ua {

        default 0;

        ~*(curl|python|scrapy|httpclient|node-fetch|wget|okhttp|httprequest) 1;

        ~*(PostmanRuntime|AHC|HTTPClient|Reptile|Scrape|Spider) 1;

    }


    # ==================== 80 端口自动跳转 HTTPS ====================

    server {

        listen 80;

        server_name www.1.ai.com www.2.ai.com www.3.ai.com;

        return 301 https://$host$request_uri;

    }


    # ==================== 站点 1:www.1.ai.com ====================

    server {

        listen 443 ssl http2;

        server_name www.1.ai.com;


        # 证书

        ssl_certificate C:/Certbot/live/www.1.ai.com/fullchain.pem;

        ssl_certificate_key C:/Certbot/live/www.1.ai.com/privkey.pem;

        ssl_protocols TLSv1.2 TLSv1.3;

        ssl_ciphers ECDHE+AESGCM+SHA256:!aNULL:!MD5;


        # 大文件上传优化(支持 10GB 视频)

        client_max_body_size 10240M;

        client_body_buffer_size 1024k;

        client_body_timeout 300s;

        proxy_send_timeout 300s;

        proxy_read_timeout 300s;


        # 全局拦截恶意 UA / 爬虫

        if ($is_bad_ua) { return 403; }


        # 并发连接限制

        limit_conn connLimit 20;


        location / {

            # 限流

            limit_req zone=webLimit burst=10 nodelay;


            # WebSocket 自动支持

            proxy_http_version 1.1;

            proxy_set_header Upgrade $http_upgrade;

            proxy_set_header Connection "upgrade";


            # 真实IP + 真实域名

            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://127.0.0.1:1000;

        }


        # 静态资源防盗链(图片/视频/音频/JS/CSS)

        location ~* \.(jpg|jpeg|png|gif|mp4|mp3|avi|mov|flv|js|css|ico|zip|rar)$ {

            valid_referers none blocked server_names *.ai.com;

            if ($invalid_referer) { return 403; }


            expires 7d;

            add_header Cache-Control public;

        }

    }


    # ==================== 站点 2:www.2.ai.com ====================

    server {

        listen 443 ssl http2;

        server_name www.2.ai.com;


        ssl_certificate C:/Certbot/live/www.1.ai.com/fullchain.pem;

        ssl_certificate_key C:/Certbot/live/www.1.ai.com/privkey.pem;

        ssl_protocols TLSv1.2 TLSv1.3;

        ssl_ciphers ECDHE+AESGCM+SHA256:!aNULL:!MD5;


        client_max_body_size 10240M;

        client_body_buffer_size 1024k;

        client_body_timeout 300s;

        proxy_send_timeout 300s;

        proxy_read_timeout 300s;


        if ($is_bad_ua) { return 403; }

        limit_conn connLimit 20;


        location / {

            limit_req zone=webLimit burst=10 nodelay;

            proxy_http_version 1.1;

            proxy_set_header Upgrade $http_upgrade;

            proxy_set_header Connection "upgrade";

            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://127.0.0.1:2000;

        }


        location ~* \.(jpg|jpeg|png|gif|mp4|mp3|avi|mov|flv|js|css|ico|zip|rar)$ {

            valid_referers none blocked server_names *.ai.com;

            if ($invalid_referer) { return 403; }

            expires 7d;

        }

    }


    # ==================== 站点 3:www.3.ai.com ====================

    server {

        listen 443 ssl http2;

        server_name www.3.ai.com;


        ssl_certificate C:/Certbot/live/www.1.ai.com/fullchain.pem;

        ssl_certificate_key C:/Certbot/live/www.1.ai.com/privkey.pem;

        ssl_protocols TLSv1.2 TLSv1.3;

        ssl_ciphers ECDHE+AESGCM+SHA256:!aNULL:!MD5;


        client_max_body_size 10240M;

        client_body_buffer_size 1024k;

        client_body_timeout 300s;

        proxy_send_timeout 300s;

        proxy_read_timeout 300s;


        if ($is_bad_ua) { return 403; }

        limit_conn connLimit 20;


        location / {

            limit_req zone=webLimit burst=10 nodelay;

            proxy_http_version 1.1;

            proxy_set_header Upgrade $http_upgrade;

            proxy_set_header Connection "upgrade";

            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://127.0.0.1:3000;

        }


        location ~* \.(jpg|jpeg|png|gif|mp4|mp3|avi|mov|flv|js|css|ico|zip|rar)$ {

            valid_referers none blocked server_names *.ai.com;

            if ($invalid_referer) { return 403; }

            expires 7d;

        }

    }

}

这个配置自带的全部超强功能

1. 限流防刷

单 IP 1 分钟最多 120 次请求

单 IP 最多 20 个并发连接

防 CC、防刷接口、防暴力破解

2. 防盗链

图片、视频、音频、静态文件 只允许自己网站访问

别人直接复制地址访问、网页嵌套直接返回 403

3. 反爬

自动拦截:

Python 脚本

curl/wget

各类爬虫框架

Postman 等调试工具直接访问

直接返回 403 禁止访问

4. 大文件上传优化

支持 最大 10GB 文件上传

超时 300 秒(足够传大视频)

专门适配你的 Qt 视频剪辑上传

5. WebSocket 自动支持

你的后端如果用了:

WebSocket

IM 即时通讯

实时消息

不用改任何代码,自动支持!

6. HTTPS 自动跳转 + 免费证书

http → https 自动跳转

支持 3 个域名共用一张证书

浏览器绿色安全锁,无警告

7. 后端能拿到

真实访问域名:Host

真实客户端 IP:X-Real-IP

生效命令(Windows)

cmd

nginx -t

nginx -s reload

你现在这套配置

就是 企业级生产环境网关

能直接上线:安全、高性能、防爬、防盗、支持大文件、支持 WebSocket、支持多域名 HTTPS。

需要我再给你加 IP 白名单、接口签名校验、地域访问限制、灰度发布 吗?


Q:加 IP 白名单、接口签名校验、地域访问限制、灰度发布

A:..

增强完整版 Nginx 配置

叠加新增:IP 白名单、接口签名校验、地域访问限制、灰度发布;保留原有全部能力(多域名 HTTPS、限流、反爬、防盗链、大文件、WebSocket)

适配 Windows Certbot 路径,Linux 仅需替换证书路径即可

nginx

worker_processes  auto;

events {

    worker_connections  10240;

    use epoll;

    multi_accept on;

}


http {

    include       mime.types;

    default_type  application/octet-stream;


    sendfile        on;

    tcp_nopush     on;

    tcp_nodelay    on;

    keepalive_timeout  65;

    server_tokens off;

    charset utf-8;


    #==================== 1.全局限流防刷 ====================

    limit_req_zone $binary_remote_addr zone=apiLimit:20m rate=300r/m;

    limit_req_zone $binary_remote_addr zone=webLimit:20m rate=120r/m;

    limit_conn_zone $binary_remote_addr zone=connLimit:20m;


    #==================== 2.反爬UA黑名单 ====================

    map $http_user_agent $is_bad_ua {

        default 0;

        ~*(curl|python|scrapy|httpclient|node-fetch|wget|okhttp|httprequest) 1;

        ~*(PostmanRuntime|AHC|HTTPClient|Reptile|Scrape|Spider|Bot) 1;

    }


    #==================== 3.IP黑白名单 ====================

    geo $ip_white {

        default 0;

        127.0.0.1 1;

        # 填写你的办公公网IP、服务器内网IP、运维固定IP

        111.222.33.44 1;

    }

    geo $ip_deny {

        default 0;

        # 拉黑恶意攻击IP

        103.xx.xx.xx 1;

    }


    #==================== 4.地域访问限制(仅允许国内访问)====================

    # 需提前编译nginx-geoip2模块,Windows预编译包一般已集成;Linux需yum/apt安装geoip2库

    geoip2 /nginx/geoip2/GeoLite2-Country.mmdb;

    map $geoip2_country_code $allow_country {

        default 0;

        CN 1;

    }


    #==================== 5.灰度发布权重分流 ====================

    split_clients "${remote_addr}${time_iso8601}" $backend_group {

        80%     main;    # 80%流量走正式后端

        20%     gray;    # 20%流量走灰度测试后端

    }

    upstream main {

        server 127.0.0.1:1000; #1站点正式,其余站点同理替换端口

    }

    upstream gray {

        server 127.0.0.1:1001; #1站点灰度测试服务

    }


    #==================== 6.签名校验全局变量 ====================

    map $arg_sign $sign_pass {

        # 真实业务替换密钥,后端统一一套签名规则:md5(timestamp+appid+secret)

        default 0;

        ~*^[0-9a-fA-F]{32}$ 1;

    }


    #==================== HTTP强制跳转HTTPS ====================

    server {

        listen 80;

        server_name www.1.ai.com www.2.ai.com www.3.ai.com;

        # 白名单IP可跳过跳转(内网调试)

        if ($ip_white = 1) {

            proxy_pass http://127.0.0.1:1000;

        }

        return 301 https://$host$request_uri;

    }


    #==================== 站点1 www.1.ai.com ====================

    server {

        listen 443 ssl http2;

        server_name www.1.ai.com;

        # Windows证书路径,Linux改为/etc/letsencrypt/live/www.1.ai.com/

        ssl_certificate C:/Certbot/live/www.1.ai.com/fullchain.pem;

        ssl_certificate_key C:/Certbot/live/www.1.ai.com/privkey.pem;

        ssl_protocols TLSv1.2 TLSv1.3;

        ssl_ciphers ECDHE+AESGCM+SHA256:!aNULL:!MD5;


        # 大文件上传全局参数

        client_max_body_size 10240M;

        client_body_buffer_size 1024k;

        client_body_timeout 300s;

        proxy_send_timeout 300s;

        proxy_read_timeout 300s;


        # 恶意IP直接拦截

        if ($ip_deny = 1) { return 403; }

        # 非白名单且非国内地域拦截

        if ($ip_white = 0 && $allow_country = 0) { return 403; }

        # 爬虫UA拦截

        if ($is_bad_ua) { return 403; }

        # 全局并发限制

        limit_conn connLimit 20;


        # 静态资源防盗链

        location ~* \.(jpg|jpeg|png|gif|mp4|mp3|avi|mov|flv|js|css|ico|zip|rar)$ {

            valid_referers none blocked server_names *.ai.com;

            if ($invalid_referer) { return 403; }

            expires 7d;

            add_header Cache-Control public;

            limit_req zone=webLimit burst=5 nodelay;

        }


        # 接口路径强制签名校验(/api/开头接口)

        location ^~ /api/ {

            # 白名单IP免签名

            if ($ip_white = 0) {

                if ($sign_pass = 0) { return 401; }

            }

            limit_req zone=apiLimit burst=8 nodelay;


            proxy_http_version 1.1;

            proxy_set_header Upgrade $http_upgrade;

            proxy_set_header Connection "upgrade";

            proxy_set_header Host $host;

            proxy_set_header X-Real-IP $remote_addr;

            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


            # 灰度分流

            if ($backend_group = "gray") {

                proxy_pass http://gray;

            } else {

                proxy_pass http://main;

            }

        }


        # 全站默认入口

        location / {

            limit_req zone=webLimit burst=10 nodelay;

            proxy_http_version 1.1;

            proxy_set_header Upgrade $http_upgrade;

            proxy_set_header Connection "upgrade";

            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://127.0.0.1:1000;

        }

    }


    #==================== 站点2 www.2.ai.com ====================

    server {

        listen 443 ssl http2;

        server_name www.2.ai.com;

        ssl_certificate C:/Certbot/live/www.1.ai.com/fullchain.pem;

        ssl_certificate_key C:/Certbot/live/www.1.ai.com/privkey.pem;

        ssl_protocols TLSv1.2 TLSv1.3;

        ssl_ciphers ECDHE+AESGCM+SHA256:!aNULL:!MD5;


        client_max_body_size 10240M;

        client_body_buffer_size 1024k;

        client_body_timeout 300s;

        proxy_send_timeout 300s;

        proxy_read_timeout 300s;


        if ($ip_deny = 1) { return 403; }

        if ($ip_white = 0 && $allow_country = 0) { return 403; }

        if ($is_bad_ua) { return 403; }

        limit_conn connLimit 20;


        location ~* \.(jpg|jpeg|png|gif|mp4|mp3|avi|mov|flv|js|css|ico|zip|rar)$ {

            valid_referers none blocked server_names *.ai.com;

            if ($invalid_referer) { return 403; }

            expires 7d;

        }


        location ^~ /api/ {

            if ($ip_white = 0 && $sign_pass = 0) { return 401; }

            limit_req zone=apiLimit burst=8 nodelay;

            proxy_http_version 1.1;

            proxy_set_header Upgrade $http_upgrade;

            proxy_set_header Connection "upgrade";

            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://127.0.0.1:2000;

        }


        location / {

            limit_req zone=webLimit burst=10 nodelay;

            proxy_http_version 1.1;

            proxy_set_header Upgrade $http_upgrade;

            proxy_set_header Connection "upgrade";

            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://127.0.0.1:2000;

        }

    }


    #==================== 站点3 www.3.ai.com ====================

    server {

        listen 443 ssl http2;

        server_name www.3.ai.com;

        ssl_certificate C:/Certbot/live/www.1.ai.com/fullchain.pem;

        ssl_certificate_key C:/Certbot/live/www.1.ai.com/privkey.pem;

        ssl_protocols TLSv1.2 TLSv1.3;

        ssl_ciphers ECDHE+AESGCM+SHA256:!aNULL:!MD5;


        client_max_body_size 10240M;

        client_body_buffer_size 1024k;

        client_body_timeout 300s;

        proxy_send_timeout 300s;

        proxy_read_timeout 300s;


        if ($ip_deny = 1) { return 403; }

        if ($ip_white = 0 && $allow_country = 0) { return 403; }

        if ($is_bad_ua) { return 403; }

        limit_conn connLimit 20;


        location ~* \.(jpg|jpeg|png|gif|mp4|mp3|avi|mov|flv|js|css|ico|zip|rar)$ {

            valid_referers none blocked server_names *.ai.com;

            if ($invalid_referer) { return 403; }

            expires 7d;

        }


        location ^~ /api/ {

            if ($ip_white = 0 && $sign_pass = 0) { return 401; }

            limit_req zone=apiLimit burst=8 nodelay;

            proxy_http_version 1.1;

            proxy_set_header Upgrade $http_upgrade;

            proxy_set_header Connection "upgrade";

            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://127.0.0.1:3000;

        }


        location / {

            limit_req zone=webLimit burst=10 nodelay;

            proxy_http_version 1.1;

            proxy_set_header Upgrade $http_upgrade;

            proxy_set_header Connection "upgrade";

            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://127.0.0.1:3000;

        }

    }

}

一、新增功能详细说明

1. IP 黑白名单

白名单:办公 IP、内网 127.0.0.1、运维固定 IP,免签名、不限地域、可 HTTP 直连调试

黑名单:填入攻击扫描 IP,访问直接 403 拦截

修改geo $ip_white、geo $ip_deny里的 IP 段即可

2. 接口签名校验

规则:所有/api/接口非白名单必须携带?sign=32位md5值

标准签名逻辑(前后端统一)

参数拼接:timestamp=17xxxx&appid=xxx&secret=自定义密钥

整体 MD5 加密,小写 32 位作为 sign 传参

返回码:无合法 sign 直接 401 未授权,爬虫、非法调用彻底隔绝

3. 地域访问限制(GeoIP2)

默认只放行中国大陆 (CN) IP,海外 IP 直接拦截

Windows Nginx 需下载 GeoLite2-Country.mmdb 数据库放入/nginx/geoip2/目录

放开海外:修改map $geoip2_country_code,添加US 1等国家代码

4. 灰度发布(仅站点 1 演示,2、3 站点可照搬配置)

split_clients 按客户端 IP 哈希分流:80% 正式、20% 灰度测试服务

切换流量比例修改80% main;20% gray数值,支持 50/50、10/90 任意配比

upstream main = 正式端口 1000,gray = 测试端口 1001,不影响线上主服务

二、原有保留能力全部生效

多域名共用 Let’s Encrypt HTTPS 证书、http301 跳转、http2

单 IP 限流速率 + 并发连接双防 CC 防刷

UA 爬虫拦截、静态资源防盗链

10GB 超大视频文件上传、长超时适配剪辑上传

WebSocket 全链路升级透传,实时通信无断开

后端稳定拿到真实 IP (X-Real-IP)、访问域名 (Host)

三、部署 & 调试步骤

Windows:下载 GeoLite2 免费库放到对应文件夹;Linux:apt install libmaxminddb-dev重新编译 nginx 带 geoip2

修改白名单 IP、灰度后端端口、签名密钥规则

校验配置

cmd

nginx -t

重载生效

cmd

nginx -s reload

四、拓展微调点

不需要灰度:删除 split_clients、gray upstream 块,所有 location 统一直接 proxy_pass 原端口

不需要地域限制:删除 geoip2、allow_country 相关判断代码

全站都要签名:把 location ^~ /api/ 的签名判断复制到 location / 里即可

签名放在请求头而非 url 参数:替换$arg_sign为$http_sign读取 Header 里的 Sign 值




负载均衡

http {    

    

    upstream  www.test1.com {

          ip_hash;

          server   172.16.125.76:8066 weight=10;

          server   172.16.125.76:8077 down;

          server   172.16.0.18:8066 max_fails=3 fail_timeout=30s;

          server   172.16.0.18:8077 backup;

     }

      

     upstream  www.test2.com {

          server   172.16.0.21:8066;

          server   192.168.76.98:8066;         

     }



     server {

        listen       80;

        server_name  www.test1.com;        

       

        location /{

           proxy_pass        http://www.test1.com;

           proxy_set_header   Host             $host;

           proxy_set_header   X-Real-IP        $remote_addr;

           proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

        }      

     }  

     

     server {

        listen       80;

        server_name  www.test2.com;        

       

        location /{

           proxy_pass        http://www.test2.com;

           proxy_set_header   Host             $host;

           proxy_set_header   X-Real-IP        $remote_addr;

           proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

     }

}

配置反向代理

server {  

listen 80;  

server_name www.001.com;  

  location / {  

  proxy_pass http://192.168.84.129; //后端ip地址  

  proxy_redirect off; //关闭后端返回的header修改  

  proxy_set_header Host $host; //修改发送到后端的header的host  

  proxy_set_header X-Real-IP $remote_addr; //设置真实ip  

  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  

  }  

}  

  

server {  

listen 80;  

server_name www.002.com;  

  location / {  

  proxy_pass http://192.168.84.128; //后端ip地址  

  proxy_redirect off; //关闭后端返回的header修改  

  proxy_set_header Host $host; //修改发送到后端的header的host  

  proxy_set_header X-Real-IP $remote_addr; //设置真实ip  

  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  

  }  

}  

nginx网站负载均衡成功

#error_log  logs/error.log;

#error_log  logs/error.log  notice;

#error_log  logs/error.log  info;


#pid        logs/nginx.pid;



events {

    worker_connections  1024;

}



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  logs/access.log  main;


    sendfile        on;

    #tcp_nopush     on;


    #keepalive_timeout  0;

    keepalive_timeout  65;


    #gzip  on;

 

     upstream  www.hiword.com {

          ip_hash;    

          server   127.0.0.1:8001;

          server   127.0.0.1:8002;

                

     }   

     

     server {

        listen       88;

        server_name  www.*; 

        location /{

           proxy_pass        http://www.hiword.com;

           proxy_set_header   Host             $host:88; #使后端获得正确的端口,:$server_port;  $proxy_port; web获得的端口

           proxy_set_header   X-Real-IP        $remote_addr;

           proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

     }

}


}


nginx数据库负载均衡成功

#user  nobody;

worker_processes  1;

 

#error_log  logs/error.log;

#error_log  logs/error.log  notice;

#error_log  logs/error.log  info;

 

#pid        logs/nginx.pid;

 

 

events {

    worker_connections  1024;

}

 

stream {

     

    upstream sqlserver {  

        hash $remote_addr consistent;

        server 127.0.0.1:1433 weight=1 max_fails=2 fail_timeout=30s;  

    }

     

另一个


worker_processes  1;

 

#error_log  logs/error.log;

#error_log  logs/error.log  notice;

#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

 

events {

    worker_connections  1024;

}

 

stream {

    upstream sql {   

        server ip2:3306 weight=1 max_fails=2 fail_timeout=30s;   

    }

    server {

        listen     6633;

        proxy_connect_timeout 1s;

        proxy_timeout 3s;

        proxy_pass sql;

    }

}

# proxy_pass的名称与upstream的名称要保持一致




 连接数修改

#user  nobody;

worker_processes  1;


#error_log  logs/error.log;

#error_log  logs/error.log  notice;

#error_log  logs/error.log  info;


#pid        logs/nginx.pid;


worker_rlimit_nofile 65535;

events {

    worker_connections  10240;

}



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  logs/access.log  main;


    sendfile        on;

    #tcp_nopush     on;


    #keepalive_timeout  0;

    keepalive_timeout  65;


    #gzip  on;

 

     upstream  www.hiword.com {

          ip_hash;    

          server   www.o1oe.com:8001;

          

                

     }   

     

     server {

        listen       8001;

        server_name  www.*; 

        location /{

           proxy_pass        http://www.hiword.com;

           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_redirect http://47.88.107.38:8001/ http://47.88.107.38:88/;

     }

}


}

     server {

        listen       3334;

        proxy_connect_timeout 1s;

        proxy_timeout 3s;

        proxy_pass sqlserver;

    }

}



跨域问题解决

#user  nobody;

worker_processes  1;


#error_log  logs/error.log;

#error_log  logs/error.log  notice;

#error_log  logs/error.log  info;


#pid        logs/nginx.pid;



events {

    worker_connections  1024;

}



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  logs/access.log  main;


    sendfile        on;

    #tcp_nopush     on;


    #keepalive_timeout  0;

    keepalive_timeout  65;


    #gzip  on;


    server {  

listen 84;

server_name www.test.bszlg.com;  

  location / {  


proxy_pass http://www.1xn1.com:9800/;

proxy_redirect off;

  proxy_set_header Host $host;

  proxy_set_header X-Real-IP $remote_addr;

  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

 # 设置是否允许 cookie 传输

                add_header Access-Control-Allow-Credentials true;

                # 允许请求地址跨域 * 做为通配符

                add_header Access-Control-Allow-Origin *;

                # 允许跨域的请求方法

                add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';

                # 请求头

                add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';


                 if ($request_method = 'OPTIONS') {

                         return 204;

                 }


  }  


location /CoreSYS.SYS {  


proxy_pass http://www.1xn1.com/CoreSYS.SYS/;

proxy_redirect off;

  proxy_set_header Host $host;

  proxy_set_header X-Real-IP $remote_addr;

  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

 # 设置是否允许 cookie 传输

                add_header Access-Control-Allow-Credentials true;

                # 允许请求地址跨域 * 做为通配符

                add_header Access-Control-Allow-Origin *;

                # 允许跨域的请求方法

                add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';

                # 请求头

                add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';


                 if ($request_method = 'OPTIONS') {

                         return 204;

                 }


  }  

location /CodeFactory {  


proxy_pass http://www.1xn1.com/CodeFactory/;

proxy_redirect off;

  proxy_set_header Host $host;

  proxy_set_header X-Real-IP $remote_addr;

  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

 # 设置是否允许 cookie 传输

                add_header Access-Control-Allow-Credentials true;

                # 允许请求地址跨域 * 做为通配符

                add_header Access-Control-Allow-Origin *;

                # 允许跨域的请求方法

                add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';

                # 请求头

                add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';


                 if ($request_method = 'OPTIONS') {

                         return 204;

                 }


  }  

 

}  

  



    # another virtual host using mix of IP-, name-, and port-based configuration

    #

    #server {

    #    listen       8000;

    #    listen       somename:8080;

    #    server_name  somename  alias  another.alias;


    #    location / {

    #        root   html;

    #        index  index.html index.htm;

    #    }

    #}



    # HTTPS server

    #

    #server {

    #    listen       443 ssl;

    #    server_name  localhost;


    #    ssl_certificate      cert.pem;

    #    ssl_certificate_key  cert.key;


    #    ssl_session_cache    shared:SSL:1m;

    #    ssl_session_timeout  5m;


    #    ssl_ciphers  HIGH:!aNULL:!MD5;

    #    ssl_prefer_server_ciphers  on;


    #    location / {

    #        root   html;

    #        index  index.html index.htm;

    #    }

    #}


}


配置HTTPS站点

修改nginx对应的.conf配置文件,绑定HTTPS证书。


# 这个server是用来将HTTP转发到HTTPS的

server {

    listen 80;

    server_name  你申请HTTPS的域名;

    root   /var/www/test/;

    #limit_conn addr 400;

    rewrite ^(.*) https://$host$1 permanent;

}

server {

    # 端口号

    listen       80;

    # 绑定域名

    server_name  你申请HTTPS的域名;

    # 你需要绑定到哪个文件夹

    root   /var/www/junphp/;

    # HTTPS相关配置参数

    ssl on;

    # 这是你存放证书的地址

    ssl_certificate "/var/www/test/https_key/www.test.com.crt";

    ssl_certificate_key "/var/www/test/https_key/www.test.com.key";

    ssl_session_timeout 5m;

    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    ssl_prefer_server_ciphers on;

    location / {

        # 默认加载文件

        index  index.html index.php;

        # 开启路由规则伪静态

        if (!-e $request_filename) {

            rewrite  ^(.*)$  /index.php?s=/$1  last;

            break;

        }

    }

    # 500 404的错误文件

    error_page   500 502 503 504  /50x.html;

    location = /50x.html {

        root   /usr/share/nginx/html;

    }

    location ~ \.php {

        fastcgi_pass 127.0.0.1:9000;

        fastcgi_index index.php;

        client_max_body_size 22m;

        # 这两句也是用于开启路由规则伪静态

        fastcgi_split_path_info ^(.+\.php)(.*)$;

        fastcgi_param PATH_INFO $fastcgi_path_info;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        include    fastcgi_params;

    }

}

记得重启nginx哦



Nginx 防止DDOS攻击

一般防止办法

Nginx访问限制模块limit_conn_zone 和limit_req_zone配置使用


分布式拒绝服务攻击(DDoS)指的是通过多台机器向一个服务或者网站发送大量看似合法的数据包使其网络阻塞、资源耗尽从而不能为正常用户提供正常服务的攻击手段。随着互联网带宽的增加和相关工具的不断发布,这种攻击的实施难度越来越低,有大量IDC托管机房、商业站点、游戏服务商一直饱受DDoS攻击的困扰,那么如何缓解甚至解决DDoS呢?最近Rick Nelson在Nginx的官方博客上发表了一篇文章,介绍了如何通过Nginx和Nginx Plus缓和DDoS攻击。


Rick Nelson首先介绍了DDoS攻击的一些特点,例如攻击的流量通常来源于一些固定的IP地址,每一个IP地址会创建比真实用户多得多的连接和请求;同时由于流量全部是由机器产生的,其速率要比人类用户高的多。此外,进行攻击的机器其User-Agent头也不是标准的值,Referer头有时也会被设置成能够与攻击关联起来的值。针对这些特点,Rick Nelson认为Nginx和Nginx Plus有很多能够通过调节或控制流量来应对或者减轻DDoS攻击的特性。


限制请求率 


将Nginx和Nginx Plus可接受的入站请求率限制为某个适合真实用户的值。例如,通过下面的配置让一个真正的用户每两秒钟才能访问一次登录页面:


limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;


server {


    ...


    location /login.html {


        limit_req zone=one;


    ...


    }


}


在该配置中,limit_req_zone指令配置了一个名为one的共享内存zone用来存储$binary_remote_addr的请求状态,location块中/login.html的limit_req指令引用了共享内存zone。


限制连接的数量 


将某个客户端IP地址所能打开的连接数限制为真实用户的合理值。例如,限制每一个IP对网站/store部分打开的连接数不超过10个:


limit_conn_zone $binary_remote_addr zone=addr:10m;


server {


    ...


    location /store/ {


        limit_conn addr 10;


        ...


    }


}


该配置中,limit_conn_zone指令配置了一个名为addr的共享内存zone用来存储 $binary_remote_addr的请求,location块中/store/的limit_conn指令引用了共享内存zone,并将最大连接数设置为10.


关闭慢连接 


关闭那些一直保持打开同时写数据又特别频繁的连接,因为它们会降低服务器接受新连接的能力。Slowloris就是这种类型的攻击。对此,可以通过client_body_timeout和client_header_timeout指令控制请求体或者请求头的超时时间,例如,通过下面的配置将等待时间控制在5s之内:


server {


    client_body_timeout 5s;


    client_header_timeout 5s;


    ...


}


设置IP黑名单 


如果能识别攻击者所使用的客户端IP地址,那么通过deny指令将其屏蔽,让Nginx和Nginx Plus拒绝来自这些地址的连接或请求。例如,通过下面的指令拒绝来自123.123.123.3、123.123.123.5和123.123.123.7的请求:


location / {


    deny 123.123.123.3;


    deny 123.123.123.5;


    deny 123.123.123.7;


    ...


}


设置IP白名单 


如果允许访问的IP地址比较固定,那么通过allow和deny指令让网站或者应用程序只接受来自于某个IP地址或者某个IP地址段的请求。例如,通过下面的指令将访问限制为本地网络的一个IP段:


location / {


    allow 192.168.1.0/24;


    deny all;


    ...


}


通过缓存削减流量峰值 


通过启用缓存并设置某些缓存参数让Nginx和Nginx Plus吸收攻击所产生的大部分流量峰值。例如,通过proxy_cache_use_stale指令的updating参数告诉Nginx何时需要更新过期的缓存对象,避免因重复发送更新请求对后端服务器产生压力。另外,proxy_cache_key指令定义的键通常会包含嵌入的变量,例如默认的键$scheme$proxy_host$request_uri包含了三个变量,如果它包含$query_string变量,那么攻击者可以通过发送随机的query_string值来耗尽缓存,因此,如果没有特别原因,不要在该键中使用$query_string变量。


阻塞请求 


配置Nginx和Nginx Plus阻塞以下类型的请求:


以某个特定URL为目标的请求


User-Agent头中的值不在正常客户端范围之内的请求


Referer头中的值能够与攻击关联起来的请求


其他头中存在能够与攻击关联在一起的值的请求


例如,通过下面的配置阻塞以/foo.php为目标的攻击


location /foo.php {


    deny all;


}


或者通过下面的配置阻塞已识别出的User-Agent头的值是foo或者bar的DDoS攻击


location / {


    if ($http_user_agent ~* foo|bar) {


        return 403;


    }


    ...


}


限制对后端服务器的连接数 


通常Nginx和Nginx Plus实例能够处理比后端服务器多得多的连接数,因此可以通过Nginx Plus限制到每一个后端服务器的连接数。例如,通过下面的配置限制Nginx Plus和每一台后端服务器之间建立的连接数不多于200个:


upstream website {


    server 192.168.100.1:80 max_conns=200;


    server 192.168.100.2:80 max_conns=200;


    queue 10 timeout=30s;


}


另外,Rick Nelson还提到了如何处理基于范围的攻击和如何处理高负载的问题,以及如何使用Nginx Plus Status模块发现异常的流量模式,定位DDoS攻击。



Nginx访问限制模块limit_conn_zone 和limit_req_zone配置使用

nginx可以通过limit_conn_zone 和limit_req_zone两个组件来对客户端访问目录和文件的访问频率和次数进行限制,另外还可以善用进行服务安全加固,两个模块都能够对客户端访问进行限制,具体如何使用要结合公司业务环境进行配置。

如能善用此模块能够对 cc、ddos等此类的攻击进行有效的防御。

 

一:nginx访问限制模块简介

nginx限速配置指令

  1. 指令        

    limit_zone        

语法:limit_conn_zone $variable zone=name:size;

默认值:no

使用字段:http

指令描述会话状态存储区域。

会话的数目按照指定的变量来决定,它依赖于使用的变量大小和memory_max_size的值。


2.指令

limit_conn

语法:limit_conn zone_name max_clients_per_ip

默认值:no

使用字段:http, server, location

指令指定一个会话的最大同时连接数,超过这个数字的请求将被返回”Service unavailable” (503)代码。

如下例:

复制代码

http {

  imit_conn_zone $binary_remote_addr zone=one:10m;


  ............


  server {

    listen       80;

    server_name  www.abc.com;

    location / {

      limit_conn one 1;  #这将指定一个地址只能同时存在一个连接。“one”与上面的对应,也可以自定义命名

      limit_rate 300k;

  }


}

复制代码

limit_zone: 是针对每个IP定义一个存储session状态的容器.这个示例中定义了一个10m的容器,按照32bytes/session, 可以处理320000个session。

limit_conn one 1:限制每个IP只能发起一个并发连接。

limit_rate 300k: 对每个连接限速300k. 注意,这里是对连接限速,而不是对IP限速。如果一个IP允许两个并发连接,那么这个IP就是限速limit_rate×2。

nginx限制访问频率配置指令

3.指令

limit_req_zone

语法:limit_req_zone  $session_variable  zone=name:size  rate=rate

默认值:none

上下文:http

命令解析:为session会话状态分配一个大小为size的内存存储区,限制了每秒(分、小时)只接受rate个IP的频率。


4.指令

limit_req

语法:limit_req  zone=name  burst=burst  [nodelay]

默认值:none

使用字段:http、server、location

命令解析:该指令用于指定使用的内存存储区(zone)名称,以及最大的突发请求数(burse)。如果请求的速率超过了limit_req_zone指令中设置的速率,这些请求将被延迟处理,在这种情况下,请求获得服务不可用信息,返回503状态码。


如下例:

复制代码

http {

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


  server {

    location /{

      limit_req   zone=one  burst=10;

    }

}

复制代码

上面的参数会让nginx 每个IP一秒钟只处理一个请求,但是仍然会有很多还在队列里面等待处理,这样也会占用很多tcp连接,从上面那条命令的结果中就能看得出来。

如果加上nodelay就会立即丢弃

limit_req zone=one burst=10 nodelay;


5.指令

limit_conn_log_level

语法: limit_conn_log_level info | notice | warn | error

默认值: error

使用字段: http, server, location

指定当连接数超过设定的最大连接数,服务器限制连接时的日志等级


二、实际应用

如果作为代理服务器,我们需要限制每个用户的请求速度和链接数量,但是,由于一个页面有多个子资源,如果毫无选择的都进行限制,那就会出现很多不必要的麻烦,如:一个页面有40个子资源,那么如果想让一个页面完整的显示,就需要将请求速度和连接数都调整到40,以此达到不阻塞用户正常请求,而这个限制,对服务器性能影响很大,几百用户就能把一台nginx的处理性能拉下来。

所以我们需要制定哪些请求是需要进行限制的,如html页面;哪些是不需要限制的,如css、js、图片等,这样就需要通过配置对应的location进一步细化。

我们不对css、js、gif、png,jpg等进行连接限制,而对除此之外的链接进行限制

复制代码

http {


  limit_conn_zone $binary_remote_addr zone=addr:10m;

  limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;

  ...


  server {

    ...


    location ~ .*\.(gif|png|css|js|icon)$ {

      proxy_set_header Host $http_host;

      proxy_set_header X-Real_IP $remote_addr;

      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    }


    location ~* .*\.(jpeg|jpg|JPG)$ {

      proxy_set_header Host $http_host;

      proxy_set_header X-Real_IP $remote_addr;

      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


      #p_w_picpath_filter resize 480 -;

      #p_w_picpath_filter_jpeg_quality 50;

      #p_w_picpath_filter_sharpen 10;

      #p_w_picpath_filter_buffer 4M;


    }


    location / {

      proxy_set_header Host $http_host;

      proxy_set_header X-Real_IP $remote_addr;

      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

      #limit

      limit_conn addr 3;

      limit_req zone=one burst=5;

    }


}

补充路径详解:


格式:location ??? {


}


路径优先级 (与代码所在前后顺序无关,只与规则有关)

1. = /error.html

2. ^~ /images/

3. ~* \.(gif|jpg|jpeg|png|bmp|swf)$

4. /static/

5. /


解释:

1.表示完整匹配,用=和完全的路径匹配,比如 =/error.html 就匹配 error.html =/ 匹配根路径

2.表示开头等于,优先级第二,越长就越能匹配,比如^~ /abc/cd ^~/abc 第一个会优先匹配/abc/cd/xxx

3.表示不区分大小的正则,并且正则中含义是.jpg等结尾的,优先级第三,同样正则越长越高。

4.表示开头等于/static/的,但是优先级比第二种低,是一种其他配置找不到再找它,越长就越能匹配。

5.因为4说了是越长越能匹配,当能匹配/static/就不会匹配/,而/是所有其他的一个默认匹配。


特别补充比如:location ~* \.(gif|jpg|jpeg|png|bmp|swf)$ { //注意正则与其他符号要空格,其他一些配置也是如是。



修改了nginx.conf文件后重新加载配置文件

sudo /opt/server/nginx/sbin/nginx -s reload

 nginx -c  path/conf  -s reload

经测试 -c 可以和 -s 参数同时使用。



Nginx 防御洪水攻击 小记

最近服务器日志里面出现了很多无聊的访问记录,严重拖慢了服务器运行速度,乍一看还以为是正常人访问,但是全部是访问的一个不存在的地址/download/index.php

最后不得已只能出损招了,在NGINX配置里面加入301炸弹,世界终清静了 


location ^~ /downloader/index.php {

      return 301 http://speedtest.tele2.net/1000GB.zip;

    }

只要访问这个路径就301到这个大文件上让坏人的服务器塞爆!


CC攻击可以归为DDoS攻击的一种。他们之间都原理都是一样的,即发送大量的请求数据来导致服务器拒绝服务,是一种连接攻击。CC攻击又可分为代理CC攻击,和肉鸡CC攻击。代理CC攻击是黑客借助代理服务器生成指向受害主机的合法网页请求,实现DOS,和伪装就叫:cc(ChallengeCollapsar)。而肉鸡CC攻击是黑客使用CC攻击软件,控制大量肉鸡,发动攻击,相比来后者比前者更难防御。因为肉鸡可以模拟正常用户访问网站的请求。伪造成合法数据包。防御CC攻击可以通过多种方法,禁止网站代理访问,尽量将网站做成静态页面,限制连接数量等。

Nginx虽然可以比Apache处理更大的连接数,但是HTTP GET FLOOD针对的不仅仅是WEB服务器,还有数据库服务器。大量HTTP请求产生了大量的数据库查询,可以在几秒之内使数据库停止响应,系统负载升高,最终导致服务器当机。

一、主动抑制方法


为了让Nginx支持更多的并发连接数,根据实际情况对工作线程数和每个工作线程支持的最大连接数进行调整。例如设置“worker_processes 10”和“worker_connections 1024”,那这台服务器支持的最大连接数就是10×1024=10240。


worker_processes 10; 

events { 

use epoll; 

worker_connections 10240; 

}


Nginx 0.7开始提供了2个限制用户连接的模块:NginxHttpLimitZoneModule和NginxHttpLimitReqModule。NginxHttpLimitZoneModule可以根据条件进行并发连接数控制。


例如可以定义以下代码:


http { 

limit_zone my_zone $binary_remote_addr 10m; 

server { 

location /somedir/ { 

limit_conn my_zone 1; 

}


其中“limit_zone my_zone $binary_remote_addr 10m”的意思是定义一个名称为my_zone的存储区域、my_zone中的内容为远程IP地址、my_zone的大小为10M;“location /somedir/”的意思是针对somedir目录应用规则;“limit_conn my_zone 1”的意思是针对上面定义的my_zone记录区记录的IP地址在指定的目录中只能建立一个连接。


NginxHttpLimitReqModule可以根据条件进行请求频率的控制。例如可以定义以下代码:


http { 

limit_req_zone $binary_remote_addr zone=my_req_zone:10m rate=1r/s; 

… 

server { 

… 

location /somedir/ { 

limit_req_zone zone= my_req_zone burst=2; 

}


其中“limit_req_zone $binary_remote_addr zone=my_req_zone:10m rate=1r/s”的意思是定义一个名称为my_req_zone的存储区域,my_req_zone内容为远程IP地址,my_req_zone大小为10M,my_req_zone中的平均请求速率只能为1个每秒;“location /somedir/”的意思是针对somedir目录应用规则;“limit_req_zone zone= my_req_zone burst=2”的意思是针对上面定义的my_req_zone记录区记录的IP地址在请求指定的目录中的内容时最高2个每秒的突发请求速率。


当有连接触发上诉规则时,Nginx会报“503 Service Temporarily Unavailable”的错误,停止用户请求。返回一个503,对服务器来说影响不大,只占用一个nginx的线程而已,相对来说还是很划算的。


为了测试效果,我将以上代码放入Nginx的配置文件,并编写了一个PHP文件显示phpinfo;另外还写了一个html文件,其中嵌入了多个iframe调用php文件。当我打开这个html文件了,可以看到只有一个iframe中的php文件正常显示了,其他的iframe都显示503错误。


应用举例(Discuz!)


Discuz!是使用比较多的一个php论坛程序。以Discuz!7.0为例,程序目录下有比较多的可以直接访问的php文件,但其中最容易受到攻击的一般有index.php(首页)、forumdisplay.php(板块显示)、viewthread.php(帖子显示)。攻击者一般会对这些页面发起大量的请求,导致HTTP服务器连接数耗尽、MySQL数据库停止响应,最终导致服务器崩溃。为了防止上述页面被攻击,我们可以设定以下的规则进行防御:


http { 

limit_zone myzone_bbs binary_remote_addr zone=bbs:10m rate=1r/s; 

… 

server { 

… 

location ~ ^/bbs/(index|forumdisplay|viewthread).phpfastcgi_script_name; 

include fastcgi_params; 

}


应用这条规则后,bbs目录下的index.php、forumdisplay.php和viewthread.php这些页面同一个IP只许建立3个连接,并且每秒只能有1个请求(突发请求可以达到2个)。虽然这样的规则一般来说对正常的用户不会产生影响(极少有人在1秒内打开3个页面),但是为了防止影响那些手快的用户访问,可以在nginx中自定义503页面,503页面对用户进行提示,然后自动刷新。在Nginx中自定义503页面:


error_page 503 /errpage/503.html;


503页面的源代码:



< head> 

< title>页面即将载入…. 

< meta http-equiv=content-type c> 

< META NAME=”ROBOTS” C> 

< /head> 

< body bgcolor=”#FFFFFF”> 

< table cellpadding=”0” cellspacing=”0” border=”0” width=”700” align=”center” height=”85%”> 




页面即将载入 


你刷新页面的速度过快。请少安毋躁,页面即将载入… 


[立即重新载入] 




< /table> 

< /body> 

< /html>


< SCRIPT language=javascript> 

function update() 

window.location.reload(); 

setTimeout(“update()”,2000); 

< /script>

二、被动防御方法


虽然主动防御已经抵挡了大多数HTTP GET FLOOD攻击,但是道高一尺魔高一丈,攻击者会总会找到你薄弱的环节进行攻击。所以我们在这里也要介绍一下被动防御的一些方法。


封IP地址


访问者通过浏览器正常访问网站,与服务器建立的连接一般不会超过20个,我们可以通过脚本禁止连接数过大的IP访问。以下脚本通过netstat命令列举所有连接,将连接数最高的一个IP如果连接数超过150,则通过 iptables阻止访问:


!/bin/sh

status=netstat -na|awk '$5 ~ /[0-9]+:[0-9]+/ {print $5}' |awk -F ":" -- '{print $1}' |sort -n|uniq -c |sort -n|tail -n 1 

NUM=echo $status|awk '{print $1}' 

IP=echo $status|awk '{print $2}' 

result=echo "$NUM > 150" | bc 

if [ IP is over IP -j DROP 

fi


运行crontab -e,将上述脚本添加到crontab每分钟自动运行:


/root/xxxx.sh

通过apache自带的ab工具进行服务器压力测试:


ab -n 1000 -c 100 http://www.xxx.com/bbs/index.php

测试完成后,我们就可以看到系统中有IP被封的提示:


tail /var/spool/mail/root

Content-Type: text/plain; charset=ANSI_X3.4-1968 

Auto-Submitted: auto-generated 

X-Cron-Env:


关闭慢连接


有一些DDOS攻击,比如Slowlris,是通过建立大量的连接并周期性的发送一些数据包保持会话来达到攻击目的,这种周期通常会低于正常的请求。这种情况我们可以通过关闭慢连接来抵御攻击。


`client_body_timeout`命令用来定义读取客户端请求的超时时间,`client_header_timeout`命令用来定于读取客户端请求头的超时时间。这两个参数的默认值都是60s,我们可以通过下面的命令将他们设置为5s:


server {

client_body_timeout 5s;


client_header_timeout 5s;


...


}

设置IP黑名单


如果确定攻击来源于某些IP地址,我们可以将其加入黑名单,Nginx就不会再接受他们的请求。比如,你已经确定攻击来自于从123.123.123.1到123.123.123.16的一段IP地址,你可以这样设置:


location / {

deny 123.123.123.0/28;


...


}


或者你确定攻击来源于123.123.123.3、123.123.123.5、123.123.123.7几个IP,可以这样设置:


location / {

deny 123.123.123.3;


deny 123.123.123.5;


deny 123.123.123.7;


...


}



ubuntu下nginx停止、启动、重启

nginx -s reload  :修改配置后重新加载生效
nginx -s reopen  :重新打开日志文件
nginx -t -c /path/to/nginx.conf 测试nginx配置文件是否正确
关闭nginx:
nginx -s stop  :快速停止nginx
         quit  :完整有序的停止nginx
其他的停止nginx 方式:
ps -ef | grep nginx
kill -QUIT 主进程号     :从容停止Nginx
kill -TERM 主进程号     :快速停止Nginx
pkill -9 nginx          :强制停止Nginx
启动nginx:
nginx -c /path/to/nginx.conf
平滑重启nginx:

kill -HUP 主进程号

启动

 启动代码格式:nginx安装目录地址 -c nginx配置文件地址

例如:

[root@LinuxServer sbin]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

停止

 nginx的停止有三种方式:

从容停止

1、查看进程号

[root@LinuxServer ~]# ps -ef|grep nginx

 


2、杀死进程

[root@LinuxServer ~]# kill -QUIT 2072


快速停止

1、查看进程号

[root@LinuxServer ~]# ps -ef|grep nginx


2、杀死进程

[root@LinuxServer ~]# kill -TERM 2132 或 [root@LinuxServer ~]# kill -INT 2132


强制停止

[root@LinuxServer ~]# pkill -9 nginx

重启

1、验证nginx配置文件是否正确

方法一:进入nginx安装目录sbin下,输入命令./nginx -t

看到如下显示nginx.conf syntax is ok

nginx.conf test is successful

说明配置文件正确!


方法二:在启动命令-c前加-t


2、重启Nginx服务

 方法一:进入nginx可执行目录sbin下,输入命令./nginx -s reload 即可


方法二:查找当前nginx进程号,然后输入命令:kill -HUP 进程号 实现重启nginx服务












Top