Preserve client IP

Related Documentation

Kong Gateway is deployed using a Kubernetes Service of type LoadBalancer. This can result in the loss of the actual client IP address, and can lead to Kong Gateway observing the IP address of the Load Balancer as the client IP address. This guide lays out different methods of solving this problem.

Preserving the client IP address in the cloud behind Load Balancers requires configuration that is specific to your use case, cloud provider, and other architecture details. The documentation for Using Source IP provides details on how networking and the various methods work inside Kubernetes. We recommend that you read this document.

To preserve the client IP address, you can use one of the following methods:

  • ExternalTrafficPolicy
  • Proxy Protocol
  • HTTP headers

ExternalTrafficPolicy: Local

As explained in the Kubernetes docs, setting service.spec.externalTrafficPolicy to Local preserves the client IP address. You don’t need to change any configuration in Kong Gateway if you are using this method to preserve the client IP address.

This method is not supported by all cloud providers.

Proxy Protocol

If you have an L4 Load Balancer that supports Proxy Protocol, and you’re terminating TCP connections at the Load Balancer before passing traffic onward to Kong Gateway, then you can configure Kong Gateway to set the client IP address through this protocol.

Once you have configured the Load Balancer to use Proxy Protocol, you need to set the following environment variables in Kong Gateway to receive the client IP from the Proxy Protocol header:

Parameter Description
KONG_PROXY_LISTEN Default: 0.0.0.0:8000 reuseport backlog=16384, 0.0.0.0:8443 http2 ssl reuseport backlog=16384

Comma-separated list of addresses and ports on which the proxy server should listen for HTTP/HTTPS traffic. The proxy server is the public entry point of Kong, which proxies traffic from your consumers to your backend services. This value accepts IPv4, IPv6, and hostnames.

Some suffixes can be specified for each pair:

  • ssl will require that all connections made through a particular address/port be made with TLS enabled.
  • http2 will allow for clients to open HTTP/2 connections to Kong’s proxy server.
  • proxy_protocol will enable usage of the PROXY protocol for a given address/port.
  • deferred instructs to use a deferred accept on Linux (the TCP_DEFER_ACCEPT socket option).
  • bind instructs to make a separate bind() call for a given address:port pair.
  • reuseport instructs to create an individual listening socket for each worker process allowing the Kernel to better distribute incoming connections between worker processes
  • backlog=N sets the maximum length for the queue of pending TCP connections. This number should not be too small in order to prevent clients seeing “Connection refused” error connecting to a busy Kong instance. Note: on Linux, this value is limited by the setting of net.core.somaxconn Kernel parameter. In order for the larger backlog set here to take effect it is necessary to raise net.core.somaxconn at the same time to match or exceed the backlog number set.
  • ipv6only=on|off whether an IPv6 socket listening on a wildcard address [::] will accept only IPv6 connections or both IPv6 and IPv4 connections
  • so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt] configures the “TCP keepalive” behavior for the listening socket. If this parameter is omitted then the operating system’s settings will be in effect for the socket. If it is set to the value “on”, the SO_KEEPALIVE option is turned on for the socket. If it is set to the value “off”, the SO_KEEPALIVE option is turned off for the socket. Some operating systems support setting of TCP keepalive parameters on a per-socket basis using the TCP_KEEPIDLE, TCP_KEEPINTVL, and TCP_KEEPCNT socket options.

This value can be set to off, thus disabling the HTTP/HTTPS proxy port for this node. If stream_listen is also set to off, this enables ‘control-plane’ mode for this node (in which all traffic proxying capabilities are disabled). This node can then be used only to configure a cluster of Kong nodes connected to the same datastore.

Example: proxy_listen = 0.0.0.0:443 ssl, 0.0.0.0:444 http2 ssl

See http://nginx.org/en/docs/http/ngx_http_core_module.html#listen for a description of the accepted formats for this and other *_listen values.

See https://www.nginx.com/resources/admin-guide/proxy-protocol/ for more details about the proxy_protocol parameter.

Not all *_listen values accept all formats specified in nginx’s documentation.

KONG_REAL_IP_HEADER Default: X-Real-IP

