找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1805

积分

0

好友

237

主题
发表于 14 小时前 | 查看: 4| 回复: 0

当你的 Nginx 服务器暴露在公网时,面临的威胁远比想象中复杂。从网络层的容量型 DDoS(如 UDP Flood、ICMP Flood),到更具迷惑性的应用层 CC 攻击(HTTP Flood),再到 OWASP Top 10 中的常客——SQL 注入、XSS、路径遍历,攻击面覆盖了从网络到应用的全栈。如何利用 Nginx 构建一道有效的防线?本文将从实战出发,为你梳理从基础安全加固到集成 ModSecurity WAF 的全套配置方案。

一、防护体系概述

1.1 威胁背景与分层防御

CC攻击(Challenge Collapsar)是当前最难防御的应用层攻击之一。攻击者模拟正常的 HTTP 请求,专门针对那些计算成本高的接口(如搜索、登录、生成验证码)发起海量并发,目的就是耗尽后端资源。它与 SYN Flood 不同,其流量在协议层完全“合法”,传统防火墙难以识别,必须在应用层实施精准的速率控制。

至于 SQL 注入、XSS 的危害已无需赘述。而路径遍历(../../../etc/passwd)和敏感文件泄露(.git/config.env)这类由配置疏忽导致的“低垂果实”,在实际渗透测试中命中率极高。

Nginx 作为市场占有率第一的 Web 服务器和反向代理,其自身的安全配置质量直接决定了服务的攻击面大小。其原生模块如 ngx_http_limit_req_module(限流)、ngx_http_limit_conn_module(限连接)、ngx_http_geo_module(地理位置)提供了基础的防护能力。结合功能强大的 ModSecurity 第三方 WAF,我们就能构建起一套分层、立体的应用层防护体系。

1.2 技术方案定位

需要明确的是,Nginx 原生安全能力与第三方 WAF 方案并非替代关系,而是互补和叠加。

  • Nginx原生模块 主要处理流量控制层的问题:连接数限制、请求速率限制、IP黑白名单、HTTP方法过滤。这些操作在请求进入上游(upstream)之前完成,性能开销极低,适合应对大规模流量冲击,是抵御 DDoS 和 CC 攻击的第一道闸门。
  • ModSecurity 3.0 则是真正的 WAF 引擎,工作在请求内容检测层:它会深度解析 HTTP 请求体,通过正则表达式等规则匹配来检测注入特征。OWASP Core Rule Set(CRS)提供了开箱即用的规则集,覆盖了 SQL 注入、XSS、远程/本地文件包含(RFI/LFI)、命令注入等主流攻击类型。

下表清晰展示了几种方案的定位差异:

方案 防护层次 性能影响 规则灵活性 适用场景
Nginx原生限流 流量控制层 极低(<1ms) 中等 大流量DDoS/CC防护
ModSecurity+CRS 内容检测层 中等(2-10ms) OWASP Top 10防护
Nginx geo模块 IP访问控制层 极低 地域封锁、IP黑名单
Lua/OpenResty 动态逻辑层 极高 复杂业务规则

1.3 适用场景与前置准备

这套组合拳非常适合以下场景:

  • 中小型WAF部署:对于流量峰值在10Gbps以下、并发连接数在10万以内的业务,Nginx + ModSecurity 完全有能力承载,无需采购昂贵的专用硬件WAF设备。
  • API网关防护:在微服务架构中,Nginx 常作为 API 网关。在此层面叠加 WAF 规则,可以在流量进入内部微服务网络之前完成安全过滤,避免攻击流量穿透。
  • 边缘安全节点:在 CDN 回源节点或边缘计算节点部署,可以在距离用户最近的位置完成流量清洗,有效降低源站压力。

开始前,请确保你的环境满足以下要求:

组件 版本要求 说明
操作系统 Ubuntu 22.04+ / CentOS Stream 8+ 推荐 Ubuntu 22.04 LTS
Nginx 1.26.x (mainline) / 1.24.x (stable) 需编译 --with-http_realip_module 等模块
ModSecurity 3.0.12+ 即 libmodsecurity3,需单独编译 Nginx 连接器
OWASP CRS 4.x 独立于 ModSecurity 版本的规则集
GeoIP2数据库 MaxMind GeoLite2 需注册免费账号获取 License Key
libmaxminddb 1.7.x+ GeoIP2 C 库依赖

