Report this

What is the reason for this report?

How to get Client IP using DO Loadbalancer and APISIX as ingress controller

Posted on October 22, 2024

Hi all,

I’m trying to get client IPs behind a DO loadbalancer using APISIX as an ingress controller / API gateway. I enabled the proxy protocol on the DO loadbalancer but can’t get it to work unfortunately.

My current configuration:

dataPlane:
  service:
    annotations:
      service.beta.kubernetes.io/do-loadbalancer-name: "lb-name"
      service.beta.kubernetes.io/do-loadbalancer-size-unit: "1"
      service.beta.kubernetes.io/do-loadbalancer-tls-passthrough: "true"
      service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"
    extraConfig:
      apisix:
        proxy_protocol:
          listen_http_port: 9181
          listen_https_port: 9182
      nginx_config:
        http:
          real_ip_header: proxy_protocol

I’m hosting multiple domains including TLS certificates (from Let’s Encrypt) on the current loadbalancer configuration, but I would like to get the client IPs. Also would like to avoid creating a loadbalancer with TLS terminiation per domain as this could increase costs unnecessarily.

Any help appreciated, thanks !



This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Hi there,

Usually enabling PROXY Protocol is the way to get the real client IP, but APISIX needs to be configured properly to handle it.

You should be able to do that by:

  1. First, enable PROXY Protocol on the LB. Add this annotation to your Kubernetes Service:

    service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"
    service.beta.kubernetes.io/do-loadbalancer-tls-passthrough: "true"
    

    This ensures the LB sends the original client IP.

  2. Then configure APISIX to expect the PROXY Protocol. Update your APISIX config:

    apisix:
      proxy_protocol:
        listen_http_port: 80
        listen_https_port: 443
      enable_tcp_pp: true
    nginx_config:
      http:
        real_ip_header: proxy_protocol
    

    Without this, APISIX won’t interpret the client IP correctly.

  3. Also, set externalTrafficPolicy: Local. This prevents Kubernetes from SNAT’ing the source IP:

    spec:
      externalTrafficPolicy: Local
    

As far as I can tell from the docs, APISIX requires dedicated ports for PROXY Protocol, so your existing listeners may need adjustments.

If PROXY Protocol isn’t working as expected, an alternative is to let the LB handle TLS termination and use X-Forwarded-For, but DigitalOcean LBs don’t support multiple TLS certificates, which could be a dealbreaker.

- Bobby

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.