The log files do not show the user's IP address, but rather that of the Docker host. Basically, I have a standard
setup: Cloudflare Tunnel (proxy) - VM with Docker-based Pangolin and Traefik.
In Traefik, the forwardedHeaders: trustedIPs are configured and pangolin server has trust_proxy: 2 configured. If I use the fork github.com/hajimAIM/badger in version v1.2.1 instead of the badger traefik plugin github.com/fosrl/badger v1.3.1, it works as expected.
I would expect my IPv4 (or IPv6, if applicable) address to be in the log file and also at Whoami under X-Real-Ip.
I would expect my IPv4 (or IPv6, if applicable) address to appear in the log file and also under X-Real-Ip in Whoami. This seems to work when I use the fork github.com/hajimAIM/badger in version v1.2.1 for Badger. However, I then have to deactivate the middleware.
Originally created by @Christopher87R on GitHub (Mar 4, 2026).
Original GitHub issue: https://github.com/fosrl/pangolin/issues/2597
### Describe the Bug
The log files do not show the user's IP address, but rather that of the Docker host. Basically, I have a standard
setup: Cloudflare Tunnel (proxy) - VM with Docker-based Pangolin and Traefik.
In Traefik, the forwardedHeaders: trustedIPs are configured and pangolin server has trust_proxy: 2 configured. If I use the fork github.com/hajimAIM/badger in version v1.2.1 instead of the badger traefik plugin github.com/fosrl/badger v1.3.1, it works as expected.
<img width="1282" height="255" alt="Image" src="https://github.com/user-attachments/assets/d0a7d01e-a25c-4fbb-8242-83e0e79cc7e5" />
<img width="610" height="829" alt="Image" src="https://github.com/user-attachments/assets/76c3c5af-d29b-4e82-a572-147ef6d63a42" />
### Environment
- OS Type & Version: Debian GNU/Linux 12 (bookworm)
- Pangolin Version: 1.16.2
- Gerbil Version: 1.3.0
- Traefik Version: 3.6
- Newt Version: not used - whoami on local VM
- Badger Version: v1.3.1
### To Reproduce
docker-compose.yml
```
name: pangolin
services:
pangolin:
image: docker.io/fosrl/pangolin:1.16.2
container_name: pangolin
restart: unless-stopped
deploy:
resources:
limits:
memory: 1g
reservations:
memory: 256m
volumes:
- ./config:/app/config
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
interval: "10s"
timeout: "10s"
retries: 15
networks:
- pangolin
gerbil:
image: docker.io/fosrl/gerbil:1.3.0
container_name: gerbil
restart: unless-stopped
depends_on:
pangolin:
condition: service_healthy
command:
- --reachableAt=http://gerbil:3004
- --generateAndSaveKeyTo=/var/config/key
- --remoteConfig=http://pangolin:3001/api/v1/
volumes:
- ./config/:/var/config
cap_add:
- NET_ADMIN
- SYS_MODULE
networks:
- pangolin
- cftunnel-transport
ports:
- 51820:51820/udp
- 21820:21820/udp
#- 443:443
#- 80:80
traefik:
image: docker.io/traefik:v3.6
container_name: traefik
restart: unless-stopped
network_mode: service:gerbil # Ports appear on the gerbil service
depends_on:
pangolin:
condition: service_healthy
command:
- --configFile=/etc/traefik/traefik_config.yml
volumes:
- ./config/traefik:/etc/traefik:ro # Volume to store the Traefik configuration
- ./config/letsencrypt:/letsencrypt # Volume to store the Let's Encrypt certificates
- ./config/traefik/logs:/var/log/traefik # Volume to store Traefik logs
environment:
TZ: "Europe/Berlin"
CF_API_EMAIL: "xxx"
CF_DNS_API_TOKEN: "xxxx"
CF_ZONE_API_TOKEN: "xxx"
whoami:
image: "traefik/whoami"
container_name: whoami
hostname: whoami
depends_on:
pangolin:
condition: service_healthy
restart: unless-stopped
networks:
- pangolin
cf-tunnel:
image: cloudflare/cloudflared:latest
container_name: cf-tunnel
hostname: cf-tunnel
restart: unless-stopped
networks:
- cftunnel-transport
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=xxx
networks:
pangolin:
driver: bridge
name: pangolin
enable_ipv6: true
cftunnel-transport:
driver: bridge
name: cftunnel-transport
enable_ipv6: true
```
config.yml
```
# To see all available options, please visit the docs:
# https://docs.pangolin.net/
gerbil:
start_port: 51820
base_endpoint: "xxx.goodsrv.de"
app:
dashboard_url: "https://pangolin.xxx.me"
log_level: "debug"
#log_level: "info"
telemetry:
anonymous_usage: true
domains:
domain1:
base_domain: "xxx.me"
server:
trust_proxy: 2
secret: "xxx"
cors:
origins: ["https://pangolin.xxx.me"]
methods: ["GET", "POST", "PUT", "DELETE", "PATCH"]
allowed_headers: ["X-CSRF-Token", "Content-Type"]
credentials: false
maxmind_db_path: "./config/GeoLite2-Country.mmdb"
email:
smtp_host: "xxx"
smtp_port: 587
smtp_user: "xxx"
smtp_pass: "xxx"
no_reply: "xxx"
flags:
require_email_verification: true
disable_signup_without_invite: true
disable_user_create_org: false
allow_raw_resources: true
```
traefik_config.yml
```
api:
insecure: true
dashboard: true
providers:
http:
endpoint: "http://pangolin:3001/api/v1/traefik-config"
pollInterval: "5s"
file:
filename: "/etc/traefik/dynamic_config.yml"
experimental:
plugins:
badger:
moduleName: "github.com/fosrl/badger"
version: "v1.3.1"
real-ip:
moduleName: "github.com/Paxxs/traefik-get-real-ip"
version: "v1.0.4"
log:
level: "INFO"
format: "common"
maxSize: 100
maxBackups: 3
maxAge: 3
compress: true
certificatesResolvers:
letsencrypt:
acme:
httpChallenge:
entryPoint: web
email: "xxx"
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
cloudflare:
acme:
email: xxx
storage: /letsencrypt/acme_cf.json
keyType: EC384
dnschallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
entryPoints:
web:
address: ":80"
http:
#middlewares:
# - real-ip@file
forwardedHeaders:
trustedIPs: &trustedIps
# Cloudflare 2024 12 14 https://www.cloudflare.com/ips
- 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/13
- 104.24.0.0/14
- 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
# local
- 172.16.0.0/16
- 172.17.0.0/16
- 172.18.0.0/16
- 172.19.0.0/16
- 172.20.0.0/16
- 172.21.0.0/16
- 172.22.0.0/16
- 172.23.0.0/16
#proxyProtocol:
# trustedIPs: *trustedIps
websecure:
address: ":443"
forwardedHeaders:
trustedIPs: *trustedIps
#proxyProtocol:
# trustedIPs: *trustedIps
transport:
respondingTimeouts:
readTimeout: "30m"
http:
#middlewares:
# - real-ip@file
#tls:
# certResolver: "letsencrypt"
tls:
certResolver: cloudflare
domains:
- main: xxx.me
encodedCharacters:
allowEncodedSlash: true
allowEncodedQuestionMark: true
serversTransport:
insecureSkipVerify: true
ping:
entryPoint: "web"
tls:
options:
default:
minVersion: VersionTLS13
sniStrict: true
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
curvePreferences:
- CurveP521
- CurveP384
```
dynamic_config.yml
```
http:
middlewares:
badger:
plugin:
badger:
disableForwardAuth: true
redirect-to-https:
redirectScheme:
scheme: https
real-ip:
plugin:
real-ip:
enableLog: true # default: false, enable to see detailed logs
deny403OnFail: true # default: false, when true returns 403 if no matching CDN header found
eraseProxyHeaders: false # default: false, erase CDN-specific headers after processing
Proxy:
- proxyHeadername: X-From-Cdn
proxyHeadervalue: cf-foo
realIP: Cf-Connecting-Ip
OverwriteXFF: true # default: false, v1.0.2 or above
- proxyHeadername: "*"
realIP: RemoteAddr
routers:
# HTTP to HTTPS redirect router
main-app-router-redirect:
rule: "Host(`pangolin.xxx.me`)"
service: next-service
entryPoints:
- web
middlewares:
- redirect-to-https
#- real-ip
- badger
# Next.js router (handles everything except API and WebSocket paths)
next-router:
rule: "Host(`pangolin.xxx.me`) && !PathPrefix(`/api/v1`)"
service: next-service
entryPoints:
- websecure
middlewares:
#- real-ip
- badger
tls:
certResolver: cloudflare
domains:
- main: "xxx.me"
sans:
- "*.xxx.me"
# API router (handles /api/v1 paths)
api-router:
rule: "Host(`pangolin.xxx.me`) && PathPrefix(`/api/v1`)"
service: api-service
entryPoints:
- websecure
middlewares:
#- real-ip
- badger
tls:
certResolver: cloudflare
domains:
- main: "xxx.me"
sans:
- "*.xxx.me"
# WebSocket router
ws-router:
rule: "Host(`pangolin.xxx.me`)"
service: api-service
entryPoints:
- websecure
middlewares:
#- real-ip
- badger
tls:
certResolver: cloudflare
domains:
- main: "xxx.me"
sans:
- "*.xxx.me"
services:
next-service:
loadBalancer:
servers:
- url: "http://pangolin:3002" # Next.js server
api-service:
loadBalancer:
servers:
- url: "http://pangolin:3000" # API/WebSocket server
tcp:
serversTransports:
pp-transport-v1:
proxyProtocol:
version: 1
pp-transport-v2:
proxyProtocol:
version: 2
```
### Expected Behavior
I would expect my IPv4 (or IPv6, if applicable) address to be in the log file and also at Whoami under X-Real-Ip.
I would expect my IPv4 (or IPv6, if applicable) address to appear in the log file and also under X-Real-Ip in Whoami. This seems to work when I use the fork github.com/hajimAIM/badger in version v1.2.1 for Badger. However, I then have to deactivate the middleware.
@Christopher87R commented on GitHub (Mar 10, 2026):
Could you please check this or can anybody help me with this issue?
<!-- gh-comment-id:4033045058 -->
@Christopher87R commented on GitHub (Mar 10, 2026):
Could you please check this or can anybody help me with this issue?
@LaurenceJJones commented on GitHub (Mar 10, 2026):
when setting the trust proxy level, did you ensure to bring down the stack (ensure the pangolin network is removed) then bring it all back up?
This is not just a pangolin problem many traefik users in general have issues with the docker-proxy causing problems with real ip.
also stating "standard setup" is not correct, we generally dont suggest you put pangolin behind a reverse proxy (cloudflared is a tunneled reverse proxy) as it should be exposed to be the gateway ingress.
<!-- gh-comment-id:4033480915 -->
@LaurenceJJones commented on GitHub (Mar 10, 2026):
when setting the trust proxy level, did you ensure to bring down the stack (ensure the pangolin network is removed) then bring it all back up?
This is not just a pangolin problem many traefik users in general have issues with the docker-proxy causing problems with real ip.
also stating "standard setup" is not correct, we generally dont suggest you put pangolin behind a reverse proxy (cloudflared is a tunneled reverse proxy) as it should be exposed to be the gateway ingress.
@AstralDestiny commented on GitHub (Mar 10, 2026):
If using cloudflared inspect your docker network and remove all the cloudflare v4/v6 and just put the docker ip range of cloudflared or the ipam you set for it.
docker inspect cloudflared, Find it's network name, docker network inspect
If it's on a different host then trust that host like 10.0.0.5/32
<!-- gh-comment-id:4033744539 -->
@AstralDestiny commented on GitHub (Mar 10, 2026):
If using cloudflared inspect your docker network and remove all the cloudflare v4/v6 and just put the docker ip range of cloudflared or the ipam you set for it.
docker inspect cloudflared, Find it's network name, docker network inspect <network name>
If it's on a different host then trust that host like 10.0.0.5/32
```
x-trusted-ips: &trustedIPs
# Internal
- 172.23.0.0/16 # Traefik
- XXXX:XXXX:XXXX:dd97::/64 # Newt
entryPoints:
http:
address: ":80"
http:
redirections:
entryPoint:
to: https
scheme: https
permanent: true
forwardedHeaders:
trustedIPs: *trustedIPs # This
https:
address: ":443"
http3:
advertisedPort: 443
asDefault: true
http:
middlewares:
- middlewares-secure-headers@file
tls:
options: default
certResolver: dns
forwardedHeaders:
trustedIPs: *trustedIPs # This
```
@Christopher87R commented on GitHub (Mar 10, 2026):
when setting the trust proxy level, did you ensure to bring down the stack (ensure the pangolin network is removed) then bring it all back up?
This is not just a pangolin problem many traefik users in general have issues with the docker-proxy causing problems with real ip.
also stating "standard setup" is not correct, we generally dont suggest you put pangolin behind a reverse proxy (cloudflared is a tunneled reverse proxy) as it should be exposed to be the gateway ingress.
Sure, I did a docker compose up -d --force-recreate
It works when I use github.com/hajimAIM/badger in version v1.2.1 - So I was surprised and assume that it is a bug.
If using cloudflared inspect your docker network and remove all the cloudflare v4/v6 and just put the docker ip range of cloudflared or the ipam you set for it.
docker inspect cloudflared, Find it's network name, docker network inspect If it's on a different host then trust that host like 10.0.0.5/32
I did exactly as you suggested and only entered the relevant IPs. Unfortunately, this did not work, and I still have the same problem.
By the way, the Cf-Connecting-Ip is deleted - whoami no longer displays it when I have Pangolin in between.
For CF Tunnel - Traefik - whoami, it works.
<!-- gh-comment-id:4034393885 -->
@Christopher87R commented on GitHub (Mar 10, 2026):
> when setting the trust proxy level, did you ensure to bring down the stack (ensure the pangolin network is removed) then bring it all back up?
>
> This is not just a pangolin problem many traefik users in general have issues with the docker-proxy causing problems with real ip.
>
> also stating "standard setup" is not correct, we generally dont suggest you put pangolin behind a reverse proxy (cloudflared is a tunneled reverse proxy) as it should be exposed to be the gateway ingress.
Sure, I did a docker compose up -d --force-recreate
It works when I use github.com/hajimAIM/badger in version v1.2.1 - So I was surprised and assume that it is a bug.
> If using cloudflared inspect your docker network and remove all the cloudflare v4/v6 and just put the docker ip range of cloudflared or the ipam you set for it.
>
> docker inspect cloudflared, Find it's network name, docker network inspect If it's on a different host then trust that host like 10.0.0.5/32
>
> ```
> x-trusted-ips: &trustedIPs
> # Internal
> - 172.23.0.0/16 # Traefik
> - XXXX:XXXX:XXXX:dd97::/64 # Newt
>
> entryPoints:
> http:
> address: ":80"
> http:
> redirections:
> entryPoint:
> to: https
> scheme: https
> permanent: true
> forwardedHeaders:
> trustedIPs: *trustedIPs # This
> https:
> address: ":443"
> http3:
> advertisedPort: 443
> asDefault: true
> http:
> middlewares:
> - middlewares-secure-headers@file
> tls:
> options: default
> certResolver: dns
> forwardedHeaders:
> trustedIPs: *trustedIPs # This
> ```
I did exactly as you suggested and only entered the relevant IPs. Unfortunately, this did not work, and I still have the same problem.
By the way, the Cf-Connecting-Ip is deleted - whoami no longer displays it when I have Pangolin in between.
For CF Tunnel - Traefik - whoami, it works.
@Christopher87R commented on GitHub (Mar 11, 2026):
I have now tried everything again and unfortunately without success. I also looked at the source code and since the Cf-Connecting-Ip header is deleted, isTrusted does not seem to be true - for whatever reason. Perhaps the trusted IP list is not being applied?
<!-- gh-comment-id:4041115669 -->
@Christopher87R commented on GitHub (Mar 11, 2026):
I have now tried everything again and unfortunately without success. I also looked at the [source code](https://github.com/fosrl/badger/blob/e0a2d76844f7ee39346e0e51ee1812f43322717e/main.go#L434) and since the Cf-Connecting-Ip header is deleted, isTrusted does not seem to be true - for whatever reason. Perhaps the trusted IP list is not being applied?
Still no success, the visitor's real IP is never displayed.
<!-- gh-comment-id:4049403899 -->
@Christopher87R commented on GitHub (Mar 12, 2026):
I have now explicitly set the IP ranges:
```
etworks:
pangolin:
driver: bridge
name: pangolin
enable_ipv6: false
ipam:
driver: default
config:
- subnet: ${NETWORKS_PANGOLIN_IPV4:-172.20.0.0/16}
cftunnel-transport:
driver: bridge
name: cftunnel-transport
enable_ipv6: false
ipam:
driver: default
config:
- subnet: ${NETWORKS_CFTUNNEL_IPV4:-172.24.0.0/16}
```
and adjusted the list of IPs accordingly:
```
forwardedHeaders:
trustedIPs: &trustedIPs
- 172.24.0.0/16
```
Still no success, the visitor's real IP is never displayed.
@Christopher87R commented on GitHub (Mar 13, 2026):
I have now done the following (perhaps a little rough and ready, but it works).
My Traefik config now uses Badger's locale plugin (to incorporate debug output).
So something is going wrong here. Do you have any idea what it is and how I can narrow it down further? Unfortunately, I'm not really familiar with Go or a setup that would allow me to debug it.
Update: When I add the IP to the default IPs in ips.go, everything works fine.
It seems as if the IP list is always overwritten by the default IP list. This happens even when I explicitly deactivate the default IPs.
Am I doing something wrong in the settings?
@miloschwartz is this more a Badger bug?
<!-- gh-comment-id:4053505261 -->
@Christopher87R commented on GitHub (Mar 13, 2026):
I have now done the following (perhaps a little rough and ready, but it works).
My Traefik config now uses Badger's locale plugin (to incorporate debug output).
```
experimental:
localPlugins:
badger:
moduleName: “github.com/fosrl/badger”
```
I also have set the CF-Tunnel IP
```
forwardedHeaders:
trustedIPs: &trustedIps
- 172.24.0.0/16
- fd00:1:be:4::0/64
http:
middlewares:
badger:
plugin:
badger:
disableForwardAuth: true
disableDefaultCFIPs: true
trustip:
- 172.24.0.0/16
- fd00:1:be:4::0/64
```
This works, and I have now incorporated the following output into the .go file:
```
func (p *Badger) isTrustedIP(remoteAddr string) bool {
ipStr, _, err := net.SplitHostPort(remoteAddr)
if err != nil {
return false
}
ip := net.ParseIP(ipStr)
log.Println("ip: ", ip)
if ip == nil {
return false
}
for _, network := range p.trustIP {
log.Println("network: ", network)
if network.Contains(ip) {
return true
}
}
return false
}
// Check if request comes from a trusted source
isTrusted := p.isTrustedIP(req.RemoteAddr)
log.Println("isTrusted: ", isTrusted, " IP: ", req.RemoteAddr)
```
The settings do not seem to be applied, because I get the following in the Traefik log file:
```
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 ip: 172.24.0.2"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 173.245.48.0/20"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 103.21.244.0/22"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 103.22.200.0/22"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 103.31.4.0/22"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 141.101.64.0/18"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 108.162.192.0/18"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 190.93.240.0/20"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 188.114.96.0/20"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 197.234.240.0/22"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 198.41.128.0/17"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 162.158.0.0/15"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 104.16.0.0/13"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 104.24.0.0/14"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 172.64.0.0/13"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 131.0.72.0/22"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 2400:cb00::/32"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 2606:4700::/32"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 2803:f800::/32"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 2405:b500::/32"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 2405:8100::/32"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 2a06:98c0::/29"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:07+01:00","level":"error","message":"2026/03/13 09:14:07 network: 2c0f:f248::/32"}
```
The strange thing is that after restarting Traefik, the following is briefly visible:
```
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:08+01:00","level":"error","message":"2026/03/13 09:14:08 ip: 172.24.0.2"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:08+01:00","level":"error","message":"2026/03/13 09:14:08 network: 172.24.0.0/16"}
{"plugin":"plugin-badger","module":"github.com/fosrl/badger","runtime":"","time":"2026-03-13T09:14:08+01:00","level":"error","message":"2026/03/13 09:14:08 isTrusted: true IP: 172.24.0.2:38254"}
```
So something is going wrong here. Do you have any idea what it is and how I can narrow it down further? Unfortunately, I'm not really familiar with Go or a setup that would allow me to debug it.
**Update:** When I add the IP to the default IPs in ips.go, everything works fine.
It seems as if the IP list is always overwritten by the default IP list. This happens even when I explicitly deactivate the default IPs.
Am I doing something wrong in the settings?
@miloschwartz is this more a Badger bug?
@Christopher87R commented on GitHub (Mar 25, 2026):
Could someone please take a look at this? To me, this clearly looks like a defect (see the analysis of the last 3 posts)
<!-- gh-comment-id:4127119677 -->
@Christopher87R commented on GitHub (Mar 25, 2026):
Could someone please take a look at this? To me, this clearly looks like a defect (see the analysis of the last 3 posts)
@LaurenceJJones commented on GitHub (Mar 25, 2026):
As noted previously, Pangolin behind a reverse proxy is not a supported deployment method. For that reason, the issue being reported would not be classified as a defect in Pangolin, as the setup is outside the supported configuration.
Looking at the current implementation, Badger’s realip handling is fairly limited and does not fully support the reverse lookup logic that would be needed here.
The most practical workaround would be to define a custom header such as X-Real-Ip, which Cloudflare should already be setting. Otherwise, if you can avoid using a plugin that removes the CF-Connecting-Ip header, the existing fallback logic should allow it to work.
Just note that the badger you define here is not the badger that is used in resources (this also caught me out recently), which is probably adding to the confusion as Pangolin defines badger@http not badger@file that gets the configuration from the config.yaml that pangolin defines and such it only have the trust integer.
<!-- gh-comment-id:4128806492 -->
@LaurenceJJones commented on GitHub (Mar 25, 2026):
As noted previously, Pangolin behind a reverse proxy is not a supported deployment method. For that reason, the issue being reported would not be classified as a defect in Pangolin, as the setup is outside the supported configuration.
Relevant code reference:
https://github.com/fosrl/badger/blob/67ad9b651eed00b74e65db5325cb3012a78ed50b/main.go#L403-L428
Looking at the current implementation, Badger’s realip handling is fairly limited and does not fully support the reverse lookup logic that would be needed here.
The most practical workaround would be to define a custom header such as X-Real-Ip, which Cloudflare should already be setting. Otherwise, if you can avoid using a plugin that removes the CF-Connecting-Ip header, the existing fallback logic should allow it to work.
```
http:
middlewares:
badger:
plugin:
badger:
disableForwardAuth: true
disableDefaultCFIPs: true
trustip:
- 172.24.0.0/16
- fd00:1:be:4::0/64
customIPHeader: "X-Real-Ip"
```
**Just note that the badger you define here is not the badger that is used in resources** (this also caught me out recently), which is probably adding to the confusion as Pangolin defines `badger@http` not `badger@file` that gets the configuration from the `config.yaml` that pangolin defines and such it only have the trust integer.
@LaurenceJJones commented on GitHub (Mar 25, 2026):
Editting looking back up, so on the traefik configuration you defined the trusted headers on both http and https entrypoints (even though your behind CF tunnel so https should basically be disabled)?
<!-- gh-comment-id:4128983618 -->
@LaurenceJJones commented on GitHub (Mar 25, 2026):
Editting looking back up, so on the traefik configuration you defined the trusted headers on both http and https entrypoints (even though your behind CF tunnel so https should basically be disabled)?
@Christopher87R commented on GitHub (Mar 26, 2026):
Editting looking back up, so on the traefik configuration you defined the trusted headers on both http and https entrypoints (even though your behind CF tunnel so https should basically be disabled)?
Yep, I defined it or both, http and https. Shouldn't http be disabled basically?
How can I define the config for badger@http?
<!-- gh-comment-id:4135546989 -->
@Christopher87R commented on GitHub (Mar 26, 2026):
> Editting looking back up, so on the traefik configuration you defined the trusted headers on both http and https entrypoints (even though your behind CF tunnel so https should basically be disabled)?
Yep, I defined it or both, http and https. Shouldn't http be disabled basically?
How can I define the config for badger@http?
@LaurenceJJones commented on GitHub (Mar 26, 2026):
How can I define the config for badger@http?
You cant and thats the issue because if you was doing typically cloudflare proxying (to public IP 80/433 port) we load the default cloudflare ranges and it works, but since its CF tunnel we have noway currently to define this for badger@http.
<!-- gh-comment-id:4135707385 -->
@LaurenceJJones commented on GitHub (Mar 26, 2026):
> How can I define the config for badger@http?
You cant and thats the issue because if you was doing typically cloudflare proxying (to public IP 80/433 port) we load the default cloudflare ranges and it works, but since its CF tunnel we have noway currently to define this for `badger@http`.
@github-actions[bot] commented on GitHub (Apr 10, 2026):
This issue has been automatically marked as stale due to 14 days of inactivity. It will be closed in 14 days if no further activity occurs.
<!-- gh-comment-id:4218926880 -->
@github-actions[bot] commented on GitHub (Apr 10, 2026):
This issue has been automatically marked as stale due to 14 days of inactivity. It will be closed in 14 days if no further activity occurs.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @Christopher87R on GitHub (Mar 4, 2026).
Original GitHub issue: https://github.com/fosrl/pangolin/issues/2597
Describe the Bug
The log files do not show the user's IP address, but rather that of the Docker host. Basically, I have a standard
setup: Cloudflare Tunnel (proxy) - VM with Docker-based Pangolin and Traefik.
In Traefik, the forwardedHeaders: trustedIPs are configured and pangolin server has trust_proxy: 2 configured. If I use the fork github.com/hajimAIM/badger in version v1.2.1 instead of the badger traefik plugin github.com/fosrl/badger v1.3.1, it works as expected.
Environment
To Reproduce
docker-compose.yml
config.yml
traefik_config.yml
dynamic_config.yml
Expected Behavior
I would expect my IPv4 (or IPv6, if applicable) address to be in the log file and also at Whoami under X-Real-Ip.
I would expect my IPv4 (or IPv6, if applicable) address to appear in the log file and also under X-Real-Ip in Whoami. This seems to work when I use the fork github.com/hajimAIM/badger in version v1.2.1 for Badger. However, I then have to deactivate the middleware.
@Christopher87R commented on GitHub (Mar 10, 2026):
Could you please check this or can anybody help me with this issue?
@LaurenceJJones commented on GitHub (Mar 10, 2026):
when setting the trust proxy level, did you ensure to bring down the stack (ensure the pangolin network is removed) then bring it all back up?
This is not just a pangolin problem many traefik users in general have issues with the docker-proxy causing problems with real ip.
also stating "standard setup" is not correct, we generally dont suggest you put pangolin behind a reverse proxy (cloudflared is a tunneled reverse proxy) as it should be exposed to be the gateway ingress.
@AstralDestiny commented on GitHub (Mar 10, 2026):
@AstralDestiny commented on GitHub (Mar 10, 2026):
If using cloudflared inspect your docker network and remove all the cloudflare v4/v6 and just put the docker ip range of cloudflared or the ipam you set for it.
docker inspect cloudflared, Find it's network name, docker network inspect
If it's on a different host then trust that host like 10.0.0.5/32
@Christopher87R commented on GitHub (Mar 10, 2026):
Sure, I did a docker compose up -d --force-recreate
It works when I use github.com/hajimAIM/badger in version v1.2.1 - So I was surprised and assume that it is a bug.
I did exactly as you suggested and only entered the relevant IPs. Unfortunately, this did not work, and I still have the same problem.
By the way, the Cf-Connecting-Ip is deleted - whoami no longer displays it when I have Pangolin in between.
For CF Tunnel - Traefik - whoami, it works.
@Christopher87R commented on GitHub (Mar 11, 2026):
I have now tried everything again and unfortunately without success. I also looked at the source code and since the Cf-Connecting-Ip header is deleted, isTrusted does not seem to be true - for whatever reason. Perhaps the trusted IP list is not being applied?
@Christopher87R commented on GitHub (Mar 12, 2026):
I have now explicitly set the IP ranges:
and adjusted the list of IPs accordingly:
Still no success, the visitor's real IP is never displayed.
@Christopher87R commented on GitHub (Mar 13, 2026):
I have now done the following (perhaps a little rough and ready, but it works).
My Traefik config now uses Badger's locale plugin (to incorporate debug output).
I also have set the CF-Tunnel IP
This works, and I have now incorporated the following output into the .go file:
The settings do not seem to be applied, because I get the following in the Traefik log file:
The strange thing is that after restarting Traefik, the following is briefly visible:
So something is going wrong here. Do you have any idea what it is and how I can narrow it down further? Unfortunately, I'm not really familiar with Go or a setup that would allow me to debug it.
Update: When I add the IP to the default IPs in ips.go, everything works fine.
It seems as if the IP list is always overwritten by the default IP list. This happens even when I explicitly deactivate the default IPs.
Am I doing something wrong in the settings?
@miloschwartz is this more a Badger bug?
@Christopher87R commented on GitHub (Mar 25, 2026):
Could someone please take a look at this? To me, this clearly looks like a defect (see the analysis of the last 3 posts)
@LaurenceJJones commented on GitHub (Mar 25, 2026):
As noted previously, Pangolin behind a reverse proxy is not a supported deployment method. For that reason, the issue being reported would not be classified as a defect in Pangolin, as the setup is outside the supported configuration.
Relevant code reference:
https://github.com/fosrl/badger/blob/67ad9b651eed00b74e65db5325cb3012a78ed50b/main.go#L403-L428
Looking at the current implementation, Badger’s realip handling is fairly limited and does not fully support the reverse lookup logic that would be needed here.
The most practical workaround would be to define a custom header such as X-Real-Ip, which Cloudflare should already be setting. Otherwise, if you can avoid using a plugin that removes the CF-Connecting-Ip header, the existing fallback logic should allow it to work.
Just note that the badger you define here is not the badger that is used in resources (this also caught me out recently), which is probably adding to the confusion as Pangolin defines
badger@httpnotbadger@filethat gets the configuration from theconfig.yamlthat pangolin defines and such it only have the trust integer.@LaurenceJJones commented on GitHub (Mar 25, 2026):
Editting looking back up, so on the traefik configuration you defined the trusted headers on both http and https entrypoints (even though your behind CF tunnel so https should basically be disabled)?
@Christopher87R commented on GitHub (Mar 26, 2026):
Yep, I defined it or both, http and https. Shouldn't http be disabled basically?
How can I define the config for badger@http?
@LaurenceJJones commented on GitHub (Mar 26, 2026):
You cant and thats the issue because if you was doing typically cloudflare proxying (to public IP 80/433 port) we load the default cloudflare ranges and it works, but since its CF tunnel we have noway currently to define this for
badger@http.@github-actions[bot] commented on GitHub (Apr 10, 2026):
This issue has been automatically marked as stale due to 14 days of inactivity. It will be closed in 14 days if no further activity occurs.