711 字
2 分钟
解决 Docker 容器走宿主机透明代理时的超时问题
2026-03-08

本篇由 Gemini 3.1 Pro 生成

记录一次解决 Docker 容器走宿主机透明代理时遇到超时的排障过程。问题比较典型,主要卡在 Linux 内核的防火墙框架冲突上。

场景与问题#

需求是让 Docker 里的 Twikoo 容器走代理,以便连通 Telegram API 和 Akismet 反垃圾接口。

一开始试了常规方案:

  1. 配置环境变量:加了 HTTP_PROXY,但 Node.js 底层默认不认系统代理变量,无效。
  2. 端口桥接:用 socat 劫持并转到主机的 7890 端口,操作繁琐且容易触发主机的端口占用(Address in use)或 Docker 的网关隔离(Connection refused)。

最后决定直接用宿主机上的 ShellCrash 做底层透明代理,划定一个 Docker 网段让其全局接管。但在配置好之后,遇到了一个非常诡异的现象: 容器的 DNS 解析成功了(拿到了返回的 Fake-IP 或真实 IP),但紧接着的 TCP 连接全部报 ETIMEDOUT 超时。

根本原因#

排查宿主机内核路由表后发现,这是 nftablesiptables 两套防火墙框架在“打架”。

  1. 目前新版的代理软件默认使用较新的 nftables 框架来接管和重定向流量。
  2. 但是 Docker 容器的网络打通(NAT 和网桥)依然重度依赖 iptables

当 Twikoo 发出的流量被代理软件的 nftables 规则强行重定向到代理端口时,这个被修改过流向的数据包到了 Docker 的 iptables 链里,被视为了非法篡改的异常包,直接被底层 DROP(丢弃)了。 这就导致了“DNS 通了,但数据包发不出去”的假死状态。

解决方案#

让代理软件和 Docker 使用同一种防火墙语言即可。

1. 切换代理防火墙框架 进入代理软件(如 ShellCrash 或其他透明代理面板)的设置菜单,将流量接管/防火墙模式从 nftables 改回 iptables。重启代理服务。

2. 创建代理专用 Docker 网段 在宿主机新建一个专门用来走代理的虚拟网络(例如 172.30.x.x):

docker network create --subnet=172.30.0.0/16 proxy_net

3. 配置透明代理接管 在代理软件的接管设置中,添加 172.30.0.0/16 网段。

4. 修改容器配置 现在 docker-compose.yml 可以做到极其精简,不需要写任何代理环境变量或 DNS 配置,直接让容器接入 proxy_net 即可实现无感连接:

version: '3'
services:
twikoo:
image: imaegoo/twikoo
container_name: twikoo
restart: always
ports:
- 8080:8080
volumes:
- ./data:/app/data
environment:
- TWIKOO_THROTTLE=1000
# --- 以下新增 ---
networks:
- proxy_net
networks:
proxy_net:
external: true

总结#

以后如果有其他容器需要走代理,直接在 compose 文件里挂载这个 proxy_net 外部网络即可。底层的 DNS 防污染和国内外分流全部由宿主机的透明代理自动处理。

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

解决 Docker 容器走宿主机透明代理时的超时问题
https://fuc.us.ci/posts/docker-proxy/
作者
Windla
发布于
2026-03-08
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时