0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Nginx的限流机制深度解析

马哥Linux运维 来源:马哥Linux运维 2026-04-10 16:40 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

引言:Nginx 不只是反向代理

很多运维工程师对 Nginx 的认知停留在"反向代理"和"负载均衡",但实际上 Nginx 在安全防护方面也相当强大——限流可以防止 CC 攻击和 API 滥用,黑白名单可以精准控制访问来源,基础安全配置可以防护常见的 Web 攻击。

这篇文章系统讲解 Nginx 的限流机制、黑白名单配置、以及生产环境推荐的安全配置,帮助你把 Nginx 打造成一道坚实的安全防线。

前置知识:Nginx 基础配置、HTTP 协议基础

实验环境:CentOS Stream 9 / Ubuntu 24.04 LTS,Nginx 1.26+

1 限流机制深度解析

1.1 限流的类型

Nginx 限流类型:
  │
  ├── 请求速率限制 (rate limiting)
  │  └── limit_req:限制每秒/每分钟请求数
  │
  ├── 并发连接限制 (connection limiting)
  │  └── limit_conn:限制单个 IP 的并发连接数
  │
  ├── 带宽限制 (bandwidth limiting)
  │  └── limit_rate:限制单连接传输速率
  │
  └── 白名单/黑名单 (access limiting)
    └── geo + map:基于 IP 的访问控制

1.2 限流算法原理

令牌桶算法(Token Bucket)

算法描述:
  - 桶中最多存放 N 个令牌
  - 每秒放入 R 个令牌
  - 每个请求消耗 1 个令牌
  - 桶满时,令牌溢出

示意图:

  令牌生成速率 R=10/秒
  桶容量 B=20

  时间 t=0: [桶满了]
        ┌─────┐
        │●●●●●│
        │●●●●●●●●●●●│ 20个
        │●●●●●●●●●●●●●●●│
        └─────┘

  时间 t=1: [消耗了10个,放入10个]
        ┌─────┐
        │●●●●●│
        │●●●●●●●│ 20个
        │●●●●●●●●●│
        └─────┘

漏桶算法(Leaky Bucket)

算法描述:
  - 请求以任意速率进入桶
  - 桶以固定速率漏水
  - 桶满时,新请求被拒绝

示意图:

  请求输入 (可变速率)   桶 (队列)    输出 (固定速率)

  ●●●●          ┌─────┐     ●
  ●●●●●●●●  ──────>   │ ● │ ──────> ●●●
              │ ●● │      ●●●
              │ ●●●│      ●●●●
              └─────┘
              (桶满则拒绝)

Nginxlimit_req使用令牌桶算法,limit_conn使用简单计数。

1.3 limit_req 配置详解

# /etc/nginx/nginx.conf

# 定义限流区域(共享内存)
# 语法:limit_req_zone key zone=name:size rate=rate;
# - key: 用于识别请求的变量(通常是 $binary_remote_addr)
# - zone: 区域名称和共享内存大小
# - rate: 速率(r/s 或 r/m)

limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/m;
limit_req_zone $binary_remote_addr zone=search_limit:10m rate=5r/s;

# 按服务器维度限流
limit_req_zone $server_name zone=server_limit:10m rate=1000r/s;

http {
  # 限流区域
  limit_req_zone $binary_remote_addr zone=global:100m rate=100r/s;

  server {
    listen 80;
    server_name example.com;

    # 全局限流
    limit_req zone=global burst=20 nodelay;

    # API 限流:每秒 10 请求,允许突发 50
    location /api/ {
      limit_req zone=api_limit burst=50 nodelay;
      proxy_pass http://backend;
    }

    # 登录限流:每分钟 1 次,防止暴力破解
    location /login {
      limit_req zone=login_limit burst=5 nodelay;
      limit_req_status 429; # 超限返回 429
      proxy_pass http://backend;
    }

    # 搜索限流:每秒 5 请求
    location /search {
      limit_req zone=search_limit burst=20 nodelay;
      proxy_pass http://backend;
    }
  }
}

1.4 突发与排队机制

# burst 参数详解
# burst=N: 允许 N 个请求排队
# nodelay: 不延迟排队请求,立即处理

# 示例 1:允许突发,不延迟
limit_req_zone $binary_remote_addr zone=test:10m rate=10r/s;
location / {
  limit_req zone=test burst=20 nodelay;
}
# 效果:允许最多 30 个请求同时处理(10 个正常 + 20 个突发)