Defines the request header field whose value will be used to replace the client address. This value sets the ngx_http_realip_module directive of the same name in the Nginx configuration.

If this value receives proxy_protocol:

  • at least one of the proxy_listen entries must have the proxy_protocol flag enabled.
  • the proxy_protocol parameter will be appended to the listen directive of the Nginx template.

See http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header for a description of this directive.

KONG_TRUSTED_IPS

Defines trusted IP addresses blocks that are known to send correct X-Forwarded-* headers. Requests from trusted IPs make Kong forward their X-Forwarded-* headers upstream. Non-trusted requests make Kong insert its own X-Forwarded-* headers.

This property also sets the set_real_ip_from directive(s) in the Nginx configuration. It accepts the same type of values (CIDR blocks) but as a comma-separated list.

To trust all /!\ IPs, set this value to 0.0.0.0/0,::/0.

If the special value unix: is specified, all UNIX-domain sockets will be trusted.

See http://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from for examples of accepted values.

For example:

KONG_TRUSTED_IPS=0.0.0.0/0,::/0  # This trusts all IPs
KONG_PROXY_LISTEN="0.0.0.0:8000 proxy_protocol, 0.0.0.0:8443 ssl proxy_protocol"
KONG_REAL_IP_HEADER=proxy_protocol

HTTP headers

If you are using an L7 Load Balancer where HTTP requests are being terminated at the Load Balancer, you need to use the x-forwarded-for or x-real-ip header to preserve details of the connection between the client and Load Balancer.

You should configure the Load Balancer to inject these headers, and then you need to set the following environment variables in Kong Gateway to pick up the client IP address from HTTP headers:

Parameter Description
KONG_REAL_IP_HEADER Default: X-Real-IP

Defines the request header field whose value will be used to replace the client address. This value sets the ngx_http_realip_module directive of the same name in the Nginx configuration.

If this value receives proxy_protocol:

  • at least one of the proxy_listen entries must have the proxy_protocol flag enabled.
  • the proxy_protocol parameter will be appended to the listen directive of the Nginx template.

See http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header for a description of this directive.

KONG_REAL_IP_RECURSIVE Default: off

This value sets the ngx_http_realip_module directive of the same name in the Nginx configuration.

See http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive for a description of this directive.

KONG_TRUSTED_IPS

Defines trusted IP addresses blocks that are known to send correct X-Forwarded-* headers. Requests from trusted IPs make Kong forward their X-Forwarded-* headers upstream. Non-trusted requests make Kong insert its own X-Forwarded-* headers.

This property also sets the set_real_ip_from directive(s) in the Nginx configuration. It accepts the same type of values (CIDR blocks) but as a comma-separated list.

To trust all /!\ IPs, set this value to 0.0.0.0/0,::/0.

If the special value unix: is specified, all UNIX-domain sockets will be trusted.

See http://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from for examples of accepted values.

real_ip_recursive is optional.

Cloud-provider specific details

For the major public clouds, there are some additional details that can help you preserve the client IP address.

GKE

You can use ExternalTrafficPolicy: Local to preserve the client IP address.

AKS

You can use ExternalTrafficPolicy: Local to preserve the client IP address.

EKS

You have three options:

  • L4 Network Load Balancer, with AWS Load Balancer Controller: In this case, you can use the Proxy Protocol method to preserve the client IP address together with ExternalTrafficPolicy: Cluster.
  • L4 in-tree network Load Balancer with the service.beta.kubernetes.io/aws-load-balancer-type: nlb annotation: In this case, you need to use ExternalTrafficPolicy: Local to preserve the client IP address.
  • L7 Load Balancer: In this case, you need to use the HTTP headers method to preserve the client IP address.

The recommended Load Balancer type for AWS is the Network Load Balancer deployed with the AWS Load Balancer Controller. You can choose this type of Load Balancer using the following annotations:

service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"

To enable proxy protocol with the AWS Load Balancer Controller, you need to set these annotations:

service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"

See the list of annotations for the AWS Load Balancer Controller for all options.

Something wrong?

Help us make these docs great!

Kong Developer docs are open source. If you find these useful and want to make them better, contribute today!