aws

CloudFront経由 , ALB経由 , EC2直接 それぞれにアクセスした際のHTTPリクエストヘッダーの内容

CORS設定のために、HTTPリクエストヘッダー(特にHOSTヘッダー)に何が飛んできてるかを把握する必要があったため、実機で確認してみました。

以下3つの経路でアクセスして、EC2上のPHP (on Apache) にてHTTPリクエストヘッダーを出力します。

  • EC2(HTTP) へ直接アクセス
  • ALB(HTTPS) → EC2(HTTP) の経路でアクセス
  • CloudFront(HTTPS) → ALB(HTTPS) → EC2(HTTP) の経路でアクセス
CloudFront〜ALB〜Webサーバのインフラ構成図

クライアントは、すべてMac の curl コマンドを使用し、curlでもリクエストおよびレスポンスヘッダーを出力してみます。

スポンサーリンク

確認手順

確認用php

getallheaders(全てのHTTPリクエストヘッダを取得する) メソッドで確認します。

$ 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クエリやヘッダなど、いろいろ指定してみます。あと無用な混乱を避けるためキャッシュは無効にしました。

オリジンリクエストポリシーを特に設定をしない

レスポンス(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クエリが記録されています。OK!

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"

補足 CloudFront設定箇所

オリジンリクエストポリシーやキャッシュの動作(キャッシュさせないなど)は、CloudFront → [ CloudFront Distributions ] で当該ディストリビューションのIDクリック →[ Behaviors ] タブ → 当該ビヘイビアにチェック入れて[ Edit ] した際の以下画面にて設定します。

AWSマネジメントコンソールのCloudFront設定画面


なお、これらのポリシーは画面左ペインの [ Policies ] より独自にカスタムできます。

以上です〜ノシ

参考

ありがとぅ~ヾ(〃^∇^)ノ♪

HTTP リクエストヘッダーと CloudFront の動作 (カスタムオリジンおよび S3 オリジン)
AWS CloudFront + ALB + httpd の組み合わせで一部のブラウザでページが表示できなかった問題の原因と対処
getallheaders — 全てのHTTPリクエストヘッダを取得する