MemoryMax 是防 DoS 的关键手段,它通过 cgroups v2 对服务进程组设硬性内存上限(如 MemoryMax=384M),超限即由 OOM Killer 单独终止该服务,避免全局 OOM,配合 MemoryAccounting、CPUQuota、Restart 等实现精准止损与快速恢复。

核心方法是使用 systemd 的 MemoryMax 指令对服务进程组施加硬性内存上限,配合 MemoryAccounting 开启监控,让内核在超限时自动终止异常进程,从而把单个服务崩溃的影响控制在最小范围。
为什么 MemoryMax 是防 DoS 的关键手段
普通漏洞(如 PHP 内存泄漏、Java 堆溢出、C 服务解析恶意请求导致无限分配)往往表现为内存持续增长。不设限时,一个服务可能吃光几 GB 内存,触发全局 OOM,连 SSH、日志服务都一起被杀;而启用 MemoryMax 后,该服务会在达到阈值时被单独终止,其他服务照常运行。
- MemoryMax=512M 表示整个服务及其所有子进程、线程的内存总和不能超过 512MB,超出即被 OOM Killer 杀掉
- 它基于 cgroups v2 实现,进程无法绕过,比 ulimit -v 更底层、更可靠
- 不会影响正常请求处理,只拦截失控增长,属于“止损”而非“阻断”
配置 MemoryMax 的标准操作步骤
以 nginx 为例,推荐用 systemctl edit 方式修改,避免覆盖上游包更新:
- 执行 sudo systemctl edit nginx.service
- 填入以下内容:
[Service] MemoryMax=384M MemoryAccounting=true
- 运行 sudo systemctl daemon-reload 加载新配置
- 重启服务:sudo systemctl restart nginx
配套建议提升防护效果
单设 MemoryMax 不够,需组合使用才能应对真实攻击场景:
- 搭配 CPUQuota=30%:防止内存泄漏同时伴随 CPU 占满,拖慢系统响应
- 设置 Restart=on-failure 和 RestartSec=3:服务被 OOM 杀掉后 3 秒内自动拉起,维持业务可用性
- 开启 PrivateTmp=yes:隔离临时文件,避免恶意脚本通过 /tmp 耗尽磁盘空间引发间接 DoS
- 对高并发服务,同步调大 LimitNOFILE=8192,但要确认 fs.file-max 内核参数已足够(sysctl -w fs.file-max=2097152)
验证是否真正生效
配置完必须验证,否则可能因单位写错(如写成 512MB 而非 512M)或 cgroup 版本不兼容导致失效:
- 查看当前加载值:systemctl show nginx.service | grep Memory(应显示 MemoryMax=402653184 字节)
- 实时观察占用:systemd-cgtop,定位到 /system.slice/nginx.service 行,看 MEMORY 列是否接近设定值
- 检查日志线索:journalctl -u nginx.service -n 30 | grep -i "killed process\|out of memory",压测中出现该提示说明机制已触发










