By default, when using Civo and NGINX Ingress Controller or Traefik, the incoming request will not pass the source IP of packets through to the Kubernetes service and ultimately to the containerized application (running in a pod). Instead, the application will see an intermediary IP (e.g. in-cluster NGINX pod’s IP as the source). With the following configuration change, the application will be able to see the source IP of packets and proceed with its business logic (i.e. If the IP is from the Asia Pacific region, redirect to the APAC corporate site, otherwise, stay on the current/global site).

preserve source ip

This figure shows the preservation of the client’s public IP when both the “externalTrafficPolicy” on the LoadBalancer service is set to “Local” as well as the “enable Proxy protocol” annotation is added and set to “send-proxy”. When the client sends the request to the Kubernetes service (1), the packet header is changed, and the request will now preserve the client’s public IP (i.e. 148.73.223.18) all the way to the pod.

This tutorial provides instructions on how to preserve the source IP for applications running on Kubernetes, with specific sections tailored for users of NGINX Ingress Controller and Traefik.

Prerequisites

Before you start with the setup to preserve the source IP for applications running on Kubernetes using NGINX Ingress Controller or Traefik on Civo, ensure you have the following prerequisites in place:

  • Civo Kubernetes Cluster: You must have an active Civo account and a Kubernetes cluster set up on Civo.
  • Kubectl: You must have kubectl installed on your host, in order to interact with the Kubernetes cluster via the command-line.
  • Helm: Helm, the package manager for Kubernetes, is required for installing the NGINX Ingress Controller or Traefik. If you haven't installed Helm yet, you can do so through our Civo Marketplace when setting up your cluster.
  • Access to Your Cluster: Ensure you have downloaded the Kubeconfig from the Civo dashboard, and the appropriate role is assigned to your user in order to create deployments, services, and ingress resources within your cluster.
  • DNS Configuration (Optional): If you plan to test the ingress with a real domain, have access to your DNS provider to configure DNS records. This is optional for testing purposes, as you can also test using the LoadBalancer IP/DNS directly.
  • Cloudflare DNS (Recommended for Testing): For faster DNS propagation during testing, it's recommended to use Cloudflare's DNS servers (1.1.1.1 and 1.0.0.1). This step is optional but can help reduce wait times during DNS propagation.
  • jq (Optional): Some commands may utilize jq, a lightweight and flexible command-line JSON processor, for parsing command output. While not mandatory, installing jq could enhance your command-line experience. Visit the jq documentation for installation instructions.
  • Familiarity with Kubernetes Concepts: A basic understanding of Kubernetes concepts, such as deployments, services, and ingress, is necessary to follow the instructions effectively.
  • Network Policies (If applicable): If your cluster has network policies in place, ensure they are configured to allow traffic as required for the ingress controllers to function properly.
Note: For the setup to preserve the source IP using an Ingress controller on Civo, it is recommended to use Kubernetes version 1.25.x or newer, NGINX Ingress Controller v1.10.0 or newer, Traefik version 2.4 or newer, and Helm version 3.5.x or newer.

Installing NGINX Ingress Controller

The following will guide you through the process of creating a deployment using the kennethreitz/httpbin image, creating a service, installing the NGINX Ingress Controller via Helm chart, changing the NGINX service configuration, and creating an ingress to ensure the preservation of the source IP.

Step 1. Create a HTTPbin Deployment using kennethreitz/httpbin image:

kubectl create deployment my-httpbin --image=kennethreitz/httpbin

Step 2. Create a Service for Deployment:

kubectl expose deployment my-httpbin --port=80 --name=my-httpbin-svc

Step 3. Install Nginx ingress controller:

helm upgrade --install ingress-nginx ingress-nginx \
    --repo https://kubernetes.github.io/ingress-nginx \
    --namespace ingress-nginx --create-namespace

Step 4. Edit the ingress-nginx-controller Service in ingress-nginx namespace:

kubectl -n ingress-nginx edit svc ingress-nginx-controller

Add this annotation:

kubernetes.civo.com/loadbalancer-enable-proxy-protocol: send-proxy
Tip: Change .spec.externalTrafficPolicy from Cluster to Local

Step 5. Edit the ingress-nginx-controller ConfigMap in ingress-nginx namespace

kubectl -n ingress-nginx edit cm ingress-nginx-controller

Add these lines under data:

real-ip-header: proxy_protocol
use-proxy-protocol: "true"

Step 6. Create an Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-httpbin-ingress
  namespace: default
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: my-httpbin-svc
            port:
              number: 80

Step 7. Hit the LoadBalancer's IP/DNS to test. One can obtain the LoadBalancer’s IP and DNS via the Civo Dashboard, below the custer information.

LoadBalancer’s IP and DNS via the Civo Dashboard

Once you have obtained the Public IP or the DNS Name form the Civo dashboard, we can test the communication to that IP/DNS via curl (e.g. curl 131.153.226.68 or curl 288d2dc3-0dc6-4bb9-b030-0a74fa32f999.lb.civo.com).

