If Traefik’s dashboard, API endpoints (/api/rawdata, /api/http/services, /api/http/routers), or /debug/pprof answer requests from the public internet, you are publishing a map of your infrastructure. The API returns every router rule, backend server URL, middleware configuration, and upstream health status. /debug/pprof adds Go runtime profiling data. Automated scanners fingerprint Traefik continuously, and the dashboard API has a history of information-disclosure issues. The fix is usually a ten-minute configuration change, but only if you know the exposure exists. Many teams never test from outside their own network.
This guide covers how to probe for the exposure from an untrusted network, the common misconfiguration patterns, and how to lock the management surface down with an IP allowlist, authentication, network policy, or a non-public entrypoint.
What this means
Traefik has two planes. The data plane serves your entrypoints (ports 80/443) and proxies traffic to backends. The control plane serves the dashboard, the REST API, and optionally the Go debug endpoints. The control plane is where the sensitive material lives:
/api/rawdatareturns the complete dynamic configuration: routers, services, middlewares, their status, and dependency relations. In effect, your entire routing table./api/http/servicesreveals every backend server URL, so an attacker learns internal hostnames, ports, and IP addresses directly./api/http/routersshows every routing rule, including rules for internal-only services that should not be publicly known./dashboard/is the web UI backed by the same API./debug/pprof/(whenapi.debugis enabled) exposes Go profiling data: goroutine dumps, heap profiles, CPU profiles. Beyond reconnaissance value, profiling endpoints can be abused to burn CPU on the proxy itself.
An attacker with this map knows which backends exist, which are unhealthy, which middleware protects which route, and where the soft targets are. In some configurations the API also exposes certificate details. Combined with known auth-middleware bypass CVEs in unpatched Traefik versions (for example CVE-2024-45410, fixed in v2.11.9 and v3.1.3), an exposed API is both an information leak and an attack surface.
The rule is simple: the dashboard entrypoint must never be published to the public internet. Not “protected later”, not “obscured on a weird port”. Never published.
flowchart LR
Internet[Public internet] -->|probe /api, /dashboard, /debug| Entry{Entrypoint}
Entry -->|published, no auth| API[Traefik API + dashboard]
Entry -->|allowlist + auth, or not published| Deny[403 / connection refused]
API --> Raw[/api/rawdata: full routing table/]
API --> Svcs[/api/http/services: backend URLs + health/]
API --> Pprof[/debug/pprof: Go profiling/]Common causes
| Cause | What it looks like | First thing to check |
|---|---|---|
api.insecure=true left on | API and dashboard served directly on the traefik entrypoint (default port 8080), no authentication, middleware does not apply | Static config: api.insecure or --api.insecure flag |
| Dashboard entrypoint bound to a public interface | Port 8080 (or the custom dashboard port) reachable from the internet via the load balancer or host firewall | Probe the public IP on the dashboard port from outside |
| Kubernetes Service exposing the dashboard port | A Service of type LoadBalancer or NodePort includes the dashboard/API port alongside 80/443 | kubectl get svc and check the published ports |
| Router for the API without auth middleware | api@internal routed on a public entrypoint with no BasicAuth, ForwardAuth, or IPAllowList attached | Dynamic config for the router targeting api@internal |
api.debug=true in production | /debug/pprof/ and /debug/vars answering on the API surface | Static config: api.debug or --api.debug flag |
| Firewall/security group wider than intended | The management port is firewalled on some paths but the cloud security group allows 0.0.0.0/0 | Probe from a genuinely external network, not from a VPN |
A subtle trap with api.insecure=true: it bypasses middleware entirely. Operators often enable insecure mode “temporarily”, then try to bolt on BasicAuth via labels or dynamic config, and it silently does nothing because the insecure API handler never passes through the middleware chain. If you want middleware-based protection, you must disable insecure mode and route api@internal explicitly.
Quick checks
Run these from a network that is genuinely outside your perimeter: a personal hotspot, a VPS in another cloud, or a scanner host. Probing from the office LAN or VPN will give you false reassurance.
# Probe the management surface from an external host.
# Any 200 here from the public internet is a finding.
for path in /api/rawdata /api/http/services /api/http/routers /dashboard/ /debug/pprof/; do
code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 "http://traefik-public-ip:8080${path}")
echo "${code} ${path}"
done
# Check whether the dashboard port is even open on the public address
nc -zv traefik-public-ip 8080
# On the host or in the pod: inspect how the API is configured
# Static config flags (process args)
ps aux | grep -o '\-\-api[^ ]*'
# Or in the static config file
grep -A5 '^api:' /etc/traefik/traefik.yml
# Kubernetes: check which ports the Traefik Service publishes
kubectl -n traefik get svc -o wide
kubectl -n traefik get svc traefik -o jsonpath='{.spec.ports[*].port}'
# See what the API actually discloses (run against the internal address)
curl -s http://localhost:8080/api/http/services | head -c 2000
Interpretation: 401 or 403 from outside means some protection exists (verify it is real and not bypassable). 404 or connection refused means the surface is not published. 200 means you have an exposure to fix now.
How to diagnose it
Establish the external truth first. Run the probe loop above from an untrusted network. Record which paths return 200, which return 401/403, and which are unreachable. This is your exposure inventory.
Determine how the API is being served. Check the static configuration for
api.insecure. If it is true, the API is bound to the traefik entrypoint directly and no middleware can protect it. If it is false (the default), look for a router in the dynamic configuration that targets theapi@internalservice and note which entrypoints it is attached to.Map the network path. If the API answers on the public IP, find out why: is the dashboard entrypoint bound to 0.0.0.0 and published by a cloud load balancer? Is there a Kubernetes Service or Ingress that includes the management port? Is a security group allowing the port from 0.0.0.0/0?
Check whether debug mode is on. Look for
api.debug=truein the static config or--api.debugin the process arguments. If/debug/pprof/answered in step 1, treat it as part of the exposure even if the dashboard itself is protected.Check the Traefik version. An exposed management surface on an unpatched version compounds the risk, because several auth-middleware bypass CVEs (path normalization, header normalization, middleware ordering issues) have been fixed in recent patch releases. If you must keep the API reachable from anywhere beyond localhost, being current on patches is not optional.
Review the audit trail. If the API was exposed, pull access logs (Traefik’s and any upstream LB logs) and look for requests to
/api/*,/dashboard/*, and/debug/*from source IPs you do not recognize. Assume anything returned by/api/rawdatais now known.
Metrics and signals to monitor
This exposure is primarily detected by external probing and network audit, not by metrics. But Traefik’s Prometheus metrics give you supporting evidence of probing and exploitation attempts:
| Signal | Why it matters | Warning sign |
|---|---|---|
Entrypoint 404 rate (traefik_entrypoint_requests_total{code="404"}) | Scanners enumerating paths and hosts show up as unmatched requests at the entrypoint | Sudden increase over 3x baseline, especially concentrated on unknown Host headers |
401/403 rate (traefik_entrypoint_requests_total{code=~"40[13]"}) | Tells you whether auth middleware on the API is being exercised or attacked | Sustained rate above 5x baseline from concentrated sources |
| Requests hitting the management entrypoint | A management entrypoint that should see near-zero traffic should see near-zero traffic | Any sustained request rate on the dashboard/API entrypoint from outside your admin ranges |
Access log review of /api/*, /debug/* paths | Confirms actual reads of the routing table, not just probes | 200 responses to these paths from unrecognized source IPs |
Source IP caveat: if Traefik sits behind a CDN or cloud load balancer, access log source IPs are the intermediary’s. Parse X-Forwarded-For for the real client address.
Fixes
Disable insecure mode and route the API deliberately
Turn off api.insecure. It exists for local development, and it disables any possibility of middleware-based protection. In production, the API and dashboard are disabled by default (api: false); if you need them, enable the API and expose api@internal through an explicit router in the dynamic configuration, with protection attached. That router is where your defenses live.
Attach an IPAllowList middleware
Restrict the management router to known admin networks using the IPAllowList middleware with sourceRange in CIDR notation. The default rejection status is 403; rejectStatusCode can be changed if you prefer to return 404 and not confirm the endpoint exists. If Traefik is behind a proxy or load balancer, configure ipStrategy (depth or excludedIPs) so the allowlist evaluates the real client IP from X-Forwarded-For rather than the LB address, otherwise you either allow nothing or allow everything.
Add authentication as a second layer
IP allowlisting plus BasicAuth or ForwardAuth on the management router gives you defense in depth: a network change alone does not open the door. Put auth middleware before any path-manipulation middleware in the chain; several published auth-bypass CVEs exploit the strip-before-auth ordering. Never ship default or placeholder credentials.
Bind the dashboard to a non-public entrypoint
The cleanest fix is architectural: serve the dashboard and API on a dedicated entrypoint bound to localhost or an internal interface only, and reach it through a VPN, bastion, or kubectl port-forward. If the port is never published by a load balancer, Service, or security group, there is nothing to misconfigure later. In Kubernetes, double-check that no Service of type LoadBalancer or NodePort includes the management port.
Turn off debug mode
Set api.debug=false (the default) in production. If you need pprof for an investigation, enable it temporarily on an internal-only entrypoint and turn it back off when done. Go profiling endpoints are both a disclosure risk and a cheap way to burn proxy CPU.
Rotate what the exposure leaked
If the API was publicly reachable for an unknown period, treat the leaked data as known: internal hostnames, ports, backend topology, and any secrets that were visible in the dynamic configuration. Review access logs for reads of /api/*, and patch Traefik to a current release before re-exposing anything, even internally.
Prevention
- Probe continuously, not once. Add an external check that periodically requests
/dashboard/and/api/rawdataagainst your public addresses and alerts if any return 200. Exposure often reappears after a Helm upgrade, a new Service, or a security group change. - Keep the API disabled unless you use it.
api: falseis the default. If nobody on the team queries the API or opens the dashboard, leave it off. - Deny by default in network policy. In Kubernetes, use NetworkPolicy so only intended namespaces can reach the management port. At the cloud layer, scope the security group for the management port to admin CIDRs, or do not create a rule at all.
- Review middleware ordering in CI. Lint dynamic configuration for routers serving
api@internaland verify auth and allowlist middleware are present and ordered before any path rewriting. - Patch Traefik on a schedule. Auth-middleware bypass fixes land in patch releases regularly. An allowlist you trust today is only as strong as the proxy version enforcing it.
How Netdata helps
- Netdata collects Traefik’s Prometheus metrics per second, so a sudden burst of entrypoint 404s or 401/403s from scanner activity is visible as it happens, not five minutes later.
- Per-entrypoint request charts make it obvious when a management entrypoint that should be idle starts serving real traffic, which is exactly what an accidental exposure looks like from the inside.
- Code-level breakdowns of
traefik_entrypoint_requests_totallet you separate scanner noise (404s on unknown hosts) from auth pressure (401/403 on the API router) without touching raw logs. - ML-based anomaly detection on request rates and error ratios catches the low-and-slow probing pattern that static thresholds miss, like a scanner spreading requests across hours.
- Alerting on the 4xx ratio at the entrypoint level gives you an early tripwire when new paths, including management paths, start receiving external attention after a config or network change.
Related guides
- Traefik 404 not found: requests arriving with no matching router
- Traefik 502 Bad Gateway: when the backend is unreachable or returns garbage
- Traefik 503 Service Unavailable: no healthy backends left in the pool
- Traefik 504 Gateway Timeout: the backend is alive but too slow
- Traefik 5xx error rate: telling Traefik-generated errors from backend errors
- Traefik access log blocking: when logging stalls request handling
- Traefik ACME challenge failed: HTTP-01, DNS-01, and TLS-ALPN-01 renewal errors
- Traefik acme.json permissions and corruption: renewal silently blocked
- Traefik ACME rate limit: too many certificates already issued for this domain
- Traefik backend connection pool: keep-alive, MaxIdleConnsPerHost, and reuse
- Traefik cannot assign requested address: ephemeral port exhaustion
- Traefik cascading backend failure: how a partial outage becomes a total one






