백엔드 서비스에 커스텀 헤더 만들기

이 페이지에서는 기본 애플리케이션 부하 분산기에서 사용하는 백엔드 서비스의 커스텀 헤더를 구성하는 방법을 설명합니다.

커스텀 요청과 응답 헤더를 사용하면 부하 분산기가 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에 따라, 사용되지 않는 양식은 허용되지 않음).
  • 헤더 값은 비워 둘 수 있습니다.
  • 헤더 값에는 부하 분산기가 제공하는 값으로 확장되는 중괄호로 묶인 하나 이상의 변수가 포함될 수 있습니다. 헤더 값에 허용되는 변수 목록은 다음 섹션에 있습니다.

예를 들어 클라이언트 리전과 클라이언트 도시에 대한 변수 이름 2개가 있는 헤더를 지정할 수 있습니다. gcloud 명령줄 도구에는 요청 헤더를 지정하는 플래그인 --custom-request-header가 있습니다. 이 플래그에는 곧은 따옴표(')만 사용해야 합니다.

플래그의 일반적인 형식은 다음과 같습니다.

    --custom-request-header='HEADER_NAME:[HEADER_VALUE]'

변수는 중괄호로 묶어야 합니다. 예를 들면 다음과 같습니다.

    --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) 클라이언트 간의 예상 왕복 전송 시간(밀리초)입니다. 이는 RFC 2988에 따라 부하 분산기의 TCP 스택으로 측정된 평활 왕복 시간(Smoothed Round Trip Time, SRTT) 매개변수입니다. 평활 RTT는 RTT 측정에서 발생할 수 있는 변이와 이상을 처리하는 알고리즘입니다.
client_region 클라이언트의 IP 주소와 연관된 국가(또는 리전)입니다. US 또는 FR과 같은 유니코드 CLDR 리전 코드입니다. 대부분의 국가에서 이 코드는 ISO-3166-2 코드와 바로 대응합니다.
client_region_subdivision 클라이언트의 IP 주소와 관련된 국가의 구획입니다(예: 주 또는 시/도). 유니코드 CLDR 하위 영역 ID입니다(예: USCA 또는 CAON). 이러한 유니코드 코드는 ISO-3166-2 표준에 정의된 하위 영역에서 파생된 것입니다.
client_city 요청이 시작된 도시의 이름입니다(예: 캘리포니아주 마운틴뷰의 경우 Mountain View). 이 변수에 유효한 값의 표준 목록은 없습니다. 도시 이름에는 US-ASCII 문자, 숫자, 공백, !#$%&'*+-.^_`|~ 문자가 포함될 수 있습니다.
client_city_lat_long 요청이 시작된 도시의 위도와 경도입니다(예: 마운틴뷰에서 요청한 경우 37.386051,-122.083851).
client_ip_address 클라이언트의 IP 주소입니다. 이는 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이 포함됩니다. 클라이언트가 TLS 대신 QUIC를 사용하여 연결하면 값은 QUIC입니다.
tls_cipher_suite TLS 핸드셰이크 중에 협상된 암호 모음입니다. 값은 IANA TLS Cipher Suite 레지스트리에서 정의한 네 자리 16진수입니다(예: TLS_RSA_WITH_AES_128_GCM_SHA256의 경우 009C). QUIC 및 암호화되지 않은 클라이언트 연결의 경우 이 값은 비어 있습니다.
tls_ja3_fingerprint 클라이언트가 HTTPS, HTTP/2 또는 HTTP/3을 사용하여 연결하는 경우 JA3 TLS/SSL 디지털 지문입니다.

부하 분산기는 값을 확인할 수 없는 경우 변수를 빈 문자열로 확장합니다. 예를 들면 다음과 같습니다.

  • IP 주소의 위치를 알 수 없는 경우의 지리적 위치 변수
  • TLS를 사용하지 않는 경우의 TLS 매개변수
  • 요청에 Origin 헤더가 포함되지 않은 경우의 {origin_request_header}
  • 요청 헤더에 포함되었을 때의 {cdn_cache_status} 헤더

지리적 값(리전, 구획, 도시)은 클라이언트의 IP 주소를 기반으로 한 추정치입니다. 때때로 Google은 정확도를 개선하고 지리적, 정치적 변화를 반영하기 위해 이러한 값을 제공하는 데이터를 업데이트합니다.

