Here’s the clean mental model for a Cloudflare → F5 → Kong API stack, plus the key headers/TLS choices and the minimum config knobs so it “just works.”
1) The traffic flow (happy path)
Client ─(HTTPS/HTTP2/3)→ Cloudflare ─(TLS to origin)→ F5 VIP ─(HTTP/HTTPS)→ Kong cluster ─→ Upstream services
- Cloudflare terminates the client TLS (always, if the orange-cloud proxy is on).
- Applies WAF, DDoS, bot rules, rate limits, geo rules, etc.
- Forwards to your F5 VIP as the “origin”.
- F5 LTM receives Cloudflare’s request.
- Usually terminates TLS again (re-encrypt to Kong or send plain HTTP on the inside).
- Load-balances across Kong nodes (pool members in Zone A/B).
- Kong Gateway routes by
Host/path to your backend (service), runs plugins (OIDC, rate-limit, etc.), and proxies to the upstream.
2) TLS choices (pick one per hop)
Cloudflare → F5 (origin TLS):
- Set Cloudflare SSL mode to Full (strict).
- Enable Authenticated Origin Pull so only Cloudflare can hit F5.
- On F5, trust Cloudflare’s Origin Pull CA and require client cert.
F5 → Kong:
- Simple: terminate on F5 and send HTTP to Kong on the private VLAN.
- End-to-end TLS: client-SSL on F5, server-SSL from F5 to Kong (re-encrypt), SNI
kong.internal(or node name).
Kong → Upstream:
- Match your upstream:
protocol=http|https, SNI if TLS, optionally mTLS to sensitive services.
3) Real client IP (do this or logs/limits will be wrong)
Cloudflare sets:
CF-Connecting-IP(client IP)X-Forwarded-For(appends client IP)X-Forwarded-Proto: https
F5 should preserve (not overwrite) X-Forwarded-For and pass X-Forwarded-Proto.
Kong must trust the proxy chain so it can compute the real client IP:
- Set (env or kong.conf):
KONG_TRUSTED_IPS=<F5 private CIDRs or F5 VIPs>(don’t trust 0.0.0.0/0)KONG_REAL_IP_HEADER=X-Forwarded-ForKONG_REAL_IP_RECURSIVE=on
- Then
client_ipin logs, rate-limit/correlation will be the actual user IP from Cloudflare.
If you prefer using Cloudflare’s header explicitly, you can have F5 copy
CF-Connecting-IPinto the leftmost position ofX-Forwarded-For.
4) Load balancing & health checks (avoid double “mystery” failover)
- Cloudflare (optional LB): usually point it at a single F5 VIP per region and let F5 do node health.
- F5 → Kong nodes: HTTP health monitor (e.g.,
GET /status/healthon each Kong). - Kong → upstreams: use Kong Upstreams/Targets with active + passive health checks to eject bad app pods.
Pick one layer to be the source of truth per hop (Cloudflare LB or F5, Kong or upstream LB) to avoid contradictory decisions.
5) Protocols & connections
- HTTP versions: client can be HTTP/2 or HTTP/3 to Cloudflare. Cloudflare→F5 is HTTP/1.1 or HTTP/2 (CF may downgrade). F5→Kong is typically HTTP/1.1.
- Keep-alive: enable OneConnect on F5 and keep-alive to Kong to avoid connection churn.
- WebSockets/gRPC: supported end-to-end; ensure Upgrade/HTTP2 is enabled through F5 and Kong Routes/Services.
6) Minimal config snippets
F5 (HTTP profile / header handling):
- Enable “Insert X-Forwarded-For” (or an iRule to append not overwrite).
- Preserve
X-Forwarded-Proto=https. - If using Authenticated Origin Pull: client-SSL requires CF client cert; trust CF Origin CA.
Kong (env):
KONG_HEADERS=latency_tokens
KONG_TRUSTED_IPS=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16, <your F5 VIPs/CIDRs>
KONG_REAL_IP_HEADER=X-Forwarded-For
KONG_REAL_IP_RECURSIVE=on
Kong Service (HTTPS upstream with SNI):
protocol: https
host: api.internal.example
port: 443
tls_verify: true
sni: api.internal.example
Kong rate limiting behind proxies: use consumer or ip policy; with trusted IPs set, ip uses the real client.
7) Observability (what to turn on)
- Cloudflare: (if plan allows) Edge logs / Security events (attack/waf/bot).
- F5: LTM logs + request logging profiles; export to ELK.
- Kong: enable Prometheus plugin, correlation-id, and http-log/file-log to ELK.
- Make sure your ELK/Loki sees
client_ip,X-Request-ID,service,route,upstream_status,latencies.{kong,proxy,request}.
8) Common pitfalls & quick fixes
- Client IP shows F5/Cloudflare: set
KONG_TRUSTED_IPSandKONG_REAL_IP_*as above; ensure F5 appends—not overwrites—X-Forwarded-For. - OIDC 401s behind CF/F5: your LB stripped
Authorization. Validate with an echo upstream; ensure F5 leavesAuthorizationintact. - Mixed-content / wrong redirects: preserve
X-Forwarded-Proto: httpsthrough to Kong and upstream so apps build HTTPS URLs. - Header too large (Set-Cookie): raise Kong Nginx proxy buffers if you see
upstream sent too big header. - Double LB flaps: don’t health-check the same hop in both Cloudflare and F5 with different intervals/paths.
9) Example end-to-end (typical, secure)
- Cloudflare Full (strict) + Authenticated Origin Pull → F5 public VIP
api.example.com:443. - F5 terminates TLS, adds XFF if missing, passes
X-Forwarded-Proto: https, LB tokongA:8000,kongB:8000. - Kong trusts F5 IPs, pulls real client IP from XFF, runs OIDC/rate-limit, sends to upstream (HTTPS with SNI).
- Logs/metrics from all 3 land in ELK/Grafana.
If you want, I can drop a ready-to-run Kong docker-compose with those envs set, plus example F5 monitor path and a Kong Service/Route pointing to your php/tomcat containers.