CORS設定のために、HTTPリクエストヘッダー(特にHOSTヘッダー)に何が飛んできてるかを把握する必要があったため、実機で確認してみました。
以下3つの経路でアクセスして、EC2上のPHP (on Apache) にてHTTPリクエストヘッダーを出力します。
- EC2(HTTP) へ直接アクセス
- ALB(HTTPS) → EC2(HTTP) の経路でアクセス
- CloudFront(HTTPS) → ALB(HTTPS) → EC2(HTTP) の経路でアクセス
クライアントは、すべてMac の curl コマンドを使用し、curlでもリクエストおよびレスポンスヘッダーを出力してみます。
HTTPリクエストヘッダーの確認手順
確認用php
全てのHTTPリクエストヘッダを取得する getallheaders メソッドで確認します。
$ cat /var/www/html/hoge.php
<?php
foreach (getallheaders() as $name => $value) {
echo "$name: $value\n";
}
?>
$
EC2(HTTP) へ直接アクセス
当然ですがHOSTヘッダはEC2のFQDNでした。
% curl -v http://ec2-11-222-333-44.ap-northeast-1.compute.amazonaws.com/hoge.php
...
### リクエストヘッダ
> GET /hoge.php HTTP/1.1
> Host: ec2-11-222-333-44.ap-northeast-1.compute.amazonaws.com
> User-Agent: curl/7.64.1
> Accept: */*
>
...
### レスポンスヘッダ
< HTTP/1.1 200 OK
< Date: Sun, 08 Nov 2020 20:15:14 GMT
< Server: Apache/2.4.46 () PHP/7.4.12
< Upgrade: h2,h2c
< Connection: Upgrade
< X-Powered-By: PHP/7.4.12
< Content-Length: 97
< Content-Type: text/html; charset=UTF-8
<
...
### レスポンス(リクエストヘッダのPHP出力)
Host: ec2-11-222-333-44.ap-northeast-1.compute.amazonaws.com
User-Agent: curl/7.64.1
Accept: */*
...
%
ALB(HTTPS) → EC2(HTTP) の経路でアクセス
ALBに割り当てたFQDNにアクセスしようとしたところ以下のerrorとなりました。
% curl -v https://alb-test-domain.com/hoge.php
...
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fe621008a00)
> GET /hoge.php HTTP/2
> Host: alb-test-domain.com
> User-Agent: curl/7.64.1
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
* http2 error: Invalid HTTP header field was received: frame type: 1, stream: 1, name: [upgrade], value: [h2,h2c]
* HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)
* stopped the pause stream!
* Connection #0 to host alb-test-domain.com left intact
curl: (92) HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)
* Closing connection 0
%
エラー内容から察するに理由は こちらの事象だと思われます。今回はhttp2 でなくとも良いので、http1.1 と明示的にversion指定してリトライ!
HOSTヘッダはALBのFQDNです。
% curl -v --http1.1 https://alb-test-domain.com/hoge.php
...
### リクエストヘッダ
> GET /hoge.php HTTP/1.1
> Host: alb-test-domain.com
> User-Agent: curl/7.64.1
> Accept: */*
>
...
### レスポンスヘッダ
< HTTP/1.1 200 OK
< Date: Sun, 08 Nov 2020 22:44:46 GMT
< Content-Type: text/html; charset=UTF-8
< Content-Length: 198
< Connection: keep-alive
< Server: Apache/2.4.46 () PHP/7.4.12
< Upgrade: h2,h2c
< X-Powered-By: PHP/7.4.12
<
...
### レスポンス(リクエストヘッダのPHP出力)
X-Forwarded-For: 111.222.33.444(自宅のアウトバウンドIP)
X-Forwarded-Proto: https
X-Forwarded-Port: 443
Host: alb-test-domain.com
X-Amzn-Trace-Id: Root=1-xxxx-yyyzzzz
User-Agent: curl/7.64.1
Accept: */*
...
%
CloudFront(HTTPS) → ALB(HTTPS) → EC2(HTTP) の経路でアクセス
CloudFrontのリクエストの概念として、以下の2つがあります。
- ビューワーリクエスト(CloudFrontに来るリクエスト)
- オリジンリクエスト(文字通りキャシュ元となるオリジンサーバへのリクエスト)
CloudFrontではオリジンリクエストポリシーというものを特に設定しないと、デフォルトで設定された情報しかオリジンに転送されません。転送されるデフォルトはここに書いてあるのですが、「など」という言葉で表現されていたので正確には把握できず。。。(それとも別な場所に記載あるのかな??)
ここらへんの挙動が気になったので、以下2つのパターンを確認しました。
- オリジンリクエストポリシーを特に設定をしない
- オリジンリクエストポリシーに Managed-AllViewer というAWS側で初めから用意されたポリシーを設定する
後者はポリシーを設定することでビューワーリクエストのすべての値(クエリ文字列、ヘッダー、Cookie)がオリジンリクエストに含まれるようになります。
では確認してみます。
オリジンへ転送される際、どの情報が削られるか知りたかったのでURLクエリやヘッダなど、いろいろ指定してみます。あと無用な混乱を避けるためキャッシュは無効にしました。
オリジンリクエストポリシーやキャッシュ動作の変更手順
オリジンリクエストポリシーやキャッシュの動作(キャッシュさせないなど)は、画面上部検索窓 [ CloudFront ] で検索 → 当該サービスをクリック → [ CloudFront Distributions ] で当該ディストリビューションのIDクリック →[ Behaviors ] タブ → 当該ビヘイビアにチェック入れて [ Edit ] した際の以下画面にて設定します。
これらのポリシーは画面左ペインの [ Policies ] より独自にカスタムできます。
オリジンリクエストポリシーを特に設定をしない場合
レスポンス(PHP出力)でのHOSTがALBのFQDNとなっており、curlで送ったヘッダも消えてしまっています。
% curl -v -H "FOO:BAR" -H "Cookie:foo=1111" "https://cf-test-domain.com/hoge.php?foo=222&bar=333"
### リクエストヘッダ
> GET /hoge.php?foo=222&bar=333 HTTP/2
> Host: cf-test-domain.com
> User-Agent: curl/7.64.1
> Accept: */*
> FOO:BAR
> Cookie:foo=1111
>
...
### レスポンスヘッダ
< HTTP/2 200
< content-type: text/html; charset=UTF-8
< content-length: 349
< date: Mon, 09 Nov 2020 15:01:14 GMT
< server: Apache/2.4.46 () PHP/7.4.12
< x-powered-by: PHP/7.4.12
< x-cache: Miss from cloudfront ・・・キャッシュヒットすると Hit from cloudfront と出力されます。
< via: 1.1 xxx.cloudfront.net (CloudFront)
< x-amz-cf-pop: NRT12-C5
< x-amz-cf-id: xxx==
<
...
### レスポンス(リクエストヘッダのPHP出力)
X-Forwarded-For: 111.222.33.444(自宅のアウトバウンドIP), 55.666.777.888(CloudFrontのIP)
X-Forwarded-Proto: https
X-Forwarded-Port: 443
Host: alb-test-domain.com ・・・ALBのFQDN
X-Amzn-Trace-Id: Root=1-xxx-yyy
User-Agent: Amazon CloudFront
X-Amz-Cf-Id: xxx==
Via: 2.0 xxx.cloudfront.net (CloudFront)
%
またEC2でのapacheのアクセスログでもURLクエリが消えています。
172.31.35.1 - - [09/Nov/2020:15:01:14 +0000] "GET /hoge.php HTTP/1.1" 200 349 "-" "Amazon CloudFront"
オリジンリクエストポリシーにManaged-AllViewerを設定した場合
レスポンス(PHP出力)でのHOSTがCloudFrontのFQDNとなっており、curlで送ったヘッダはしっかりと記録されています。
% curl -v -H "FOO:BAR" -H "Cookie:foo=1111" "https://cf-test-domain.com/hoge.php?foo=222&bar=333"
...
### リクエストヘッダ
> GET /hoge.php?foo=222&bar=333 HTTP/2
> Host: cf-test-domain.com
> User-Agent: curl/7.64.1
> Accept: */*
> FOO:BAR
> Cookie:foo=1111
>
...
### レスポンスヘッダ
< HTTP/2 200
< content-type: text/html; charset=UTF-8
< content-length: 381
< date: Mon, 09 Nov 2020 15:37:14 GMT
< server: Apache/2.4.46 () PHP/7.4.12
< x-powered-by: PHP/7.4.12
< x-cache: Miss from cloudfront
< via: 1.1 xxx.cloudfront.net (CloudFront)
< x-amz-cf-pop: NRT12-C5
< x-amz-cf-id: xxx==
<
...
### レスポンス(リクエストヘッダのPHP出力)
X-Forwarded-For: 111.222.33.444(自宅のアウトバウンドIP), 55.666.777.888(CloudFrontのIP)
X-Forwarded-Proto: https
X-Forwarded-Port: 443
Host: cf-test-domain.com
X-Amzn-Trace-Id: Root=1-xxx-yyy
User-Agent: curl/7.64.1
X-Amz-Cf-Id: xxx==
Via: 2.0 xxx.cloudfront.net (CloudFront)
Cookie: foo=1111
Accept: */*
foo: BAR
%
またEC2でのapacheのアクセスログでもURLクエリが記録されています。
172.31.35.1 - - [09/Nov/2020:15:37:14 +0000] "GET /hoge.php?foo=222&bar=333 HTTP/1.1" 200 381 "-" "curl/7.64.1"
今回は以上です〜ノシ
参考
ありがとぅ~ヾ(〃^∇^)ノ♪
HTTP リクエストヘッダーと CloudFront の動作 (カスタムオリジンおよび S3 オリジン)
AWS CloudFront + ALB + httpd の組み合わせで一部のブラウザでページが表示できなかった問題の原因と対処
getallheaders — 全てのHTTPリクエストヘッダを取得する