# 示例 2:允许突发,延迟处理
location / {
  limit_req zone=test burst=20; # 超过 10r/s 的请求会延迟
}
# 效果:请求被延迟而不是拒绝,响应变慢但不返回错误

# 示例 3:不允许突发
location / {
  limit_req zone=test burst=0; # 严格按速率处理
}
# 效果:超过速率的请求直接拒绝

# 示例 4:delay 参数(延迟突发)
location / {
  limit_req zone=test burst=20 delay=10;
}
# 效果:前 10 个突发请求正常处理,后续请求延迟

1.5 limit_req 日志控制

# 限流日志配置
limit_req_log_level info warn error;

server {
  listen 80;
  server_name example.com;

  # 设置返回状态码
  limit_req_status 503;

  location /api/ {
    limit_req zone=api_limit burst=50 nodelay;
    # 触发限流时记录 warn 级别日志
    proxy_pass http://backend;
  }
}

2 限并发(limit_conn)配置

2.1 并发连接限制原理

# 定义并发限制区域
# 语法:limit_conn_zone key zone=name:size;

limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn_zone $server_name zone=server_conn:10m;

server {
  listen 80;
  server_name example.com;

  # 限制单个 IP 最多 10 个并发连接
  limit_conn addr 10;

  # 限制整个服务器最多 1000 个并发连接
  limit_conn server_conn 1000;

  # 设置返回状态码
  limit_conn_status 503;

  location / {
    proxy_pass http://backend;
  }
}

2.2 针对特定资源的并发限制

# 下载站点并发限制
server {
  listen 80;
  server_name download.example.com;

  # 整体并发限制
  limit_conn addr 100;

  location /download/ {
    # 下载目录限制为 5 个并发
    limit_conn addr 5;
    limit_conn_status 503;

    alias /var/www/download/;
    autoindex on;
  }

  location /video/ {
    # 视频限制为 2 个并发(节省带宽)
    limit_conn addr 2;
    limit_conn_status 503;

    alias /var/www/video/;
  }
}

2.3 带宽限制

server {
  listen 80;
  server_name example.com;

  location / {
    proxy_pass http://backend;
  }

  # 限制下载速度(字节/秒)
  # 这里 500k = 512000 bytes/s
  location /download/ {
    alias /var/www/download/;
    limit_rate_after 10m; # 前 10MB 不限速
    limit_rate 500k;    # 之后限速 500KB/s
  }

  # 根据状态限制速度
  map $status $limit_rate {
    200   1m;   # 成功响应限速 1MB/s
    302   5m;   # 重定向限速 5MB/s
    default 500k;  # 其他情况限速 500KB/s
  }

  location /video/ {
    alias /var/www/video/;
    limit_rate $limit_rate;
  }
}

3 黑白名单配置

3.1 基于 IP 的访问控制

server {
  listen 80;
  server_name example.com;

  # 基本deny/allow 语法(旧方法,按顺序匹配)
  # 注意:旧方法按顺序匹配,匹配到就停止

  # 允许内网,deny 其他所有
  allow 10.0.0.0/8;
  allow 172.16.0.0/12;
  allow 192.168.0.0/16;
  deny all;

  # 或者反过来:拒绝某些IP
  deny 192.168.1.100;
  deny 192.168.1.200;
  allow all;

  location / {
    proxy_pass http://backend;
  }
}

3.2 geo 模块实现动态黑白名单

# geo 模块:根据 IP 地址映射值
geo $geo {
  default    0;

  # 白名单
  10.0.0.0/8   1;
  172.16.0.0/12 1;
  192.168.0.0/16 1;

  # 黑名单(高风险 IP)
  192.168.1.100 2;
  192.168.1.200 2;

  # 特定 IP
  1.2.3.4    0;  # 明确放行
  5.6.7.8    99;  # 明确拒绝
}

server {
  listen 80;
  server_name example.com;

  # 黑名单直接拒绝
  if ($geo = 99) {
    return 403;
  }

  # 白名单特殊处理
  if ($geo = 1) {
    # 内网用户不限流
    set $limit_rate 0;
  }

  location / {
    # 黑名单用户限制
    if ($geo = 2) {
      limit_rate 10k;
    }

    proxy_pass http://backend;
  }
}

3.3 map 模块实现复杂规则

# map 模块:根据变量值映射到另一个值

# 定义 IP 名单文件
map $remote_addr $ip_whitelist {
  default     0;
  include     /etc/nginx/whitelist.conf;
}

