1

I am using Docker 17.04.0-ce on Ubuntu 16.04.

I am running several containers on my host which expose public ports, some should be only accessible by certain ip ranges, while others, like an nginx proxy listening on port 80 and 443, should be publicly accessible.

Using the default configuration my iptables configuration of the INPUT chain was ignored, allowing all containers with bound ports to be accessed from anywhere. So I learned that I had to provide the --iptables=false option to docker, which worked fine.

While I now can control the access to the different ports using iptables, my nginx container is no longer able to see the ip address of the connecting client, but only gets the ip of the docker0 bridge (172.17.41.1 in my case).

Is there any way to allow the nginx container to see the connecting clients ip without loosing control over iptables again?

Side note: I do not want to put all containers on the host net (--net=host).

1
  • 1
    So, how did you solve this at the end?
    – qqilihq
    Aug 28, 2017 at 16:08

3 Answers 3

1

This depends on your IPTABLES setup. It sounds as if you masquerade while forwarding, something like this:

iptables -t nat -A POSTROUTING --out-interface docker0 -j MASQUERADE

If you want the client to see the original IP, you have to disable masquerading, and just use NAT and PREROUTING. There are tons of manuals for this out there.

Just make sure your containers use your host as default route, otherwise you'll end up not being able to answer because your responses don't originate from the correct ip.

To say more, you'd need to post your iptables configuration...

3
  • thanks for your answer, but iptables -t nat -L POSTROUTING does not show a single entry (this is what you meant, right?)
    – muffel
    Jul 10, 2016 at 12:55
  • Can you post all iptables commands you use which are related to this container / interface?
    – BeerSerc
    Jul 11, 2016 at 14:53
  • I tried it again with a clean new VM and did the following steps: (1) added --iptables=false option to docker daemon. (2) ran the following command docker run --rm -it -p 80:80 nginx:1.11 (3) If I open a web browser with the VM's ip, the nginx container output shows the internal docker ip (172.17.0.1 in my case), instead of the correct ip of my remote host. If I omitted the --iptables=false option, the correct ip is shown.
    – muffel
    Jul 13, 2016 at 10:41
1

I was able to see connecting clients ip from my container using --net=host.

  1. use --iptables=false, so docker will not mess up with your host's iptables config.
  2. Enable ip forwarding on your docker host: echo 1>/proc/sys/net/ipv4/ip_forward
  3. --net=host Tell Docker to skip placing the container inside of a separate network stack. In essence, this choice tells Docker to not containerize the container's networking! docker run -d -p 80:80 --net=host -name some-container your-image

From https://docs.docker.com/v1.5/articles/networking/#the-world :

--net=host — Tells Docker to skip placing the container inside of a separate network stack. In essence, this choice tells Docker to not containerize the container's networking! While container processes will still be confined to their own filesystem and process list and resource limits, a quick ip addr command will show you that, network-wise, they live “outside” in the main Docker host and have full access to its network interfaces. Note that this does not let the container reconfigure the host network stack — that would require --privileged=true — but it does let container processes open low-numbered ports like any other root process. It also allows the container to access local network services like D-bus. This can lead to processes in the container being able to do unexpected things like restart your computer. You should use this option with caution.

2
  • thanks, but I do not want to place the container in the same network. They need to communication without being reachable from the outer network. I should have mentioned this before.
    – muffel
    Jul 10, 2016 at 12:55
  • I've been trying to get my containers to run on the host network for the past 2 days only to find out that it isn't supported on non-Linux OS. stackoverflow.com/a/52554681/687245
    – louis1204
    Jul 14 at 20:35
0

By default, Docker use a userland proxy (docker-proxy) to expose ports.

Try disable it with:

--userland-proxy=false
2
  • thanks for your answer! If I understand the documentation correctly this option forces docker to uses plain iptables rules. But that is what I disabled in the first place because I what to restrict the traffic by manual rules. So no option for me (or am I missing something?)
    – muffel
    Jul 10, 2016 at 12:59
  • This option disable the userland proxy and add iptables rules instead. But if you disable iptables, i think you juste have to add masquerade and nat manually to iptables. Jul 12, 2016 at 8:51

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.