3

I have a pair of docker containers running on the host machine, these containers together makes my application fulfill. So for each iteration/instance of my application requires a pair of docker containers to run. So far I'm using the --link parameter while running the second container to link the first container and get the IP of the first container from hosts file to use it programmatically.

Now, I need to setup a transparent proxy for the second docker container. so that, all http (port 80) traffic of the second container should be going through the port 8080 of the first container.

First container IP: 172.17.0.4 (Has proxy service running on port 8080). Second container IP: 172.17.0.6 (Has client tools like browser). I wanted to forward all http traffic (Port 80) of the 172.17.0.6 to the port 8080 of the 172.17.0.4.

i.e) Traffic to 80 of 172.17.0.4 <---> 8080 of 172.17.0.6

I have tried adding the iptables rules inside the second container for the above configuration. But none of them worked.

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

Doesn't work.

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

Doesn't work.

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

So my question is, how can I configure a transparent proxy inside a docker container that can forward all traffic of a specified port to another container's port?

P.S: If I manually add the proxy settings to the browser in the second container. It is working fine. But I wanted to set the transparent proxy for the entire container, not only the browser. so that any network request from any tool inside the second container will be forwarded to the first container's proxy port.

I have read some tutorials on reverse-proxying the all the containers running together using nginx/HAProxy. But I wanted to configure individual container with it's own proxy container as a pair.

3

Thank you all for your time to answer. Basically what I'm trying to do is to proxy the outgoing/originated traffic of the 2nd container (NOTE: I'm NOT trying to proxy the incoming traffic, so cannot use the Apache mod_proxy or Nginx proxy_pass. These modules works for incoming traffic). 1st container runs a proxy service on port 8080.

As Thierno suggested I can use http_proxy and https_proxy ENV variables to proxy the outgoing traffic, but unfortunately NOT all the applications/services running in your operating system respects these http_proxy and https_proxy ENV variables. There are applications that force skip the proxy settings. That is the reason why I wanted to use iptables to enforce the traffic rules. Thus none of the application/service can skip the proxy.

The mistake I did in the previous settings on the question is, I was trying to route the incoming traffic to port 80 to 8080 of proxy server. Since the 1st container doesn't have any incoming traffic it won't work and it is logically wrong to PREROUTE/POSTROUTE the traffic to achieve what I was looking for. To route the originated/outgoing traffic, we need to use OUTPUT chain of the iptables.

My Solution:

I have used RedSocks with iptables combination to enforce the proxy for the complete outgoing traffic from the server. Here is the iptables configuration I've used:

# Create new chain for RedSocks

root# iptables -t nat -N REDSOCKS

# Ignore LANs and some other reserved addresses

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

# Redirect all the http to redsocks local port

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

# for https traffic just replace port 80 with 443

# Use all REDSOCKS chain for all the outgoing traffic at eth0

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

Now, configure redsocks to listen to the local port 12345 for the incoming traffic and forward it to the proxy server's IP and port. To do this edit redsocks.conf as like this,

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

just save the conf and restart the redsocks service. Now all the outgoing traffic originated from the 1st container will be enforced to use the proxy. (NOTE: I've used iptables-persistent to persist the rules over server reboots) Actually I have implemented the same for both http and https traffic by adding another line to the iptables configuration. Although it's not a transparent proxy, it does the job for me.

If anyone have any other alternative solutions to this please suggest.

  • Great! Thanks for sharing this. Although it's not transparent it at least solves the problem in the case where you have a client that you cannot fix but you can manipulate the image it runs in. – jkp Feb 1 '17 at 16:08
0

Reciprocal linking isn't something docker has, so far as I know ( info revealed at run time about a container back ported or reciprocated to a progenitor). That's probably why most tutorials have a third, common ancestor, 'proxy' being used.

If you're willing to use frameworks like fig or weave, that I believe have yaml or json configuration files, you'd probably be able to set this up with just two reciprocal containers.

If you're willing to have a third, then all the ports and plumbing could be linked via the common ancestor for both of your 'sibling' containers.

0

I think that using the $http_proxy env var should help.

You can set an entrypoint in your docker file (for the container #2) to export the env var when the container is starting. Somewhere in your entrypoint, you should have something like this:

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

I don't know exactly if your client (browser) can use the $http_proxy env var, but it should exist a similar method. By example, for 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);

Tips: use printenv on the second container to know what variables name you should use in your entrypoint

  • Thank you Thierno. Yes, My browser uses the http_proxy and https ENV variables. But I wanted to implement the proxy for the whole outgoing/originate traffic out of the container, basically any application/service running inside the system. I found only way to achieve this is to enforce the traffic to use proxy server using iptables or any other firewall tool. Please suggest if you can find any alternate to my answer below. – Gowtham Sadasivam Jan 31 '15 at 6:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.