FrankenPHP需在Caddy层和PHP层协同设限:Caddy用request_body指令硬拦截超大请求并返回413,PHP层同步配置post_max_size与upload_max_filesize,并重启进程生效。

FrankenPHP 本身不提供类似 Nginx client_max_body_size 或 Spring Boot max-request-size 那样的直接配置项,因为它的设计是将 Web 服务器与 PHP 运行时深度整合——HTTP 请求解析由其内嵌的 Caddy(Go net/http)完成,而 PHP 层仍受传统 PHP ini 限制约束。要真正拦截超大恶意请求,必须在**两个层面协同设限**:Caddy 协议层(前置硬拦截)和 PHP 解析层(兜底校验)。
Caddy 层:用 request_body 指令做第一道闸门
FrankenPHP 使用 Caddy 作为 HTTP 引擎,因此可通过 Caddyfile 的 request_body 指令在请求体被读取前就拒绝超限请求,返回标准 413 错误,且不进入 PHP 流程。
- 在对应路由块中添加:
request_body 20MB(支持k、m、g单位) - 该指令作用于整个匹配路径,例如上传接口可单独设高限:
/api/upload { request_body 100MB } - 非上传路径建议保持严格(如
5MB),避免 JSON 攻击或表单炸弹 - 注意:该限制对所有请求方法(POST/PUT/PATCH)生效,且优先级高于 PHP 层
PHP 层:同步收紧 post_max_size 和 upload_max_filesize
即使 Caddy 拦截了大部分恶意请求,PHP 运行时仍需设防——防止绕过 Caddy(如直连 PHP-FPM 兼容模式)、或某些特殊编码触发异常解析。
- 修改 FrankenPHP 启动时加载的
php.ini(通常位于frankenphp/php.ini或通过FRANKENPHP_PHP_INI_PATH指定) - 确保:
post_max_size = 20M(必须 ≥upload_max_filesize) - 同时设:
upload_max_filesize = 10M(仅控制单文件,不影响 multipart 总大小) - 重启 FrankenPHP 进程使 ini 生效(不是 reload,因 PHP 配置在进程启动时加载)
补充防护:禁用分块传输 + 设置读取超时
慢速攻击(如每秒只发几字节)可能绕过大小限制,持续占用连接资源。Caddy 提供原生支持来堵住这一缺口:
立即学习“PHP免费学习笔记(深入)”;
- 在 Caddyfile 全局或站点块中加:
timeout 10s(等价于read_timeout) - 显式禁用分块上传(防御
Transfer-Encoding: chunked绕过):encode zstd gzip不影响,但需确认未启用transfer_encoding插件 - 若业务明确不需要分块,可在 Caddyfile 中用
header -Transfer-Encoding清除该头,配合后端逻辑拒绝含此头的请求
验证是否生效
不要只看返回状态码,要确认拦截发生在哪一层:
- 用
curl -X POST --data-binary @huge.bin http://localhost/api/upload测试,观察是否立即返回 413 且无 PHP 日志输出 → 表明 Caddy 层生效 - 故意把 Caddy 的
request_body调小(如 1KB),再发一个 2KB 的 JSON 请求,确认返回 413 而非 PHP 的 400/500 → 排除 PHP 层误报 - 检查 FrankenPHP 日志(
frankenphp.log)中是否有request body too large类提示,这是 Caddy 内部日志关键词



