Note:It may take up to 10 minutes for DNS to propagate across the internet. To expedite this process, you can optionally set your DNS resolver address in your DNS server configuration to use Cloudflare DNS (1.1.1.1) for faster DNS propagation results (https://developers.cloudflare.com/1.1.1.1/setup/linux/).

Installing Traefik Ingress Controller through an Helm chart

Civo K3s clusters are created by default with a Traefik Ingress Controller. If you removed this default when creating the cluster,you can add it through a Helm chart.

Step 1. Create a HTTPbin Deployment using kennethreitz/httpbin image:

kubectl -n default create deployment my-httpbin --image=kennethreitz/httpbin

Step 2. Create a Service for Deployment above:

kubectl -n default expose deployment my-httpbin --port=80 --name=my-httpbin-svc

Step 3. Create traefik-values.yaml file (NOTE: This file can be saved anywhere on your local filesystem):

service:
  annotations:
    kubernetes.civo.com/loadbalancer-enable-proxy-protocol: send-proxy
  spec:
    externalTrafficPolicy: Local

additionalArguments:
  - "--entrypoints.web.proxyProtocol.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
  - "--entrypoints.websecure.proxyProtocol.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"

Step 4. Install Nginx ingress controller:

helm upgrade --install traefik traefik/traefik --values traefik-values.yaml --namespace traefik --create-namespace

Step 5. Create an Ingress Resource:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-httpbin-ingress
  namespace: default
spec:
  rules:
  - http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: my-httpbin-svc
            port:
              number: 80

Step 6. Use curl to send traffic to the LoadBalancer's IP/DNS to test (NOTE: You can obtain the IP/DNS in the same fashion as above in step 7 of the Installing NGINX Ingress Controller section of this article):

curl <LB_IP>/ip

Or…

curl <LB_DNS>/ip
Note:Refer to point #7 in Nginx Ingress section on how to obtain the LoadBalancer's DNS/IP - which also already contains a note about the 1.1.1.1 DNS resolver.

Security Implications

When enabling the proxy protocol and exposing real client IPs to applications, several security implications must be carefully considered:

Concern Description
IP Spoofing Risk Exposing real client IPs can increase the risk of IP spoofing, where an attacker might impersonate another user's IP address. It's essential to ensure that your application has mechanisms in place to detect and mitigate such risks, possibly through rate limiting, IP reputation analysis, or more sophisticated network security solutions.
Firewall Rules With the source IP preserved, you might need to adjust your firewall rules to reflect the traffic you expect to allow or block accurately. This adjustment is crucial to prevent unauthorized access while ensuring legitimate traffic is not inadvertently blocked.
Load Balancer Configuration Ensure that your load balancer is correctly configured to use the proxy protocol. A misconfiguration could lead to loss of client IP information or even block incoming traffic.
Network Policies In Civo Kubernetes environments, network policies might need to be updated to account for traffic flow based on real client IPs. This update ensures that only allowed IPs can access certain services, enhancing your cluster's security posture.
Privacy Considerations Storing or logging real client IPs can have privacy implications, depending on your jurisdiction and applicable data protection laws. Ensure that your application complies with such regulations by implementing appropriate data handling and privacy measures.

Troubleshooting

Encountering issues during or after setup is not uncommon. Here are some troubleshooting tips for common issues related to LoadBalancer configuration, DNS propagation delays, or errors in applying the YAML files:

LoadBalancer Issues:

  • Ensure the LoadBalancer supports the proxy protocol.
  • Verify the annotations used for the LoadBalancer service is correctly applied and supported by your cloud provider or infrastructure.
  • Check the LoadBalancer's logs for any errors or warnings that might indicate misconfiguration or operational issues.

DNS Propagation Delays:

  • Use tools like dig or nslookup to verify that your DNS records are correctly set up and propagating. Remember, DNS propagation can take time, varying from a few minutes to 48 hours.
  • Modify your /etc/hosts file (or its equivalent on non-Unix systems) to map the domain name directly to the LoadBalancer's IP for immediate testing.

Errors Applying YAML Files:

  • Verify the syntax and integrity of your YAML files. Tools like yamllint can help check for syntax errors.
  • Ensure that you have the necessary permissions to apply the configurations. Running kubectl auth can-i <action> <resource> can help identify permission issues.
  • Check for deprecated or unsupported Kubernetes API versions in your YAML files, especially if you're using an older version of Kubernetes.

General Troubleshooting:

  • Review the logs of your Ingress controller and application pods. These logs can provide valuable insights into what might be going wrong.
  • Ensure your Kubernetes cluster is healthy and that all nodes are ready and not experiencing issues.
  • Use kubectl describe commands to inspect the state and events related to your deployments, services, and ingress resources for any anomalies or errors.

Summary

Configuring NGINX or Traefik Ingress Controllers on a Civo Kubernetes cluster to preserve source IP is vital for applications that rely on client IP for functionality or security. This tutorial outlines the steps to achieve source IP preservation, including setting up the necessary tools, modifying service annotations, and adjusting ingress resources.

Key security considerations such as IP spoofing risks, firewall adjustments, and privacy implications are highlighted, ensuring that applications handle client IP information securely and in compliance with regulations.

Ultimately, this tutorial provides a clear pathway for configuring your Kubernetes environment on Civo to preserve client IP information, enhancing application functionality and security.

Here are concise resources to enhance your Kubernetes ingress setup on Civo: