name: implementing-api-gateway-security-controls description: > 在API网关层实施安全控制,包括认证强制执行、速率限制、请求验证、IP白名单、TLS终止和威胁防护。 配置API网关(Kong、AWS API Gateway、Azure APIM、Apigee)作为集中式安全执行点, 在流量到达后端服务前对所有API流量进行验证、节流和监控。 domain: cybersecurity subdomain: api-security tags: [api-security, api-gateway, kong, aws-api-gateway, rate-limiting, waf] version: 1.0.0 author: mahipal license: Apache-2.0
实施API网关安全控制
适用场景
- 为微服务API部署集中式认证和授权层
- 对所有API端点实施速率限制、节流和配额管理
- 在网关级别根据OpenAPI规范配置请求/响应验证
- 为API流量设置TLS终止、双向TLS和证书管理
- 将WAF规则与API网关集成,阻断注入、XSS和已知攻击模式
不适用作为唯一安全层。API网关提供纵深防御,但后端服务也必须验证授权和输入。
前置条件
- 已选择并部署API网关平台(Kong、AWS API Gateway、Azure APIM或Apigee)
- 所有后端API的OpenAPI/Swagger规范
- 网关域名的TLS证书
- 已为OAuth2/OIDC配置身份提供商(IdP)(Okta、Auth0、Azure AD)
- 监控和日志基础设施(CloudWatch、Datadog、ELK)
- 后端服务端点已注册并可从网关访问
工作流程
步骤1:Kong网关安全配置
# kong.yml - 带安全插件的声明式Kong配置
_format_version: "3.0"
services:
- name: user-service
url: http://user-service:8080
routes:
- name: user-api
paths:
- /api/v1/users
methods:
- GET
- POST
- PUT
- PATCH
- DELETE
strip_path: false
plugins:
# 1. 认证:JWT验证
- name: jwt
config:
uri_param_names:
- jwt
header_names:
- Authorization
claims_to_verify:
- exp
maximum_expiration: 3600 # 令牌最大有效期1小时
# 2. 速率限制
- name: rate-limiting
config:
minute: 60
hour: 1000
policy: redis
redis_host: redis
redis_port: 6379
fault_tolerant: true
hide_client_headers: false
limit_by: credential # 按用户而非按IP
# 3. 请求大小限制
- name: request-size-limiting
config:
allowed_payload_size: 1 # 最大1MB
size_unit: megabytes
# 4. IP限制(管理端点)
- name: ip-restriction
service: admin-service
config:
allow:
- 10.0.0.0/8
- 172.16.0.0/12
# 5. 机器人检测
- name: bot-detection
config:
deny:
- "sqlmap"
- "nikto"
- "nmap"
- "masscan"
# 6. CORS配置
- name: cors
config:
origins:
- "https://app.example.com"
methods:
- GET
- POST
- PUT
- PATCH
- DELETE
headers:
- Authorization
- Content-Type
credentials: true
max_age: 3600
# 7. 响应转换器 - 移除敏感头部
- name: response-transformer
config:
remove:
headers:
- X-Powered-By
- Server
add:
headers:
- "X-Content-Type-Options: nosniff"
- "X-Frame-Options: DENY"
- "Strict-Transport-Security: max-age=31536000; includeSubDomains"
- "Content-Security-Policy: default-src 'none'"
步骤2:AWS API Gateway安全配置
import boto3
import json
apigw = boto3.client('apigatewayv2')
# 创建带双向TLS的API
api_response = apigw.create_api(
Name='secure-api',
ProtocolType='HTTP',
DisableExecuteApiEndpoint=True, # 强制使用自定义域名
)
api_id = api_response['ApiId']
# 配置授权器(带Cognito的JWT)
authorizer = apigw.create_authorizer(
ApiId=api_id,
AuthorizerType='JWT',
IdentitySource='$request.header.Authorization',
Name='cognito-jwt-authorizer',
JwtConfiguration={
'Audience': ['your-app-client-id'],
'Issuer': 'https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxx'
}
)
# 创建带授权器的路由
apigw.create_route(
ApiId=api_id,
RouteKey='GET /api/v1/users',
AuthorizerId=authorizer['AuthorizerId'],
AuthorizationType='JWT',
)
# 配置节流
apigw.create_stage(
ApiId=api_id,
StageName='prod',
DefaultRouteSettings={
'ThrottlingBurstLimit': 100,
'ThrottlingRateLimit': 50.0, # 每秒50个请求
},
AccessLogSettings={
'DestinationArn': 'arn:aws:logs:us-east-1:123456789:log-group:api-access-logs',
'Format': json.dumps({
'requestId': '$context.requestId',
'ip': '$context.identity.sourceIp',
'caller': '$context.identity.caller',
'user': '$context.identity.user',
'requestTime': '$context.requestTime',
'httpMethod': '$context.httpMethod',
'resourcePath': '$context.resourcePath',
'status': '$context.status',
'protocol': '$context.protocol',
'responseLength': '$context.responseLength'
})
}
)
# WAF关联
waf = boto3.client('wafv2')
web_acl = waf.create_web_acl(
Name='api-security-acl',
Scope='REGIONAL',
DefaultAction={'Allow': {}},
Rules=[
{
'Name': 'AWS-AWSManagedRulesSQLiRuleSet',
'Priority': 1,
'Statement': {
'ManagedRuleGroupStatement': {
'VendorName': 'AWS',
'Name': 'AWSManagedRulesSQLiRuleSet'
}
},
'OverrideAction': {'None': {}},
'VisibilityConfig': {
'SampledRequestsEnabled': True,
'CloudWatchMetricsEnabled': True,
'MetricName': 'SQLiRuleSet'
}
},
{
'Name': 'RateLimit',
'Priority': 2,
'Statement': {
'RateBasedStatement': {
'Limit': 2000,
'AggregateKeyType': 'IP'
}
},
'Action': {'Block': {}},
'VisibilityConfig': {
'SampledRequestsEnabled': True,
'CloudWatchMetricsEnabled': True,
'MetricName': 'RateLimitRule'
}
},
],
VisibilityConfig={
'SampledRequestsEnabled': True,
'CloudWatchMetricsEnabled': True,
'MetricName': 'ApiSecurityACL'
}
)
步骤3:使用OpenAPI Schema进行请求验证
# Kong OAS验证插件配置
plugins:
- name: oas-validation
config:
api_spec: |
openapi: "3.0.3"
info:
title: Secure API
version: "1.0"
paths:
/api/v1/users:
post:
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name, email]
properties:
name:
type: string
maxLength: 100
pattern: "^[a-zA-Z ]+$"
email:
type: string
format: email
maxLength: 255
additionalProperties: false # 阻止批量赋值
responses:
'201':
description: User created
validate_request_body: true
validate_request_header_params: true
validate_request_query_params: true
validate_request_uri_params: true
verbose_response: false # 错误信息中不暴露Schema详情
步骤4:双向TLS配置
# 为mTLS生成CA和客户端证书
# 1. 创建CA
openssl genrsa -out ca.key 4096
openssl req -new -x509 -key ca.key -out ca.crt -days 365 \
-subj "/CN=API Gateway CA/O=Example Corp"
# 2. 创建客户端证书
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr \
-subj "/CN=api-client/O=Example Corp"
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out client.crt -days 365
# Kong mTLS配置
# 将CA证书上传到Kong
curl -X POST http://kong-admin:8001/ca_certificates \
-F "cert=@ca.crt"
# 启用mTLS插件
curl -X POST http://kong-admin:8001/services/user-service/plugins \
--data "name=mtls-auth" \
--data "config.ca_certificates[]=$(cat ca_cert_id)" \
--data "config.revocation_check_mode=SKIP" \
--data "config.authenticated_group_by=CN"
步骤5:日志和监控配置
# 用于API安全事件的CloudWatch监控
import boto3
cloudwatch = boto3.client('cloudwatch')
logs = boto3.client('logs')
# 为安全事件创建指标过滤器
security_filters = [
{
'name': 'UnauthorizedAccess',
'pattern': '{ $.status = 401 || $.status = 403 }',
'metric': 'UnauthorizedAccessCount'
},
{
'name': 'RateLimitHits',
'pattern': '{ $.status = 429 }',
'metric': 'RateLimitHitCount'
},
{
'name': 'ServerErrors',
'pattern': '{ $.status >= 500 }',
'metric': 'ServerErrorCount'
},
{
'name': 'LargeResponses',
'pattern': '{ $.responseLength > 1000000 }',
'metric': 'LargeResponseCount'
},
]
for sf in security_filters:
logs.put_metric_filter(
logGroupName='api-access-logs',
filterName=sf['name'],
filterPattern=sf['pattern'],
metricTransformations=[{
'metricName': sf['metric'],
'metricNamespace': 'APISecurityMetrics',
'metricValue': '1',
'defaultValue': 0
}]
)
# 为异常401/403峰值创建告警
cloudwatch.put_metric_alarm(
AlarmName='API-UnauthorizedAccessSpike',
MetricName='UnauthorizedAccessCount',
Namespace='APISecurityMetrics',
Statistic='Sum',
Period=300, # 5分钟
EvaluationPeriods=1,
Threshold=100,
ComparisonOperator='GreaterThanThreshold',
AlarmActions=['arn:aws:sns:us-east-1:123456789:security-alerts'],
AlarmDescription='5分钟内超过100次未授权访问尝试'
)
核心概念
| 术语 | 定义 |
|---|---|
| API网关(API Gateway) | 所有API流量的集中入口点,在路由到后端服务前强制执行认证、授权、速率限制和请求验证 |
| 速率限制(Rate Limiting) | 控制客户端在时间窗口内的API请求数量,防止滥用并确保资源公平分配 |
| 请求验证(Request Validation) | 在转发到后端服务前,验证传入的API请求是否符合预期的Schema(数据类型、必填字段、值范围) |
| 双向TLS(Mutual TLS,mTLS) | 客户端和服务器双方均出示证书的双向TLS认证,为API间通信提供强身份验证 |
| WAF集成(WAF Integration) | 在API网关层应用Web应用防火墙规则,阻断常见攻击模式(SQL注入、XSS、路径遍历) |
| OAuth2/OIDC | 基于令牌的认证协议,网关在允许访问前针对身份提供商验证JWT令牌 |
工具和系统
- Kong Gateway:开源API网关,具有丰富的安全、速率限制和认证插件生态系统
- AWS API Gateway:托管API网关服务,内置节流、WAF集成和Lambda授权器
- Azure API Management:企业级API网关,具有基于策略的安全、开发者门户和Azure AD集成
- Apigee(Google Cloud):API管理平台,具有威胁防护、配额管理和API分析
- Envoy Proxy:高性能代理,在服务网格架构中用作API网关,具有广泛的过滤链
常见场景
场景:使用Kong Gateway保护微服务API
背景:公司正在将单体API迁移到微服务架构,每个微服务都有自己的REST API。安全团队需要在不修改每个服务的情况下实施集中式认证、速率限制和请求验证。
方法:
- 将Kong Gateway部署为单一入口点,将流量路由到8个后端微服务
- 配置JWT验证插件,验证公司Keycloak身份提供商的令牌
- 应用速率限制:普通用户每分钟60个请求,高级用户每分钟300个请求,通过JWT Claims识别
- 启用OAS验证插件,拒绝不符合OpenAPI规范的请求(阻断批量赋值和注入攻击)
- 为网关后的服务间通信配置mTLS
- 配置响应转换器删除Server和X-Powered-By头,并添加安全头
- 集成AWS WAF实现SQL注入和XSS防护规则
- 将访问日志配置到CloudWatch,并设置安全指标过滤器和告警
注意事项:
- 仅依赖网关进行授权,而后端服务也需要验证权限
- 未按认证用户配置速率限制(仅按IP允许攻击者通过IP轮换绕过)
- 使用详细错误响应,暴露内部服务架构信息
- 部署后未使用安全工具测试网关配置
- 网关和后端服务之间缺少双向TLS,允许直接访问后端
输出格式
## API网关安全配置报告
**网关**: Kong 3.5(Kubernetes部署)
**后端服务**: 8个微服务
**日期**: 2024-12-15
### 已实施安全控制
| 控制措施 | 插件/功能 | 配置 |
|---------|---------------|---------------|
| 认证 | JWT插件 | Cognito IdP,最大TTL 1小时 |
| 速率限制 | 速率限制插件 | 60 req/min(用户),Redis后端 |
| 请求验证 | OAS验证 | 严格模式,不允许额外属性 |
| TLS | Kong TLS | 仅TLS 1.3,启用HSTS |
| mTLS | mTLS认证插件 | 管理API需要客户端证书 |
| WAF | AWS WAF | SQL注入、XSS、基于速率的规则 |
| 响应头 | 响应转换器 | 删除Server头,添加安全头 |
| 日志 | HTTP日志插件 | CloudWatch,安全指标过滤器 |
### 验证结果
- JWT验证:过期/无效令牌正确拒绝(测试了50个载荷)
- 速率限制:在60 req/min强制执行,返回带Retry-After头的429
- 请求验证:格式错误的请求被拒绝并返回400(测试了30个无效载荷)
- mTLS:无客户端证书的请求被拒绝并返回401
- WAF:SQL注入载荷被阻断(测试了Top 100 SQL注入模式)