DEV Community

s.shivasurya
s.shivasurya

Posted on

Get Remote Ip Address of the Client in Container When using Reverse proxy as Nginx in Docker Swarm

Getting remote IP address and forwarding to the internal service is not a big deal when running in normal server instance. But when you set up and think to scale using Docker Swarm it's quite frustrating and it made me a whole day to figure out and fix it.

Docker Swarm networking overlay doesn't provide access to the IP Address of the client which is normally treated as L4 layer. There is a huge discussion going on in GitHub (https://github.com/moby/moby/issues/25526 ) with exploding comments. Why?

  1. You can't monitor user access and logs location
  2. Rate limiting with IP level checks
  3. Monitoring tools such as Prometheus needs exact client IP to bring better analytics and monitoring
  4. Proving country-specific information such as pricing, payments, timezone and even more personalized geographical based contents.

Solution Please,

  1. Hardware-level -> Add L7 load balancer as a physical machine ( server instance ) and terminate the SSL and forward the traffic with the IP Address x-real-ip or x-forwarded-for to your internal service or application behind a proxy

  2. Swarm Solution ( Work Around that completely defeats the purpose of Docker swarm and routing with load balancing )

services:
  load_balancer:
    image: nginx:some_version
    deploy:
      mode: global
      constraint:
         - node.role == worker ( It's upto your wish )
    ports:
      - target: 80
        published: 80
        protocol: tcp
        **mode: host**
      - target: 443
        published: 443
        protocol: tcp
        **mode: host**
    networks:
      - your_internal_overlay_network
      - your_external_overlay_network

networks:
   your_internal_overlay_network:
   your_external_overlay_network:
     - external:
         name: your_external_overlay_network ( create with docker network command )


`

This will simply allow the nginx container to receive the traffic in 80 & 443 and forwards to the intranet service. But the twist is you can't scale this container just using the docker scale command which is bind to 80 & 443 once and doesn't share the load between multiple containers when the traffic to the application increases. It's not that bad, but you can balance pretty high traffic such as 3K req/min and it depends on the machine. Now, Your nginx receives the Real Client Ip and you can forward it internally for processing.

Alternate costly solution:

Switch to Load Balancer such as ELB ( Aws load balancer to manage your certificate and SSL offloading and bring your swarm proxy behind the ELB. Giving this option, You give in the lock to AWS and when you migrate from the platform it will create chaos. )

If you have any doubts, do let me know. Happy Docking!

Top comments (0)