将环回接口上的端口转发到远程 IP/端口

Jim*_*mmy 5 networking nat iptables port-forwarding loopback

我有两个 Docker 容器,我试图以特定方式将它们联网。容器 A 在端口 6379 上运行 Redis 服务器。容器 B 正在运行交互式 shell,需要访问 Redis。使用 Docker 的链接功能,容器 B 中的用户可以通过 10.1.0.2:6379 连接到 Redis,该地址通过 Docker 设置的虚拟 eth0 接口传输。

有一个程序将在容器 B 中运行,它希望 Redis 在环回接口的 6379 端口可用。假设此程序无法配置为指向不同的 IP。

我想将流量转发到 127.0.0.1:6379 到 10.1.0.2:6379。我在 NAT 表上尝试了几种 iptables 规则的变体,但是在尝试连接到本地地址/端口时,我要么得到“连接被拒绝”,要么连接永远挂起。用什么iptables规则可以达到这个效果?

这是我尝试过的一件事:

$ sudo iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-A INPUT -d 10.1.0.2/32 -p tcp -m tcp --dport 6379 -j SNAT --to-source 127.0.0.1
-A OUTPUT -p tcp -m tcp --dport 6379 -j DNAT --to-destination 10.1.0.2:6379
Run Code Online (Sandbox Code Playgroud)

尝试redis-cli使用上述规则连接到 Redis只会永远挂起。我尝试了一个使用 PREROUTING/POSTROUTING 而不是 INPUT/OUTPUT 的版本,这导致立即“连接被拒绝”。

and*_*ler 3

我会为此使用 socat:

socat TCP-LISTEN:6379,fork TCP:10.1.0.2:6379
Run Code Online (Sandbox Code Playgroud)

您可能想使用主管或类似工具来运行它。在Ubuntu上:

apt-get install socat supervisor

cat > /etc/supervisor/conf.d/redis-socat.conf << EOF
[program:redis-socat]
command = socat TCP-LISTEN:6379,fork TCP:10.1.0.2:6379
autorestart = true
user = nobody
EOF

supervisorctl reload
Run Code Online (Sandbox Code Playgroud)

现在您可以使用以下命令启动/停止 redis-socat 进程:

supervisorctl start redis-socat 
supervisorctl stop redis-socat
Run Code Online (Sandbox Code Playgroud)

它还会在启动时自动启动。