二、详细配置步骤

2.1 基础安全加固:缩小攻击面

在部署高级功能前,先做好基础加固,这能有效阻挡大量自动化扫描和低级别攻击。

2.1.1 隐藏版本信息
默认配置下,Nginx 会在响应头中暴露具体版本号(如 Server: nginx/1.26.0),这无异于告诉攻击者该针对哪个版本的漏洞进行利用。

# /etc/nginx/nginx.conf - http 块全局配置
http {
    # 关闭版本号暴露
    server_tokens off;

    # 自定义 Server 头(需编译 headers-more-nginx-module 模块)
    more_set_headers 'Server: webserver';
    # 若无此模块,仅 server_tokens off 也已足够。切勿设置为其他真实服务器名(如 Apache),以免造成误导。
}

2.1.2 禁用不安全的 HTTP 方法
生产环境通常只需要 GET、POST、HEAD 三种方法。TRACE 方法存在跨站追踪(XST)风险,而 DELETE/PUT/PATCH 若后端鉴权不严,则直接暴露危险操作入口。

# /etc/nginx/conf.d/security.conf
server {
    # 采用白名单方式限制 HTTP 方法,比黑名单更安全。
    # 返回 444(Nginx 特有,直接关闭连接不发送响应)比 405 更节省资源。
    if ($request_method !~ ^(GET|POST|HEAD)$) {
        return 444;
    }

    # 如果是 API 服务器,可能需要额外允许 PUT、DELETE、PATCH
    # location /api/ {
    #     if ($request_method !~ ^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)$) {
    #         return 444;
    #     }
    # }
}

2.1.3 请求体限制与超时控制
这是防御慢速攻击(如 Slowloris、Slow POST)的关键。Slowloris 通过保持大量半开连接耗尽服务器的连接池,慢速 POST 则以极低速率发送请求体,长时间占用 worker 进程。

# /etc/nginx/nginx.conf
http {
    # 限制请求体大小,防止大文件上传攻击耗尽资源
    client_max_body_size 10m;

    # 读取请求头超时,防 Slowloris
    client_header_timeout 5s;
    # 读取请求体超时,防 Slow POST
    client_body_timeout 10s;
    # 发送响应超时,防客户端故意不接收响应
    send_timeout 10s;

    # 限制单个 keepalive 连接的请求数,防止攻击者用少量连接发起大量请求
    keepalive_requests 100;
    keepalive_timeout 65s;

    # 限制请求头缓冲区大小,超大请求头往往是攻击特征
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;
}

2.1.4 防止目录遍历与敏感文件泄露
这是渗透测试中最常见且最容易修复的漏洞之一。

# /etc/nginx/conf.d/security.conf
server {
    # 禁止访问所有隐藏文件(.git, .env, .htaccess 等)
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # 禁止访问备份文件、临时文件
    location ~* \.(bak|sql|tar|gz|zip|log|conf|ini|old|orig|tmp)$ {
        deny all;
        access_log off;
        log_not_found off;
    }

    # 禁止访问版本控制目录
    location ~ ^/(\.git|\.svn|\.hg) {
        deny all;
    }

    # 禁止目录列表,防止目录遍历
    autoindex 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 "strict-origin-when-cross-origin" always;
    # CSP需根据业务具体配置,此处仅为示例
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'" always;
}

2.2 DDoS 与 CC 攻击防护配置

2.2.1 连接数限制(limit_conn 模块)
limit_conn 限制的是同一时刻的并发连接数,而非请求速率。正常浏览器并发通常在 2-6 个,单个 IP 超过 20 个就值得警惕。

# /etc/nginx/nginx.conf - http 块
http {
    # 定义连接数共享内存区,10m 可存储约 16 万个 IP 的状态
    limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m;
    limit_conn_status 503; # 超限返回状态码
    limit_conn_log_level warn;
}

