NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

注目のタグ

    VPC Flow LogsのTCPフラグを読み解く

    本記事は  ネットワークウィーク  11日目の記事です。
    💻  10日目  ▶▶ 本記事 ▶▶  12日目  🌐

    はじめに

    こんにちはネットワークウィーク11日目担当の山本です!
    AWS上でシステムを運用していると、誰もが一度は「なぜかEC2に繋がらない」、「通信が途中で途切れる」といったネットワークのトラブルに直面すると思います。 オンプレミスのサーバーであれば、Wiresharkなどのツールでパケットをキャプチャして原因を特定できますが、クラウドのVPC内部ではそうはいきません。 ここで真価を発揮するのが、VPC Flow Logsです。 本記事では、このFlow Logsのtcp-flagsフィールドを、TCPの接続フェーズと紐づけて解説します。

    TCP接続の基本:3ウェイ・ハンドシェイク

    Flow Logsの tcp-flags を理解するためには、まずTCP(Transmission Control Protocol)の接続確立プロセスである「3ウェイ・ハンドシェイク」の知識が欠かせません。 このプロセスは、クライアントとサーバーがお互いに通信準備ができたことを確認し合うための、以下の3つのステップで構成されています。

    1. SYN (Synchronize): クライアントからサーバーへの接続要求。

    2. SYN/ACK (Synchronize-Acknowledge): サーバーからクライアントへの応答と確認応答。

    3. ACK (Acknowledge): クライアントからサーバーへの最終確認。

    なぜPingやTracerouteだけではネットワークの真実が見えないのか?

    AWS環境でのネットワーク障害対応は、従来のオンプレミスの知識が通用しない特有の難しさがあります。アプリケーションが「接続タイムアウト」や「接続拒否」を起こしたとき、エンジニアは常に「これはファイアウォールやルーティングの問題なのか?」それとも「EC2インスタンス内部のアプリケーションやOSの設定ミスなのか?」という原因の切り分けのジレンマに直面します。

    AWSの「不可視性」とトラブルシューティングの壁

    オンプレミスでは、ネットワーク機器にログインし、tcpdumpやtracerouteでパケットの消失点を特定できました。しかし、AWSの仮想ネットワークでは、パケットがセキュリティグループ (SG) やネットワーク ACL (NACL) でドロップされても、その証拠はブラックボックスの中に隠されてしまいます。従来のツールでは、単にタイムアウトが表示されるだけで、どこで、なぜドロップされたのかまでは特定できません。

    原因追及の手がかり:Flow LogsのTCPフラグ

    このAWS仮想ネットワークの壁を越え、パケットの真実を明らかにするツールのひとつがVPC Flow Logsです。Flow Logsは、トラフィックのメタデータ(送信元/宛先IP、ポート、アクション)を記録しますが、特にtcp-flagsフィールドは、パケットがどのTCPステート(状態)で処理されたかという、決定的な情報を含んでいます。 この tcp-flags の値は、パケットの「意思表示」を記録します。

    • パケットが途中で消えたのか?
    • ターゲットに到達し、明示的に拒否されたのか?

    TCPフラグの基礎とFlow Logsへのマッピング

    標準的なネットワーク解析ではTCPフラグはSYNやACKといった名称で表示されますが、Flow Logsではtcp-flagsフィールドに「18」や「4」といった10進数の数値が記録されます。 この10進数は、同時にアクティブになった複数のTCPフラグのビットマスク(総和)です。Flow Logsは、単一のパケット内で立ったすべてのフラグの値を合計した結果を記録しています。

    トラブルシューティングに必須の4大フラグ

    トラブルシューティングにおいて最も重要な、以下の4つのTCPフラグとその10進数値(重み)を説明します。

    主要なTCPフラグ
    フラグ 役割 10進数 (重み)
    SYN (Synchronize) 接続の開始要求 2
    ACK (Acknowledge) 受信確認応答 16
    RST (Reset) 接続の強制切断 4
    FIN (Finish) 接続の正常終了要求 1

    複合フラグの読み解き方

    最も頻繁に出現する、複数のフラグが同時に立つケースを解説します。

    1. 接続応答: SYNとACK
      SYN (2) + ACK (16) = 18
      意味:サーバーがクライアントの接続要求を受信し、それに応答している(ハンドシェイクの2番目のパケット)。

    2. データ転送中の切断要求: FINとACK
      FIN (1) + ACK (16) = 17
      意味:クライアントまたはサーバーがデータ転送を終了し、正常な切断プロセスを開始している。

    3. 強制切断の確認応答: RSTとACK
      RST (4) + ACK (16) = 20
      意味:接続が異常終了したことに対する確認応答。

    【実践】正常なフローとトラブルシューティングパターン

    今回は、ログの切り分けが簡易的になるよう以下のような構成で検証しました。
    ローカルの実行環境は「Windows 11」、EC2インスタンスは「Amazon Linux 2023」です。

    Flow Logsの設定は以下のようになります。
    デフォルトのログ形式では、tcp-flagが含まれないためカスタム形式を選択して追加しています。

    接続確認のために、EC2インスタンスへApacheをインストールして起動しておきます。
    SSMで接続して以下のコマンドを実行するかEC2インスタンス起動時のユーザーデータに以下を設定しておくと自動で実行してくれます。
    ※セキュリティグループのインバウンドルールでローカルPCのアクセスが許可されているかどうかは必ず確認してください。

    #!/bin/bash
    # Apache HTTPサーバー (httpd) をインストールし、起動して有効化する
    
    # 1. パッケージリストを更新(Amazon Linux, RHEL系の場合)
    dnf update -y
    
    # 2. Apache HTTPサーバーをインストール
    dnf install -y httpd
    
    # 3. Apacheサービスを起動
    systemctl start httpd
    
    # 4. インスタンスの再起動時に自動的にApacheが起動するように設定
    systemctl enable httpd

    Apacheが起動できたら、ローカル環境でcurlコマンドを使って確認します。

    # -v: 詳細モード (Verbose) で、接続の詳細やTCPフラグの状態を確認できる
    C:\Users> curl -v http://[EC2インスタンスのパブリックIPアドレスまたはDNS名]

    実行できたら今回ログの格納先に指定しているCloud Watch Logsから確認してみましょう。

    パターン①正常な接続

    まず「正常な接続」がFlow Logsでどのように記録されるかを理解することが重要です。 TCP接続の確立「3ウェイ・ハンドシェイク」の一連の動きがFlow Logsに異なるレコードとして記録されます。

    一見するとレコードが2つしか記録されていないし、tcp-flagsの値も前述で説明した値と異なるように見えますね。
    ただ、これは今回のような短い通信の場合に同一のログ集約期間に複数の通信がまとめられてしまうためにおこる現象になります。 公式ドキュメントにも以下のような記載がありました。

    単一の集約間隔内で開かれて閉じられた短い接続の場合 (数秒など)、同じ方向のトラフィックフローに関して、Flow Logsレコードの同じ行にフラグが設定されることがあります。
    フローログレコードの例 - Amazon Virtual Private Cloud

    したがって、視覚的にはまとめられているが実際の通信は行われているという解釈になります。
    クライアント→サーバ:SYN (2) + FIN (1) = 3
    サーバ→クライアント:SYN (2) + ACK (16) + FIN (1) = 19

    試しにWiresharkでパケットを確認してみると、やはり通信はきちんと行われていることがわかります。

    パターン②サーバからの応答なし


    このパターンは、curlを実行した際に「Timed out」(タイムアウト)が発生するか、あるいはFlow Logsに「REJECT OK 2」のみが記録される状態です。これは、パケットがEC2インスタンスに到達する前に、AWSのネットワーク層で破棄されていることを示します。したがって、Flow Logsにログが記録されないときはルーティングまたはNACL、「REJECT OK 2」のログが記録されるときはセキュリティグループでパケットが破棄されていることを疑いましょう。

    パターン③サーバからの接続拒否


    このパターンでは、ログに「Accept OK 4」と記録され、ステートがRSTになっています。 つまりSYNパケットはEC2インスタンスに正常に到達しますが、EC2インスタンス側が「このポートは開いていません」と接続を拒否します。 したがって、この場合問題はAWSのネットワーク設定にはありませんのでEC2インスタンスでWebサーバー(Apache)が稼働しているかを確認しましょう。

    おわりに

    今回の過程で得られた最も重要な教訓は、「ネットワークの問題」と「サーバーの問題」、そして「ログ記録の特性」を Flow Logs のデータから明確に切り分けることの意義です。 AWS環境の「見えないネットワークの真実」を映し出す鏡であるVPC Flow Logsを有効活用し、トラブルシューティングに役立てていただければ幸いです。

    執筆者 : 山本将望
    食べることが生きがいのインフラエンジニア
    執筆記事一覧 : https://tech.nri-net.com/archive/author/m4-yamamoto