map $remote_addr $ip_blacklist {
  default     0;
  include     /etc/nginx/blacklist.conf;
}

map $request_uri $rate_limit {
  default                 100r/s;
  ~* ^/api/v1/login           1r/m;
  ~* ^/api/v1/search           5r/s;
  ~* ^/admin               10r/s;
}

server {
  listen 80;
  server_name example.com;

  # 黑名单拒绝
  if ($ip_blacklist = 1) {
    return 403;
  }

  # 限流
  limit_req_zone $binary_remote_addr zone=api:10m rate=$rate_limit;

  location / {
    limit_req zone=api burst=50 nodelay;
    proxy_pass http://backend;
  }
}

3.4 维护模式实现

# 维护模式配置

map $ Maintenance_mode $limit {
  default 0;
  on   99; # 维护模式返回 99,即无限流
}

geo $whitelist {
  default     0;
  # 允许运维人员 IP 访问
  10.0.1.0/24   1;
  192.168.1.100  1;
}

server {
  listen 80;
  server_name example.com;

  # 维护开关(可通过 API 或文件控制)
  set $maintenance false;
  # 或者从文件读取
  # set_from_config_file $maintenance /var/www/maintenance.flag;

  # 白名单在维护模式下仍可访问
  if ($whitelist = 1) {
    set $maintenance false;
  }

  if ($maintenance = true) {
    return 503;
  }

  location / {
    proxy_pass http://backend;
  }

  # 503 错误时显示维护页面
  error_page 503 @maintenance;
  location @maintenance {
    root /var/www/html;
    rewrite ^(.*)$ /maintenance.html break;
    internal;
  }
}

4 黑白名单文件管理

4.1 名单文件格式

# /etc/nginx/whitelist.conf 格式
# 每行一个 IP 或网段
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
203.0.113.0/24
123.45.67.89

# /etc/nginx/blacklist.conf 格式
# 被禁止的 IP
192.168.1.100
10.10.10.50
123.123.123.123

# 也可以是网段
192.168.100.0/24

4.2 动态更新名单脚本

#!/bin/bash
# update_blacklist.sh - 自动更新黑名单

BLACKLIST_FILE="/etc/nginx/blacklist.conf"
BLACKLIST_URL="https://api.example.com/blacklist/ipv4"

# 备份当前黑名单
cp"$BLACKLIST_FILE""${BLACKLIST_FILE}.bak"

# 下载新黑名单
curl -s"$BLACKLIST_URL">"$BLACKLIST_FILE"

# 检查文件是否有效
if[ $? -eq 0 ] && [ -s"$BLACKLIST_FILE"];then
 # 测试 Nginx 配置
  nginx -t

 if[ $? -eq 0 ];then
   # 重新加载 Nginx
    nginx -s reload
   echo"$(date): 黑名单已更新"
 else
   # 恢复备份
    mv"${BLACKLIST_FILE}.bak""$BLACKLIST_FILE"
   echo"$(date): Nginx 配置测试失败,已恢复"
 fi
else
 echo"$(date): 下载失败,已恢复"
  mv"${BLACKLIST_FILE}.bak""$BLACKLIST_FILE"
fi
# 添加到 crontab
echo"*/5 * * * * /usr/local/bin/update_blacklist.sh">> /var/spool/cron/root

# 或者使用 systemd timer
cat > /etc/systemd/system/nginx-blacklist.service << 'EOF'
[Unit]
Description=Nginx Blacklist Update
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/update_blacklist.sh
EOF

cat > /etc/systemd/system/nginx-blacklist.timer << 'EOF'
[Unit]
Description=Nginx Blacklist Update Timer
Requires=nginx-blacklist.service

[Timer]
OnCalendar=*/5 * * * *
Persistent=true

[Install]
WantedBy=timers.target
EOF

sudo systemctl enable --now nginx-blacklist.timer

5 基础安全配置

5.1 隐藏版本号和指纹

server {
  listen 80;
  server_name example.com;

  # 隐藏 Nginx 版本号
  server_tokens off;

  # 隐藏 PHP 版本号(需在 php-fpm 配置)
  # /etc/php-fpm.d/www.conf
  # php_admin_value[expose_php] = off

  # 自定义响应头
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-Frame-Options "SAMEORIGIN" always;
  add_header X-XSS-Protection "1; mode=block" always;
  add_header Referrer-Policy "no-referrer-when-downgrade" always;
  add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;

  # 移除暴露信息的响应头
  proxy_set_header X-Powered-By "";
  proxy_set_header X-AspNetMvc-Version "";

  location / {
    proxy_pass http://backend;
  }
}

