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
简单的安全防护
-
禁止 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; } } -
配置限流
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; } } } -
防盗链配置
location ~* ^/images/ { # 白名单:只允许这些来源访问 valid_referers none blocked server_names *.example.com example.com; if ($invalid_referer) { return 403; # 或返回默认图片 # rewrite ^(.*)$ /images/blocked.png last; } } -
异常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; } -
异常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}'
基础统计
-
统计总请求数
wc -l access.log #output #1862696 access.log -
统计总流量
awk '{sum+=$10} END {printf "total: %.2f GB\n", sum/1024/1024/1024}' access.log #output: #total: 193.13 GB -
统计独立 IP 数
awk '{print $1}' access.log | sort -u | wc -l #output: #44196
TOP统计
-
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 ...... -
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 -
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 -
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 分析
-
统计 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的,显然是爬虫 -
查找 curl 请求
grep -F 'curl' access.log | wc -l #output 161419 -
curl 请求总流量
grep -F 'curl' access.log | awk '{sum+=$10} END {printf "%.2f GB\n", sum/1024/1024/1024}' #output 100.12 GB
时间维度分析
-
按小时统计流量
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 -
按分钟统计流量(精确定位峰值)
# 统计 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 -
查找流量最大的分钟
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 -
特定时间段分析
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}'异常流量识别
- 检查 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 -
检查高频请求 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 次 -
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 次
总结
以上都是一些常规的排查手段,适用于在发现流量异常以后快速定位问题。但这些都是属于后置分析了,安全防护还是得前置分析、安全过滤,再配合风控监控才能更好的保障网站安全。后置分析只是属于事后出问题的排查手段罢了。