server {
    # 每个 IP 全局最多 20 个并发连接
    limit_conn conn_per_ip 20;

    # 静态资源可适当放宽,因为浏览器会并发请求多个资源
    location /static/ {
        limit_conn conn_per_ip 50;
    }

    # 登录接口需严格限制,防止撞库攻击
    location /api/login {
        limit_conn conn_per_ip 5;
    }
}

2.2.2 请求速率限制(limit_req 模块,漏桶算法)
limit_req 基于漏桶算法。请求以任意速率进入“桶”,但以固定速率(rate)流出处理。burst 定义桶的容量,nodelay 决定桶内积压的请求是立即处理还是排队等待。

# /etc/nginx/nginx.conf - http 块
http {
    # 全局请求速率限制区
    limit_req_zone $binary_remote_addr zone=req_per_ip:10m rate=10r/s;
    # 登录接口严格限流区
    limit_req_zone $binary_remote_addr zone=login_zone:10m rate=1r/s;
    # API 接口限流区
    limit_req_zone $binary_remote_addr zone=api_zone:10m rate=30r/s;

    limit_req_status 429; # 超限返回 429 Too Many Requests,语义更准确
    limit_req_log_level warn;
}

server {
    # 全局限流:允许突发 20 个请求,超出部分立即拒绝(nodelay)
    limit_req zone=req_per_ip burst=20 nodelay;

    location /api/login {
        # 登录接口:每秒1个请求,允许5个突发,超出立即拒绝
        limit_req zone=login_zone burst=5 nodelay;
    }

    location /api/ {
        limit_req zone=api_zone burst=50 nodelay;
    }
}

2.2.3 基于地理位置的访问控制(GeoIP2 模块)
如果业务只面向特定地区用户,封锁其他地区的 IP 可以显著减少无谓的扫描流量。

# 安装依赖并下载 GeoIP2 数据库(需替换 YOUR_LICENSE_KEY)
apt install -y libmaxminddb0 libmaxminddb-dev mmdb-bin
wget -O /tmp/GeoLite2-Country.tar.gz \
"https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=YOUR_LICENSE_KEY&suffix=tar.gz"
tar -xzf /tmp/GeoLite2-Country.tar.gz -C /etc/nginx/geoip/
# /etc/nginx/conf.d/geoip.conf
# 需要编译 ngx_http_geoip2_module
geoip2 /etc/nginx/geoip/GeoLite2-Country.mmdb {
    $geoip2_country_code country iso_code;
}

# 定义允许访问的国家/地区白名单
map $geoip2_country_code $allowed_country {
    default         0;  # 默认拒绝
    CN              1;  # 中国大陆
    HK              1;  # 香港
    TW              1;  # 台湾
    MO              1;  # 澳门
}

server {
    # 非白名单国家返回 444,直接断开连接
    if ($allowed_country = 0) {
        return 444;
    }
}

2.2.4 SYN Flood 防护(内核参数调优)
Nginx 层面的配置对 SYN Flood 无效,必须在操作系统内核层面进行加固。

# /etc/sysctl.d/99-nginx-security.conf
# SYN Flood 防护内核参数

# 启用 SYN Cookie,半连接队列满时使用 Cookie 验证
net.ipv4.tcp_syncookies = 1
# 增大半连接队列大小
net.ipv4.tcp_max_syn_backlog = 65536
# 减少 SYN 重传次数,加速回收半开连接
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
# 允许复用 TIME_WAIT 连接,缓解端口耗尽
net.ipv4.tcp_tw_reuse = 1

# 应用配置
sysctl -p /etc/sysctl.d/99-nginx-security.conf

2.3 集成 ModSecurity WAF 进行深度内容检测

ModSecurity 3.0 是一个独立的 WAF 引擎库,Nginx 通过 ModSecurity-nginx 连接器模块与之交互,架构清晰,性能优于旧版。

2.3.1 编译安装 ModSecurity 3.0

# 安装编译依赖
sudo apt install -y build-essential git libpcre2-dev libxml2-dev \
    libcurl4-openssl-dev libyajl-dev libgeoip-dev liblmdb-dev \
    libfuzzy-dev pkg-config automake libtool