5.2 防止常见攻击

# 防止 SQL 注入
if ($query_string ~* "union.*select.*(") {
  return 403;
}

# 防止 XSS
if ($query_string ~* "

5.3 HTTPS 安全配置

server {
  listen 443 ssl http2;
  server_name example.com;

  # SSL 证书
  ssl_certificate /etc/nginx/ssl/example.com.crt;
  ssl_certificate_key /etc/nginx/ssl/example.com.key;

  # TLS 版本控制(禁用 SSLv3 和 TLS 1.0/1.1)
  ssl_protocols TLSv1.2 TLSv1.3;

  # 密码套件配置
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers off;

  # OCSP Stapling
  ssl_stapling on;
  ssl_stapling_verify on;
  resolver 8.8.8.8 8.8.4.4 valid=300s;
  resolver_timeout 5s;

  # SSL 会话缓存
  ssl_session_cache shared10m;
  ssl_session_timeout 1d;
  ssl_session_tickets off;

  # HSTS (HTTP Strict Transport Security)
  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

  # 安全头部
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-Frame-Options "SAMEORIGIN" always;
  add_header X-XSS-Protection "1; mode=block" always;
  add_header Referrer-Policy "no-referrer-when-downgrade" always;

  # SSL 证书安全检查(定期执行)
  # openssl s_client -connect example.com:443 -tls1_2
}

# HTTP 重定向到 HTTPS
server {
  listen 80;
  server_name example.com;
  return 301 https://$server_name$request_uri;
}

5.4 请求大小和超时控制

http {
  # 请求体大小限制(默认 1M)
  client_max_body_size 10m;
  client_body_buffer_size 128k;

  # 请求头大小限制
  large_client_header_buffers 4 8k;

  # 超时设置
  client_body_timeout 15s;
  client_header_timeout 15s;
  send_timeout 30s;

  # 保持连接
  keepalive_timeout 65;
  keepalive_requests 100;

  server {
    listen 80;
    server_name example.com;

    # 上传目录特殊限制
    location /upload {
      client_max_body_size 100m;
      client_body_timeout 300s;
    }
  }
}

6 CC 攻击防护实战

6.1 CC 攻击识别

#!/bin/bash
# detect_cc.sh - 检测 CC 攻击

LOG_FILE="/var/log/nginx/access.log"
THRESHOLD=100 # 单 IP 每分钟请求数阈值

echo"=== CC 攻击检测 ==="

# 统计最近 1 分钟每个 IP 的请求数
awk -vlimit=$THRESHOLD'{
  ip[$1]++
  time[$1, $4]++
}
END {
  for (key in time) {
    split(key, parts, SUBSEP)
    if (time[key] > limit) {
      print parts[1], "请求数:", time[key]
    }
  }
}'"$LOG_FILE"| sort | uniq

echo""
echo"=== 短时间高频请求 TOP 20 ==="
awk'{print $1}'"$LOG_FILE"| sort | uniq -c | sort -rn | head -20

echo""
echo"=== 响应码分布 ==="
awk'{print $9}'"$LOG_FILE"| sort | uniq -c | sort -rn

6.2 CC 攻击防护配置

# CC 防护配置示例

# 1. 基础限流
limit_req_zone $binary_remote_addr zone=cc_protect:100m rate=100r/s;

# 2. 按 URI 限流(某些 URI 更容易被攻击)
limit_req_zone $binary_remote_addr zone=api_limit:50m rate=30r/s;
limit_req_zone $binary_remote_addr zone=search_limit:50m rate=5r/s;

# 3. 浏览器指纹验证
map $http_user_agent $is_bot {
  default             0;
  ~*python|curl|wget|scrapy   1;
  ~*bot|spider|crawl       2;
}

server {
  listen 80;
  server_name example.com;

  # User-Agent 过滤
  if ($is_bot = 1) {
    limit_req zone=cc_protect burst=10;
  }
  if ($is_bot = 2) {
    return 403;
  }

  # 动态限流(根据响应状态动态调整)
  limit_req_zone $binary_remote_addr zone=dynamic:50m rate=10r/s;

  # URI 限流
  location /api/ {
    limit_req zone=api_limit burst=50 nodelay;
    proxy_pass http://api_backend;
  }

  location /search {
    limit_req zone=search_limit burst=20 nodelay;
    proxy_pass http=backend;
  }

  # 静态资源允许较高并发
  location /static/ {
    limit_req zone=cc_protect burst=200 nodelay;
    proxy_pass http://static_backend;
    expires 7d;
    add_header Cache-Control "public, no-transform";
  }
}

