CHAPTER2 Networking

SNI

SNIとはServer Domain Indicationの略。 これを理解するにはまずTLSの仕組みを抑えておく。

TLS

確認すべきはTLSOSI参照モデルのセッション層のプロトコルであり、HTTPレイヤよりもずっと下ということである。

TLSは本来クライアントが「接続するサーバが本物であるかどうかをサーバから送られてくる証明書を利用して検証する」という作業がある。 (SNIを利用しなければ)原則サーバーが応答出来る証明書の数は一つだけである。

例えば下記の例のように、「一つのサーバで複数のドメインのサイト(www.pyons04.comとwww.sftp04.com)を運用したい」といった事象が発生したときにサーバーは送られてくるアクセスがどちらのドメインに対するものなのか、判断できない。

バーチャルホスト - Wikipedia

  • 「私(サーバ)はwww.pyons04.comのサーバとして登録済ですよ」
  • 「私(サーバ)はww.aoyama.comのサーバとして登録済ですよ」

ということを表す証明書のうち、どちらを返却すべきか定まらない。

そこでサーバはより下のIPレイヤの情報を活用して、必要なドメイン毎に異なるIPアドレスを登録し同じサーバでもアクセスされたIPアドレス毎に異なる証明書を返却するという方法が利用できる。これをIPベースバーチャルホストと呼ぶ。

一方2つのホストで同じIPアドレスを使いつつ、送付する証明書を使い分ける方法も存在する。これを名前ベースバーチャルホストと呼ぶがSNIが登場するまでは下記のような証明書を発行していた。

  • 「私(サーバ)はwww.pyons04.comのサーバとしてもwww.aoyama.comのサーバとしても登録済ですよ」

上記のような証明書を返すことで高価なIPアドレスをいくつも登録する必要がなくなった。

しかし登録するドメインが増えるごとに新ドメインを追記した新しい証明書を発行して登録するしかなく、これもまた面倒な作業であった。高価なIPベースバーチャルホストも煩雑な名前ベースバーチャルホストHTTPSの普及を妨げていた。

SNIでは、クライアントが(HTTPSセッションを確立する前の)セッション層の接続を確立する時点でほしいドメインをリクエストしてしまい、サーバは証明書の返却時にこれを参照して返却する証明書を決定する。

CloudFrontにおけるMulti-DomainとSNI

CloudFrontにも当然TLS証明書が必要になる。 CloudFrontのサーバ自体そもそもマルチテナントであり、(EC2のように独立したサーバがレスポンスしているのではなく)ありとあらゆるドメインのコンテンツを一つのManagedされたサーバがレスポンスしている。

従ってCloudFrontでも当然上記のような事態が発生する。 CloudFrontはSNIを標準でサポートしているので、ユーザーがこれらを気にする必要はない。

ただし、一部の非常に古いブラウザではそもそもSNIがサポートされていなかったりする。 そうした後方互換性の確保が必須の場合、固定IPアドレスを購入にしてCloudFrontに割り当ててやりIPベースバーチャルホストを実現することも出来る。

NLBとALBのロードバランシングオプション

NLBのロードバランシングオプションと言えば原則PortBaseのRoutingPolicy程度しか存在しない。例えばPort80ならインスタンス1にPort22ならインスタンス2に、と言ったルーティングオプションが用意されている程度である。

その代わり、ALBに比べてNLBは非常に高速でレイテンシが少ない。NLBであってもHTTPリクエストを捌くことは出来るので、パフォーマンスの要件が厳しく且つ単純なロードバランシングしか要求されなければ、NLBを利用してロードバランシングを行うことも可能である。

一方、ALBにはいろいろとルーティングオプションが用意されている。

RoutingPolicy Example
HostBase www.siteA.comwww.siteB.com
PathBase .com/reservation.com/rooms
HTTPMethodBase POST/GET/PUT/DELETE
QueryParameterBase /?param=abc&number=12345

