记录一次docker网络故障-mtu
简述
- 从云服务器上通过 wg 隧道将网站的请求转到内网
- 配置后,页面打开无响应最后超时
排查步骤
- 从云服务器宿主机测试目标站点
curl -i -s -o /dev/null -w "%{http_code}\n" http://192.168.5.30 -H "Host: www.chenwx.top"
200
curl -i http://192.168.5.30 -H "Host: www.chenwx.top"
# 正常打开页面查看内网服务的nginx日志, 正常响应, 且耗时很低。
- 更换容器网络进行验证
docker run --rm -it --network host nginx:1.25.3-alpine \
curl -I -s -o /dev/null -w "%{http_code}\n" \
-H "Host: www.chenwx.top" http://192.168.5.30
成功响应 200
docker run --rm -it --network host nginx:1.25.3-alpine \
curl -H "Host: www.chenwx.top" http://192.168.5.30
成功响应 html
docker run --rm -it --network bridge nginx:1.25.3-alpine \
curl -I -s -o /dev/null -w "%{http_code}\n" \
-H "Host: www.chenwx.top" http://192.168.5.30
成功响应 200
docker run --rm -it --network bridge nginx:1.25.3-alpine \
curl -H "Host: www.chenwx.top" http://192.168.5.30
未响应 html, 阻塞现象说明
- host 网络模式下, 只访问http头和完整页面访问都是正常的;
- 桥接网络模式下, 只接收http响应头时是正常的, 如果接收 html body 就会失败;
说明桥接模式下小包是正常的,大数据包会失败, 基本定位 99%是 MTU 的问题。
解决办法: 查看 wg 网卡设置的 mtu 值是 1408, 于是将 docker 桥接网络的 mtu 值也修改为一致;
- 检查当前 MTU
[root@ecs2 nginx]# docker network inspect bridge --format='{{json .Options}}' | jq .
{
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
}修改值
/etc/docker/daemon.json
{
"mtu": 1408
}
# 再看值已经变了
[root@ecs2 nginx]# docker network inspect bridge --format='{{json .Options}}' | jq .
{
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1408"
}- 再次测试还是失败
确认因为自己用的一个单独创建的 docker 网络, 所以值是没有变的, 即 daemon.json 内的 mtu 不影响独立创建的网络
docker network inspect traefik --format='{{json .Options}}' | jq .
{} # 实际还是个空值- 删除原有网络后, 再新建一个自定义 MTU 的网络
docker compose down
docker network rm traefik
docker network create traefik --opt com.docker.network.driver.mtu=1408
[root@ecs2 nginx]# docker network inspect traefik --format='{{json .Options}}' | jq .
{
"com.docker.network.driver.mtu": "1408"
}- 启动服务, 验证通过
至于为什么 wireguard 的 mtu 值会是 1408, 因为wg增加一层封包后原本应该是 1420;
但不知道为什么腾讯云轻量服务器不能使用 1420 这个值, 只能逐个往下减少, 一直试到 1408 wireguard 组网才成功;
最后更新于