How can a web-server container inside a docker bridge network get the public IP address of a HTTP request?

Hi,

I have a few .NET microservices inside a docker compose bridge network. The gateway (reverse proxy) of this network is the only one that is communicating with outside world via its published ports. For every HTTP request, I’m getting the ::ffff:172.18.0.1 as the IP address which is the docker compose gateway IP address. How can I know what is the public IP address of the request?

docker-compose-q

You can use Proxy Protocol or let the proxy to set some HTTP headers containing the original IP, then get the “Real IP” from HTTP headers like “X-Forwarded-For”. I don’t know yarp, but I think this is the relevant documentation

https://microsoft.github.io/reverse-proxy/articles/transforms.html

I already did that. No luck :frowning:

Does docker provide the original IP address in forward headers?

Docker itself doesn’t do anything with HTTP headers and doesn’t change anything in the applications. It will just do the isolation of the process so the proxy server and the application in the container should work together to get the original IP address.

The clients connect to the proxy, the proxy forwards the request so it becomes the client. It has to forward the original IP address in an HTTP header so the application can use that. Note that the application to which the proxy forwarded the request has to read the header without proxy protocol. Recently I don’t use proxy protocol by the way, but I don’t remember why. Even if your application can handle that header, you will still see the IP of the proxy in an HTTPD access log by default. You can change that in the HTTPD configuration file. This is probably true for any server software, but I can’t say for sure.

You see, my gateway is also inside the private docker network. Now when I inspect the Network the gateway has the 172.18.0.11 address itself. And the private bridge network has the following config:

...
    "Scope": "local",
    "Driver": "bridge",
    "EnableIPv6": false,
    "IPAM": {
        "Driver": "default",
        "Options": null,
        "Config": [
            {
                "Subnet": "172.18.0.0/16",
                "Gateway": "172.18.0.1"
            }
        ]
    },
    "Internal": false,
    "Attachable": false,
    "Ingress": false,
    "ConfigFrom": {
        "Network": ""
    },
    "ConfigOnly": false,
...

All other containers are getting the 172.18.0.1 IP address, which is not the proxy’s address but the docker network gateway address. This means the proxy is doing its job and the clients are also using the forward headers correctly. Now the problem is that how can the proxy ask docker for the real IP address. Basically the docker also has to provide the original IP address to the proxy in some way.

Otherwise I have to put my proxy outside of the docker bridge network, or I have to change the network mode on docker compose.

x-forwarded-for docker-compose network · Issue #1287 · nginx-proxy/nginx-proxy (github.com)

I have been using Jason Wilder’s nginx-proxy with Docker Compose for years, so believe me, it works :slight_smile:

On your shared picture the Reverse Proxy is YARP. That should work the same way. Of course, the proxy is in Docker’s network, but when you forward a port from the host to the container and you send the request fto the host machine’s IP address, it will see the client’s IP address. You would only see the gateway’s IP if you sent the request to localhost like this:

curl localhost:9999

since this sends the request to a loopback interface and the “gateway” is actually your server. You can for example run a service on your host which listens on 172.18.0.1. The result is the same when you send the request directly to the container’s IP address.

curl 172.18.0.2

but it would work from an external machine or by sending the request the host’s IP

curl <HOST IP>

When the proxy sends the request to the application container, it should see the proxy container’s IP address since that is where the request is coming from.so there is nothing between those containers to change the IP.

You only see the IP of the gateway when the gateway creates a new request.