新規 – AWS Application Load Balancer に対するホストベースのルーティングのサポート | Amazon Web Services ブログ

Jumbo Frame

Jumbo FrameとはIEEE802.3で規定された1500MTUよりも大きいフレームのこと。

ジャンボフレーム - Wikipedia

AWSでは一部のEC2インスタンスVPCのみでこのフレームに対応している。VPC-PeeringやInternetGatewayを介してしまうと、1500MTUまでしかやり取りできないようだ。

特定の AWS リージョン (EC2-Classic)、1 つの VPC、または VPC ピア接続の外側では、最大パスが 1500 MTU になることがあります。VPN 接続およびインターネットゲートウェイを介して送信されるトラフィックは 1500 MTU に制限されます。

EC2 インスタンスのネットワークの最大送信単位 (MTU) - Amazon Elastic Compute Cloud

更にJumbo-Frameにすることで、(元から)1500MTUのフレームで送信するよりも通信速度が遅くなることがある。これは、通信先がJumboFrameの受信に対応してないことが判明すると、9000MTUのフレームを1500MTUのフレームにカプセル化が行われるからである。

パケットは中間システムによってフラグメント化されるため、このトラフィックの速度が低下します。VPC 外に向かうトラフィックの速度を低下させずに VPC 内のジャンボ フレームを使用するには、ルートごとに MTU サイズを設定するか、または MTU サイズやルートの異なる複数の Elastic ネットワークインターフェイスを使用します。

因みに、Jumbo Frameの送信に失敗した場合の動作はTCP/IPの実装に依るようだ。下記によるとWinodwsではIEEE802.3で規定されている最小値(1500MTUですらない)にまでフレームを小さくして再送してしまう。

例えばWindows OSではMTUサイズを以後は576にして、再送する、というふうに動作している(576は規格で要請されているMTUの最小保証値)。これにより、まったく通信できなくなるという事態は回避できるが、ジャンボ・フレームどころか、通常のイーサネットのフル・サイズのパケットすらも使わないので、通信のパフォーマンスはあまりよくない。

第5回 イーサネットを高速化するジャンボ・フレーム技術:PCハードウェア強化ラボ(3/3 ページ) - @IT

なお、インターネットゲートウェイであってもMTUは指定するもののインターネットゲートウェイはManagedServiceなので帯域幅については指定が不要である。必要な分に応じてスケーリングが行われる。

インターネットゲートウェイは、IPv4 トラフィックおよび IPv6 トラフィックをサポートしています。ネットワークトラフィックに可用性のリスクや帯域幅の制約が発生することはありません。

インターネットゲートウェイ - Amazon Virtual Private Cloud

IPv6とEagressGateway

NAT-GatewayとInternet-Gateway

そもそもNAT-GatewayとInternet-Gatewayは別個の機能である。

インターネットゲートウェイは NAT ゲートウェイからインターネットにアクセスするために必要ですが(後略)

AWS、プライベート通信における NAT ゲートウェイのインターネットゲートウェイへの依存を排除

改めて確認したいのでは、NAT変換はInternet-Gatewayでも実施されているということである。[PrivateSubnetからの通信]と[PublicSubnetからの通信]の場合ではNAT変換の行われる場所が2つに分離する。

Gateway NAT
NAT-Gateway PrivateSubnet-PrivateIPAddress↔PublicIPAdress on NAT-Gateway
Internet-Gateway PublicSubnet-PrivateIPAddress↔PublicIPAdress on Internet-Gateway

当然、NAT-Gatewayを経由してPublicIPAdressに変換されたパケットもInternetGatewayを通過することになる。しかしパケットはNAT変換等を行わず、パケットのルーティングのみを行う。

インターネットゲートウェイは 2 つの目的を果たします。1 つは、インターネットでルーティング可能なトラフィック送信先VPC のルートテーブルに追加することです。もう 1 つは、パブリック IPv4 アドレスが割り当てられているインスタンスに対してネットワークアドレス変換 (NAT) を行うことです。

