I Tried Receiving Amazon CloudFront's CloudFront-Viewer-ISP and CloudFront-Viewer-TLS-Details Headers at the Origin

I Tried Receiving Amazon CloudFront's CloudFront-Viewer-ISP and CloudFront-Viewer-TLS-Details Headers at the Origin

Checked the CloudFront-Viewer-ISP and CloudFront-Viewer-TLS-Details headers from Amazon CloudFront at the origin. ISP names arrived as strings containing spaces, and the keyExchange value showed whether PQC was used.
2026.11.01

This page has been translated by machine translation. View original

Introduction

In October 2026, Amazon CloudFront became able to forward two headers, CloudFront-Viewer-ISP and CloudFront-Viewer-TLS-Details, to the origin. From these headers, you can check the viewer's ISP name and TLS connection information such as the key exchange method, including PQC.

https://aws.amazon.com/jp/about-aws/whats-new/2026/10/cloudfront-viewer-isp-post-quantum-visbility/

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/adding-cloudfront-headers.html

In this article, I attach an origin request policy with these two headers added to a distribution, and check the values that reached the origin in the access log.

Verification Method

Origin Request Policy

Save the following content as origin-request-policy.json. The two headers are specified in HeadersConfig. To keep the query parameter case in the origin's log, I set QueryStringBehavior to all.

{
  "Name": "cfv-1031-viewer-isp-tls-details",
  "Comment": "Add CloudFront-Viewer-ISP and CloudFront-Viewer-TLS-Details to origin requests",
  "HeadersConfig": {
    "HeaderBehavior": "whitelist",
    "Headers": {
      "Quantity": 2,
      "Items": [
        "CloudFront-Viewer-ISP",
        "CloudFront-Viewer-TLS-Details"
      ]
    }
  },
  "CookiesConfig": {
    "CookieBehavior": "none"
  },
  "QueryStringsConfig": {
    "QueryStringBehavior": "all"
  }
}
aws cloudfront create-origin-request-policy \
  --origin-request-policy-config file://origin-request-policy.json

If you specify the ID of the created policy in OriginRequestPolicyId in the distribution's cache behavior, the two headers will reach the origin.

Verification Environment

Item Value
Origin EC2 running Amazon Linux 2023, nginx 1.30.6. The two headers are recorded in the access log
Connection to origin Specify the public DNS name of an Elastic IP, using HTTP 80
Distribution Default domain (*.cloudfront.net) and default certificate. Viewer protocol is HTTPS only
Cache policy Managed-CachingDisabled. Every request is forwarded to the origin
Client Docker's alpine/openssl:latest (OpenSSL 3.5.9) with the key exchange group specified. The host's curl 8.18.0 (OpenSSL 3.5.9) connects without specifying a group
Connection source One line in my working environment (one global IP)
nginx log format (/etc/nginx/conf.d/viewer-log.conf)
log_format viewer escape=json
  '{"time":"$time_iso8601",'
  '"uri":"$request_uri",'
  '"status":$status,'
  '"viewer_isp":"$http_cloudfront_viewer_isp",'
  '"viewer_tls_details":"$http_cloudfront_viewer_tls_details"}';

access_log /var/log/nginx/viewer.log viewer;

OpenSSL Client

I ran the following script inside a Docker container. The arguments are the CloudFront domain, the key exchange group, and the value of case used to tell requests apart in the log.

#!/bin/sh
set -eu

DOMAIN="$1"
GROUP="$2"
CASE="$3"

(
  printf 'GET /?case=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n' \
    "$CASE" "$DOMAIN"
  sleep 3
) |
  openssl s_client \
    -connect "${DOMAIN}:443" \
    -servername "$DOMAIN" \
    -tls1_3 \
    -groups "$GROUP" \
    -brief 2>&1 |
  grep -E 'Protocol version|Ciphersuite|Negotiated TLS1.3 group|Peer Temp Key|HTTP/1.1|x-cache|error|alert'

Here is an example run. The CloudFront domain is masked.

./openssl-request.sh dxxxxxxxxxxxxx.cloudfront.net X25519MLKEM768 pqc-x25519mlkem768

I keep standard input open with sleep 3. Without it, although the TLS connection information was displayed, the request was not recorded in the origin's log.

To also check a connection without a specified group, I sent one request from the host's curl.

Verification Results

CloudFront-Viewer-ISP

I used a KDDI-family ISP line for the verification. In the six requests sent from this one line, the value of CloudFront-Viewer-ISP was au one net in all cases. This value reached the origin as a string containing spaces, as is.

CloudFront-Viewer-ISP is added only when CloudFront can identify the ISP, so the origin side needs to take requests without the header into account.

CloudFront-Viewer-TLS-Details

This is the value that reached the origin for a connection using PQC (X25519MLKEM768). I formatted the access log record for presentation.

{
  "tlsVersion": "TLSv1.3",
  "cipherSuite": "TLS_AES_128_GCM_SHA256",
  "handshakeType": "fullHandshake",
  "keyExchange": "X25519MLKEM768",
  "signatureScheme": "rsa_pss_rsae_sha256",
  "signaturePublicKeyType": "rsa2048"
}

This is the value for a conventional connection (X25519 specified on the client).

{
  "tlsVersion": "TLSv1.3",
  "cipherSuite": "TLS_AES_128_GCM_SHA256",
  "handshakeType": "fullHandshake",
  "keyExchange": "x25519",
  "signatureScheme": "rsa_pss_rsae_sha256",
  "signaturePublicKeyType": "rsa2048"
}

In this distribution, which uses the default *.cloudfront.net certificate, the signature scheme and the certificate's public key type were the same values as in the conventional connection, even for the connection using PQC.

Values of keyExchange

The PQC key exchange methods supported by CloudFront are two: X25519MLKEM768 and SecP256r1MLKEM768, and they can be used only with TLS 1.3.

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/secure-connections-supported-viewer-protocols-ciphers.html

These are the results of five connections, each limited to a single key exchange group.

Group specified by the client Client-side display keyExchange that reached the origin
X25519MLKEM768 Negotiated TLS1.3 group: X25519MLKEM768 X25519MLKEM768
SecP256r1MLKEM768 Negotiated TLS1.3 group: SecP256r1MLKEM768 SecP256r1MLKEM768
X25519 Peer Temp Key: X25519, 253 bits x25519
prime256v1 Peer Temp Key: ECDH, prime256v1, 256 bits secp256r1
secp384r1 Peer Temp Key: ECDH, secp384r1, 384 bits secp384r1

For reference, even with curl 8.18.0 (OpenSSL 3.5.9), which does not specify a key exchange group, X25519MLKEM768 was selected in this environment.

Summary

By adding CloudFront-Viewer-ISP and CloudFront-Viewer-TLS-Details to the origin request policy, I was able to check the viewer's ISP name and the key exchange method, including PQC, at the origin.

If you want to use the connection source's ISP or key exchange method for decisions or logging on the origin side, give this update a try.

Share this article

AWSのお困り事はクラスメソッドへ