综合 Caddy 2.11.9:/wp-admin/ 404 的回归修了,FastCGI 的 env 也不再被请求头覆盖

2026-11-05 21:03:06

Caddy 2.11.9:/wp-admin/ 404 的回归修了,FastCGI 的行为也跟着变了

2.11.9 是叠在 2.11.8 之上的快速跟进版本,修掉 2.11.8 引入的一个回归,另加几处安全修复,主要集中在 FastCGI。内容全部是从 master 回迁的修复,外加少量小增补。在 2.11.8 上跑 PHP 的话,建议升级。

修复与变动

PHP 目录索引(2.11.8 引入的回归):像 /wp-admin/ 这种带尾斜杠的目录请求,会被目录本身匹配中,而不是匹配它的 index.php,请求根本没到 PHP,通常直接 404。WordPress 后台和其他靠尾斜杠 URL 提供 index 的应用都受影响。修复后,try_files 模式只有在候选以 / 结尾时才匹配目录。(#8352)

带占位符的路径匹配器:{env.FOO} 这类占位符在查找前不再被小写成 {env.foo};它们的值与静态模式一样,和请求路径做大小写不敏感的比较。(#8343)

plain_time_format:file_server browse 的新选项,用来设置纯文本目录列表(Accept: text/plain)的时间格式。(#8084)

路径清理、header 重写和 weighted_round_robin 选择减少了内存分配。(#7842)

插件作者可以用新增的 httpcaddyfile.Helper.IsNamedRoute() 判断某条指令是否正在命名路由(named route)内被解析。(#8354)

破坏性变更

冲突的 client_auth 现在是 Caddyfile 错误

两个 site 块共享同一域名的 TLS 连接策略、但 client_auth 设置不同时,适配器以前会保留第一个、静默丢掉另一个,这可能悄悄去掉一个更严格的 mTLS 要求。现在这种情况直接报错。(#8306)

FastCGI 脚本歧义返回 400

下面两种情况无法确定到底运行哪个脚本,一律返回 400:

  • 转义路径(含 % 的路径匹配器看到的那份)与解码后的路径会选中不同脚本,例如 /public/tool.php%2f..%2f..%2fadmin%2ftool.php(#8357)
  • Windows 上,脚本路径含 8.3 短名分量(如 ADMINI~1)或含 :(NTFS 备用数据流)(#8356)

FastCGI 的 env 值优先于请求头

客户端不能再发一个同名请求头,覆盖你用 env 设的 HTTP_* 变量。(#8358)

安全修复

  • fastcgi:客户端可以发送匹配的请求头,覆盖 FastCGI transport(或 php_fastcgi)的 env 子指令设置的任意 HTTP_* 变量,例如决定应用在 HTTP_X_AUTH_USER 里看到的用户。现在配置值优先。(GHSA-q34h-28rj-5hjm,#8358)
  • fastcgi:Windows 上,NTFS 8.3 短名和备用数据流可以运行一个路径规则本想拒绝的脚本。(GHSA-9cr8-wmhh-39pm,#8356)
  • fastcgi:编码斜杠和点段可以让一个含 % 的路径匹配器批准某个脚本,实际运行的却是另一个。(#8357)
  • fastcgi:HTTP/2 下,与 :authority 一起发送的 host 字段会让应用看到的 host(HTTP_HOST)与 Caddy 实际路由的 host 不一致。(#8355)
  • httpcaddyfile:合并 TLS 连接策略时,更严格的 client_auth 可能被静默丢弃。(#8306)
  • go-jose 升到 v4.1.6,对应 GHSA-mgcc-cww5-fp2q。(#8299)

如果应用依赖上面这些有问题的行为,这些补丁可能构成破坏性变更。

2.11 系列里更早的、对 PHP 站点有影响的变更

  • 非法或只由点组成的 host(如 ..)在所有协议上都会被拒绝并返回 400,且发生在任何路由执行之前。(#8328)
  • request_body max_size 现在只要 Content-Length 超限,立刻以 413 拒绝请求。(#8337)
  • 没有 index.php 的 php_fastcgi 站点:请求不存在的路径时,现在按文档中的 first_exist_fallback try 策略所承诺的,以 index.php 交给 PHP,而不是落到 file_server 返回 404。PATH_INFO 和 DOCUMENT_URI 现在由规范化后的路径推导(合并重复斜杠、去掉 . 段);REQUEST_URI 不变。
  • try_files 中以 / 结尾的文件候选只匹配目录,所以 /foo.txt/ 不再匹配文件 /foo.txt。(#8326)
  • 即使请求带 Cache-Control: no-transform,encode 也会压缩响应。
  • 请求头默认上限 16 KiB(此前是 Go 的 1 MB 默认值)。超出的请求得到 431 Request Header Fields Too Large,用 max_header_size 调高。
  • 默认新增 1 分钟的 idle 读写超时:请求体读取或响应写入停顿超过该时间就中断连接。写入之间的停顿(如 SSE)不计入。用 read_body_idle 和 write_idle 调整。
  • 含 . 的请求头字段现在会被丢弃,处理方式与 2.11.4 对下划线的处理相同。PHP 会把 . 折叠成 _,所以这些字段可以冒充合法请求头。需要保留的用 expected_dot_headers 放行。
  • 自 2.11.1 起,HTTPS 的 reverse_proxy 会自动把 Host 设为 {upstream_hostport},可以删掉多余的 header_up Host {upstream_hostport} 行。
  • 自 2.11.1 起,客户端认证 CA 文件缺失或格式错误会让 provisioning 失败,而不是静默关闭客户端认证。
复制全文 生成海报 Caddy FastCGI PHP 运维 Web服务器

推荐文章

程序员茄子在线接单