6.3 自动封锁脚本

#!/bin/bash
# auto_block.sh - 自动封锁攻击 IP

LOG_FILE="/var/log/nginx/access.log"
BLACKLIST_FILE="/etc/nginx/blacklist.conf"
THRESHOLD=500 # 每分钟请求超过此值则封锁
WINDOW=1   # 时间窗口(分钟)

echo"$(date): 开始检测和封锁"

# 获取最近 N 分钟的高频 IP
CURRENT_MIN=$(date +"%d/%b/%Y:%H:%M")

# 使用 awk 统计并封锁
awk -vlimit=$THRESHOLD-v blacklist=$BLACKLIST_FILE'
BEGIN {
  # 读取现有黑名单
  while ((getline line < blacklist) > 0) {
    blocked[line] = 1
  }
  close(blacklist)
}

{
  ip = $1
  requests[ip]++
}

END {
  for (ip in requests) {
    if (requests[ip] > limit && !blocked[ip]) {
      print ip >> blacklist
      print "封锁 IP:", ip, "请求数:", requests[ip]
      system("nginx -t && nginx -s reload")
    }
  }
}
'"$LOG_FILE"

echo"$(date): 检测完成"

7 综合配置示例

7.1 生产环境完整配置

# /etc/nginx/nginx.conf

user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;

error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;

events {
  worker_connections 10240;
  use epoll;
  multi_accept on;
}

