worker_rlimit_nofile是nginx每个worker进程的文件描述符上限声明,需与系统limits、systemd limitnofile、内核fs.file-max协同配置,并配合租户路由隔离、limit_conn限流及可观测性才可防范多租户侧渠道劫持。

在多租户网关场景下,worker_rlimit_nofile 本身不用于“阻断侧渠道劫持”,它也不是安全机制,而是一个资源配额控制参数。所谓“侧渠道劫持”(如通过耗尽文件描述符导致其他租户服务降级或拒绝服务)属于资源争抢型 DoS 风险,防范核心在于隔离 + 预留 + 可观测,而非靠单个 Nginx 指令实现“阻断”。真正起作用的是系统层与 Nginx 层协同的资源边界设定。
明确 worker_rlimit_nofile 的定位
该指令仅声明每个 worker 进程最多能打开多少文件描述符(fd),例如设为 worker_rlimit_nofile 32768,即每个 worker 最多用 32768 个 fd —— 包括客户端连接、上游 socket、日志句柄、缓存文件等。它不阻止租户主动发起连接,也不做租户级鉴权或限流,只是给每个 worker 划一条硬性资源红线,防止单个 worker 因 fd 耗尽崩溃,间接保护同进程内其他租户请求不被连带影响。
实现租户间 fd 隔离的关键动作
-
按租户拆分 worker 进程:避免多个租户共享同一 worker。可通过
worker_processes auto配合 CPU 绑核(worker_cpu_affinity),再结合反向代理路由规则,将不同租户流量固定调度到指定 worker(需配合ip_hash或自定义 sticky 策略),使每个 worker 实质服务少数租户,便于 fd 消耗归因 -
为每个租户配置独立 upstream 与 keepalive 连接池:减少跨租户上游连接混用。例如:
upstream tenant_a_backend {<br> server 10.0.1.10:8080;<br> keepalive 32;<br>}<br>upstream tenant_b_backend {<br> server 10.0.2.10:8080;<br> keepalive 32;<br>}这样即使租户 A 大量建连,也不会挤占租户 B 的 upstream fd 配额 -
限制单租户最大并发连接数:用
limit_conn基于 $tenant_id 变量控制,例如:limit_conn_zone $tenant_id zone=per_tenant:10m;<br>limit_conn per_tenant 1000;
从连接入口掐住源头,比等 fd 耗尽再报错更主动
系统层必须同步收紧的边界
仅改 Nginx 配置无法防劫持。若系统对 nginx 用户的硬限制是 100 万,而你只设 worker_rlimit_nofile 65536,恶意租户仍可能拉满所有 worker 的 fd 上限,造成全局挤压。因此必须:
- 在
/etc/security/limits.conf中为 nginx 用户设合理硬限,例如:nginx hard nofile 262144(即 4 个 worker × 65536) - 若用 systemd 启动,补上:
[Service]<br>LimitNOFILE=262144
- 确认内核
fs.file-max足够(建议 ≥ 总 worker 数 × worker_rlimit_nofile × 1.5),避免全局耗尽
可观测性作为兜底防线
没有监控的限制等于无效。需实时跟踪:
- 各 worker 进程当前 fd 使用量:
lsof -p $(pgrep nginx | head -n1) | wc -l - 租户维度连接数:
nginx -T | grep limit_conn结合 access_log 中 $tenant_id 统计 - 错误日志中是否出现
accept() failed (24: Too many open files)或connect() failed (24: Too many open files),后者说明 upstream 连接已受阻
不复杂但容易忽略:worker_rlimit_nofile 是隔离的起点,不是终点。它让每个 worker “有边界地干活”,但真正防住侧渠道,得靠租户路由分离、连接数硬限、系统级 caps 三者卡死。











