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_fallbacktry 策略所承诺的,以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 失败,而不是静默关闭客户端认证。