http {
  include    /etc/nginx/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" '
          'rt=$request_time uct="$upstream_connect_time" '
          'uht="$upstream_header_time" urt="$upstream_response_time"';

  access_log /var/log/nginx/access.log main buffer=16k flush=5s;

  # 性能优化
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  keepalive_timeout 65;
  keepalive_requests 1000;
  types_hash_max_size 2048;

  # 安全头部
  server_tokens off;
  add_header X-Frame-Options "SAMEORIGIN" always;
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-XSS-Protection "1; mode=block" always;

  # Gzip 压缩
  gzip on;
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

  # 限流区域定义
  limit_req_zone $binary_remote_addr zone=global:100m rate=100r/s;
  limit_req_zone $binary_remote_addr zone=api:50m rate=50r/s;
  limit_req_zone $binary_remote_addr zone=login:10m rate=1r/m;
  limit_req_zone $server_name zone=server_limit:100m rate=1000r/s;

  limit_conn_zone $binary_remote_addr zone=addr:50m;
  limit_conn_zone $server_name zone=server_conn:50m;

  # IP 名单
  geo $whitelist {
    default     0;
    10.0.0.0/8   1;
    172.16.0.0/12  1;
    192.168.0.0/16 1;
  }

  map $request_uri $rate_limit {
    default             50r/s;
    ~* ^/api/v1/login       1r/m;
    ~* ^/api/v1/search       10r/s;
    ~* ^/admin           10r/s;
    ~* ^/static          500r/s;
  }

  # 封禁 IP 列表
  map $remote_addr $is_blocked {
    default     0;
    include     /etc/nginx/blocked.conf;
  }

  # 上游服务器
  upstream backend {
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
    keepalive 32;
  }

  upstream api_backend {
    server 127.0.0.1:9000 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:9001 max_fails=3 fail_timeout=30s;
    keepalive 64;
  }

  server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    # 封禁 IP
    if ($is_blocked = 1) {
      return 403;
    }

    # 全局限流
    limit_req zone=global burst=200 nodelay;

    # 根路径
    location / {
      limit_req zone=api burst=100 nodelay;
      proxy_pass http://backend;
      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;
      proxy_set_header Connection "";
    }

    # API 接口
    location /api/ {
      limit_req zone=api burst=50 nodelay;
      limit_req_status 429;
      proxy_pass http://api_backend;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_http_version 1.1;
      proxy_set_header Connection "";
    }

    # 登录接口(严格限流)
    location /api/v1/login {
      limit_req zone=login burst=10 nodelay;
      limit_req_status 429;
      proxy_pass http://api_backend;
    }

    # 搜索接口
    location /api/v1/search {
      limit_req zone=api burst=30 nodelay;
      proxy_pass http://api_backend;
    }

    # 静态资源
    location /static/ {
      alias /var/www/static/;
      expires 7d;
      add_header Cache-Control "public, no-transform";
      limit_req zone=global burst=500 nodelay;
    }

    # 上传(严格限制大小和速度)
    location /upload {
      client_max_body_size 100m;
      client_body_timeout 300s;
      limit_req zone=login burst=5 nodelay;
      proxy_pass http://api_backend;
    }

    # 健康检查
    location /health {
      access_log off;
      return 200 "OK";
    }

    # 封禁敏感路径
    location ~ /. {
      deny all;
    }

    location ~ .(env|config|ini|log|sh|sql|conf|bak)$ {
      deny all;
    }

    # 错误页面
    error_page 429 /429.html;
    location = /429.html {
      root /usr/share/nginx/html;
    }

    error_page 502 503 504 /50x.html;
    location = /50x.html {
      root /usr/share/nginx/html;
    }
  }

  # HTTPS 配置
  server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared10m;
    ssl_session_timeout 1d;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # 引用 HTTP 配置
    # 使用 include 复用上述 server 块配置
    include /etc/nginx/conf.d/*.conf;
  }

  # HTTP 重定向到 HTTPS
  server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
  }
}

7.2 配置文件结构建议

# 推荐的文件结构
/etc/nginx/
├── nginx.conf       # 主配置
├── mime.types       # MIME 类型
├── conf.d/
│  ├── upstream.conf   # 上游服务器配置
│  ├── blacklist.conf   # 黑名单 IP
│  ├── whitelist.conf   # 白名单 IP
│  ├── blocked.conf    # 被封禁 IP
│  ├── rate_limit.conf  # 限流区域定义
│  ├── security.conf   # 安全配置
│  └── ssl.conf     # SSL 配置
└── ssl/
  ├── example.com.crt
  └── example.com.key

7.3 配置语法检查

#!/bin/bash
# test_nginx_config.sh - 验证 Nginx 配置

echo"=== Nginx 配置测试 ==="

# 测试主配置
nginx -t

if[ $? -eq 0 ];then
 echo""
 echo"=== 配置测试通过 ==="
 echo""
 echo"=== 正在检查常用配置 ==="

 # 检查语法错误
 echo"1. 检查 conf.d/*.conf"
 forfin/etc/nginx/conf.d/*.conf;do
   if[ -f"$f"];then
     echo"  文件:$(basename $f)"
   fi
 done

 # 检查 SSL 证书
 echo""
 echo"2. SSL 证书检查"
 if[ -f /etc/nginx/ssl/example.com.crt ];then
   echo"  证书:$(openssl x509 -in /etc/nginx/ssl/example.com.crt -noout -dates)"
 fi

 # 检查端口监听
 echo""
 echo"3. 端口监听检查"
  ss -tlnp | grep :80
  ss -tlnp | grep :443

 # 检查限流区域
 echo""
 echo"4. 限流区域"
  grep -E"limit_req_zone|limit_conn_zone"/etc/nginx/nginx.conf

 echo""
 echo"=== 所有检查完成 ==="
else
 echo"✗ 配置测试失败,请检查语法"
fi

8 监控与日志分析

8.1 限流统计

#!/bin/bash
# rate_limit_stats.sh - 限流统计

LOG_FILE="/var/log/nginx/error.log"

echo"=== Nginx 限流统计 ==="
echo""

# 统计限流次数
echo"[1] 限流触发次数(按类型]"
grep -c"limiting requests""$LOG_FILE"2>/dev/null ||echo"0"
grep -c"limiting connections""$LOG_FILE"2>/dev/null ||echo"0"

# 统计限流来源 TOP 10
echo""
echo"[2] 限流触发 TOP 10 IP"
grep"limiting requests""$LOG_FILE"2>/dev/null | 
  awk'{print $NF}'| 
  sed's/client: //'| 
  sort | uniq -c | sort -rn | head -10

# 统计被拒绝的 IP
echo""
echo"[3] 429 错误 TOP 10"
awk'$9 == "429" {print $1}'/var/log/nginx/access.log 2>/dev/null | 
  sort | uniq -c | sort -rn | head -10

# 统计 403 错误(可能被黑名单拦截)
echo""
echo"[4] 403 错误(可能拦截)TOP 10"
awk'$9 == "403" {print $1}'/var/log/nginx/access.log 2>/dev/null | 
  sort | uniq -c | sort -rn | head -10

# 统计限流原因
echo""
echo"[5] 限流原因分布"
grep"limiting requests""$LOG_FILE"2>/dev/null | 
  grep -oE'zone="[^"]+"'| 
  sort | uniq -c | sort -rn

8.2 Prometheus 指标

# Nginx 暴露 metrics(需要 nginx-module-vts 或 nginx-prometheus)
# 或者使用 access_by_lua 记录到 Prometheus

# 使用 Lua 模块记录指标
location /metrics {
  access_log off;
  # 限流指标
  limit_req_status 429;
  limit_conn_status 503;
}
# Prometheus 告警规则
groups:
-name:nginx_rate_limit_alerts
 rules:
  -alert:HighRateLimitRejections
   expr:|
     sum(rate(nginx_http_requests_total{status="429"}[5m]))
     / sum(rate(nginx_http_requests_total[5m])) * 100 > 10
   for:5m
   labels:
    severity:warning
   annotations:
    summary:"Nginx 限流拒绝率过高"
    description:"429 错误率超过 10%,当前值:{{ $value }}%"

  -alert:HighConnectionRejections
   expr:|
     sum(rate(nginx_http_requests_total{status="503"}[5m]))
     / sum(rate(nginx_http_requests_total[5m])) * 100 > 5
   for:5m
   labels:
    severity:critical
   annotations:
    summary:"Nginx 并发连接拒绝率过高"
    description:"503 错误率超过 5%,当前值:{{ $value }}%"

9 总结与检查清单

限流配置速查

# 限流区域定义
limit_req_zone $binary_remote_addr zone=name:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=name:10m;

# 应用限流
limit_req zone=name burst=20 nodelay;
limit_req_status 429;

# 应用并发限制
limit_conn name 10;
limit_conn_status 503;

# 带宽限制
limit_rate_after 10m;
limit_rate 500k;

黑白名单速查

# 基本 IP 控制
allow 10.0.0.0/8;
deny all;

# geo 模块
geo $geo {
  default 0;
  10.0.0.0/8 1;
}

# map 模块
map $remote_addr $is_blocked {
  default 0;
  include /etc/nginx/blacklist.conf;
}

安全配置速查

# 隐藏版本
server_tokens off;

# 安全头部
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=31536000" always;

# 防止敏感文件
location ~ /. { deny all; }
location ~ .(env|config|ini|log)$ { deny all; }

# HTTPS
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;

排查检查清单

#!/bin/bash
# nginx_security_check.sh - 安全配置检查

echo"=========================================="
echo"  Nginx 限流与安全配置检查"
echo"=========================================="

echo""
echo"[1] 限流配置检查"
grep -E"limit_req_zone|limit_conn_zone"/etc/nginx/nginx.conf

echo""
echo"[2] 限流应用检查"
grep -E"limit_req|limit_conn"/etc/nginx/nginx.conf | head -20

echo""
echo"[3] 安全头部检查"
grep -E"server_tokens|X-Frame|X-Content|X-XSS|Strict-Transport"/etc/nginx/nginx.conf

echo""
echo"[4] SSL/TLS 配置"
grep -E"ssl_protocols|ssl_ciphers"/etc/nginx/nginx.conf

echo""
echo"[5] 黑名单检查"
if[ -f /etc/nginx/blocked.conf ];then
 echo"已封锁 IP 数:$(wc -l < /etc/nginx/blocked.conf)"
    echo"最近封禁:"
    tail -5 /etc/nginx/blocked.conf
else
    echo"未配置黑名单文件"
fi

echo""
echo"[6] Nginx 版本"
nginx -v 2>&1

echo""
echo"[7] 配置语法测试"
nginx -t

echo""
echo"=========================================="

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 服务器
    +关注

    关注

    14

    文章

    10338

    浏览量

    91719
  • HTTP
    +关注

    关注

    0

    文章

    538

    浏览量

    35537
  • nginx
    +关注

    关注

    0

    文章

    193

    浏览量

    13198

原文标题:一次说清楚 Nginx 限流、黑白名单和基础安全配置

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    解析keepalived+nginx实现高可用方案技术

    之前讲了Nginx 如何实现负载均衡以及如何实现动静分离,实现系统的分布式部署,提高系统的并发性能。但是,有个问题:如果Nginx 系统挂了,整个系统就都不可用了。Nginx 处于整个系统非常重要
    的头像 发表于 09-30 15:52 4649次阅读
    <b class='flag-5'>解析</b>keepalived+<b class='flag-5'>nginx</b>实现高可用方案技术

    I2C通信设计深度解析

    I2C通信设计深度解析
    发表于 08-12 21:31

    深度解析Tengine的调试与资源监控方法论

    摘要: Tengine是由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,提供更强大的流量负载均衡能力、全站HTTPS服务、安全防攻击、链路追踪等众多高级特性。团队
    发表于 06-12 17:37

    AUTOSAR架构深度解析 精选资料推荐

    AUTOSAR架构深度解析本文转载于:AUTOSAR架构深度解析目录AUTOSAR架构深度解析A
    发表于 07-28 07:40

    AUTOSAR架构深度解析 精选资料分享

    AUTOSAR架构深度解析本文转载于:AUTOSAR架构深度解析AUTOSAR的分层式设计,用于支持完整的软件和硬件模块的独立性(Independence),中间RTE(Runtime
    发表于 07-28 07:02

    C语言深度解析

    C语言深度解析,本资料来源于网络,对C语言的学习有很大的帮助,有着较为深刻的解析,可能会对读者有一定的帮助。
    发表于 09-28 07:00

    一文知道Nginx服务器的缓存原理和机制

    Nginx服务器的缓存原理,是在学习过程中比较重要的一个知识点,学习通透之后,对于自己的能力会有不小的提升——而且提升不只限于nginx一方面,技术理论一通百通,对于理解其他内容也会有很大帮助。
    的头像 发表于 10-05 09:01 2973次阅读
    一文知道<b class='flag-5'>Nginx</b>服务器的缓存原理和<b class='flag-5'>机制</b>

    深度解析Asp.Net2.0中的Callback机制

    深度解析Asp.Net2.0中的Callback机制(ups电源技术维修)-该文档为深度解析Asp.Net2.0中的Callback
    发表于 09-27 16:28 1次下载
    <b class='flag-5'>深度</b><b class='flag-5'>解析</b>Asp.Net2.0中的Callback<b class='flag-5'>机制</b>

    Nginx如何监控

    搭建了Nginx集群后,需要继续深入研究的就是日常Nginx监控。
    的头像 发表于 08-22 10:03 2104次阅读

    限流方案常用算法 常用的限流方案

    需要注意的是借助Redis实现的限流方案可用于分布式系统,而guava实现的限流只能应用于单机环境。如果你觉得服务器端限流麻烦,可以在不改任何代码的情况下直接使用容器限流
    发表于 04-08 10:50 780次阅读

    搭建Keepalived+Lvs+Nginx高可用集群负载均衡

    nginx包,推荐使用稳定版本 2、上传nginx到linux系统 3、安装依赖环境 (1)安装gcc环境   yum install gcc-c++   (2)安装PCRE库,用于解析正则表达式   yum install 
    的头像 发表于 06-25 15:39 4403次阅读
    搭建Keepalived+Lvs+<b class='flag-5'>Nginx</b>高可用集群负载均衡

    Nginx 如何实现高性能低消耗

    Nginx具有丰富的模块库、灵活的配置、较低资源消耗等优点。下面,我们一起深入看一下Nginx的工作机制 1. Nginx 如何实现高性能低消耗的呢? 我们从以下几个方面说明以下:
    的头像 发表于 11-11 11:31 1294次阅读
    <b class='flag-5'>Nginx</b> 如何实现高性能低消耗

    Nginx核心功能深度解析

    Nginx核心功能深度解析
    的头像 发表于 05-09 10:50 984次阅读

    Nginx限流与防爬虫配置方案

    在互联网业务快速发展的今天,网站面临着各种流量冲击和恶意爬虫的威胁。作为运维工程师,我们需要在保证正常用户访问的同时,有效防范恶意流量和爬虫攻击。本文将深入探讨基于Nginx限流与防爬虫解决方案,从原理到实践,为大家提供一套完整的防护体系。
    的头像 发表于 09-09 15:52 1047次阅读

    Nginx中Master与Worker进程的工作机制

    Nginx是现代互联网架构中最常用的Web服务器和反向代理软件。很多运维工程师使用Nginx多年,却对其核心架构一知半解,配置优化时只会机械地调整几个参数。本文从Nginx进程模型出发,深入讲解worker进程的工作
    的头像 发表于 04-08 14:21 87次阅读