7.9 KiB
7.9 KiB
Envoy Gateway 配置指南
概述
Envoy Gateway 作为 API 统一入口,提供以下功能:
- JWT 身份验证:所有 API 请求(除登录/注册)都需要有效的 JWT token
- CSRF 防护:防止跨站点请求伪造攻击
- 速率限制:防止 DDoS 攻击
- TLS 加密:所有通信都加密
- 负载均衡:分担后端服务的流量
架构
┌─────────────┐
│ Client │
└──────┬──────┘
│ HTTP/HTTPS (Port 80/443)
│
┌──────▼────────────────┐
│ Envoy Gateway │
│ ┌────────────────┐ │
│ │ JWT Validator │ │ ◄─── JWT Verification (offline)
│ │ CSRF Filter │ │
│ │ Rate Limiter │ │
│ │ Router │ │
│ └────────────────┘ │
└────────┬─────────────┘
│ gRPC/HTTP
┌────┴────┬──────────┐
│ │ │
┌───▼──┐ ┌──▼────┐ ┌──▼─────┐
│User │ │Order │ │User │
│API │ │API │ │RPC │
└──────┘ └───────┘ └────────┘
部署步骤
1. 生成 TLS 证书
# 为 Envoy 生成自签名证书(生产环境应使用正式证书)
kubectl create secret tls envoy-tls \
--cert=path/to/tls.crt \
--key=path/to/tls.key \
-n juwan
# 或生成自签名证书(仅用于测试)
openssl req -x509 -newkey rsa:4096 -keyout tls.key -out tls.crt \
-days 365 -nodes -subj "/CN=api.juwan.local"
kubectl create secret tls envoy-tls \
--cert=tls.crt \
--key=tls.key \
-n juwan
2. 部署 Envoy Gateway
# 应用 Envoy 配置
kubectl apply -f deploy/k8s/envoy-gateway.yaml
# 查看部署状态
kubectl get pods -n juwan -l app=envoy-gateway
kubectl get svc -n juwan envoy-gateway
3. 配置 JWKS 端点
在 user-rpc 中暴露 JWKS 端点,供 Envoy 验证 JWT:
在 app/users/rpc 中添加 HTTP 路由(go-zero)
编辑 app/users/rpc/internal/handler/ 或在 main.go 中:
// 在 rpc server 启动时,添加 HTTP 端点用于暴露 JWKS
import (
"net/http"
"juwan-backend/app/users/rpc/internal/utils"
)
// 在 main 函数中
http.HandleFunc("/.well-known/jwks.json", func(w http.ResponseWriter, r *http.Request) {
secretKey := os.Getenv("JWT_SECRET_KEY")
if secretKey == "" {
secretKey = "your-default-secret-key"
}
jwksJSON, err := utils.GenerateJWKSEndpoint(secretKey, "default-key-id")
if err != nil {
http.Error(w, "Failed to generate JWKS", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(jwksJSON))
})
// 在单独的 goroutine 中启动 HTTP 服务器
go func() {
http.ListenAndServe(":8080", nil)
}()
或使用 Echo 框架(更推荐):
// 在 main.go 中
import "github.com/labstack/echo/v4"
e := echo.New()
e.GET("/.well-known/jwks.json", func(c echo.Context) error {
secretKey := os.Getenv("JWT_SECRET_KEY")
jwksJSON, _ := utils.GenerateJWKSEndpoint(secretKey, "default-key-id")
return c.JSONBlob(http.StatusOK, []byte(jwksJSON))
})
go func() {
e.Start(":8080")
}()
4. 更新环境变量
在 K8s Secret 中配置 JWT_SECRET_KEY:
apiVersion: v1
kind: Secret
metadata:
name: jwt-secret
namespace: juwan
type: Opaque
data:
JWT_SECRET_KEY: "$(echo -n 'your-secret-key-change-this' | base64)"
5. 验证 JWKS 端点
# 端口转发
kubectl port-forward -n juwan svc/user-rpc-svc 9001:9001
# 验证 JWKS 端点可访问
curl http://localhost:9001/.well-known/jwks.json
JWT 验证流程
1. 登录获取 Token
curl -X POST http://api.juwan.local/api/v1/users/login \
-H "Content-Type: application/json" \
-d '{
"username": "testuser",
"password": "password123"
}'
# 响应:
# {
# "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
# "expires": 1708780800
# }
2. 使用 Token 访问受保护资源
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://api.juwan.local/api/v1/users/123
# Envoy 验证步骤:
# 1. 从 Authorization header 提取 token
# 2. 从 JWKS 端点获取公钥(缓存 5 分钟)
# 3. 验证 token 签名
# 4. 检查 token 过期时间
# 5. 将验证后的用户信息添加到请求头(X-USER-ID)
# 6. 转发请求到 user-api
CSRF 防护
配置说明
Envoy 的 CSRF 过滤器检查:
- 只对 POST/PUT/DELETE/PATCH 请求进行检查
- 检查
Origin和Refererheader - 验证请求来自已知域名
跨域请求配置
# Envoy 配置中允许的来源
additional_origins:
- exact: "https://admin.juwan.local"
- exact: "https://web.juwan.local"
Token 黑名单检查(可选)
如果需要验证 token 未被撤销,可启用额外的 RPC 验证:
# envoy-gateway.yaml 中取消注释
- name: envoy.filters.http.ext_authz
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
grpc_service:
envoy_grpc:
cluster_name: user_rpc_cluster
failure_mode_allow: false
然后在 user-rpc 中实现 ValidateToken RPC:
rpc ValidateToken(ValidateTokenReq) returns(ValidateTokenResp);
故障排查
1. JWT 验证失败
# 查看 Envoy 日志
kubectl logs -n juwan -l app=envoy-gateway -f
# 验证 JWKS 端点是否可访问
kubectl exec -it -n juwan <envoy-pod> -- \
curl http://user-rpc-svc:9001/.well-known/jwks.json
2. 无法连接到后端服务
# 验证服务发现
kubectl get endpoints -n juwan
# 验证网络策略
kubectl get networkpolicy -n juwan
# 测试连接
kubectl exec -it -n juwan <envoy-pod> -- \
curl http://user-api-svc:8888/health
3. CSRF 错误
- 确保设置了
Origin和Refererheader - 检查
additional_origins配置是否包含你的域名
性能优化
1. JWKS 缓存
cache_ttl:
seconds: 300 # 缓存 5 分钟,减少 RPC 调用
2. 连接池
http2_protocol_options: {} # 启用 HTTP/2 多路复用
3. 速率限制调整
根据实际流量调整令牌桶参数:
token_bucket:
max_tokens: 10000 # 最大令牌数
tokens_per_fill: 10000 # 每次填充的令牌数
fill_interval: 1s # 填充间隔
监控和日志
访问日志
# 查看访问日志
kubectl logs -n juwan -l app=envoy-gateway --follow
# 格式包含:
# - 请求时间、方法、路径
# - 响应状态码、字节数
# - 上游服务信息
Prometheus 指标
Envoy 在 :9901/stats 暴露 Prometheus 指标:
kubectl port-forward -n juwan svc/envoy-gateway 9901:9901
curl localhost:9901/stats | grep jwt
生产环境检查清单
- 使用正式 TLS 证书(不是自签名)
- 配置正确的 JWT_SECRET_KEY(强密码)
- 启用 HTTPS(关闭 HTTP)
- 配置网络策略限制访问
- 启用访问日志和监控
- 设置合理的速率限制
- 测试 token 过期和刷新流程
- 配置告警规则