使用自定义请求和响应标头,您可以指定负载均衡器可以添加到 HTTP(S) 请求和响应中的额外标头。根据负载均衡器检测到的信息,这些标头可以包含以下信息:
- 客户端的延迟时间
- 客户端 IP 地址的地理位置
- TLS 连接的参数
后端服务支持自定义请求标头,而后端服务和后端存储桶支持自定义响应标头。
默认情况下,负载均衡器会将某些标头添加到其作为代理在后端与客户端之间处理的所有 HTTP(S) 请求和响应。如需了解详情,请参阅目标代理。
准备工作
如有必要,请更新到 Google Cloud CLI 的最新版本:
gcloud components update
自定义标头的工作原理
自定义标头的工作原理如下:
当负载均衡器向后端转发请求时,负载均衡器会添加请求标头。
负载均衡器仅会向客户端请求添加自定义请求标头,而不会向健康检查探测添加自定义请求标头。如果后端需要将特定标头用于授权,而健康检查数据包中缺少该标头,则健康检查可能会失败。
负载均衡器会在将响应返回给客户端之前设置响应标头。
要启用自定义标头,您可以在后端服务或后端存储桶的属性中指定标头列表。
您可以将每个标头指定为 header-name:header-value
字符串。标头必须包含用于分隔标头名称和标头值的英文冒号。
标头名称必须符合以下要求:
- 标头名称必须是有效的 HTTP 标头字段名称定义(根据 RFC 7230)。
- 标头名称不得为
X-User-IP
或CDN-Loop
。 - 不得使用以下跃点标头:
Keep-Alive
、Transfer-Encoding
、TE
、Connection
、Trailer
、Upgrade
、Proxy-Authorization
和Proxy-Authenticate
。根据 RFC 2616,这些标头不会由缓存存储,也不会由目标代理传播。 - 标头名称不得以
X-Google
、X-Goog-
、X-GFE
或X-Amz-
开头。 - 标头名称不能在已添加标头的列表中出现多次。
标头值必须符合以下要求:
- 标头值必须是有效的 HTTP 标头字段定义(根据 RFC 7230,不允许使用已过时的格式)。
- 标头值可以为空。
- 标头值可以包含一个或多个由花括号括起来的变量,这些变量可扩展为负载均衡器提供的值。标头值中允许使用的变量列表将在下一部分中介绍。
gcloud
命令行工具有一个用于指定请求标头的标志,即 --custom-request-header
。使用此标志时,请务必将标头名称和标头值用直引号 ('
) 括起来。
该标志的常规格式如下:
--custom-request-header='HEADER_NAME:[HEADER_VALUE]'
以下示例展示了包含两个变量(client_region
和 client_city
,用大括号括起)的标头值。
--custom-request-header='X-Client-Geo-Location:{client_region},{client_city}'
如果客户端位于加利福尼亚州山景城,则负载均衡器会添加如下所示的标头:
X-Client-Geo-Location:US,Mountain View
标头值支持的变量
以下变量可以出现在自定义标头值中。
变量 | 说明 |
---|---|
cdn_cache_id | 用于传送请求的缓存实例的位置代码和 ID。此值与 Logging 中 Cloud CDN 请求日志的 jsonPayload.cacheId 字段中填充的值相同。 |
cdn_cache_status | 当前缓存状态。对于启用 Cloud CDN 的后端传送的任何对象,值可以是 hit 、miss 、revalidated 、stale 、uncacheable 或 disabled 。 |
origin_request_header | 反映的是请求中跨域资源共享 (CORS) 用例的 Origin 标头的值。 |
client_rtt_msec | 负载均衡器与 HTTP(S) 客户端之间的预计往返传输时间,以毫秒为单位。这是负载均衡器的 TCP 堆栈根据 RFC 2988 测量的平滑往返时间 (SRTT) 参数。 平滑 RTT 是一种算法,用于处理 RTT 测量中可能发生的变体和异常。 |
client_region | 与客户端 IP 地址相关联的国家/地区(或区域)。这是一个 Unicode CLDR 区域代码,例如 US 或 FR 。(对于大多数国家/地区,这些代码直接对应于 ISO-3166-2 代码。) |
client_region_subdivision | 与客户端 IP 地址相关联的国家/地区的下属行政单位,例如省或州。这是一个 Unicode CLDR 下属行政单位 ID,例如 USCA 或 CAON 。(这些 Unicode 代码从 ISO-3166-2 标准定义的下属行政单位派生而来。) |
client_city | 发起请求的城市名称,例如表示加利福尼亚州山景城的 Mountain View 。此变量没有标准的有效值列表。城市名称可以包含 US-ASCII 字母、数字、空格和以下字符:!#$%&'*+-.^_`|~ 。 |
client_city_lat_long | 发出请求的城市的纬度和经度,例如 37.386051,-122.083851 (表示请求来自山景城)。 |
client_ip_address | 客户端的 IP 地址。除非客户端使用代理,或者 X-Forwarded-For 标头已被篡改,否则这通常与 X-Forwarded-For 标头中属于倒数第二个地址的客户端 IP 地址相同。 |
client_port | 客户端的来源端口。 |
client_encrypted | 如果客户端和负载均衡器之间的连接已加密(使用 HTTPS、HTTP/2 或 HTTP/3),则为 true ;否则为 false 。
|
client_protocol | 用于客户端和负载均衡器之间通信的 HTTP 协议。HTTP/1.0 、HTTP/1.1 、HTTP/2 或 HTTP/3 之一。 |
server_ip_address | 客户端所连接的负载均衡器的 IP 地址。这在多个负载均衡器共享公共后端时非常有用。这与 X-Forwarded-For 标头中的最后一个 IP 地址相同。 |
server_port | 客户端所连接的目标端口号。 |
tls_sni_hostname | 由客户端在 TLS 或 QUIC 握手期间提供的服务器名称指示(如 RFC 6066 中所定义)。系统会将主机名转换为小写字母并移除结尾的任何英文句点。 |
tls_version | 客户端与负载均衡器在 SSL 握手期间协商的 TLS 版本。可能的值包括 TLSv1 、TLSv1.1 、TLSv1.2 、TLSv1.3 。如果客户端使用 QUIC(而不是 TLS)进行连接,则值将为 QUIC 。 |
tls_cipher_suite | 在 TLS 握手期间协商的加密套件。该值是由 IANA TLS 加密套件注册系统定义的四位十六进制数字,例如表示 TLS_RSA_WITH_AES_128_GCM_SHA256 的 009C 。对于 QUIC 和未加密的客户端连接,此值为空。 |
tls_ja3_fingerprint | JA3 TLS/SSL 指纹(如果客户端使用 HTTPS、HTTP/2 或 HTTP/3 进行连接)。 |
负载均衡器在无法确定变量值时会将变量扩展为空字符串。例如:
- IP 地址的位置未知时的地理位置变量
- 未使用 TLS 时的 TLS 参数
- 请求不包含
Origin
标头时的{origin_request_header}
- 请求标头中包含时的
{cdn_cache_status}
标头
地理位置值(区域、下属行政单位和城市)是根据客户端 IP 地址估算的值。Google 会不时地更新提供这些值的数据,以便提高准确性并反映地理和政治方面的变化。即使原始 X-Forwarded-For
标头包含有效的位置信息,Google 也会使用负载均衡器收到的数据包中包含的来源 IP 地址信息来估算客户端位置。
负载均衡器添加的标头会覆盖任何同名的现有标头。标头名称不区分大小写。当标头名称传递至 HTTP/2 后端时,HTTP/2 协议会将标头名称编码为小写。
在标头值中,前导空格和尾随空格无意义,因此不会传递至后端。为了允许在标头值中使用花括号,负载均衡器会将两个左花括号 ({{
) 解释为一个左花括号 ({
),而将两个右花括号 (}}
) 解释为一个右花括号 (}
)。
双向 TLS 自定义标头
如果在负载均衡器的 TargetHttpsProxy 上配置了双向 TLS (mTLS),则可以使用以下额外的标头变量。
变量 | 说明 |
---|---|
client_cert_present | 如果客户端在 TLS 握手期间提供了证书,则为 true ;否则为 false 。
|
client_cert_chain_verified | 如果根据配置的 TrustStore 验证了客户端证书链,则为 true ;否则为 false 。
|
client_cert_error | 代表错误情况的预定义字符串。如需详细了解错误字符串,请参阅 mTLS 客户端验证模式。 |
client_cert_sha256_fingerprint | 客户端证书的 Base64 编码 SHA-256 指纹。 |
client_cert_serial_number | 客户端证书的序列号。如果序列号超过 50 字节,则 client_cert_error 设置为 client_cert_serial_number_exceeded_size_limit ,序列号设置为空字符串。 |
client_cert_spiffe_id | 主题备用名称 (SAN) 字段中的 SPIFFE ID。如果值无效或超过 2048 字节,则 SPIFFE ID 设置为空字符串。 如果 SPIFFE ID 长度超过 2048 字节,则 |
client_cert_uri_sans | URI 类型 SAN 扩展的 Base64 编码列表(以逗号分隔)。
SAN 扩展从客户端证书中提取。
如果 |
client_cert_dnsname_sans | DNSName 类型 SAN 扩展的 Base64 编码列表(以逗号分隔)。SAN 扩展从客户端证书中提取。 如果 |
client_cert_valid_not_before | 在此时间戳(RFC 3339 日期字符串格式)之前,客户端证书无效。
例如 2022-07-01T18:05:09+00:00 。
|
client_cert_valid_not_after | 在此时间戳(RFC 3339 日期字符串格式)之后,客户端证书无效。
例如 2022-07-01T18:05:09+00:00 。
|
client_cert_issuer_dn | 证书中完整“颁发者”字段的 base64 编码的 DER 编码。 如果 |
client_cert_subject_dn | 证书中完整“主题”字段的 base64 编码的 DER 编码。 如果 |
client_cert_leaf | 已建立的 mTLS 连接(证书在其中通过了验证)的客户端叶证书。证书编码符合 RFC 9440 标准。这表示二进制 DER 证书使用 Base64 编码,且任一侧用英文冒号分隔。 如果 |
client_cert_chain | 已建立的 mTLS 连接(客户端证书在其中通过了验证)的客户端证书链的英文逗号分隔证书列表(按标准 TLS 顺序排列),不包括叶证书。证书编码符合 RFC 9440 标准。 如果 |
配置自定义请求标头
控制台
要向现有后端服务添加自定义请求标头,请执行以下操作:
- 转到负载均衡摘要页面。
转到“负载均衡”页面 - 点击后端。
- 点击后端服务的名称。
- 点击修改 。
- 点击 Advanced configurations (Session affinity, connection draining timeout, security policies)(高级配置 [会话亲和性、连接排空超时时间、安全政策])。
- 在自定义请求标头下,点击添加标头 (Add header)。
- 输入自定义请求标头的标头名称和标头值。
- 输入其他任何自定义请求标头。
- 点击保存。
要从后端服务中移除自定义请求标头,请执行以下操作:
- 转到负载均衡摘要页面。
转到“负载均衡”页面 - 点击后端。
- 点击后端服务的名称。
- 点击修改 。
- 点击 Advanced configurations (Session affinity, connection draining timeout, security policies)(高级配置 [会话亲和性、连接排空超时时间、安全政策])。
- 点击您要移除的自定义请求标头名称旁边的 X。
- 点击保存。
gcloud
如需指定自定义请求标头,请使用带有 --custom-request-header
标志的 gcloud compute backend-services
create
或 gcloud compute backend-services
update
命令。
要使用自定义请求标头创建后端服务,请运行以下命令:
gcloud compute backend-services create BACKEND_SERVICE_NAME \ --global-health-checks \ --global \ --protocol HTTPS \ --health-checks https-basic-check \ --custom-request-header='HEADER_NAME:[HEADER_VALUE]'
要添加更多请求标头,请通过重复使用 --custom-request-header
标志来指定唯一的标头名称和值。
要向现有后端服务添加自定义标头,请运行以下命令:
gcloud compute backend-services update BACKEND_SERVICE_NAME \ --global \ --custom-request-header='HEADER_1_NAME:[HEADER_1_VALUE]' \ --custom-request-header='HEADER_2_NAME:[HEADER_2_VALUE]'
上一步会将后端服务中已经存在的任何标头替换为您在该命令中指定的请求标头。
要从后端服务移除所有标头,请运行以下命令:
gcloud compute backend-services update BACKEND_SERVICE_NAME \ --global \ --no-custom-request-headers
API
向 backendServices.patch
方法发出 PATCH
请求。
PATCH https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices/BACKEND_SERVICE_NAME "customRequestHeaders": [ "client_city:Mountain View" ]
Terraform
如需了解使用自定义标头创建负载均衡器的 Terraform 脚本,请参阅全球外部应用负载均衡器的 Terraform 示例。
配置自定义响应标头
控制台
要向现有后端服务添加自定义响应标头,请执行以下操作:
- 转到负载均衡摘要页面。
转到“负载均衡”页面 - 点击后端。
- 点击后端服务的名称。
- 点击修改 。
- 点击 Advanced configurations (Session affinity, connection draining timeout, security policies)(高级配置 [会话亲和性、连接排空超时时间、安全政策])。
- 在自定义响应标头下,点击添加标头。
- 输入自定义响应标头的标头名称和标头值。
- 输入其他任何自定义响应标头。
- 点击保存。
要从后端服务中移除自定义响应标头,请执行以下操作:
- 转到负载均衡摘要页面。
转到“负载均衡”页面 - 点击后端。
- 点击后端服务的名称。
- 点击修改 。
- 点击 Advanced configurations (Session affinity, connection draining timeout, security policies)(高级配置 [会话亲和性、连接排空超时时间、安全政策])。
- 点击您要移除的自定义响应标头名称旁边的 X。
- 点击保存。
gcloud
对于后端服务,请使用带有 --custom-response-header
标志的 gcloud compute backend-services
create
或 gcloud compute backend-services
update
命令。
对于后端存储桶,请使用带有 --custom-response-header
标志的 gcloud compute backend-buckets
create
或 gcloud compute backend-buckets
update
命令。
gcloud compute backend-services (create | update) BACKEND_SERVICE_NAME --custom-response-header='HEADER_NAME:[HEADER_VALUE]'
gcloud compute backend-buckets (create | update) BACKEND_BUCKET_NAME --custom-response-header='HEADER_NAME:[HEADER_VALUE]'
使用 X-Frame-Options
标头的示例:
gcloud compute backend-buckets update gaming-lab \ --custom-response-header='X-Frame-Options: DENY'
使用 Strict-Transport-Security
标头的示例:
以下示例展示了如何添加自定义响应标头以支持 HTTP 严格传输安全协议 (HSTS):
gcloud compute backend-services update customer-bs-name \ --global \ --custom-response-header='Strict-Transport-Security: max-age=63072000'
API
对于后端存储桶,请使用 Method: backendBuckets.insert
或 Method: backendBuckets.update
API 调用。
对于后端服务,请使用 Method: backendServices.insert
或 Method: backendServices.update
API 调用。
使用以下 API 调用之一:
POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendBuckets PUT https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendBuckets/BACKEND_BUCKET_NAME POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices PUT https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices/BACKEND_SERVICE_NAME
将以下代码段添加到 JSON 请求正文:
"customResponseHeaders":HEADER_NAME:[HEADER_VALUE]
Terraform
如需了解使用自定义标头创建负载均衡器的 Terraform 脚本,请参阅全球外部应用负载均衡器的 Terraform 示例。
设置 Cloud Storage 的响应标头
如果您需要对 Cloud Storage 的响应设置 HTTP 标头(例如跨域资源政策、X-Frame-Options
或 X-XSS-Protection
标头),Google Cloud 提供了将 Cloud CDN 自定义标头与 Cloud Storage 搭配使用的选项。为此,您可以在负载均衡器后端存储桶级层配置自定义标头,如本页面所述。
只有在客户端请求发送到负载均衡器 IP 地址时,在后端存储桶级层配置的自定义响应标头才会添加到响应中。如果客户端的请求直接发送到 Cloud Storage API,则自定义标头不会添加到响应中。
将自定义标头与 Google Cloud Armor 搭配使用
配置 Google Cloud Armor 安全政策时,您可以配置 Google Cloud Armor 以插入自定义标头和值。如果 Google Cloud Armor 安全政策配置为插入与全球外部应用负载均衡器或经典版应用负载均衡器的自定义标头相同的自定义标头名称,则 Google Cloud Armor 安全政策中指定的标头值会被负载均衡器填充的值覆盖。如果您不希望覆盖 Google Cloud Armor 政策,请确保不要使用相同的名称。
限制
以下限制适用于在全球负载均衡器中使用自定义标头的情况:
- 每个后端服务的所有自定义请求标头(名称和值组合,且在变量扩展之前)的总大小不得超过 8 KB 或 16 个请求标头。
- 每个后端服务的所有自定义响应标头(名称和值组合,且在变量扩展之前)的总大小不得超过 8 KB 或 16 个响应标头。
后续步骤
- 如需查看示例使用场景,请参阅配置具有外部后端的负载均衡器。