nginx 中不存在“并发空间”限制概念,正则灾难性回溯导致的是cpu耗尽而非内存溢出;应通过减少正则使用、规避高危写法、设置pcre2匹配限值及资源隔离三重手段防护。

直接限制正则表达式解析的“并发空间”在 Nginx 中并不存在——Nginx 本身不为正则匹配分配独立内存池或并发槽位,它用的是 PCRE(或 PCRE2)库进行单次请求路径匹配,而恶意正则(如灾难性回溯)会阻塞 worker 进程线程,导致 CPU 持续 100%,本质是**CPU 耗尽而非内存溢出**。因此,“限制最大并发解析空间”这个说法有概念偏差。真正有效的做法,是通过降低正则使用频次、规避高危写法、设置超时与资源隔离三重手段,防止单个恶意 URI 触发回溯风暴拖垮整个 worker。
避免在 location 中滥用复杂正则
Nginx 的 location ~ 和 location ~* 是回溯风险主入口。只要一个请求命中含脆弱正则的 location 块,就可能卡死当前 worker。
- 优先用前缀匹配(
location /api/)代替正则,95% 的路由需求无需正则 - 必须用正则时,禁用捕获组:用
(?:...)替代(...),减少回溯状态数 - 绝对避免嵌套量词组合,例如
/(a+)+/、/([a-z]+:)+/、/.*\.(js|css|png)/(末尾点号+星号极易触发回溯) - 用
location ^~ /static/强制前缀优先,防止被后续正则块意外覆盖
启用正则执行时间硬限制(PCRE2 ≥ 10.30 + Nginx ≥ 1.21.0)
新版 PCRE2 支持 match_limit 和 match_limit_recursion,Nginx 可透传控制:
- 编译 Nginx 时需启用
--with-pcre-jit并链接 PCRE2 ≥ 10.30 - 在
nginx.conf的http块中添加:pcre_jit on; pcre_match_limit 1000; pcre_match_limit_recursion 500; - 这两个值不是越大越好:设为 1000/500 可拦截绝大多数灾难性回溯,同时不影响正常 URI 匹配(典型匹配仅消耗 10–50 单位)
用 try_files + 精确 location 分流,绕过正则解析
把“需要校验路径安全”的静态资源访问,改造成无正则路径判定:
- 不要写:
location ~ ^/files/(.+)$ { ... } - 改为:
location /files/ { alias /data/uploads/; # 先尝试真实文件,命中即返回;否则交由后端或报错 try_files $uri =403; } -
try_files不走正则,只做简单字符串拼接和文件系统检查,零回溯风险 - 配合
alias+internal或严格root配置,还能一并防御路径遍历
隔离高风险模块到独立 worker 进程
若业务强依赖复杂正则(如旧版 API 网关),可将这部分流量路由到专用 worker,避免影响主站:
- 用
worker_cpu_affinity和worker_processes划分资源域 - 通过
upstream+proxy_pass把正则密集型 location 转发到监听本地不同端口的 Nginx 实例(该实例单独调低pcre_match_limit并启用日志采样) - 结合
limit_conn对该 upstream 的连接数硬限(例如每 IP 最多 2 连接),从源头压制并发攻击面











