4 min read

Traefik x-forwarded-for headers

To describe the concept of the x-forwarded-for headers and how to configure additionally those headers Kubernetes cluster is needed. K3s is easy to install and ready to use Kubernetes cluster.

Read a detailed article on how to install k3s.

Install k3s kubernetes cluster
What is k3s? K3s is a lightweight and certified Kubernetes distribution built by the Rancher. It’s currently in the sandbox projects category at the CNCF. K3s is a production-grade distribution of Kubernetes which is in nature lightweight and the foremost reason for building it was the need to use…

A shorter version of how to install with one-liner is given below.

curl -sfL https://get.k3s.io | sh -

X-forwarded-for headers on Traefik

By default, the following headers are automatically added when proxying requests:

To describe the concept of the x-forwarded-for headers and how to configure additionally those headers Kubernetes cluster is needed. K3s is easy to install and ready to use Kubernetes cluster.

Read a detailed article on how to install k3s.

Install k3s kubernetes cluster
What is k3s? K3s is a lightweight and certified Kubernetes distribution built by the Rancher. It’s currently in the sandbox projects category at the CNCF. K3s is a production-grade distribution of Kubernetes which is in nature lightweight and the foremost reason for building it was the need to use…

A shorter version of how to install with one-liner is given below.

curl -sfL https://get.k3s.io | sh -

X-forwarded-for headers on Traefik

By default, the following headers are automatically added when proxying requests:

Client's IP X-Forwarded-For, X-Real-Ip
Host X-Forwarded-Host
Port X-Forwarded-Port
Protocol X-Forwarded-Proto
Proxy Server's Hostname X-Forwarded-Server

Deploy nginx, clusterIP service for nginx, and ingress which will Traefik forward from itself to the nginx container.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app.kubernetes.io/name: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx
spec:
  rules:
  - http:
      paths:
      - backend:
          service:
            name: my-service
            port:
              number: 80
        path: /nginx
        pathType: Prefix

After applying this YAML manifest we can send requests to the Nginx easily.

$ curl localhost/nginx
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.14.2</center>
</body>
</html>

Debugging the deployed pod can show us information about the network packets going through the nginx container. Using ephemeral containers for attaching to the running pod can do this.

$ k debug -it nginx-deployment-557757876d-v5fm9 --image=leodotcloud/swiss-army-knife --target=nginx -- /bin/bash
Targeting container "nginx". If you don't see processes from this container it may be because the container runtime doesn't support this feature.
Defaulting debug container name to debugger-5lqvt.
If you don't see a command prompt, try pressing enter.
root@nginx-deployment-557757876d-v5fm9:~# tcpdump -i eth0 -s 0 -A 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'

Tcpdump command will listen to the HTTP GET request and will display everything about that request.

Sending the the curl request to the localhost/nginx will provide information like shown below.

Host: localhost
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cache-Control: max-age=0
Sec-Ch-Ua: "Google Chrome";v="117", "Not;A=Brand";v="8", "Chromium";v="117"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Linux"
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 10.42.0.14
X-Forwarded-Host: localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: traefik-7fbbb44c44-kwsqk
X-Real-Ip: 10.42.0.14

After inspection of the headers from the incoming request:

  • X-Forwarded-For: 10.42.0.14
  • X-Forwarded-Host: localhost
  • X-Forwarded-Port: 80
  • X-Forwarded-Proto: http
  • X-Forwarded-Server: traefik-7fbbb44c44-kwsqk
  • X-Real-Ip: 10.42.0.14

All this information provides data about the source of the incoming requests that can be used to condition the response to the request.