We’re going to explore how to enhance the security of your Traefik server. We’ll discuss Access Control Lists (ACLs), rate limiting, and GeoIP blocking, and also take a look at how to only permit traffic from certain networks like Cloudflare.
1. Access Control Lists (ACLs)
Traefik uses middlewares to allow or deny access based on a set of conditions. Here’s an example of how to allow a specific IP address:
http:
middlewares:
trusted-ips:
ipAllowList:
sourceRange:
- '192.168.1.0/24' # Local network
- '10.0.0.0/8' # Private network
- '203.0.113.0/24' # Specific trusted range
ipStrategy:
depth: 2 # Consider X-Forwarded-For depth
excludedIPs:
- '127.0.0.1/32' # Exclude localhost
routers:
secure-router:
middlewares:
- trusted-ips
This configuration allows access from specified IP ranges while considering forwarded headers from proxies.
2. Rate Limiting
Protect your services from abuse using Traefik’s rate limiting middleware with configurable burst and sustained rates:
http:
middlewares:
api-rate-limit:
rateLimit:
average: 100 # Requests per second (sustained)
burst: 200 # Maximum burst size
period: 1m # Time window for rate calculation
sourceCriterion:
ipStrategy:
depth: 1 # Consider proxy depth
excludedIPs:
- '127.0.0.1/32'
strict-rate-limit:
rateLimit:
average: 10
burst: 20
period: 1m
routers:
api-router:
middlewares:
- api-rate-limit
admin-router:
middlewares:
- strict-rate-limit
This provides different rate limits for different services - more permissive for APIs, stricter for admin interfaces.
3. Allow only Cloudflare IPs
Restrict access to only Cloudflare’s edge servers when using Cloudflare as a CDN/proxy:
http:
middlewares:
cloudflare-only:
ipAllowList:
sourceRange:
# IPv4 ranges (update regularly from https://www.cloudflare.com/ips/)
- '103.21.244.0/22'
- '103.22.200.0/22'
- '103.31.4.0/22'
- '104.16.0.0/13'
- '104.24.0.0/14'
- '108.162.192.0/18'
- '131.0.72.0/22'
- '141.101.64.0/18'
- '162.158.0.0/15'
- '172.64.0.0/13'
- '173.245.48.0/20'
- '188.114.96.0/20'
- '190.93.240.0/20'
- '197.234.240.0/22'
- '198.41.128.0/17'
# IPv6 ranges
- '2400:cb00::/32'
- '2606:4700::/32'
- '2803:f800::/32'
- '2405:b500::/32'
- '2405:8100::/32'
- '2a06:98c0::/29'
- '2c0f:f248::/32'
ipStrategy:
depth: 1
Important: Update these IP ranges regularly as Cloudflare may change them. Check https://www.cloudflare.com/ips/ for current ranges.
4. Trusted Proxy Configuration
When your Traefik instance sits behind reverse proxies like Cloudflare, load balancers, or CDNs, these intermediaries mask the real client IP addresses. Instead of seeing the actual visitor’s IP, Traefik only sees the proxy’s IP address. This breaks IP-based security features like rate limiting and access control.
The solution is configuring Traefik to trust specific proxy IPs and extract the real client IP from HTTP headers like X-Forwarded-For. This restoration of true client IPs ensures your security policies work correctly while maintaining the benefits of your proxy infrastructure.
# Static configuration (docker-compose command or traefik.yml)
entryPoints:
web:
address: ':80'
forwardedHeaders:
trustedIPs:
- '103.21.244.0/22'
- '103.22.200.0/22'
- '103.31.4.0/22'
- '104.16.0.0/13'
- '104.24.0.0/14'
- '108.162.192.0/18'
- '131.0.72.0/22'
- '141.101.64.0/18'
- '162.158.0.0/15'
- '172.64.0.0/13'
- '173.245.48.0/20'
- '188.114.96.0/20'
- '190.93.240.0/20'
- '197.234.240.0/22'
- '198.41.128.0/17'
insecure: false # Only trust specified IPs
websecure:
address: ':443'
forwardedHeaders:
trustedIPs:
# Same Cloudflare IP ranges as above
- '103.21.244.0/22'
# ... (same list)
insecure: false
This enables accurate client IP detection for security policies while maintaining CDN benefits.
5. Security Headers Middleware
Security headers are HTTP response headers that instruct browsers how to behave when handling your site’s content. They provide crucial protection against cross-site scripting (XSS), clickjacking, content type sniffing, and other client-side attacks. Modern web applications should implement these headers as a fundamental security layer.
These headers work by telling the browser to enforce security policies - for example, preventing your site from being embedded in frames (clickjacking protection), forcing HTTPS connections (HSTS), and restricting resource loading (CSP). While they don’t protect your server directly, they create a security boundary in the user’s browser.
http:
middlewares:
security-headers:
headers:
accessControlAllowMethods:
- GET
- OPTIONS
- PUT
- POST
- DELETE
accessControlMaxAge: 100
hostsProxyHeaders:
- X-Forwarded-Host
referrerPolicy: "strict-origin-when-cross-origin"
forceSTSHeader: true
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: true
contentTypeNosniff: true
browserXssFilter: true
customFrameOptionsValue: "SAMEORIGIN"
customRequestHeaders:
X-Forwarded-Proto: "https"
customResponseHeaders:
X-Robots-Tag: "noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex"
server: ""
X-Powered-By: ""
contentSecurityPolicy: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'self';"
6. Authentication Middleware
Authentication adds a verification layer before users can access your services. This is essential for admin panels, APIs, and any sensitive content. Traefik supports multiple authentication methods, from simple basic auth to sophisticated OAuth flows.
Basic authentication provides quick protection with username/password combinations, while forward authentication delegates to external services like OAuth providers. Choose based on your security requirements - basic auth for simple internal tools, OAuth for production applications with user management needs.
http:
middlewares:
basic-auth:
basicAuth:
users:
- "admin:$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi" # admin:password
realm: "Traefik Dashboard"
removeHeader: true
oauth-forward:
forwardAuth:
address: "http://oauth-proxy:4181"
authResponseHeaders:
- "X-Forwarded-User"
- "X-Auth-User"
trustForwardHeader: true
7. Circuit Breaker for Resilience
Circuit breakers protect your infrastructure from cascading failures. When a backend service becomes unhealthy or overloaded, the circuit breaker temporarily stops forwarding requests to it, preventing the problem from spreading to other parts of your system.
Think of it like an electrical circuit breaker in your home - when there’s too much load, it trips to prevent damage. In web applications, this means detecting when error rates or network issues exceed thresholds, then failing fast instead of letting requests pile up and timeout. This maintains overall system stability during partial outages.
http:
middlewares:
circuit-breaker:
circuitBreaker:
expression: "NetworkErrorRatio() > 0.30 || ResponseCodeRatio(500, 600, 0, 600) > 0.25"
checkPeriod: 10s
fallbackDuration: 30s
recoveryDuration: 10s
8. Complete Security Stack Example
Real-world security requires layering multiple protections. No single security measure is sufficient - attackers who bypass one layer should encounter another. This defense-in-depth approach combines IP filtering, rate limiting, authentication, and other measures into comprehensive protection.
The key is creating middleware chains that apply appropriate security levels for different types of services. Public APIs need different protection than admin interfaces, and you can mix and match middlewares to create the right security posture for each endpoint.
http:
middlewares:
security-stack:
chain:
middlewares:
- cloudflare-only
- security-headers
- api-rate-limit
- circuit-breaker
admin-security:
chain:
middlewares:
- trusted-ips
- basic-auth
- strict-rate-limit
- security-headers
routers:
api-secure:
rule: "Host(`api.example.com`)"
middlewares:
- security-stack
service: api-service
tls:
certResolver: letsencrypt
admin-secure:
rule: "Host(`admin.example.com`)"
middlewares:
- admin-security
service: admin-service
tls:
certResolver: letsencrypt
9. Enhanced Logging and Monitoring
Security without visibility is incomplete. Comprehensive logging provides the data needed to detect attacks, investigate incidents, and improve your security posture over time. Structured JSON logs make it easier to analyze patterns and integrate with security tools.
Good logging captures not just successful requests, but failed authentication attempts, blocked IPs, and suspicious patterns. This creates an audit trail that’s essential for both real-time alerting and post-incident analysis. The logs also feed into automated defense systems like Fail2Ban.
# Static configuration
accessLog:
format: json
fields:
defaultMode: keep
names:
ClientUsername: drop
headers:
defaultMode: keep
names:
User-Agent: keep
Authorization: drop
Content-Type: keep
X-Forwarded-For: keep
X-Real-IP: keep
log:
level: INFO
format: json
api:
dashboard: true
debug: false
insecure: false
metrics:
prometheus:
buckets:
- 0.1
- 0.3
- 1.2
- 5.0
addEntryPointsLabels: true
addServicesLabels: true
Fail2Ban Integration
Fail2Ban automatically blocks IP addresses that show malicious behavior by analyzing log files and creating temporary firewall rules. This provides dynamic protection against brute force attacks, bot scanning, and other automated threats.
The integration works by parsing Traefik’s access logs to identify suspicious patterns - multiple authentication failures, requests for non-existent files, or attempts to access sensitive paths. When thresholds are exceeded, Fail2Ban adds the offending IP to a blocklist.
# /etc/fail2ban/filter.d/traefik-auth.conf
[Definition]
failregex = .*"ClientHost":"<HOST>".*"OriginStatus":401.*
.*"ClientHost":"<HOST>".*"OriginStatus":403.*
.*"ClientHost":"<HOST>".*"OriginStatus":404.*"RequestMethod":"POST".*
ignoreregex =
# /etc/fail2ban/filter.d/traefik-botsearch.conf
[Definition]
failregex = .*"ClientHost":"<HOST>".*"RequestPath":"/\.(env|git|svn|htaccess).*"
.*"ClientHost":"<HOST>".*"RequestPath":".*(admin|wp-admin|phpmyadmin).*"
.*"ClientHost":"<HOST>".*"RequestPath":".*(sql|php|asp).*"
# /etc/fail2ban/jail.local
[traefik-auth]
enabled = true
filter = traefik-auth
logpath = /var/log/traefik/access.log
maxretry = 5
bantime = 3600
findtime = 600
[traefik-botsearch]
enabled = true
filter = traefik-botsearch
logpath = /var/log/traefik/access.log
maxretry = 3
bantime = 86400
findtime = 600
10. Timeout and Performance Configuration
Proper timeout configuration serves both performance and security purposes. Timeouts prevent resource exhaustion attacks where malicious clients hold connections open indefinitely, while also ensuring responsive user experiences by failing fast when backends are slow.
Connection limits and health checks add another layer of protection. By restricting concurrent connections and actively monitoring backend health, you prevent both accidental overload and deliberate resource exhaustion attempts.
# Static configuration
serversTransport:
maxIdleConnsPerHost: 42
forwardingTimeouts:
dialTimeout: 30s
responseHeaderTimeout: 60s
idleConnTimeout: 90s
insecureSkipVerify: false
# Service-specific timeouts
http:
services:
secure-service:
loadBalancer:
servers:
- url: "http://backend:8080"
healthCheck:
path: "/health"
interval: 30s
timeout: 10s
scheme: http
sticky:
cookie:
name: "traefik-session"
secure: true
httpOnly: true
sameSite: strict
11. Additional Security Hardening
Docker Security Configuration
Container security is crucial since Traefik often runs with elevated privileges to access the Docker socket. These measures implement the principle of least privilege - Traefik gets only the minimal permissions needed to function, reducing the impact of potential compromises.
Running as non-root, dropping capabilities, and using read-only filesystems all limit what an attacker can do if they manage to exploit the application. The security options work together to create a hardened container environment.
services:
traefik:
image: traefik:v3
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
- seccomp:unconfined
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
read_only: true
user: "1000:1000" # Non-root user
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme:/etc/traefik/acme:rw
- ./logs:/var/log/traefik:rw
tmpfs:
- /tmp
environment:
- TRAEFIK_LOG_LEVEL=INFO
networks:
- traefik
File Permission Security
File system permissions are your last line of defense. Even if an attacker gains access to your server, properly configured permissions can prevent them from reading sensitive configuration files or SSL certificates.
Certificate files are particularly sensitive - they contain private keys that, if compromised, allow attackers to impersonate your services. Restrictive permissions ensure only authorized processes can access these critical files.
# Set restrictive permissions
chmod 600 /etc/traefik/acme/acme.json
chmod 640 /etc/traefik/traefik.yml
chown traefik:traefik /etc/traefik/acme/acme.json
chown root:traefik /etc/traefik/traefik.yml
These configurations provide defense-in-depth security for production Traefik deployments, protecting against common attack vectors while maintaining performance and reliability.
Buy Me a Coffee