我有一台具有两个公共 IP 的服务器(Ubuntu):第一个是动态的,第二个是静态的。
服务器上运行的软件连接到公共互联网端点,该端点位于用于将 IP 列入白名单的防火墙后面,因此它需要使用静态 IP 进行出站流量才能正常工作。
服务器配置为静态 IP 位于环回接口上,并设置为
$ sudo vim /etc/network/interfaces.d/eip.cfg
auto lo:1
iface lo:1 inet static
address <static_ip>/32
post-up ip route replace default via <dynamic_ip> src <static_ip>
网络重启后,可以看到静态 IP,如下所示:
$ curl ipinfo.io/ip
<static_ip>
因此,一切正常,并且可以卷曲另一端。一切都很好。
问题
该软件使用 Docker,因此位于使用自定义网络的容器内。
我已经测试过使用--network=host
并且效果很好,因为这将容器放在了主机的网络上(它在那里工作)。
问题是容器必须位于自定义网络上,因为它连接到该网络上的其他内部服务。
我知道 Docker 使用 MASQUERADE,并且可以将其关闭并手动配置 iptables。但是,我想知道还有哪些其他可用选项以及可以推荐的选项是什么。
我愿意听取建议 - 也许有人已经这样做了!谢谢!
答案1
容器中生成的数据包是通过 Docker 主机接口转发的,而不是由主机生成的。src
添加到默认路由的提示不起作用,因为数据包已经有源地址。我相信 iptables masq 仅根据出站接口选择源 IP 地址,所以我认为你只能在默认 MASQ 规则之前插入一条新规则(就像 serverfault 的答案)。
iptables -t nat -I POSTROUTING -p all -s <docker_network>/24 \
-j SNAT --to-source <static_ip>
除非您熟悉 Dockers 对 iptables 的使用,否则完全关闭它可能会导致更多问题。
答案2
最简单的解决方案是使用--outgoing-ip
命令选项docker run
命令。此示例表示具有传出 IPv4 地址的容器。对于 IPv6,请改用--outgoing-ip6
。
另一种方法是在网络定义中定义它并添加一些iptables规则,你会得到类似这样的内容:
# docker network create <NETWORK NAME> --subnet=192.168.10.0/24 \ --gateway=192.168.10.1
# iptables -t nat -I POSTROUTING -s \ 192.168.10.0/24 -j SNAT --to-source OUTGOING_IP
Docker 将有POSTROUTING 规则。
然后将容器连接到这个创建的自定义网络。这些容器的所有流量都将通过指定的 IP 地址。
# docker network connect <NETWORK-NAME> <CONTAINER>