부하 분산기가 추가한 헤더는 이름이 동일한 기존 헤더를 덮어씁니다. 헤더 이름은 대소문자를 구분하지 않습니다. 헤더 이름이 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_errorclient_cert_serial_number_exceeded_size_limit로 설정되고 일련번호가 빈 문자열로 설정됩니다.
client_cert_spiffe_id

제목 대체 이름(SAN) 필드의 SPIFFE ID입니다. 값이 유효하지 않거나 2,048바이트를 초과할 경우 SPIFFE ID가 빈 문자열로 설정됩니다.

SPIFFE ID가 2,048바이트보다 길면 client_cert_errorclient_cert_spiffe_id_exceeded_size_limit로 설정됩니다.

client_cert_uri_sans

쉼표로 구분된 Base64로 인코딩된 URI 유형의 SAN 확장 프로그램 목록입니다. SAN 확장 프로그램은 클라이언트 인증서에서 추출됩니다. SPIFFE ID는 client_cert_uri_sans 필드에 포함되지 않습니다.

client_cert_uri_sans가 512바이트보다 길면 client_cert_errorclient_cert_uri_sans_exceeded_size_limit로 설정되고 쉼표로 구분된 목록이 빈 문자열로 설정됩니다.

client_cert_dnsname_sans

쉼표로 구분된 Base64로 인코딩된 DNSName 유형의 SAN 확장 프로그램 목록입니다. SAN 확장 프로그램은 클라이언트 인증서에서 추출됩니다.

client_cert_dnsname_sans가 512바이트보다 길면 client_cert_errorclient_cert_dnsname_sans_exceeded_size_limit로 설정되고 쉼표로 구분된 목록이 빈 문자열로 설정됩니다.

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_issuer_dn이 512바이트보다 길면 client_cert_issuer_dn_exceeded_size_limit 문자열이 client_cert_error에 추가되고 client_cert_issuer_dn이 빈 문자열로 설정됩니다.

client_cert_subject_dn

인증서의 전체 제목 필드에서 Base64로 인코딩된 DER 인코딩입니다.

client_cert_subject_dn이 512바이트보다 길면 client_cert_subject_dn_exceeded_size_limit 문자열이 client_cert_error에 추가되고 client_cert_subject_dn이 빈 문자열로 설정됩니다.

client_cert_leaf

인증서가 유효성 검사를 통과한 설정된 mTLS 연결의 클라이언트 리프 인증서입니다. 인증서 인코딩은 RFC 9440을 준수합니다. 즉, 바이너리 DER 인증서가 Base64를 사용하여 인코딩되고 양쪽에서 콜론으로 구분됩니다.

client_cert_leaf가 인코딩되지 않은 상태에서 16KB를 초과하면 문자열 client_cert_validated_leaf_exceeded_size_limitclient_cert_error에 추가되고 client_cert_leaf가 빈 문자열로 설정됩니다.

client_cert_chain

리프 인증서를 포함하지 않은 클라이언트 인증서가 검증을 통과한 설정된 mTLS 연결의 클라이언트 인증서 체인에 대한 표준 TLS 순서의 쉼표로 구분된 인증서 목록입니다. 인증서 인코딩은 RFC 9440을 준수합니다.

Base64 인코딩 전의 client_cert_leafclient_cert_chain을 합친 크기가 16KB를 초과하면 문자열 client_cert_validated_chain_exceeded_size_limitclient_cert_error에 추가되고 client_cert_chain이 빈 문자열로 설정됩니다.

커스텀 요청 헤더 구성

콘솔

기존 백엔드 서비스에 커스텀 요청 헤더를 추가하려면 다음 안내를 따르세요.

  1. 부하 분산 요약 페이지로 이동합니다.
    부하 분산 페이지로 이동
  2. 백엔드를 클릭합니다.
  3. 백엔드 서비스의 이름을 클릭합니다.
  4. 수정 을 클릭합니다.
  5. 고급 구성(세션 어피니티, 연결 드레이닝 제한 시간, 보안 정책)을 클릭합니다.
  6. 커스텀 요청 헤더에서 헤더 추가를 클릭합니다.
  7. 커스텀 요청 헤더의 헤더 이름헤더 값을 입력합니다.
  8. 추가 커스텀 요청 헤더를 입력합니다.
  9. 저장을 클릭합니다.

