ToutyRater / v2ray-guide

https://toutyrater.github.io/
1.65k stars 447 forks source link

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

Closed ghost closed 4 weeks ago

ghost commented 5 years ago

由于此教程里用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 commented 5 years ago

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

shaohao commented 4 years ago

这个问题我暂时找到如下解决方案:主要问题发生在配置了旁路由的情况。比如主路由地址是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 commented 4 years ago

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

ToutyRater commented 4 years ago

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

shaohao commented 4 years ago

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

shaohao commented 4 years ago

今天把docker应用和v2ray运行在同一台机器(或虚拟机)的问题彻底解决了。 个人觉得目前最好的解决办法还是把v2ray独立出来。 我最后的解决方案是: 1.v2ray以docker容器方式运行,并通过透明代理的脚本设置为二级路由器,容器以macvlan挂在host机器上保证物理网络上可作为二级路由所用,假设此接口ip设为为192.168.1.253,网络上上级主路由ip为192.168.1.1,作为macvlan的gateway。

  1. host机器上的其他docker应用运行在自己的usernet上,同时把v2ray容器也加入到usernet上,假设此usernet为172.20.0.0/24,v2ray用docker network connect --ip=172.20.0.253加入此网。
  2. 通过以上设置,运行v2ray的docker即可作为物理网络的二级路由,又可作为docker应用的二级路由。而且使用docker可以不干扰host自身的iptables和router。
  3. 唯一缺憾,所有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 commented 4 years ago

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

JiaLiangC commented 1 month ago

补充下:用的v2raya 最新版本,设置那里开启了IP 转发就好了,使用bridge的docker 内网也能访问外网了。