跳转到主内容
极星编程网:以代码为星,赴技术山海!

Hyperf微服务如何防止大报文攻击_调整Swoole的package_max_length

不能只调大 package_max_length 来“解决”大报文攻击,它本质是缓冲区配置项,不是安全策略;盲目增大反而会放大 DoS 风险。 直接结论:不能只调大
package_max_length
来“解决”大报文攻击,它本质是缓冲区配置项,不是安全策略;盲目增大反而会放大 DoS 风险。 为什么调整
package_max_length
不能防攻击 这个配置只是告诉 Swoole “单次接收的 HTTP 包(header + body)最大允许多大”,底层用的是固定大小内存缓存区。它不校验来源、不区分合法上传还是恶意构造的超长 payload,也不做流式解析或分块限速。 常见误操作是看到
Request Entity Too Large
就立刻把
package_max_length
设成 100MB —— 这等于给攻击者开了个内存喷射口:一个并发就能吃掉几十 MB 内存,100 个并发就可能拖垮整台机器。 真正需要的是分层防御: 接入层(如 Nginx)提前拦截超大请求(
client_max_body_size
) 应用层(Hyperf)对上传路径做白名单 + 文件类型 + 单文件大小校验 协议层(Swoole)用
package_max_length
做兜底,但值必须略大于业务最大合法包(比如 20MB),而非无上限 在 Hyperf 中正确设置
package_max_length
该配置必须写在
config/autoload/server.php
的
settings
数组里,且仅对 HTTP server 生效(RPC 或 WebSocket server 需单独配):
'settings' => [ 'package_max_length' => 20 * 1024 * 1024, // 20MB,不是 200MB 'enable_coroutine' => true, 'worker_num' => swoole_cpu_num() * 2, ],
注意三点: Swoole 6.1.1 Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。 下载 值必须是整数,单位字节;
20 * 1024 * 1024
比硬写
20971520
更易维护 不要在
servers
子项里重复设 —— 它属于全局
settings
,不是 per-server 改完必须重启服务(
php bin/hyperf.php start
),热更新不生效 配合上传逻辑做实际防护 光调 Swoole 参数没用,Hyperf 的上传控制器必须自己校验。例如:
public function upload(UploadFile $file) { if ($file->getSize() > 10 * 1024 * 1024) { throw new BadRequestHttpException('File too large, max 10MB'); } if (! in_array($file->getMimeType(), ['image/jpeg', 'image/png'])) { throw new BadRequestHttpException('Unsupported mime type'); } // 后续保存... }
关键点: 用
$file->getSize()
而不是
$_FILES
—— Hyperf 的
UploadFile
对象已加载进内存,大小可即时读取 校验必须在 move 或写入前完成,否则攻击者可能先占满临时目录 如果走 OSS/MinIO 等对象存储,建议用预签名 URL + 前端直传,完全绕过 PHP 层接收大 body 容易被忽略的协程上下文陷阱 在协程环境下,
package_max_length
影响的不只是上传:所有 HTTP 请求(包括 POST JSON、表单、甚至恶意构造的超长 header)都会走同一缓冲区。如果你的接口接收大 JSON,又没做 body 解析限长,一样会触发错误。 更隐蔽的问题是:Swoole 默认不校验
Content-Length
是否真实 —— 攻击者发一个
Content-Length: 999999999
但只发几个字节,Swoole 会一直等、直到超时或缓冲区填满。所以务必同时设置:
http_parse_post
关闭(Hyperf 默认关,避免自动解析爆炸式 form data)
request_slowlog_timeout
(如 5s),及时杀掉卡住的请求 用
max_request
控制 Worker 寿命,防止长期运行下内存缓慢泄漏 最终防线不在数字大小,而在是否让每个请求都明确知道自己能拿多少、该拒绝什么、以及失败后是否干净退出。

相关文章