백엔드 서비스에서 커스텀 요청 헤더를 삭제하려면 다음 안내를 따르세요.

  1. 부하 분산 요약 페이지로 이동합니다.
    부하 분산 페이지로 이동
  2. 백엔드를 클릭합니다.
  3. 백엔드 서비스의 이름을 클릭합니다.
  4. 수정 을 클릭합니다.
  5. 고급 구성(세션 어피니티, 연결 드레이닝 제한 시간, 보안 정책)을 클릭합니다.
  6. 삭제하려는 커스텀 요청 헤더의 이름 옆에 있는 X를 클릭합니다.
  7. 저장을 클릭합니다.

gcloud

커스텀 요청 헤더를 지정하려면 gcloud compute backend-services create 또는 gcloud compute backend-services update 명령어를 --custom-request-header 플래그와 함께 사용합니다.

커스텀 요청 헤더를 사용하여 백엔드 서비스를 만들려면 다음 안내를 따르세요.

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 예시를 참조하세요.

커스텀 응답 헤더 구성

콘솔

기존 백엔드 서비스에 커스텀 응답 헤더를 추가하려면 다음 안내를 따르세요.

  1. 부하 분산 요약 페이지로 이동합니다.
    부하 분산 페이지로 이동
  2. 백엔드를 클릭합니다.
  3. 백엔드 서비스의 이름을 클릭합니다.
  4. 수정 을 클릭합니다.
  5. 고급 구성(세션 어피니티, 연결 드레이닝 제한 시간, 보안 정책)을 클릭합니다.
  6. 커스텀 응답 헤더에서 헤더 추가를 클릭합니다.
  7. 커스텀 응답 헤더의 헤더 이름헤더 값을 입력합니다.
  8. 추가 커스텀 응답 헤더를 입력합니다.
  9. 저장을 클릭합니다.

백엔드 서비스에서 커스텀 응답 헤더를 삭제하려면 다음 안내를 따르세요.

  1. 부하 분산 요약 페이지로 이동합니다.
    부하 분산 페이지로 이동
  2. 백엔드를 클릭합니다.
  3. 백엔드 서비스의 이름을 클릭합니다.
  4. 수정 을 클릭합니다.
  5. 고급 구성(세션 어피니티, 연결 드레이닝 제한 시간, 보안 정책)을 클릭합니다.
  6. 삭제할 커스텀 응답 헤더 이름 옆의 X를 클릭합니다.
  7. 저장을 클릭합니다.

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 Strict Transport Security(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 Storage를 통해 Cloud CDN용 커스텀 헤더를 사용할 수 있는 옵션을 제공합니다. 이 페이지에 설명된 대로 부하 분산기 백엔드 버킷 수준에서 커스텀 헤더를 구성하면 됩니다.

백엔드 버킷 수준에서 구성된 커스텀 응답 헤더는 클라이언트 요청이 부하 분산기 IP 주소로 전송되는 경우에만 응답에 추가됩니다. 클라이언트 요청이 Cloud Storage API로 직접 전송된 경우에는 커스텀 헤더가 응답에 추가되지 않습니다.

Google Cloud Armor에 커스텀 헤더 사용

Google Cloud Armor 보안 정책을 구성할 때 Google Cloud Armor에서 커스텀 헤더와 값을 삽입하도록 구성할 수 있습니다. Google Cloud Armor 보안 정책이 전역 외부 애플리케이션 부하 분산기 또는 기본 애플리케이션 부하 분산기의 커스텀 헤더와 동일한 커스텀 헤더 이름을 삽입하도록 구성된 경우 Google Cloud Armor 보안 정책에 지정된 헤더 값이 부하 분산기에서 채운 값을 덮어씁니다. Google Cloud Armor 정책을 덮어쓰지 않으려면 같은 이름을 사용하지 마세요.

제한사항

다음 제한사항은 전역 부하 분산기에 사용되는 커스텀 헤더에 적용됩니다.

  • 백엔드 서비스마다 커스텀 요청 헤더를 최대 16개까지 지정할 수 있습니다.
  • 백엔드 서비스마다 커스텀 응답 헤더를 최대 16개까지 지정할 수 있습니다.
  • 백엔드 서비스당 모든 커스텀 요청 헤더의 총 크기(이름과 값의 결합, 변수 확장 전)는 8KB를 초과할 수 없습니다.
  • 백엔드 서비스당 모든 커스텀 응답 헤더의 총 크기(이름과 값의 결합, 변수 확장 전)는 8KB를 초과할 수 없습니다.

다음 단계