らくがきちょう

なんとなく ~所属組織/団体とは無関係であり、個人の見解です~

AWS NLB は Source IP/Port を維持するが DSR 動作はしない

AWS Black Belt Online Seminar は毎回、素晴らしい内容です。 2017 年公開の資料なので、最新の情報ではありませんが NLB の基本的動作については ELB Update - Network Load Balancer (NLB) と関連サービス に分かりやすく、且つ、丁寧にかかれています。 この資料の P.20 に下記の記載があります。

  • クライアントの Source IP と Port が、そのまま Target まで届く
    • Target はクライアントと直接通信しているかの様に見える
    • 実際は、行きも帰りも NLB を通っている (DSR ではない)
    • IP Target (後述) の場合は保持されず、NLB からの通信となる
      • Direct Connect は接続されている VPC からのみ通信可能なので、こちらで回避

Instance Target で NLB を設定すると分散対象のサーバでは送信元パケットで「クライアントのアドレス」が確認出来る為、一見すると「NLB は DSR 動作している」ように見えますが、上述の Black Belt 資料に記載がある通り、実は DSR 動作をしていないそうです。 今回は検証環境で実際のトラフィックフローを確認してみました。

DSR した場合のトラフィックフロー (※ NLB はこの動作をしない)

NLB が「DSR 動作をしている」と仮定すると、トラフィックフローは下図のようになっているはずです。 後述しますが、実際にパケットをキャプチャしてみると Black Belt 資料に記載がある通り、この動作 (DSR 動作) はしていませんでした。

f:id:sig9:20200417114949p:plain:w600

NLB を利用した場合のトラフィックフロー

結果から述べると、NLB を経由した場合は以下のトラフィックフローになっていました。

f:id:sig9:20200417114952p:plain:w600

実際のパケットキャプチャ

実際にテスト環境で NLB 環境で動作確認し、パケットをキャプチャしてみます。

クライアント側でのパケットキャプチャ結果

クライアント (PC-11) から NLB に対して curl で HTTP GET リクエストを実行してみます。

[root@ip-10-0-1-11 ~]# curl http://10.0.1.100/
Hello, Web-101!

クライアント側でのパケットキャプチャ結果は以下の通りです。

01:59:17.857688 IP 10.0.1.11.38366 > 10.0.1.100.http: Flags [S], seq 1619515716, win 26883, options [mss 8961,sackOK,TS val 114241761 ecr 0,nop,wscale 7], length 0
01:59:17.858472 IP 10.0.1.100.http > 10.0.1.11.38366: Flags [S.], seq 1698624790, ack 1619515717, win 26847, options [mss 8653,sackOK,TS val 3307127713 ecr 114241761,nop,wscale 7], length 0
01:59:17.858485 IP 10.0.1.11.38366 > 10.0.1.100.http: Flags [.], ack 1, win 211, options [nop,nop,TS val 114241762 ecr 3307127713], length 0
01:59:17.858627 IP 10.0.1.11.38366 > 10.0.1.100.http: Flags [P.], seq 1:75, ack 1, win 211, options [nop,nop,TS val 114241762 ecr 3307127713], length 74: HTTP: GET / HTTP/1.1
01:59:17.858944 IP 10.0.1.100.http > 10.0.1.11.38366: Flags [.], ack 75, win 210, options [nop,nop,TS val 3307127714 ecr 114241762], length 0
01:59:17.859184 IP 10.0.1.100.http > 10.0.1.11.38366: Flags [P.], seq 1:291, ack 75, win 210, options [nop,nop,TS val 3307127714 ecr 114241762], length 290: HTTP: HTTP/1.1 200 OK
01:59:17.859190 IP 10.0.1.11.38366 > 10.0.1.100.http: Flags [.], ack 291, win 219, options [nop,nop,TS val 114241763 ecr 3307127714], length 0
01:59:17.859409 IP 10.0.1.11.38366 > 10.0.1.100.http: Flags [F.], seq 75, ack 291, win 219, options [nop,nop,TS val 114241763 ecr 3307127714], length 0
01:59:17.859709 IP 10.0.1.100.http > 10.0.1.11.38366: Flags [F.], seq 291, ack 76, win 210, options [nop,nop,TS val 3307127714 ecr 114241763], length 0
01:59:17.859717 IP 10.0.1.11.38366 > 10.0.1.100.http: Flags [.], ack 292, win 219, options [nop,nop,TS val 114241763 ecr 3307127714], length 0

以下の事柄が分かります。

  • NLB (10.0.1.100) からのパケットのみ、受信していること
  • Web-101 (10.0.1.101) からのパケットは 受信していない こと

Web サーバ側でのパケットキャプチャ結果

