▎ 现象:rclone 通过 WebDAV 上传到 AList,AList 后端是某云盘存储,每次都在文件上传时 405 失败。裸机部署正常,docker 部署必现。
一、症状
rclone 日志:
2026/05/27 21:38:30 ERROR : … Failed to copy: Method Not Allowed: 405
AList 日志同步报:
PUT /dav/…/Season 1/魔法少女小圆 - S01E01.mkv | 405 | 1m0s
Post "https://vip-lixian-08.guangyapan.com/…?sequential&uploads":
read tcp 172.17.0.7:49256->47.102.69.6:443: i/o timeout
特征:
- 失败前正好卡 60 秒
- 失败发生在向云盘 OSS 发起 ?uploads(OSS InitiateMultipartUpload)阶段
- 错误码是 i/o timeout,不是 connection refused
- 裸机部署 AList 完全正常,只有 docker 部署复现
二、第一个误导:405 不是真正的错
翻 AList 源码 server/webdav/webdav.go 的 handlePut:
err = fs.PutDirectly(ctx, path.Dir(reqPath), fsStream)
if errs.IsNotFoundError(err) {
return http.StatusNotFound, err
}
// TODO(rost): Returning 405 Method Not Allowed might not be appropriate.
if err != nil {
return http.StatusMethodNotAllowed, err // ← 所有非 404 一律 405
}
注释里作者自己标了 TODO——AList WebDAV 把所有 PUT 失败(除"对象不存在"外)都包装成 405。所以 405 只是症状,真错误在底层网络层。
三、真正的根因:MTU 黑洞
关键线索
宿主机网卡:
ens18: mtu 1400
inet 192.168.88.104
docker0 默认 MTU 是 1500。容器从 docker0 出来的包按 1500 协商 MSS,到 ens18 时装不进 1400 的物理 MTU,包被静默丢弃,中间设备又不返回 ICMP "Fragmentation Needed"——这就是经典的 PMTU 黑洞。
为什么偏偏在 TLS 握手时报错
普通 HTTP 小包 < 1400,不触发。但 TLS 握手时服务端发的证书包通常 2~4 KB,必须分片为多个 TCP 段。其中至少有一个段达到链路 MTU 上限——这个包发不出去,TLS 握手卡死,TCP 读超时(默认 60s)后失败。
具体到 AList 这个场景:
- 列表、元数据接口:小包,正常
- OSS 分片上传初始化(InitiateMultipartUpload):响应含较大的 XML 和签名信息,踩坑
- 已经握手成功的连接传数据:MSS 协商过了,有时也能传完
这解释了为什么有些操作正常、有些操作必失败。
为什么裸机没问题
裸机进程直接走 ens18,内核 PMTU discovery 把 ens18 自己的 MTU=1400 直接用进 TCP MSS,对端收到的 SYN 里 MSS 就是合理的。问题在 docker bridge 多了一层 NAT,PMTU 信息没有正确同步到容器命名空间。
四、解决方案
4.1 改 /etc/docker/daemon.json
{
"mtu": 1400,
"default-network-opts": {
"bridge": {
"com.docker.network.driver.mtu": "1400"
}
}
}
两个字段缺一不可:
┌───────────────────────────────────────────────────────────┬────────────────────────────────┬──────────────────────┐
│ 字段 │ 作用 │ 备注 │
├───────────────────────────────────────────────────────────┼────────────────────────────────┼──────────────────────┤
│ mtu │ 控制 docker0 默认 bridge │ 老版本 docker 也支持 │
├───────────────────────────────────────────────────────────┼────────────────────────────────┼──────────────────────┤
│ default-network-opts.bridge.com.docker.network.driver.mtu │ 控制以后新建的所有 bridge 网络 │ Docker 24+ 才支持 │
└───────────────────────────────────────────────────────────┴────────────────────────────────┴──────────────────────┘
应用:
systemctl restart docker
4.2 重建已存在的网络
default-network-opts 只对新建网络生效,已经存在的 bridge 网络(包括 compose 自动建的)还是老 MTU。







Comments NOTHING