ALB Header 配置实战
验证:未记录
- 适用版本
- 未记录
- 验证范围
- 尚未登记验证记录。
ALB(Application Load Balancer,应用负载均衡器)能修改部分 HTTP(Hypertext Transfer Protocol,超文本传输协议)头。先读 Header 基础与排障,再按本页验收预发布环境。
1. 能改什么,在哪里改#
| 配置位置 | 能力 | 边界 |
|---|---|---|
| Listener attributes(监听器属性) | 添加/覆盖 HSTS、CSP、X-Content-Type-Options、X-Frame-Options 和六个 CORS 响应头 | 整个监听器生效,不能按路径/Host 分别配置这些属性;值最长 1K 字节 |
| Listener attributes | 关闭 ALB 的 Server: awselb/2.0 |
不等于清理应用的 Server 或 X-Powered-By |
| HTTPS listener attributes | 重命名 ALB 生成的 TLS/mTLS 请求头 | TLS 是 Transport Layer Security(传输层安全),mTLS 是 mutual TLS(双向 TLS);不是任意请求头编辑器 |
| Load balancer attributes(负载均衡器属性) | X-Forwarded-For 的 append/preserve/remove | ALB 范围生效;默认 append |
| Listener rule transforms(监听器规则变换) | Host、URL 重写 | 非默认规则支持;不改变之前已按条件做出的路由决定 |
| 应用/反向代理 | Cache-Control、Set-Cookie、自定义头、动态 CSP/CORS | ALB 的响应头功能不是任意字段修改器 |
六个 CORS 头是 Access-Control-Allow-Origin/Methods/Headers/Credentials、Access-Control-Expose-Headers、Access-Control-Max-Age。CORS 是 Cross-Origin Resource Sharing(跨源资源共享);HSTS 是 HTTP Strict Transport Security(HTTP 严格传输安全);CSP 是 Content Security Policy(内容安全策略)。
ALB 配置非空值时覆盖后端同名响应头,空值表示停止该项修改;只校验基本输入格式,不替你验证策略是否正确。依据:响应头能力、规则重写。
2. Hands-on 前置条件#
使用已有预发布 HTTPS 443 监听器和真实应用,可沿用 三层 VPC 实战。准备 AWS CLI(Command-Line Interface,命令行接口)v2、jq、curl,以及短期角色身份。需要读取监听器/规则/属性和修改指定监听器属性的权限;不要使用长期访问密钥。
上线前确认:
- 盘点该监听器所有站点、路径、登录流程和静态资源;修改影响整个监听器。
- 证书、域名、HTTPS 正常,HTTP 已重定向到 HTTPS;后端资源 Content-Type 正确。
- 本次是尚未启用 HSTS 的预发布试运行;若已有更严格策略,不能照抄降低它。
- 若由 Terraform 或 Kubernetes 控制器管理,正式变更应修改对应配置来源;CLI 验证需协调,防止被自动覆盖。
控制台路径:EC2 → Load Balancers → 选中 ALB → Listeners and rules → 选中监听器 → Attributes → Edit。以下使用同一功能的 官方 CLI 接口。
第一步:选择资源并备份#
以下在同一个 Bash 会话执行,替换两个占位值。输出可能包含内部域名,备份留在本地,不提交仓库。
set -euo pipefail
export AWS_PROFILE='staging-operator'
export AWS_REGION='ap-southeast-1'
export AWS_PAGER=''
export LISTENER_ARN='替换为预发布HTTPS监听器ARN'
export BASE='https://api.staging.example.com'
umask 077
WORK=$(mktemp -d)
aws sts get-caller-identity
aws elbv2 describe-listeners --listener-arns "$LISTENER_ARN" > "$WORK/listener.json"
jq -e '.Listeners | length == 1 and .[0].Protocol == "HTTPS" and .[0].Port == 443' "$WORK/listener.json"
aws elbv2 describe-rules --listener-arn "$LISTENER_ARN" > "$WORK/rules.json"
aws elbv2 describe-listener-attributes --listener-arn "$LISTENER_ARN" > "$WORK/before.json"
jq '.Attributes' "$WORK/before.json"
printf 'Backup directory: %s\n' "$WORK"ARN 是 Amazon Resource Name(AWS 资源名称)。人工核对账号、监听器、关联站点和现有属性,确认目标正确才继续。
第二步:生成最小变更和精确回退#
试运行 HSTS 300 秒,不加 includeSubDomains/preload;不直接给共用站点下发 CSP 或 CORS。
cat > "$WORK/change.json" <<'JSON'
[
{"Key":"routing.http.response.strict_transport_security.header_value","Value":"max-age=300"},
{"Key":"routing.http.response.x_content_type_options.header_value","Value":"nosniff"},
{"Key":"routing.http.response.server.enabled","Value":"false"}
]
JSON
# 原始快照必须包含全部待改键;缺项立即停止,不猜默认值。
jq --slurpfile change "$WORK/change.json" '
[.Attributes[] | select(.Key as $k | any($change[0][]; .Key == $k))]
| if length == ($change[0] | length) then . else error("missing rollback attributes") end
' "$WORK/before.json" > "$WORK/rollback.json"
jq . "$WORK/rollback.json"
aws elbv2 modify-listener-attributes --listener-arn "$LISTENER_ARN" --attributes "file://$WORK/change.json"第三步:配置与业务双重验收#
aws elbv2 describe-listener-attributes --listener-arn "$LISTENER_ARN" > "$WORK/after.json"
jq -e --slurpfile change "$WORK/change.json" '.Attributes as $a | all($change[0][]; . as $wanted | any($a[]; . == $wanted))' "$WORK/after.json"
export READ_PATH='/health/ready' # 替换为真实无副作用的 GET 路径
curl -sS --max-time 15 -D "$WORK/response.headers" -o /dev/null "$BASE$READ_PATH"
cat "$WORK/response.headers"预期 Strict-Transport-Security: max-age=300、X-Content-Type-Options: nosniff,无 ALB 的 Server: awselb/2.0。若仍有 nginx 等 Server 值,处理其来源,不要认定该开关失效。
验收范围至少包括:每个 Host 的正常 GET、登录/重定向、静态脚本与样式、可安全触发的 401/403/404,以及浏览器 Console。记录状态码、响应头和变更前后的错误率;外层有 CDN 时,还要区分缓存响应与 ALB 实时响应。配置读取正确不代表所有业务正常。
第四步:回退并确认#
有问题时恢复本次涉及的三个属性,避免覆盖其他人的无关变更;执行前确认这三个键未被其他发布同时修改。
aws elbv2 modify-listener-attributes --listener-arn "$LISTENER_ARN" --attributes "file://$WORK/rollback.json"
aws elbv2 describe-listener-attributes --listener-arn "$LISTENER_ARN" > "$WORK/restored.json"
jq -e --slurpfile old "$WORK/rollback.json" '.Attributes as $a | all($old[0][]; . as $wanted | any($a[]; . == $wanted))' "$WORK/restored.json"
curl -sS --max-time 15 -D - -o /dev/null "$BASE$READ_PATH"恢复空 HSTS 值只是不再覆盖后端头,不会清除浏览器已缓存的 HSTS。本次短期试运行可等待最后一次收到策略后 300 秒;需要主动撤销时,经评估通过有效 HTTPS 下发 max-age=0,但父域策略或预加载仍可能生效。保留备份至验收结束。
3. CORS 和 CSP 如何落地#
单一前端源、所有路由策略相同时,可以在专用监听器静态配置 CORS。属性采用 routing.http.response.<名称>.header_value:
| 名称 | 示例值 |
|---|---|
access_control_allow_origin |
https://portal.staging.example.com |
access_control_allow_methods |
GET,POST,OPTIONS,仅列真实允许的方法 |
access_control_allow_headers |
authorization,content-type,按接口收敛 |
access_control_allow_credentials |
仅在确实需要 Cookie 等凭证时设置 true |
access_control_expose_headers |
x-request-id,仅在前端需要读取时设置 |
access_control_max_age |
试运行 300,避免错误预检结果长期缓存 |
实施时按上面的 change.json 格式另建一次变更,重新备份并重新生成回退文件。包含逗号的值使用 JSON 文件,避免 CLI 简写解析歧义。应用必须能正确响应 OPTIONS;仅添加响应头不会自动生成预检成功响应。若有监听器认证规则,也要核对预检是否被重定向至登录页。
多源白名单、不同业务策略交给应用,ALB 对应属性留空,避免覆盖应用决定。按 通用篇的跨域验收步骤 测试允许源、拒绝源、实际请求和浏览器凭证场景。CSP 先在应用以 Report-Only 观察,动态 nonce 和报告头由应用管理,再决定是否适合统一到监听器。
4. X-Forwarded-For 不要盲目信任#
假设客户端直连 ALB,自带 X-Forwarded-For: 198.51.100.77,ALB 看到的连接来源为 203.0.113.10:
| 模式 | 后端收到的值 | 判断 |
|---|---|---|
| append(默认) | 198.51.100.77, 203.0.113.10 |
第一个值可以是伪造的 |
| preserve | 198.51.100.77 |
不追加连接来源,不能据此获得可信真实客户端地址 |
| remove | 无此字段 | 依赖此头的审计/限流会受影响 |
读取当前配置:
LB_ARN=$(jq -r '.Listeners[0].LoadBalancerArn' "$WORK/listener.json")
aws elbv2 describe-load-balancer-attributes --load-balancer-arn "$LB_ARN" --query 'Attributes[?Key==`routing.http.xff_header_processing.mode`]'这是负载均衡器属性,不是监听器属性。本例不修改它。后端安全组仅允许受控 ALB 入口,框架明确配置可信代理;存在 CDN/其他代理时按真实拓扑解析,不固定取某个位置。参见 AWS 转发头说明。
本文已核对官方属性与本地命令语法;实际云端响应、业务兼容性及浏览器行为需按上述步骤在目标环境验收。