I’ve personally used Cloudflare and it’s proxy feature for a while now and it’s a great feature. It is a one-click feature that allows you to proxy your traffic through Cloudflare’s network. This is great for hiding your real IP address and adding an extra layer of security to your server.
However, it does have a few quirks that you need to be aware of. One of which is that it does not automatically add the X-Forwarded-For
header to the requests it proxies. This can cause problems with some services that need to know the real IP address of the client.
This is where Traefik2 and it’s middleware and forwarded headers feature comes in. It allows you to add the X-Forwarded-For
header to the requests it proxies, which can then be used by other services to get the real IP address of the client.
In this tutorial, we will setup a Traefik2 middleware and forwarded headers to handle the X-Forwarded-For
header for Cloudflare Proxy.
Setup
In my own setup, I use the default Traefik2 installation that comes with K3s. Only a few minor changes were needed to get this working.
Helm Chart Config
We need to instruct the Traefik2 helm chart to allow forwarded headers, specifically for itself and Cloudflare.
---
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: traefik
namespace: kube-system
spec:
valuesContent: |-
ports:
web:
forwardedHeaders:
trustedIPs:
- 10.0.0.1/8
- 103.21.244.0/22
- 103.22.200.0/22
- 103.31.4.0/22
- 104.16.0.0/13
- 104.24.0.0/14
- 108.162.192.0/18
- 131.0.72.0/22
- 141.101.64.0/18
- 162.158.0.0/15
- 172.64.0.0/13
- 173.245.48.0/20
- 188.114.96.0/20
- 190.93.240.0/20
- 197.234.240.0/22
- 198.41.128.0/17
proxyProtocol:
trustedIPs:
- 10.0.0.1/8
websecure:
forwardedHeaders:
trustedIPs:
- 10.0.0.1/8
- 103.21.244.0/22
- 103.22.200.0/22
- 103.31.4.0/22
- 104.16.0.0/13
- 104.24.0.0/14
- 108.162.192.0/18
- 131.0.72.0/22
- 141.101.64.0/18
- 162.158.0.0/15
- 172.64.0.0/13
- 173.245.48.0/20
- 188.114.96.0/20
- 190.93.240.0/20
- 197.234.240.0/22
- 198.41.128.0/17
proxyProtocol:
trustedIPs:
- 10.0.0.1/8
service:
spec:
externalTrafficPolicy: Local
Traefik2 Middleware
Next we need to create the middleware that will whitelist the Cloudflare IPs and add the X-Forwarded-For
header to the requests it proxies.
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: cloudflare-ip-whitelist
namespace: default
spec:
ipWhiteList:
sourceRange:
# Cloudflare IPs
- "103.21.244.0/22"
- "103.22.200.0/22"
- "103.31.4.0/22"
- "104.16.0.0/13"
- "104.24.0.0/14"
- "108.162.192.0/18"
- "131.0.72.0/22"
- "141.101.64.0/18"
- "162.158.0.0/15"
- "172.64.0.0/13"
- "173.245.48.0/20"
- "188.114.96.0/20"
- "190.93.240.0/20"
- "197.234.240.0/22"
- "198.41.128.0/17"
# IPv6 Cloudflare ranges
- "2400:cb00::/32"
- "2606:4700::/32"
- "2803:f800::/32"
- "2405:b500::/32"
- "2405:8100::/32"
- "2a06:98c0::/29"
- "2c0f:f248::/32"
ipStrategy:
depth: 0
excludedIPs: []
Traefik2 Ingress
Finally, we need to add the middleware to the ingress rule for the service we want to proxy through Cloudflare.
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
traefik.ingress.kubernetes.io/proxy-protocol: "true"
traefik.ingress.kubernetes.io/forwarded-headers-trust-all: "true"
traefik.ingress.kubernetes.io/custom-request-headers: |
X-Forwarded-For: ||
X-Real-Ip: ||
CF-Connecting-IP: ||
traefik.ingress.kubernetes.io/router.middlewares: default-cloudflare-ip-whitelist@kubernetescrd
name: wordpress-ingress
namespace: default
spec:
ingressClassName: traefik
...
The ingress will only allow requests from the Cloudflare IPs and add the X-Forwarded-For
header to the requests it proxies.
HTTP 403 Forbidden for everything else.