# 克隆并编译 ModSecurity
cd /usr/local/src
sudo git clone --depth 1 -b v3.0.13 https://github.com/owasp-modsecurity/ModSecurity.git
cd ModSecurity
sudo git submodule init
sudo git submodule update
sudo ./build.sh
sudo ./configure --with-pcre2 --with-lmdb
sudo make -j$(nproc)
sudo make install
# 验证:ls -la /usr/local/lib/libmodsecurity.so*

2.3.2 编译 Nginx 连接器模块

# 克隆连接器源码
cd /usr/local/src
sudo git clone --depth 1 https://github.com/owasp-modsecurity/ModSecurity-nginx.git

# 下载与当前 Nginx 版本一致的源码
NGINX_VER=$(nginx -v 2>&1 | grep -oP '\d+\.\d+\.\d+')
sudo wget http://nginx.org/download/nginx-${NGINX_VER}.tar.gz
sudo tar xzf nginx-${NGINX_VER}.tar.gz
cd nginx-${NGINX_VER}

# 基于当前 Nginx 参数编译动态模块
NGINX_ARGS=$(nginx -V 2>&1 | grep 'configure arguments' | sed 's/configure arguments: //')
eval sudo ./configure ${NGINX_ARGS} --add-dynamic-module=/usr/local/src/ModSecurity-nginx
sudo make modules

# 复制模块并加载
sudo cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/
# 然后在 nginx.conf 顶部添加: load_module modules/ngx_http_modsecurity_module.so;

2.3.3 配置 OWASP CRS 4.x 规则集
CRS 4.x 在误报率和检测精度上比 3.x 有显著提升。

# 下载 CRS
cd /etc/nginx
sudo git clone --depth 1 -b v4.7.0 \
    https://github.com/coreruleset/coreruleset.git /etc/nginx/owasp-crs
sudo cp /etc/nginx/owasp-crs/crs-setup.conf.example /etc/nginx/owasp-crs/crs-setup.conf

ModSecurity 主配置文件:

# /etc/nginx/modsecurity/modsecurity.conf
# 规则引擎模式:DetectionOnly 只记录不拦截(调试用),On 为拦截模式
SecRuleEngine DetectionOnly

# 请求体检查
SecRequestBodyAccess On
SecRequestBodyLimit 13107200    # 请求体大小限制
SecRequestBodyNoFilesLimit 131072

# 响应体检查(对性能影响大,按需开启)
SecResponseBodyAccess Off

# 审计日志配置
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogType Serial
SecAuditLog /var/log/nginx/modsec_audit.log

# 临时文件目录
SecTmpDir /tmp/modsecurity/tmp
SecDataDir /tmp/modsecurity/data

