我的解决方案:

我的解决方案:

我在主机上运行了一对 docker 容器,这些容器一起使我的应用程序得以实现。因此,对于我的应用程序的每个迭代/实例,都需要一对 docker 容器来运行。到目前为止,我在运行第二个容器时使用 --link 参数来链接第一个容器,并从 hosts 文件中获取第一个容器的 IP 以编程方式使用它。

现在,我需要为第二个 docker 容器设置一个透明代理。这样,第二个容器的所有 http(端口 80)流量都应该通过第一个容器的端口 8080。

第一个容器IP:172.17.0.4(在端口上运行代理服务8080).第二个容器IP:172.17.0.6(有浏览器等客户端工具)。我想转发所有 http 流量(端口80) 的172.17.0.6到港口8080172.17.0.4

IE)流量到 172.17.0.4 的 80 <--> 172.17.0.6 的 8080

我尝试在第二个容器内添加 iptables 规则以实现上述配置。但都不起作用。

~# sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 172.17.0.4:8080

不起作用。

~# sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 172.17.0.4:8080

不起作用。

~# sudo iptables -t nat -A POSTROUTING -j MASQUERADE

所以我的问题是,如何在 Docker 容器内配置一个透明代理,以便将指定端口的所有流量转发到另一个容器的端口?

附言: 如果我手动将代理设置添加到第二个容器中的浏览器。它工作正常。但我想为整个容器设置透明代理,而不仅仅是浏览器。这样第二个容器内任何工具的任何网络请求都将转发到第一个容器的代理端口。

我读过一些关于使用 nginx/HAProxy 对所有同时运行的容器进行反向代理的教程。但我想将单个容器与其自己的代理容器配置为一对。

答案1

谢谢大家抽出时间回答。基本上,我想做的是代理传出/发起第二个集装箱的运输(笔记:我是不是尝试代理传入流量,因此无法使用 Apache mod_proxy 或 Nginx proxy_pass。这些模块适用于传入流量)。第一个容器在端口 8080 上运行代理服务。

正如 Thierno 建议的那样,我可以使用 http_proxy 和 https_proxy ENV 变量来代理传出流量,但不幸的是不是操作系统中运行的所有应用程序/服务都遵守这些 http_proxy 和 https_proxy ENV 变量。有些应用程序会强制跳过代理设置。这就是我想要使用的原因iptables 执行流量规则. 因此没有任何应用程序/服务可以跳过代理。

我在之前的设置中犯的错误是,我试图将传入流量路由到代理服务器的端口 80 到 8080。由于第一个容器没有任何传入流量,因此它无法工作,而且PREROUTE/POSTROUTE 通信在逻辑上是错误的实现我想要的效果。要路由发起/传出的流量,我们需要使用输出链的 iptables。

我的解决方案:

我已将 RedSocks 与 iptables 结合使用,以强制代理服务器发出的所有传出流量。以下是我使用的 iptables 配置:

# 为 RedSocks 创建新链

root# iptables -t nat -N REDSOCKS

# 忽略 LAN 和一些其他保留地址

root# iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
root# iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
root# iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
root# iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
root# iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
root# iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
root# iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
root# iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN

# 将所有 http 重定向到 redsocks 本地端口

root# sudo iptables -t nat -A REDSOCKS -p tcp --dport 80 -j REDIRECT --to-ports 12345

# 对于 https 流量,只需将端口 80 替换为 443

# 使用所有 REDSOCKS 链来处理 eth0 上的所有传出流量

root# sudo iptables -t nat -A OUTPUT -p tcp -o eth0 -j REDSOCKS

现在,配置 redsocks 以监听本地端口 12345 的传入流量并将其转发到代理服务器的 IP 和端口。为此编辑 redsocks.conf就像这样,

redsocks {
local_ip = 127.0.0.1;
local_port = 12345;
ip = 172.17.0.4;
port = 8080;
type = http-relay;
}

只需保存配置并重新启动 redsocks 服务。现在所有来自第一个容器的传出流量都将被强制使用代理。(笔记:我使用 iptables-persistent 在服务器重启后保留规则)实际上,我通过在 iptables 配置中添加另一行,为 http 和 https 流量实现了相同的功能。虽然它不是透明代理,但它为我完成了工作。

如果有人对此有其他替代解决方案,请提出建议。

答案2

据我所知,docker 没有提供相互链接功能(运行时会显示有关容器反向移植或向祖先容器相互移植的信息)。这可能就是为什么大多数教程都使用了第三个共同祖先“代理”。

如果您愿意使用像 fig 或 weave 这样的框架(我相信它们有 yaml 或 json 配置文件),您可能只需使用两个相互容器即可进行设置。

如果您愿意拥有第三个,那么所有端口和管道都可以通过两个“兄弟”容器的共同祖先进行链接。

答案3

我认为使用$http_proxy环境变量应该有帮助。

您可以在 docker 文件中设置一个入口点(针对容器 #2),以便在容器启动时导出环境变量。在您的入口点的某个地方,您应该有类似以下内容:

export http_proxy=http://$CONATAINER1_PORT_8080_TCP_ADDR:$CONATAINER1_PORT_8080_TCP_PORT

我不知道你的客户端(浏览器)是否可以使用 $http_proxy 环境变量,但应该存在类似的方法。例如,对于 Firefox:

user_pref("network.proxy.http", "$CONATAINER1_PORT_8080_TCP_ADDR");
user_pref("network.proxy.http_port", $CONATAINER1_PORT_8080_TCP_PORT);
user_pref("network.proxy.type", 1);

尖端:printenv在第二个容器上使用以了解您应该在入口点使用什么变量名称

相关内容