Web サーバ側でのパケットキャプチャ結果は以下の通りです。

01:59:17.858057 IP 10.0.1.11.38366 > 10.0.1.101.http: Flags [S], seq 1619515716, win 26883, options [mss 8653,sackOK,TS val 114241761 ecr 0,nop,wscale 7], length 0
01:59:17.858089 ARP, Request who-has 10.0.1.11 tell 10.0.1.101, length 28
01:59:17.858198 ARP, Reply 10.0.1.11 is-at 02:9d:7d:56:1d:aa, length 42
01:59:17.858215 IP 10.0.1.101.http > 10.0.1.11.38366: Flags [S.], seq 1698624790, ack 1619515717, win 26847, options [mss 8961,sackOK,TS val 3307127713 ecr 114241761,nop,wscale 7], length 0
01:59:17.858623 IP 10.0.1.11.38366 > 10.0.1.101.http: Flags [.], ack 1, win 211, options [nop,nop,TS val 114241762 ecr 3307127713], length 0
01:59:17.858774 IP 10.0.1.11.38366 > 10.0.1.101.http: Flags [P.], seq 1:75, ack 1, win 211, options [nop,nop,TS val 114241762 ecr 3307127713], length 74: HTTP: GET / HTTP/1.1
01:59:17.858790 IP 10.0.1.101.http > 10.0.1.11.38366: Flags [.], ack 75, win 210, options [nop,nop,TS val 3307127714 ecr 114241762], length 0
01:59:17.859005 IP 10.0.1.101.http > 10.0.1.11.38366: Flags [P.], seq 1:291, ack 75, win 210, options [nop,nop,TS val 3307127714 ecr 114241762], length 290: HTTP: HTTP/1.1 200 OK
01:59:17.859303 IP 10.0.1.11.38366 > 10.0.1.101.http: Flags [.], ack 291, win 219, options [nop,nop,TS val 114241763 ecr 3307127714], length 0
01:59:17.859520 IP 10.0.1.11.38366 > 10.0.1.101.http: Flags [F.], seq 75, ack 291, win 219, options [nop,nop,TS val 114241763 ecr 3307127714], length 0
01:59:17.859542 IP 10.0.1.101.http > 10.0.1.11.38366: Flags [F.], seq 291, ack 76, win 210, options [nop,nop,TS val 3307127714 ecr 114241763], length 0
01:59:17.859841 IP 10.0.1.11.38366 > 10.0.1.101.http: Flags [.], ack 292, win 219, options [nop,nop,TS val 114241763 ecr 3307127714], length 0

以下の事柄が分かります。

  • クライアント (10.0.1.11) からのパケットのみ、受信していること
  • NLB (10.0.1.100) からのパケットは 受信していない こと
  • つまり、NLB を経由していても送信元アドレスが維持されている

「従来の DSR」と「AWS NLB」の比較

「従来の DSR」と「AWS NLB」を比較してみます。

DSR の特徴

DSR 構成には一般的に以下のような特徴があると思います。

  1. 以下のトラフィックフローになる
  2. LB で戻りトラフィックを処理する必要が無い為、パフォーマンスが改善する
  3. トラフィックが往復ともに LB を経由することが前提である機能が使えない (例. SSL/TLS オフロード等)
  4. 負荷分散対象となるサーバで、戻りパケットの送信元アドレスを LB の VIP にする必要がある

AWS NLB では負荷分散対象サーバ側での DSR 用設定が不要

DSR 構成では Windows サーバにしろ、Linux サーバにしろ、上記 4. の設定が必要でした。 しかし、AWS NLB では恰も DSR のように「Source IP/Port は維持されている」にも関わらず、クライアントに通信を戻す際は「NLB のアドレスから戻ってくる」為に上記 4. の対処が不要です。 これは大きなメリットだと思います。

AWS NLB であれば、そもそも十分なパフォーマンスが期待出来る

また、NLB は AWS インフラで提供され、しかも AWS ALB とは違い「暖機運転」が不要なので突発的なバーストトラフィックにも強い、という特性があります。 従来の DSR には上記 2. の「パフォーマンスの優位性」がありましたが、AWS NLB は往復のパケットが経由しているとしても、「NLB がボトルネックになる」というケースは考えづらいのでは無いかと思われます。

他サービス同様、NLB はメンテナンスが不要

NLB も他のサービス同様、AWS のサービスなので「脆弱性対応」などのメンテナンスを意識してユーザが実施する必要がありません。「敢えて AWS インフラ内部に Linux/Windows で DSR な LB を構築する」という構成は手間が面倒で "敢えて自前で LVS を作ろう!" といったケースは少ないと思いますが…