Nginx常规配置和日常排查记录

Nginx基本配置

server {
    listen [::]:443 ssl;
    server_name www.example.com;
  
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    #ssl安全配置
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers         AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
    #ssl缓存控制
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;
  
    location / {
        # 域名会解析到 /etc/hosts 中配置的 IPv4
        proxy_pass https://www.example.com;
  
        # 转发真实客户端 IP
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
  
    		# 连接超时控制
        proxy_connect_timeout  300s;
        proxy_send_timeout  300s;
        proxy_read_timeout  300s;

        # buffer控制
        proxy_buffering    off;
        proxy_buffer_size  512k;
        proxy_buffers 10  512k;
        client_max_body_size 100m;
  
        # SSL 配置
        proxy_ssl_server_name on;
        proxy_ssl_name www.example.com;
        proxy_ssl_verify off;
  
        # HTTP/1.1以及websocket支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

#均衡动态解析
http {
    # DNS 解析器
    resolver 8.8.8.8 114.114.114.114 valid=300s;
    resolver_timeout 5s;
  
    # 定义 upstream
    upstream backend_ipv4 {
        server 123.0.123.100:443;
        keepalive 32;
    }
}

server {
    listen [::]:443 ssl;
    server_name www.example.com;
  
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
  
    location / {
        proxy_pass https://backend_ipv4;
  
        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_set_header X-Forwarded-Proto $scheme;
  
        proxy_ssl_server_name on;
        proxy_ssl_name www.example.com;
        proxy_ssl_verify off;
  
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

#格式化日志,添加http_x_forwarded_for等记录真实客户端IP地址
http {
    log_format detailed '$remote_addr - $http_x_real_ip - $http_x_forwarded_for - '
                        '[$time_local] "$request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent"';
  
    access_log /var/log/nginx/access.log detailed;
}

配置生效和验证

#配置验证
# 1. 测试配置语法
nginx -t

# 2. 重载配置
nginx -s reload

# 3. 查看 Nginx 连接的后端
netstat -antp | grep nginx | grep ESTABLISHED
# 应该看到连接到后端 IPv4 地址

# 4. 查看日志
tail -f /var/log/nginx/access.log

简单的安全防护

  1. 禁止 curl/wget 访问

    # 完全禁止
    location / {
        if ($http_user_agent ~* (curl|wget|aria2|axel|thunder)) {
            return 403 "Download tools not allowed";
        }
    }
    
    # 只针对特定目录
    location ~* ^/images/ {
        if ($http_user_agent ~* (curl|wget)) {
            return 403;
        }
    }
    
  2. 配置限流

    http {
        # 定义限流区域
        limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
        limit_req_zone $binary_remote_addr zone=uploads:10m rate=2r/s;
        limit_conn_zone $binary_remote_addr zone=addr:10m;
    
        # 针对特定 User-Agent 限流
        map $http_user_agent $limit_bot {
            default "";
            ~*(curl|wget|python|scrapy|spider|bot) $binary_remote_addr;
        }
        limit_req_zone $limit_bot zone=bot_limit:10m rate=1r/m;
    }
    
    server {
        # 全局限流
        limit_req zone=general burst=20 nodelay;
        limit_conn addr 10;
    
        # 上传目录严格限流
        location ~* ^/images/ {
            limit_req zone=uploads burst=5 nodelay;
            limit_conn addr 3;
    
            # 如果检测到 bot
            if ($limit_bot) {
                limit_req zone=bot_limit burst=5;
            }
        }
    }
    
  3. 防盗链配置

    location ~* ^/images/ {
        # 白名单:只允许这些来源访问
        valid_referers none blocked server_names
                       *.example.com example.com;
    
        if ($invalid_referer) {
            return 403;
            # 或返回默认图片
            # rewrite ^(.*)$ /images/blocked.png last;
        }
    }
    
  4. 异常IP封禁-nginx

    # 创建黑名单文件
    cat > /etc/nginx/blocked_ips.conf << 'EOF'
    # 单个 IP
    deny 192.168.1.100;
    
    # IP 段
    deny 240e:abcd:1::/80;
    deny 192.168.1.0/24;
    EOF
    
    # 在 nginx.conf 中引入
    http {
        include /etc/nginx/blocked_ips.conf;
    }
    
  5. 异常IP封禁-iptables

    # 临时封禁(iptables)
    # IPv4
    iptables -I INPUT -s 192.168.1.100 -j DROP
    
    # IPv6
    ip6tables -I INPUT -s 240e:abcd::/80 -j DROP
    
    # 保存规则
    iptables-save > /etc/iptables/rules.v4
    ip6tables-save > /etc/iptables/rules.v6
    

日志解压命令

# 解压并删除原文件
gunzip access.log-20260109.gz

# 解压并保留原文件
gunzip -k access.log-20260109.gz

#直接读取压缩日志(推荐,不占用额外空间)
# 查看内容
zcat access.log-20260109.gz | less
# 统计 IP
zcat access.log-20260109.gz | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
# 统计流量
zcat access.log-20260109.gz | awk '{sum+=$10} END {printf "%.2f GB\n", sum/1024/1024/1024}'

基础统计

  1. 统计总请求数

    wc -l access.log
    #output
    #1862696 access.log
    
  2. 统计总流量

    awk '{sum+=$10} END {printf "total: %.2f GB\n", sum/1024/1024/1024}' access.log
    #output:
    #total: 193.13 GB
    
  3. 统计独立 IP 数

    awk '{print $1}' access.log | sort -u | wc -l
    #output:
    #44196
    

TOP统计

  1. Top 10 IP(按请求次数)

    awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
    #output:
     154909 240e:abcd::1
       1931 240e:abcd::2
       1639 240e:abcd::3
       1498 240e:abcd::4
       1473 240e:abcd::5
       1389 240e:abcd::6
       ......
    
  2. Top 10 IP(按流量大小)

    awk '{ip[$1]+=$10} END {for (i in ip) print ip[i], i}' access.log | sort -rn | head -10
    #output:
    796411613 240e:abcd::44
    792375868 240e:abcd::52
    751346929 240e:abcd::5a
    751345550 240e:abcd::4c
    748461146 240e:abcd::16
    739672668 240e:abcd::87
    738583393 240e:abcd::9a
    737849826 240e:abcd::4b
    721596446 240e:abcd::25
    714558631 240e:abcd::61
    
    #输出MB格式,方便看
    awk '{ip[$1]+=$10} END {for (i in ip) printf "%.2f MB %s\n", ip[i]/1024/1024, i}' access.log | sort -rn | head -10
    #output:
    759.52 MB 240e:abcd::44
    755.67 MB 240e:abcd::52
    716.54 MB 240e:abcd::5a
    716.54 MB 240e:abcd::4c
    713.79 MB 240e:abcd::16
    705.41 MB 240e:abcd::87
    704.37 MB 240e:abcd::9a
    703.67 MB 240e:abcd::4b
    688.17 MB 240e:abcd::25
    681.46 MB 240e:abcd::61
    
  3. Top 10 URL(按请求次数)

    awk '{print $7}' access.log | sort | uniq -c | sort -rn | head -10
    #output:
     213943 /
      66412 /index.html
      54921 /images/abcd.jpg
      54903 /Public/static/image/ico.png
      54138 /images/def.png
      54109 /images/bdbd.png
      53865 /images/cgdg.png
      45707 /favicon.ico
      42146 /images/d789.jpg
      41830 /images/f453.png
    
  4. Top 10 URL(按流量大小)

    awk '{url[$7]+=$10} END {for (i in url) print url[i], i}' access.log | sort -rn | head -10
    #output:
    21292890641 /images/2075bd6.png
    19957255430 /images/f01a7c57.jpg
    19638046038 /images/faa2ecb.jpg
    17732345455 /images/ad39ba8a.jpg
    14957439205 /images/71b8ee3b.png
    13954412826 /images/ad94b5d50.jpg
    12748310533 /images/cb1baf348.mp4
    12367313079 /images/d5852852c.jpg
    10047490169 /images/033ee9ddb.jpg
    9492413264 /images/465a04c.png
    
    #按照MB输出
    awk '{url[$7]+=$10} END {for (i in url) printf "%.2f MB %s\n", url[i]/1024/1024, i}' access.log | sort -rn | head -10
    #output:
    20306.48 MB /images/20s75bd6.png
    19032.72 MB /images/f01ga7c57.jpg
    18728.30 MB /images/faa2secb.jpg
    16910.88 MB /images/ad39vba8a.jpg
    14264.53 MB /images/71bs8ee3b.png
    13307.97 MB /images/ad94vb5d50.jpg
    12157.74 MB /images/cb1baaf348.mp4
    11794.39 MB /images/d58bv52852c.jpg
    9582.03 MB /images/033eec9ddb.jpg
    9052.67 MB /images/465ae04c.png
    
    #这里明显的问题就是这些图片资源访问流量较大
    

User-Agent 分析

  1. 统计 User-Agent 分布

    awk -F'"' '{print $6}' access.log | sort | uniq -c | sort -rn | head -20
    #output
    1057917 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36
     280104 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
     161409 curl/7.68.0
      66308 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
      60751 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36
      48489 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
      31229 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36
      27351 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
      23730 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36
      13357 Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
      11047 Mozilla/5.0 (Windows NT 10.0; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0
       8706 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Safari/537.36
       8615 Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
       7850 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36
       5843 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
       4608 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36
       4471 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
       4185 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 SLBrowser/9.0.6.8151 SLBChan/33 SLBVPV/64-bit
       3261 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36
       2560 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36
    
    #这里非常明显的反应curl的请求量巨大,说明有人在使用curl不间断的访问服务,甚至还有访问bot.html的,显然是爬虫
    
  2. 查找 curl 请求

    grep -F 'curl' access.log | wc -l
    #output
    161419
    
  3. curl 请求总流量

    grep -F 'curl' access.log | awk '{sum+=$10} END {printf "%.2f GB\n", sum/1024/1024/1024}'
    #output
    100.12 GB
    

时间维度分析

  1. 按小时统计流量

    awk '{
        match($4, /\[([^:]+):([^:]+)/, time)
        hour = time[1] " " time[2] ":00"
        traffic[hour] += $10
    } END {
        for (h in traffic) {
            printf "%s  %.2f GB\n", h, traffic[h]/1024/1024/1024
        }
    }' access.log | sort
    
    #output
    11/Jan/2026 03:00  3.15 GB
    11/Jan/2026 04:00  9.04 GB
    11/Jan/2026 05:00  9.04 GB
    11/Jan/2026 06:00  9.29 GB
    11/Jan/2026 07:00  8.79 GB
    11/Jan/2026 08:00  8.80 GB
    11/Jan/2026 09:00  9.18 GB
    11/Jan/2026 10:00  8.99 GB
    11/Jan/2026 11:00  9.04 GB
    11/Jan/2026 12:00  8.86 GB
    11/Jan/2026 13:00  9.01 GB
    11/Jan/2026 14:00  8.92 GB
    11/Jan/2026 15:00  9.07 GB
    11/Jan/2026 16:00  9.01 GB
    11/Jan/2026 17:00  8.93 GB
    11/Jan/2026 18:00  9.12 GB
    11/Jan/2026 19:00  9.35 GB
    11/Jan/2026 20:00  8.68 GB
    11/Jan/2026 21:00  9.26 GB
    11/Jan/2026 22:00  8.81 GB
    11/Jan/2026 23:00  9.00 GB
    12/Jan/2026 00:00  7.80 GB
    12/Jan/2026 01:00  2.00 GB
    
  2. 按分钟统计流量(精确定位峰值)

    # 统计 21 点每一分钟的流量
    grep "2026:21:" access.log | awk '{
        match($4, /2026:21:([0-9]{2})/, time)
        minute = time[1]
        traffic[minute] += $10
    } END {
        for (m in traffic) {
            printf "21:%s  %.2f MB\n", m, traffic[m]/1024/1024
        }
    }' | sort
    
    #output
    21:00  499.30 MB
    21:01  88.92 MB
    21:02  63.81 MB
    21:03  126.52 MB
    21:04  320.49 MB
    21:05  136.02 MB
    21:06  103.57 MB
    21:07  87.55 MB
    21:08  267.66 MB
    21:09  31.02 MB
    21:10  312.40 MB
    21:11  127.93 MB
    21:12  170.59 MB
    21:13  131.20 MB
    21:14  126.97 MB
    21:15  148.29 MB
    21:16  92.40 MB
    21:17  186.07 MB
    21:18  23.00 MB
    21:19  53.84 MB
    21:20  359.95 MB
    21:21  11.83 MB
    21:22  23.65 MB
    21:23  96.75 MB
    21:24  30.01 MB
    21:25  673.95 MB
    21:26  8.66 MB
    21:27  50.04 MB
    21:28  66.98 MB
    21:29  107.61 MB
    21:30  589.39 MB
    21:31  91.15 MB
    21:32  50.53 MB
    21:33  90.26 MB
    21:34  214.48 MB
    21:35  290.22 MB
    21:36  93.93 MB
    21:37  96.95 MB
    21:38  11.91 MB
    21:39  76.34 MB
    21:40  524.43 MB
    21:41  117.25 MB
    21:42  116.97 MB
    21:43  213.26 MB
    21:44  144.35 MB
    21:45  144.57 MB
    21:46  130.15 MB
    21:47  64.52 MB
    21:48  92.17 MB
    21:49  39.69 MB
    21:50  490.01 MB
    21:51  128.44 MB
    21:52  169.73 MB
    21:53  145.54 MB
    21:54  139.48 MB
    21:55  142.55 MB
    21:56  129.14 MB
    21:57  105.96 MB
    21:58  216.63 MB
    21:59  90.41 MB
    
  3. 查找流量最大的分钟

    awk '{
        match($4, /\[([^:]+):([^:]+):([^:]+)/, time)
        minute = time[1] ":" time[2] ":" time[3]
        traffic[minute] += $10
    } END {
        for (m in traffic) {
            printf "%s  %.2f GB\n", m, traffic[m]/1024/1024/1024
        }
    }' access.log | sort -k2 -rn | head -20
    
    #output
    11/Jan/2026:14:05  0.74 GB
    11/Jan/2026:12:15  0.74 GB
    11/Jan/2026:13:10  0.70 GB
    11/Jan/2026:20:30  0.69 GB
    11/Jan/2026:05:50  0.67 GB
    11/Jan/2026:21:25  0.66 GB
    11/Jan/2026:08:37  0.65 GB
    11/Jan/2026:15:00  0.62 GB
    11/Jan/2026:06:47  0.62 GB
    12/Jan/2026:00:19  0.60 GB
    11/Jan/2026:18:38  0.60 GB
    11/Jan/2026:11:19  0.60 GB
    11/Jan/2026:19:34  0.59 GB
    11/Jan/2026:19:00  0.59 GB
    11/Jan/2026:17:20  0.59 GB
    11/Jan/2026:23:30  0.58 GB
    11/Jan/2026:21:30  0.58 GB
    11/Jan/2026:10:27  0.58 GB
    11/Jan/2026:16:40  0.57 GB
    11/Jan/2026:15:30  0.57 GB
    
  4. 特定时间段分析

    TIME="11/Jan/2026:21:20"
    
    # 总流量
    grep "11/Jan/2026:21:20" access.log | \
    awk '{sum+=$10} END {printf "total: %.2f MB\n", sum/1024/1024}'
    
    # curl 流量
    grep "11/Jan/2026:21:20" access.log | grep -F 'curl' | \
    awk '{sum+=$10} END {printf "curl total: %.2f MB\n", sum/1024/1024}'
    

    异常流量识别

    1. 检查 IP 网段集中度
    awk '{
        split($1, ip, ":")
        if (length(ip) > 4) {
            # IPv6
            prefix = ip[1] ":" ip[2] ":" ip[3] ":" ip[4]
        } else {
            # IPv4
            split($1, ip, ".")
            prefix = ip[1] "." ip[2] "." ip[3]
        }
        segment[prefix]++
    } END {
        for (s in segment) {
            if (segment[s] > 10) {
                printf "%s.*  %d 个IP\n", s, segment[s]
            }
        }
    }' access.log | sort -k2 -rn | head -10
    
    #output
    240e:a0:abc.*  154909 个IP
    240e:de7:aa61:6.*  68883 个IP
    240e:de7:abc:7.*  58917 个IP
    240e:de7:abc:701.*  12888 个IP
    240e:de7:abc:9.*  11984 个IP
    240e:de7:abc:5.*  7068 个IP
    2409:adde:31a:124.*  6432 个IP
    240e:6ddd:abc0.*  3915 个IP
    240e:abcd:efee.*  1643 个IP
    
  5. 检查高频请求 IP(可能是爬虫)

    awk '{count[$1]++} END {
        for (ip in count) {
            if (count[ip] > 1000) {
                printf "%s  %d 次\n", ip, count[ip]
            }
        }
    }' access.log | sort -k10 -rn
    
    #output
    240e:abcd:defe:a36b  154909 次
    240e:eeee:abbf::1234  1114 次
    240e:eeee:abbf::5678  1498 次
    240e:cdef:a::20:307  1303 次
    2409:9527:bcdd:121::cc6a  1473 次
    2409:9527:abee:132::332  1389 次
    
  6. HTTP 状态码分布

    awk '{print $9}' access.log | \
    sort | uniq -c | sort -rn | \
    awk '{
        code = $2
        count = $1
        printf "状态码 %s: %d 次", code, count
        if (code ~ /^2/) print " 成功"
        else if (code ~ /^3/) print " 重定向"
        else if (code ~ /^4/) print " 客户端错误"
        else if (code ~ /^5/) print " 服务器错误"
        else print ""
    }'
    
    #output
    状态码 200: 1200076 次 成功
    状态码 499: 433061 次 客户端错误
    状态码 301: 128017 次 重定向
    状态码 502: 49484 次 服务器错误
    状态码 500: 42933 次 服务器错误
    状态码 302: 6366 次 重定向
    状态码 404: 1515 次 客户端错误
    状态码 206: 617 次 成功
    状态码 504: 274 次 服务器错误
    状态码 304: 239 次 重定向
    状态码 403: 103 次 客户端错误
    状态码 400: 3 次 客户端错误
    状态码 303: 3 次 重定向
    状态码 "-": 2 次
    状态码 ": 2 次
    状态码 Temporarily": 1 次
    

总结

以上都是一些常规的排查手段,适用于在发现流量异常以后快速定位问题。但这些都是属于后置分析了,安全防护还是得前置分析、安全过滤,再配合风控监控才能更好的保障网站安全。后置分析只是属于事后出问题的排查手段罢了。