Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

容器(docker)桥接(bridge)模式时的代理问题 #10

Closed
unknowndevQwQ opened this issue Aug 5, 2020 · 9 comments
Closed

容器(docker)桥接(bridge)模式时的代理问题 #10

unknowndevQwQ opened this issue Aug 5, 2020 · 9 comments

Comments

@unknowndevQwQ
Copy link

unknowndevQwQ commented Aug 5, 2020

我已经按照 #3 设置了内核参数,但还是会发生这种情况
复现问题的步骤:

  1. 启用 cgproxy 和 docker,启用 cgproxy 网关代理并且设置 "cgroup_proxy": ["/system.slice/containerd.service","/system.slice/docker.service","/"]
  2. 重启机器
  3. 在这时 docker 内容器查询 dns 没有经过 cgproxy(但是设置了代理 dns)
  4. 重启 cgproxy 后发现 docker 内容器无法解析 dns

可能有用的文件
cgp.log
tproxy.json.txt

一点额外信息:
发行版是 Arch
安装了 nftables 和 iptables-nft

@springzfx
Copy link
Owner

springzfx commented Aug 5, 2020

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模块造成的, 见下文

@unknowndevQwQ
Copy link
Author

unknowndevQwQ commented Aug 6, 2020

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 联网的容器也可以用这个方法解决问题吗? 可以

@unknowndevQwQ
Copy link
Author

unknowndevQwQ commented Aug 7, 2020

我的问题解决了,不过在搜索时发现了另一个可能的解决方式 :
iptables -t raw -I PREROUTING -i BRIDGE -s x.x.x.x -j NOTRACK(暂未尝试)
但是这玩意没解决我的问题,因为在这之后什么也没有发生(顺便 systemd-nspawn 里的容器也出现类似问题了)

来源:
https://blog.csdn.net/quqi99/article/details/7447233 (用 ctrl + F 搜寻 net.bridge.bridge-nf-call-iptables=1)

@springzfx springzfx changed the title cgproxy 在开启网关代理并且晚于 docker 启动后 docker 内容器无法解析 容器(docker)桥接(bridge)模式时的代理问题 Aug 11, 2020
@unknowndevQwQ
Copy link
Author

顺带一提可能的坑,设置 bridge-nf-call-xtables 后有可能需要重启一下 docker 才会生效

@lilydjwg
Copy link

lilydjwg commented Aug 13, 2020

说一下,这个不是网桥的问题,而是 br_netfilter 的问题。docker 会加载这个模块,见 moby/moby#13162 。systemd-nspawn 不加载这个模块,所以(不通过其它途径加载这个模块的话)不应当受影响。

另外 sysctl.d(5) Example 2 有在模块加载时使用 udev 自动应用 sysctl 设置的方案。

PS: 我看了许久,还是没弄明白这里讨论的问题是什么……

@unknowndevQwQ
Copy link
Author

说一下,这个不是网桥的问题,而是 br_netfilter 的问题。docker 会加载这个模块,见 https://github.com/moby/moby/pull/13162。systemd-nspawn 不加载这个模块,所以(不通过其它途径加载这个模块的话)不应当受影响。

建议在句号前加一个空格,现在看起来这个链接把句号也加进去了

PS: 我看了许久,还是没弄明白这里讨论的问题是什么……

只是想让 docker 和 nspawn 里的容器正常走代理而已……

@lilydjwg
Copy link

lilydjwg commented Aug 13, 2020

只是想让 docker 和 nspawn 里的容器正常走代理而已……

什么叫「正常」……要走透明代理的话,直接在网关的 PREROUTING 链上操作不就好了吗?

@unknowndevQwQ
Copy link
Author

只是想让 docker 和 nspawn 里的容器正常走代理而已……

什么叫「正常」……要走透明代理的话,直接在网关的 FORWARD 链上操作不就好了吗?

但是我不会这个操作……
于是就成这样了

@springzfx
Copy link
Owner

springzfx commented Aug 13, 2020

正如依云姐所指出的,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

contrun referenced this issue in vampire-rip/vampire-docs Apr 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants