Get real dual stack address to backend with cloudflare and without

Hi there,

I'm trying to get X-Forwarded-For to include the real IP address of the client, when using IPv4 and IPv6.
Currently it works for IPv4, but on IPv6 requests, it shows the docker bridge interface.

Currently whoami service says (snip means I censored it):

Hostname: 5af160072009
IP: 127.0.0.1
IP: 172.19.0.3
RemoteAddr: 172.19.0.2:33494
GET / HTTP/1.1
Host: whoami.<snip>.fi
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.63
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,fi;q=0.8
Dnt: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 172.17.0.1
X-Forwarded-Host: whoami.<snip>.fi
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: 2bac83b05f97
X-Real-Ip: 172.17.0.1

Docker Compose for Traefik:

version: "3.7"
services:

## Traefik - Reverse Proxy
  traefik:
    container_name: traefik
    image: traefik:latest # the picodon tag refers to v2.3.x
    restart: always
    command: # CLI arguments
      - --global.checkNewVersion=true
      - --global.sendAnonymousUsage=false
      - --entryPoints.http.address=:80
#      - --entrypoints.http.http.redirections.entryPoint.to=https # entrypoints.<your_entrypoint_name>.http.redirections...
      - --entryPoints.https.address=:443
      - --entryPoints.https.forwardedHeaders.trustedIPs=::/0,0.0.0.0/0
      - --entryPoints.https.proxyProtocol.trustedIPs=::/0,0.0.0.0/0
      - --entrypoints.https.http.tls.certresolver=dns-cloudflare
      - --entrypoints.https.http.tls.domains[0].main=$DOMAINNAME
      - --entrypoints.https.http.tls.domains[0].sans=*.$DOMAINNAME
      - --entrypoints.https.http.tls.domains[1].main=$DOMAIN
      - --entrypoints.https.http.tls.domains[1].sans=*.$DOMAIN 
      - --entrypoints.https.http.tls.domains[1].main=$DOMAINDEV
      - --entrypoints.https.http.tls.domains[2].sans=*.$DOMAINDEV
      - --entryPoints.traefik.address=:8080
      - --api=true
      - --api.insecure=true
      - --api.dashboard=true
#      - --serversTransport.insecureSkipVerify=true
      - --log=true
      - --log.level=DEBUG # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC
      - --accessLog=true
      - --accessLog.filePath=/traefik.log
      - --accessLog.bufferingSize=100 # Configuring a buffer of 100 lines
      - --accessLog.filters.statusCodes=400-499
      - --providers.docker=true
      - --providers.docker.exposedByDefault=false
      - --providers.docker.network=traefik_proxy
      - --providers.docker.swarmMode=false
      - --providers.file.directory=/rules # Load dynamic configuration from one or more .toml or .yml files in a directory.
      - --providers.file.watch=true # Only works on top level files in the rules folder
#      - --certificatesResolvers.dns-cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory # LetsEncrypt Staging Server - uncomment when testing
      - --certificatesResolvers.dns-cloudflare.acme.email=$CLOUDFLARE_EMAIL
      - --certificatesResolvers.dns-cloudflare.acme.storage=/acme.json
      - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.provider=cloudflare
      - --certificatesresolvers.dns-cloudflare.acme.dnschallenge.resolvers=$DNS_RESOLVER # pihole IP
    networks:
      traefik_proxy:
      docker_socket:
    ports:
      - target: 80
        published: 80
        protocol: tcp
        mode: host
      - target: 8080
        published: 8080
        protocol: tcp
        mode: host
      - target: 443
        published: 443
        protocol: tcp
        mode: host
    security_opt:
      - no-new-privileges:true # https://docs.docker.com/engine/reference/run/#security-configuration
    volumes:
      - $TRAEFIK2DIR/traefik/rules:/rules # file provider directory
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - $TRAEFIK2DIR/traefik/acme/acme.json:/acme.json
    environment:
      - CF_API_EMAIL=$CLOUDFLARE_EMAIL
      - CF_API_KEY=$CLOUDFLARE_API_KEY
    secrets:
      - "cf-api-email"
      - "cf-api-key"
    labels:
      - "traefik.enable=true"
      # HTTP Routers
      - "traefik.http.routers.traefik-rtr.entrypoints=https"
      - "traefik.http.routers.traefik-rtr.rule=Host(`traefik.$DOMAINNAME`)"
      - "traefik.http.routers.traefik-rtr.priority=10"
      ## Middlewares
      - "traefik.http.routers.traefik-rtr.middlewares=traefik-headers,rate-limit@file,authelia@docker"
      - "traefik.http.middlewares.traefik-headers.headers.accesscontrolallowmethods=GET, OPTIONS, PUT"
      - "traefik.http.middlewares.traefik-headers.headers.accesscontrolalloworiginlist=https://$DOMAINNAME"
      - "traefik.http.middlewares.traefik-headers.headers.accesscontrolmaxage=100"
      - "traefik.http.middlewares.traefik-headers.headers.addvaryheader=true"
      - "traefik.http.middlewares.traefik-headers.headers.allowedhosts=traefik.$DOMAINNAME"
      - "traefik.http.middlewares.traefik-headers.headers.hostsproxyheaders=X-Forwarded-Host"
      - "traefik.http.middlewares.traefik-headers.headers.sslredirect=true"
      - "traefik.http.middlewares.traefik-headers.headers.sslhost=traefik.$DOMAINNAME"
      - "traefik.http.middlewares.traefik-headers.headers.sslforcehost=true"
      - "traefik.http.middlewares.traefik-headers.headers.sslproxyheaders.X-Forwarded-Proto=https"
      - "traefik.http.middlewares.traefik-headers.headers.stsseconds=63072000"
      - "traefik.http.middlewares.traefik-headers.headers.stsincludesubdomains=true"
      - "traefik.http.middlewares.traefik-headers.headers.stspreload=true"
      - "traefik.http.middlewares.traefik-headers.headers.forcestsheader=true"
      - "traefik.http.middlewares.traefik-headers.headers.framedeny=true"
#      - "traefik.http.middlewares.traefik-headers.headers.customframeoptionsvalue=SAMEORIGIN" # This option overrides FrameDeny
      - "traefik.http.middlewares.traefik-headers.headers.contenttypenosniff=true"
      - "traefik.http.middlewares.traefik-headers.headers.browserxssfilter=true"
#      - "traefik.http.middlewares.traefik-headers.headers.contentsecuritypolicy=frame-ancestors 'none'; object-src 'none'; base-uri 'none';"
      - "traefik.http.middlewares.traefik-headers.headers.referrerpolicy=same-origin"
      - "traefik.http.middlewares.traefik-headers.headers.featurepolicy=camera 'none'; geolocation 'none'; microphone 'none'; payment 'none'; usb 'none'; vr 'none';"
      - "traefik.http.middlewares.traefik-headers.headers.customresponseheaders.X-Robots-Tag=none,noarchive,nosnippet,notranslate,noimageindex,"
      ## Services - API
      - "traefik.http.routers.traefik-rtr.service=api@internal"
      ## API Forward Auth Bypass # Used for willfantom/SUI - automatic traefik dashboard
      - "traefik.http.routers.traefik-bypass.entrypoints=https"
      - "traefik.http.routers.traefik-bypass.rule=Host(`traefik.$DOMAINNAME`)"
      - "traefik.http.routers.traefik-bypass.middlewares=traefik-headers,traefik-basicauth,rate-limit@file"
      - "traefik.http.middlewares.traefik-basicauth.basicauth.users=$MY_USERNAME:$TRAEFIK_PASSWORD"
      - "traefik.http.routers.traefik-bypass.priority=20"
      - "traefik.http.routers.traefik-bypass.service=api@internal"

whoami service:

whoami:
    container_name: whoami
    image: containous/whoami:v1.3.0
    restart: always
    networks:
      - traefik_proxy
    security_opt:
      - no-new-privileges:true
    labels:
      - "traefik.enable=true"
      # HTTP Routers
      - "traefik.http.routers.whoami-rtr.entrypoints=https"
      - "traefik.http.routers.whoami-rtr.rule=Host(`whoami.$DOMAINNAME`)"
      ## Middlewares
      - "traefik.http.routers.whoami-rtr.middlewares=chain-authelia@file"
      ## HTTP Services
      - "traefik.http.routers.whoami-rtr.service=whoami-svc"
      - "traefik.http.services.whoami-svc.loadbalancer.server.port=80"

chain-authelia:

[http.middlewares]
  [http.middlewares.chain-authelia.chain]
    middlewares = ["secure-headers","cloudflare-ipwhitelist", "authelia@docker"]

cloudflare-ipwhitelist:

[http.middlewares]
  [http.middlewares.cloudflare-ipwhitelist.ipWhiteList]
    sourceRange = [
      "172.0.0.0/8",
      "173.245.48.0/20",
      "103.21.244.0/22",
      "103.22.200.0/22",
      "103.31.4.0/22",
      "141.101.64.0/18",
      "108.162.192.0/18",
      "190.93.240.0/20",
      "188.114.96.0/20",
      "197.234.240.0/22",
      "198.41.128.0/17",
      "162.158.0.0/15",
      "104.16.0.0/12",
      "172.64.0.0/13",
      "131.0.72.0/22",
      "2400:cb00::/32",
      "2606:4700::/32",
      "2803:f800::/32",
      "2405:b500::/32",
      "2405:8100::/32",
      "2a06:98c0::/29",
      "2c0f:f248::/32"
      ]
    #[http.middlewares.test-ipwhitelist.ipWhiteList.ipStrategy]
    #  depth = 2

secure-headers

[http.middlewares]
  [http.middlewares.secure-headers.headers]
    accessControlAllowMethods= ["GET", "OPTIONS", "PUT"]
    accessControlMaxAge = 100
    hostsProxyHeaders = ["X-Forwarded-Host", "Cf-Connecting-Ip"]
    sslRedirect = true
    stsSeconds = 63072000
    stsIncludeSubdomains = true
    stsPreload = true
    forceSTSHeader = true
    contentTypeNosniff = true
    browserXssFilter = true
    referrerPolicy = "same-origin"
    featurePolicy = "camera 'none'; geolocation 'none'; microphone 'none'; payment 'none'; usb 'none'; vr 'none';"
    [http.middlewares.secure-headers.headers.customResponseHeaders]
      X-Robots-Tag = "none,noarchive,nosnippet,notranslate,noimageindex,"

The "fix" was to set traefik to host networking mode or to an network with an IPv6 address.

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.