容器(docker)桥接(bridge)模式时的代理问题
unknowndevQwQ opened this issue · 9 comments
我已经按照 #3 设置了内核参数,但还是会发生这种情况
复现问题的步骤:
- 启用 cgproxy 和 docker,启用 cgproxy 网关代理并且设置
"cgroup_proxy": ["/system.slice/containerd.service","/system.slice/docker.service","/"]
- 重启机器
- 在这时 docker 内容器查询 dns 没有经过 cgproxy(但是设置了代理 dns)
- 重启 cgproxy 后发现 docker 内容器无法解析 dns
可能有用的文件
cgp.log
tproxy.json.txt
一点额外信息:
发行版是 Arch
安装了 nftables 和 iptables-nft
docker默认网络桥接(--net=bridge)
桥接有特殊的工作方式,目前的解决方法为:
sudo sysctl -w net.bridge.bridge-nf-call-iptables=0
sudo sysctl -w net.bridge.bridge-nf-call-ip6tables=0
这时走的是网关代理。
如果 --net=host的话,则是/system.slice/docker.service下的流量
edit: 原因是docker加载的br_netfilter模块造成的, 见下文
docker默认网络桥接(--net=bridge)
桥接有特殊的工作方式,目前的解决方法为:sudo sysctl -w net.bridge.bridge-nf-call-iptables=0 sudo sysctl -w net.bridge.bridge-nf-call-ip6tables=0
这时走的是网关代理。
如果 --net=host的话,则是/system.slice/docker.service下的流量
好的,那么 systemd-nspawn 里用的 bridge 联网的容器也可以用这个方法解决问题吗? 可以
我的问题解决了,不过在搜索时发现了另一个可能的解决方式 : 但是这玩意没解决我的问题,因为在这之后什么也没有发生(顺便 systemd-nspawn 里的容器也出现类似问题了)
iptables -t raw -I PREROUTING -i BRIDGE -s x.x.x.x -j NOTRACK(暂未尝试)
来源:
https://blog.csdn.net/quqi99/article/details/7447233 (用 ctrl + F 搜寻 net.bridge.bridge-nf-call-iptables=1)
顺带一提可能的坑,设置 bridge-nf-call-xtables
后有可能需要重启一下 docker 才会生效
说一下,这个不是网桥的问题,而是 br_netfilter 的问题。docker 会加载这个模块,见 moby/moby#13162 。systemd-nspawn 不加载这个模块,所以(不通过其它途径加载这个模块的话)不应当受影响。
另外 sysctl.d(5) Example 2 有在模块加载时使用 udev 自动应用 sysctl 设置的方案。
PS: 我看了许久,还是没弄明白这里讨论的问题是什么……
说一下,这个不是网桥的问题,而是 br_netfilter 的问题。docker 会加载这个模块,见 https://github.com/moby/moby/pull/13162。systemd-nspawn 不加载这个模块,所以(不通过其它途径加载这个模块的话)不应当受影响。
建议在句号前加一个空格,现在看起来这个链接把句号也加进去了
PS: 我看了许久,还是没弄明白这里讨论的问题是什么……
只是想让 docker 和 nspawn 里的容器正常走代理而已……
只是想让 docker 和 nspawn 里的容器正常走代理而已……
什么叫「正常」……要走透明代理的话,直接在网关的 PREROUTING 链上操作不就好了吗?
只是想让 docker 和 nspawn 里的容器正常走代理而已……
什么叫「正常」……要走透明代理的话,直接在网关的 FORWARD 链上操作不就好了吗?
但是我不会这个操作……
于是就成这样了
正如依云姐所指出的,br_netfilter模块使得bridge的二层包经过了iptables,docker加载这个的目的是为了避免hairpin nat(一个无关紧要的东西),但是TPROXY不支持接收这类型的包,因此无法代理。
解决的方法还是上面的,禁用这种行为就好了,甚至可以直接手动unload这个模块。
sudo sysctl -w net.bridge.bridge-nf-call-iptables=0
sudo sysctl -w net.bridge.bridge-nf-call-ip6tables=0
sudo sysctl -w net.bridge.bridge-nf-call-arptables = 0