インターネットゲートウェイ - Amazon Virtual Private Cloud

PublicSubnetに存在するインスタンスであっても、固定のIPv4アドレスが割り当てられているとは限らない。家庭にあるような普通のLANの如く一つの固定IPv4アドレスをNATで使いまわしている場合がある。この場合Internet-Gatewayに割り当てられた固定IPv4アドレスへのNAT変換を実施しなければ、インターネットとの通信は行えない。

InternetGatewayにはElasticIPという固定のIPublicIPv4アドレスを紐付けておく。これをNAT変換における外側のIPアドレスとして利用している。

一方「固定のIPv4アドレスを持つインスタンスがPublicSubnetに存在する場合はInternet-GatewayによるNATは必要ない」と考えていた。しかしこの考えは前提がそもそも誤りであった。

インスタンスは、VPC とサブネット内で定義されたプライベート(内部)IP アドレス空間のみを認識します。

インターネットゲートウェイ - Amazon Virtual Private Cloud

つまりインスタンスにPublicIPアドレスを直接紐付けることは出来ないのだ。

しかし、ElasticIPをインスタンスに紐付けるオプションについてはAWS内でも解説されている。これはInternetGatewayのNAT変換リストにElasticIPAddress↔PrivateIPAddressのエントリが登録されるというだけで、インスタンス自体がPublicIPAddressを保持できるわけではない。

【図解/AWS】インターネットGWとNAT-GWの違い〜各メリット、パブリックサブネットとは〜 | SEの道標

IPv6の特殊性とEgressGateway

VPC内でインスタンスを起動すると、デフォルトではPrivateIPv4Addressが割り当てられる。先述したようにPublicIPv4Addressを直接インスタンス保有することは出来ない(Internet-Gatewayのエントリとして保持するだけ)。

一方、VPC内でのインスタンス起動のオプションでIPv6のPublicアドレスを付与させることも出来る(正確にはVPCIPv6のアドレスを持つサブネットとして登録する)。

Amazon EC2 インスタンスの IP アドレス指定 - Amazon Elastic Compute Cloud

与えられたIPv6のアドレスはPublicであるため、通常のInternetGatewayさえあれば(特に固定のIPアドレスを割り当てるようなことをしなくても)直接外部からアクセスが可能になる。

IPv6になることで、大量のアドレスが利用可能になりますので、 Elastic IPやGlobal IPをいちいちアタッチしなくても、インターネット側からIPv6のアドレスでEC2に簡単にアクセスできるようになります。 逆に、IPv6のアドレスをアサインしてしまうと、全世界に公開されてしまうので、外から入れない仕組みを考える必要があります。

【re:Invent 2016】IPv6がVPCとEC2に来たので試してみた - サーバーワークスエンジニアブログ

Egress(Only)Gatewayでは、PublicIPv6Addressを持つインスタンスに対して外部から直接接続可能にするのを防ぐことが出来る。インスタンスが保持するPublicIPAddressをEgressGatewayに登録したNATエントリを利用して別のIPv6PublicAddressに強制的に変換するからである。

Egress-Only インターネットゲートウェイは、IPv6 トラフィックでのみ使用されます。IPv4 経由での送信専用のインターネット通信を可能にするには、代わりに NAT ゲートウェイを使用します。

Egress-Only インターネットゲートウェイ - Amazon Virtual Private Cloud

Static IP AdressとLoad Balancer

そもそもLoad BalancerにIPアドレスを紐付ける動機がよくわかっていない。Global Accelatorというのを使うらしい。

オンプレミスのDNS(キャッシュ)サーバをVPCから利用する

VPCではSubnetに属するクライアントのDHCP接続について細かく決定することが出来る。DHCPDNSキャッシュサーバにオンプレミスのサーバのIPAddressを登録しておけば、好きなDNSサーバを利用させることが出来る。

VPC の DHCP オプションセット - Amazon Virtual Private Cloud