How to make Docker container see real user IP?

Finally, answering my own question.

After some research I have found that it was IP masquerading that caused Docker to recognize client addresses incorrectly.

The cause

In my case, firewalld is configured to share internet connection with other machines in local network. This is accomplished by setting zone to public for the external interface (enp3s0) and to internal for the local interfaces (enp1s0, enp2s0), and by enabling IP masquerading for outgoing packages.

And that’s it. Masquerading is also applied to packages coming from public network to docker networks, as if the package was going to (another) external interface.

Solution

As far as I understand all that iptables and Docker stuff, there is one acceptable workaround: add all virtual network interfaces created by Docker to the internal zone, so masquerading rule is not applied to packages going to the corresponding networks. For example:

# firewall-cmd --permanent --zone=internal --change-interface=br-192821446c9a

To make the solution persistent, it is required to create the corresponding script in the /etc/sysconfig/network-scripts directory. For example, for the br-192821446c9a interface, a file /etc/sysconfig/network-scripts/ifcfg-br-192821446c9a should be created, with the following content:

DEVICE=br-192821446c9a
TYPE=Bridge
BOOTPROTO=none
IPADDR=172.18.0.1
PREFIX=16
DEFROUTE=yes
IPV4_DNS_PRIORITY=100
NAME=br-192821446c9a
ONBOOT=no
ZONE=internal

Hope this answer will save somebody’s time.

Leave a Comment