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

V2ray透明代理主机上部署docker,容器无法访问网络的问题 #71

Open
ripley1901 opened this issue Nov 1, 2019 · 7 comments

Comments

@ripley1901
Copy link

由于此教程里用v2ray实现透明代理的配置是我遇到过的最全面最详细的,所以在此再发一个issue。

大家都知道docker非常流行且实用,在运行v2ray透明代理的linux主机上部署几个docker愿望是不可避免的。
然而,实现起来却困难重重。

我相信其他人也遇到过这种情况,问题表现在:

透明代理正常运行,局域网里的设备可访问docker容器,但是docker容器无法访问外网。

我是在用docker部署RSSHub时遇到此问题。
我觉得问题出在
ip route add local 0.0.0.0/0 dev lo table 100

iptables的V2RAY_MASK链上,

docker使用172.17.0.0/24,貌似会在loop里死循环。

@ToutyRater
Copy link
Owner

ToutyRater commented Nov 1, 2019

那试试通过 iptabels 将 172.17.0.0/24 RETURN 怎么样。
如果还不行再看看 RETURN 掉所有保留 IP

@shaohao
Copy link

shaohao commented Mar 1, 2020

这个问题我暂时找到如下解决方案:主要问题发生在配置了旁路由的情况。比如主路由地址是192.168.1.1,旁路由地址是198.168.1.2。一般旁路由的网关会设置成主路由的192.168.1.1。为保证旁路有中的docker能访问外网那么就需要加入如下规则到V2RAY的chain中
iptables -t mangle -A V2RAY -d 192.168.1.1/32 -p udp -j RETURN
注意配置到tproxy前面,基本上和那些保留地址放一起就好了。这样旁路有就能访问外网了。
其实按照之前的配置,旁路由也是可以访问外网的,只是dns的udp包被v2ray给处理掉了,导致地址解析失败,自然无法访问,但是你如果尝试直接使用ip地址是可以访问外网的。
但是以上解决方案会导致docker中应用的dns走主路由的正常dns解析,无法享用v2ray的dns分流特性。这个,留待后续再行解决吧。

@shaohao
Copy link

shaohao commented Mar 1, 2020

后续跟进研究了一下:一般是把网络上机器的网关设置成装了v2ray的旁路由ip就可以了。而旁路由上若运行了docker,则这个docker自己就创建了一个172.18.0.0的桥接网络,所有docker app都挂在这个桥接网络上,可以理解成运行在网络上的独立一群机器。所以,只要保证docker中的app的网关指向旁路由的ip既可以解决问题。但事实上所有docker app的网关均为旁路由自己设定的主路由的ip。现在要做的,就是想办法把docker桥接网的默认网关换成旁路有自己的ip就可以了。暂时还没找到解决办法,后续跟进

@ToutyRater
Copy link
Owner

@shaohao
感谢分享,你这么一说我就明白是怎么回事了。这个问题不难解决,新建一个用户,将Docker 运行在该用户中,然后利用 iptables 的 --uid-owner 匹配,将该用户的流量转发到 V2Ray 透明代理的端口即可。

@shaohao
Copy link

shaohao commented Mar 3, 2020

这个我没想到过啊。。。有时间回去试一下。我正好也是旁路有docker遇到这样的问题。

@shaohao
Copy link

shaohao commented Mar 10, 2020

今天把docker应用和v2ray运行在同一台机器(或虚拟机)的问题彻底解决了。
个人觉得目前最好的解决办法还是把v2ray独立出来。
我最后的解决方案是:
1.v2ray以docker容器方式运行,并通过透明代理的脚本设置为二级路由器,容器以macvlan挂在host机器上保证物理网络上可作为二级路由所用,假设此接口ip设为为192.168.1.253,网络上上级主路由ip为192.168.1.1,作为macvlan的gateway。
2. host机器上的其他docker应用运行在自己的usernet上,同时把v2ray容器也加入到usernet上,假设此usernet为172.20.0.0/24,v2ray用docker network connect --ip=172.20.0.253加入此网。
3. 通过以上设置,运行v2ray的docker即可作为物理网络的二级路由,又可作为docker应用的二级路由。而且使用docker可以不干扰host自身的iptables和router。
4. 唯一缺憾,所有docker应用需要手动重新设置路由,把每个docker应用的默认路由改为v2ray的ip
ip route del default
ip route add default via 172.20.0.253 dev eth0
这样,每个docker应用自身的网络访问都会走v2ray的docker。同时,要确保物理网络能访问到这些docker应用
ip router add 192.168.1.0/24 via 172.20.0.1
这样,物理网络访问的时候还是走usernet的默认网关。
通过以上设定,基本上就能保证网络主机和docker应用均能正常使用,唯一不足是docker应用运行时需要--cap-add=NET_ADMIN才能修改ip 路由。v2ray的docker因为可以使用自定义脚本,还好处理,但是docker应用往往都是固定死entrypoint的,不好修改,每次重启都要进入运行中的应用容器手动修改,暂时还没有特别好的办法,网上有使用docker events来进行处理的,但个人感觉仍不是特别方便。

@mackgim
Copy link

mackgim commented May 9, 2020

iptables -t mangle -A V2RAY -s 172.17.0.0/16 -j RETURN
我加了这一句,外网就可以访问docker了。
但是ssh,在外网再也登不上了。 没找到办法。

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

4 participants