This commit is contained in:
wwweww
2026-02-23 20:36:21 +08:00
parent 4898aecd3b
commit fdbcde13b2
52 changed files with 11263 additions and 194 deletions
+320
View File
@@ -0,0 +1,320 @@
# 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 证书
```bash
# 为 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
```bash
# 应用 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` 中:
```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 框架(更推荐)**
```go
// 在 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
```yaml
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 端点
```bash
# 端口转发
kubectl port-forward -n juwan svc/user-rpc-svc 9001:9001
# 验证 JWKS 端点可访问
curl http://localhost:9001/.well-known/jwks.json
```
## JWT 验证流程
### 1. 登录获取 Token
```bash
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 访问受保护资源
```bash
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``Referer` header
- 验证请求来自已知域名
### 跨域请求配置
```yaml
# Envoy 配置中允许的来源
additional_origins:
- exact: "https://admin.juwan.local"
- exact: "https://web.juwan.local"
```
## Token 黑名单检查(可选)
如果需要验证 token 未被撤销,可启用额外的 RPC 验证:
```yaml
# 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
```protobuf
rpc ValidateToken(ValidateTokenReq) returns(ValidateTokenResp);
```
## 故障排查
### 1. JWT 验证失败
```bash
# 查看 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. 无法连接到后端服务
```bash
# 验证服务发现
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``Referer` header
- 检查 `additional_origins` 配置是否包含你的域名
## 性能优化
### 1. JWKS 缓存
```yaml
cache_ttl:
seconds: 300 # 缓存 5 分钟,减少 RPC 调用
```
### 2. 连接池
```yaml
http2_protocol_options: {} # 启用 HTTP/2 多路复用
```
### 3. 速率限制调整
根据实际流量调整令牌桶参数:
```yaml
token_bucket:
max_tokens: 10000 # 最大令牌数
tokens_per_fill: 10000 # 每次填充的令牌数
fill_interval: 1s # 填充间隔
```
## 监控和日志
### 访问日志
```bash
# 查看访问日志
kubectl logs -n juwan -l app=envoy-gateway --follow
# 格式包含:
# - 请求时间、方法、路径
# - 响应状态码、字节数
# - 上游服务信息
```
### Prometheus 指标
Envoy 在 `:9901/stats` 暴露 Prometheus 指标:
```bash
kubectl port-forward -n juwan svc/envoy-gateway 9901:9901
curl localhost:9901/stats | grep jwt
```
## 生产环境检查清单
- [ ] 使用正式 TLS 证书(不是自签名)
- [ ] 配置正确的 JWT_SECRET_KEY(强密码)
- [ ] 启用 HTTPS(关闭 HTTP
- [ ] 配置网络策略限制访问
- [ ] 启用访问日志和监控
- [ ] 设置合理的速率限制
- [ ] 测试 token 过期和刷新流程
- [ ] 配置告警规则
## 参考文档
- [Envoy JWT Authentication](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/jwt_authn/v3/config.proto)
- [Envoy CSRF Protection](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/csrf/v3/csrf.proto)
- [JWT RFC 7519](https://tools.ietf.org/html/rfc7519)