Forwarding a port on the loopback interface to a remote IP/port

I have two Docker containers that I'm trying to network together in a specific way. Container A is running a Redis server on port 6379. Container B is running an interactive shell and needs to access Redis. Using Docker's linking feature, a user inside container B can connect to Redis on through 10.1.0.2:6379, which travels through the virtual eth0 interface set up by Docker.

There is a program that will be running in container B that expects Redis to be available at port 6379 on the loopback interface. Assume that this program cannot be configured to point at a different IP.

I'd like to forward traffic to 127.0.0.1:6379 to 10.1.0.2:6379. I have tried several variations of iptables rules on the NAT table, but I either get "connection refused" when trying to connect to the local address/port, or the connection just hangs forever. What iptables rules can I use to achieve this effect?

Here is one of the things I tried:

$ 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

Attempting to connect to Redis with redis-cli using the above rules just hangs forever. I've tried a version of this that uses PREROUTING/POSTROUTING instead of INPUT/OUTPUT and that resulted in an immediate "connection refused."


I would use socat for that:

socat TCP-LISTEN:6379,fork TCP:10.1.0.2:6379

You might want to run this using supervisor or a similar tool. On 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

Now you can start/stop the redis-socat process using:

supervisorctl start redis-socat 
supervisorctl stop redis-socat

It will also automatically start at boot time.