Skip to content

Instantly share code, notes, and snippets.

@iconoclasthero
Last active August 20, 2026 23:12
Show Gist options
  • Select an option

  • Save iconoclasthero/b0e9f08900e357a3cec496e41c35d3c1 to your computer and use it in GitHub Desktop.

Select an option

Save iconoclasthero/b0e9f08900e357a3cec496e41c35d3c1 to your computer and use it in GitHub Desktop.
# CrowdSec local customization for Traefik logs behind Cloudflare.
#
# Traefik sees the Cloudflare edge server as the connection source, so the
# standard crowdsecurity/traefik-logs parser initially sets evt.Meta.source_ip
# to the Cloudflare edge IP (for example, 104.23.251.67). Traefik also preserves
# the original client address in the CF-Connecting-IP request header.
#
# For this header to appear in the Traefik JSON access log, Traefik must
# explicitly retain it in its access-log configuration, e.g.:
#
# fields:
# headers:
# defaultMode: drop
# names:
# CF-Connecting-IP: keep
# CF-IPCountry: keep
# X-Forwarded-Host: keep
#
# Traefik emits request headers in JSON access logs with a "request_" prefix,
# so CF-Connecting-IP appears as "request_Cf-Connecting-Ip" in the log and
# therefore as evt.Unmarshaled.traefik['request_Cf-Connecting-Ip'] here.
#
# This parser replaces evt.Meta.source_ip with the original client address.
# It MUST run in s02-enrich, after crowdsecurity/traefik-logs has populated
# evt.Unmarshaled.traefik, but BEFORE geoip-enrich and any other enrichment
# that depends on evt.Meta.source_ip.
#
# The filename is intentionally prefixed with "01-" so this parser runs at the
# beginning of the s02-enrich stage, before the other enrichment parsers.
# This ordering is important: evt.Meta.source_ip must contain the "real" client
# conneting IP before any enrichment that consumes that field runs. Do not rename
# or move this file to a name that sorts later in the directory. Doing so could
# cause an installed or future enrichment parser to operate on the Cloudflare
# edge IP instead of the "real" connecting client IP. E.g. Renaming/moving the
# file to a name alphanumerically *after* geoip-enrich will cause GeoIP/ASN
# enrichment to operate on the Cloudflare edge IP instead of the "real"
# connecting client IP.
#
# The parser is deliberately scoped to Traefik events by checking that the
# Traefik JSON has been unmarshaled. The CF-Connecting-IP value is then copied
# into evt.Meta.source_ip, which is the field consumed by subsequent enrichment
# stages and scenarios.
#
# The "local/" namespace identifies this as a site-specific customization
# rather than a parser supplied by a CrowdSec collection.
#
# File: /etc/crowdsec/parsers/s02-enrich/01-Cf-Connecting-Ip.yaml
# Pangolin/CrowdSec Docker host path:
# ../pangolin/config/crowdsec/parsers/s02-enrich/01-Cf-Connecting-Ip.yaml
name: local/cf-connecting-ip-override
description: Override source IP with Cloudflare's CF-Connecting-IP header for CF-Proxied connctions
filter: "evt.Unmarshaled.traefik != nil"
statics:
- meta: source_ip
expression: "evt.Unmarshaled.traefik['request_Cf-Connecting-Ip']"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment