Traefik 中间件深度配置:限流、认证、IP 白名单与错误页面定制
如果你已经掌握了 Traefik 的基础部署,那么中间件(Middleware)才是真正发挥 Traefik 威力的地方。Traefik 中间件是请求处理管道中的"过滤器",可以在请求到达后端服务之前或响应返回客户端之前对其进行各种变换与控制。本文将深入探讨中间件链的高级用法,涵盖限流、Basic Auth、IP 白名单、请求头改写以及自定义错误页面等场景,帮助你构建一套生产级别的 API 网关防护体系。
环境要求
本教程所需的服务器环境:
- 服务器 :雨云服务器 rainyun-com ,注册填 2026off 领 5 折
- 推荐机型:2 核 4GB 内存,足以承载中等流量的 Traefik 实例及后端服务
- 操作系统:Ubuntu 22.04 LTS / Debian 12
- 软件依赖:Docker 25+、Docker Compose v2.24+、Traefik v3.x
2 核 4GB 的机型在日常 Web 应用场景下可轻松应对数千 QPS,对于中间件的功能验证与生产小型项目而言完全足够。
前置准备
目录结构
traefik/
├── docker-compose.yml
├── traefik.yml # 静态配置
├── config/
│ ├── middlewares.yml # 动态配置:中间件定义
│ └── routers.yml # 动态配置:路由定义
├── certs/ # TLS 证书目录
└── logs/
├── access.log
└── traefik.log
基础 docker-compose.yml
yaml
version: "3.8"
services:
traefik:
image: traefik:v3.0
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "8080:8080" # Dashboard(生产环境应关闭或保护)
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- ./config:/etc/traefik/config:ro
- ./certs:/certs
- ./logs:/logs
networks:
- traefik-net
networks:
traefik-net:
external: true
静态配置 traefik.yml
yaml
api:
dashboard: true
insecure: false
log:
level: INFO
filePath: /logs/traefik.log
accessLog:
filePath: /logs/access.log
bufferingSize: 100
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
providers:
docker:
exposedByDefault: false
network: traefik-net
file:
directory: /etc/traefik/config
watch: true
certificatesResolvers:
letsencrypt:
acme:
email: admin@example.com
storage: /certs/acme.json
httpChallenge:
entryPoint: web
部署步骤
1. 创建 Docker 网络
bash
docker network create traefik-net
2. 初始化 ACME 证书存储
bash
touch ./certs/acme.json
chmod 600 ./certs/acme.json
3. 启动 Traefik
bash
docker compose up -d
docker compose logs -f traefik
4. 验证 Dashboard
访问 http://your-server-ip:8080 查看 Traefik Dashboard(注意:生产环境务必保护此端口)。
核心功能配置
中间件声明方式
Traefik 支持三种中间件声明方式,适合不同的使用场景:
方式一:Docker 标签(Label)
适合简单场景,中间件与服务定义在同一个 docker-compose.yml 中:
yaml
services:
myapp:
image: myapp:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`app.example.com`)"
- "traefik.http.routers.myapp.middlewares=rate-limit@docker,auth@docker"
# 定义限流中间件
- "traefik.http.middlewares.rate-limit.ratelimit.average=100"
- "traefik.http.middlewares.rate-limit.ratelimit.burst=50"
# 定义 Basic Auth 中间件
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$xyz$$hashed"
方式二:文件配置(推荐用于复杂场景)
yaml
# config/middlewares.yml
http:
middlewares:
# 限流:每秒 100 请求,峰值 200
rate-limit:
rateLimit:
average: 100
burst: 200
period: 1s
sourceCriterion:
ipStrategy:
depth: 1
# Basic Auth 认证
basic-auth:
basicAuth:
users:
- "admin:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
removeHeader: true
# IP 白名单
ip-whitelist:
ipWhiteList:
sourceRange:
- "127.0.0.1/32"
- "10.0.0.0/8"
- "192.168.1.0/24"
ipStrategy:
depth: 1
# 请求头改写
headers-rewrite:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
X-Real-IP: ""
X-Custom-Header: "traefik-gateway"
customResponseHeaders:
X-Frame-Options: "SAMEORIGIN"
X-Content-Type-Options: "nosniff"
Strict-Transport-Security: "max-age=31536000; includeSubDomains"
accessControlAllowMethods:
- GET
- OPTIONS
- POST
- PUT
accessControlAllowHeaders:
- "Content-Type"
- "Authorization"
方式三:Kubernetes CRD(IngressRoute)
yaml
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: rate-limit
namespace: default
spec:
rateLimit:
average: 100
burst: 50
RateLimit 精细化配置
Traefik 的限流中间件支持按来源 IP、请求路径等维度限流:
yaml
http:
middlewares:
# 全局 API 限流
api-rate-limit:
rateLimit:
average: 200
burst: 500
period: 1s
sourceCriterion:
requestHeaderName: "X-API-Key" # 按 API Key 限流
# 登录接口严格限流(防暴力破解)
login-rate-limit:
rateLimit:
average: 5
burst: 10
period: 1m
sourceCriterion:
ipStrategy:
depth: 2 # 从 X-Forwarded-For 取第2个 IP
ForwardAuth 外部认证
ForwardAuth 将鉴权逻辑委托给外部认证服务(如 Authelia、authentik),是生产环境 SSO 的推荐方案:
yaml
http:
middlewares:
# 对接外部认证服务
forward-auth:
forwardAuth:
address: "http://authelia:9091/api/verify?rd=https://auth.example.com"
trustForwardHeader: true
authResponseHeaders:
- "Remote-User"
- "Remote-Groups"
- "Remote-Name"
- "Remote-Email"
自定义错误页面
yaml
http:
middlewares:
# 自定义错误页面
custom-errors:
errors:
status:
- "400-499"
- "500-599"
service: error-pages@docker
query: "/{status}.html"
services:
# 错误页面服务(需单独部署静态文件服务)
error-pages:
loadBalancer:
servers:
- url: "http://error-pages:80"
配套的 docker-compose 错误页面服务:
yaml
services:
error-pages:
image: nginx:alpine
volumes:
- ./error-pages:/usr/share/nginx/html:ro
labels:
- "traefik.enable=true"
- "traefik.http.services.error-pages.loadbalancer.server.port=80"
中间件链组合
将多个中间件组合成链,按顺序执行:
yaml
http:
middlewares:
# 定义中间件链:IP 检查 → 限流 → 认证 → 请求头改写
security-chain:
chain:
middlewares:
- ip-whitelist
- rate-limit
- basic-auth
- headers-rewrite
在路由中引用中间件链:
yaml
http:
routers:
secure-api:
rule: "Host(`api.example.com`) && PathPrefix(`/v1`)"
middlewares:
- security-chain
service: api-service
tls:
certResolver: letsencrypt
进阶用法
动态修改配置(热重载)
Traefik 文件 Provider 支持配置热重载,无需重启即可生效:
bash
# 修改 config/middlewares.yml 后,Traefik 自动检测变化并重载
# 可通过 Dashboard 或日志确认重载时间
tail -f ./logs/traefik.log | grep "Provider configuration changed"
按路径分配不同限流策略
yaml
http:
routers:
# 公开 API:宽松限流
public-api:
rule: "Host(`api.example.com`) && PathPrefix(`/public`)"
middlewares:
- api-rate-limit
service: api-service
# 管理接口:严格限流 + 认证
admin-api:
rule: "Host(`api.example.com`) && PathPrefix(`/admin`)"
middlewares:
- login-rate-limit
- ip-whitelist
- forward-auth
service: api-service
压缩中间件
yaml
http:
middlewares:
compress:
compress:
excludedContentTypes:
- "text/event-stream"
minResponseBodyBytes: 1024
常见问题
Q:限流后客户端收到 429,但 IP 识别不准确?
检查 ipStrategy.depth 配置,如果你的服务在 CDN 或负载均衡后面,需要设置正确的 depth 或者 excludedIPs 来跳过代理 IP。
Q:ForwardAuth 导致无限重定向?
确认认证服务的 rd(重定向)参数指向的是认证页面而非受保护页面,同时检查 trustForwardHeader 是否正确设置。
Q:Basic Auth 密码如何生成?
bash
# 使用 htpasswd 生成(Apache 工具)
htpasswd -nb admin yourpassword
# 或使用 openssl
echo $(htpasswd -nB admin) | sed -e 's/\$/\$\$/g'
注意:在 Docker Label 中 $ 需要转义为 $$,在 YAML 文件中无需转义。
Q:如何验证中间件是否生效?
bash
# 测试限流
for i in $(seq 1 20); do curl -s -o /dev/null -w "%{http_code}\n" https://api.example.com/; done
# 测试 IP 白名单
curl -v https://api.example.com/ 2>&1 | grep "403\|Forbidden"
Q:自定义错误页面不显示?
确认错误页面服务已正常运行,且 Traefik 能访问到它。检查 errors.service 名称格式是否正确(serviceName@provider)。
总结
Traefik 的中间件系统提供了极其灵活的请求处理能力,通过合理组合 RateLimit、ForwardAuth、IP 白名单等中间件,可以在不修改后端代码的情况下为应用增加完善的安全防护层。中间件链的热重载特性更让运维变更无需停机,大大提升了运维效率。
想要搭建自己的 Traefik 网关环境?选雨云服务器 rainyun-com 的 2 核 4GB 机型,稳定可靠,带宽充裕。注册账号时输入 2026off,即得 5 折。