# 加载 OWASP CRS
Include /etc/nginx/owasp-crs/crs-setup.conf
Include /etc/nginx/owasp-crs/rules/*.conf

在 Nginx 站点配置中启用:

# /etc/nginx/conf.d/waf.conf
server {
    listen 443 ssl;
    server_name example.com;

    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;

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

2.3.4 编写自定义规则
CRS 覆盖通用攻击,业务特有的安全需求需自定义规则。规则文件应在 CRS 之后加载。

# /etc/nginx/modsecurity/custom-rules.conf
# 规则1:拦截已知恶意扫描器的 User-Agent
SecRule REQUEST_HEADERS:User-Agent "@rx (?i)(sqlmap|nikto|nessus|dirbuster|gobuster)" \
    "id:100001,\
    phase:1,\
    deny,\
    status:403,\
    log,\
    msg:'恶意扫描器检测',\
    tag:'custom/scanner-detection',\
    severity:'CRITICAL'"

# 规则2:阻止双扩展名文件上传绕过
SecRule FILES_NAMES "@rx \.(php|jsp|asp|cgi)\." \
    "id:100002,\
    phase:2,\
    deny,\
    status:403,\
    log,\
    msg:'双扩展名文件上传拦截',\
    tag:'custom/upload-protection'"

# 规则3:针对特定认证接口的增强速率限制(示例,与 limit_req 互补)
SecRule REQUEST_URI "@beginsWith /api/v1/auth" \
    "id:100003,\
    phase:1,\
    pass,\
    log,\
    setvar:'ip.auth_counter=+1',\
    expirevar:'ip.auth_counter=60'"

SecRule IP:AUTH_COUNTER "@gt 20" \
    "id:100004,\
    phase:1,\
    deny,\
    status:429,\
    log,\
    msg:'认证接口请求频率超限',\
    tag:'custom/rate-limit'"

# 规则4:内部网络健康检查接口白名单(跳过WAF检测)
SecRule REMOTE_ADDR "@ipMatch 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" \
    "id:100010,\
    phase:1,\
    pass,\
    nolog,\
    ctl:ruleEngine=Off,\
    chain"
    SecRule REQUEST_URI "@beginsWith /health"

2.4 启动验证与监控

2.4.1 启动与基础验证

# 准备目录并检查配置
sudo mkdir -p /tmp/modsecurity/{tmp,data}
sudo chown www-data:www-data /tmp/modsecurity/{tmp,data}
sudo nginx -t
sudo nginx -s reload
# 确认模块加载:nginx -V 2>&1 | grep modsecurity

2.4.2 WAF 功能测试

# 测试 SQL 注入拦截
curl -i "https://example.com/?id=1' OR '1'='1"
# 测试 XSS 拦截
curl -i "https://example.com/?q=<script>alert(1)</script>"
# 测试路径遍历拦截
curl -i "https://example.com/../../etc/passwd"
# 测试自定义规则(恶意 User-Agent)
curl -i -A "sqlmap/1.7" "https://example.com/"
# 测试正常请求
curl -i "https://example.com/"

2.4.3 审计日志确认
确认 DetectionOnly 模式日志正常后,再将 SecRuleEngine 改为 On

sudo tail -50 /var/log/nginx/modsec_audit.log
# 日志中应包含拦截记录,如 [id "942100"] [msg "SQL Injection Attack Detected via libinjection"]

三、运维实践与进阶

3.1 性能优化最佳实践

ModSecurity 的主要性能开销在于正则匹配。高并发下需优化:

  • 调整偏执等级(Paranoia Level):在 crs-setup.conf 中设置 tx.blocking_paranoia_level=1(从低开始)。
  • 按需禁用规则组:如后端非 Java,可禁用相关规则 SecRuleRemoveById 944100-944999
  • 静态资源跳过WAF
    location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
        modsecurity off;
        expires 30d;
    }
  • 建立精准白名单:对内部健康检查等安全流量关闭规则引擎。

3.2 自动化与监控

基于日志的自动封禁脚本:可以编写脚本分析 access.log,对短时间内触发大量 429/403 状态的 IP 自动加入 Nginx 黑名单,并通过 fail2ban 与 iptables 联动实现更长时间的封禁。详细的脚本示例和 fail2ban 配置因篇幅较长,其核心思想是:监控特定状态码(429限流、403WAF拦截)或匹配攻击特征,达到阈值后自动更新封禁列表并重载 Nginx。

集成监控系统:通过 nginx-prometheus-exporter 暴露 Nginx 指标(如 429/403 请求率、活跃连接数),在 Prometheus 中设置告警规则,当限流触发率或 WAF 拦截率异常升高时及时告警。同时,使用 Filebeat 采集 ModSecurity 审计日志至 ELK Stack,便于进行 安全事件分析 和追溯。

四、总结

Nginx 安全配置是一个典型的分层防御体系:内核参数加固网络层,原生模块高效过滤异常流量,ModSecurity WAF 深度检测内容,再辅以自动化工具进行主动响应。这套“廉价操作前置,昂贵操作后置”的组合拳,能以合理的成本为中小型 Web 服务提供坚实的安全保障。

配置完成后,切记要在测试环境充分验证,并建立持续的监控和备份机制。安全是一个持续的过程,规则需要随着业务和威胁的变化而不断调优。希望这份实战指南能帮助你更好地加固你的 Nginx 服务。如果在实践中遇到更多有趣的场景或解决方案,欢迎在 云栈社区 与大家分享讨论。




上一篇:Redis 8.6 TimeSeries 实战:轻量级时序数据存储与性能压测
下一篇:嵌入式面试必问:从SRAM到LPDDR,详解RAM内存分类与选型
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-1 20:56 , Processed in 0.506799 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表