Gemcook Tech Blog
🦈

【Wireshark】ALB経由でのEC2通信をパケットキャプチャしてみる

に公開

この記事を書いた背景

Wiresharkかっけえ! おいらも何かパケットキャプチャしてみたい

でも何のパケットを見る…?

AWSを普段よく使うから、AWS絡めれたらいいな

ALBとEC2ええやん!よくある構成だし

【Wireshark】ALB経由でのEC2通信をパケットキャプチャしてみる

この記事でやること

AWSのマネコンをぽちぽちして、以下の構成を作ります。

外部(Client〜ALB)はHTTPSで暗号化し、内部(ALB〜EC2)はVPC内の閉じたネットワークでHTTP通信する構成です。TLS終端にして、HTTPS通信とHTTP通信の違いを見れたらいいなと思ってこのような構成にしています。

その後、Wiresharkで通信をパケットキャプチャします。

Wiresharkとは

https://ja.wikipedia.org/wiki/Wireshark

Wiresharkとは、ネットワーク上を流れる通信データ(パケット)をキャプチャして、その内容を詳しく解析できるオープンソースのLANアナライザです。

どんな通信が行われているのか、視覚的にわかりやすく表示してくれる優れもの!

YouTubeによくある「カフェの無料Wi-Fiは危ないのか?」みたいな動画を見ていると、Wiresharkを使っている様子がたまに映っていますね。

↓これとか

https://youtu.be/HlRRXdcn5ho?si=DXYwoDJjJn2-tDdu

↓これとか

https://youtu.be/FnhD7ljtPhY?si=GtBVhTpMo-9u7gIf

AWSの環境セットアップ

①EC2インスタンスを作る

  • マネジメントコンソールから「EC2 → インスタンスを起動」
    • AMI: Amazon Linux 2023
    • インスタンスタイプ: t2.micro など小さめで
    • ネットワーク: なんでもいいが、僕は以前学習用に作ったVPCを使用
    • パブリックIPを自動割り当てに設定
    • セキュリティグループのインバウンドルールを設定
      • HTTP(80)
      • HTTPS(443)
      • SSH(22)

インスタンス起動時に指定したキーペア(.pemファイル)を使って、SSH接続します。

ssh -i <キーペアの所在パ> ec2-user@<EC2のPublic IPv4アドレ>

Amazon Linux 2023 の鳥さんが出てきたらOK。

②HTTPサーバー起動

SSHでEC2インスタンスに接続できたら、インスタンス内で簡易HTTPサーバーを起動します。

本番環境ならNginxやApacheを使うことが多いですが、今回は簡易的なもので十分なので、Pythonのhttp.serverを使います。Pythonといっても、追加でインストールや設定をする必要はなく、Amazon Linux 2023には標準でPythonがインストールされています。

sudo yum install -y python3
sudo python3 -m http.server 80

サーバーが起動できているかどうかは、ブラウザで http://<EC2のPublic IPv4 DNS> にアクセスして確認します。DNSで名前解決はまだしていないので直打ちです。

Directory listing が表示されたらOK。HTTPでの通信なので「保護されていない通信」と表示されます。

③Route53でドメインを取得

Route53にて格安でドメイン(.linkドメイン)を取得します。年5ドルでした。勉強代です。

④ACMで証明書を発行

HTTPS通信のためにSSL証明書を発行します。以下の記事と同じ流れなので詳細は割愛します。

https://dev.classmethod.jp/articles/issuing-certificate-with-acm/

⑤ALBの作成

  • ロードバランサーの種類はALBを選ぶ
  • スキーム: インターネット向け
  • IPアドレスタイプ: IPv4
  • リスナー: HTTPS(443)
  • アベイラビリティゾーン: EC2と同じVPC・サブネットを選択
  • リスナーに以下の2つを追加
    • HTTP(80)
    • HTTPS(443)
  • SSL証明書の設定で、先ほど発行した証明書を指定
  • ターゲットグループを作成
    • ターゲットタイプ: インスタンス
    • プロトコル: HTTP
    • ポート: 80
    • VPC: EC2と同じもの
    • ヘルスチェックパス: /

⑥DNSの設定

作成したALBをRoute53と紐づけます。Route53にレコードを追加します。

  • レコードタイプ: A
  • エイリアス: はい
  • エイリアス先: 作成したALB

設定後、ブラウザでドメインにアクセスして、Directory listing が表示されたら成功です。HTTPSで起動しているので「保護されていない通信」の表示はありません。

以上でAWS側の環境セットアップは完了です。

WireSharkの出番じゃ!

Wiresharkは公式サイトからダウンロードできます。

Wiresharkを開くと、利用可能なネットワークインターフェースのリストが表示されます。

ここからキャプチャしたいインターフェースを選択してキャプチャを開始できます。

今回自分はインターネットへの接続をキャプチャするのでWifi: en0を選択します。

通信区間 確認方法
クライアント → ALB ローカルWiresharkで port 443 をキャプチャ
ALB → EC2 sshdumpでEC2上の port 80 をリアルタイムキャプチャ

HTTPS通信を見る(クライアント→ALB)

  • Wiresharkでローカルのネットワークインターフェースを選択(en0 など)

  • キャプチャフィルタtcp port 443を設定

  • ブラウザまたは curl でアクセス

  • Protocol 列が「TLSv1.2 / TLSv1.3」 になっている
  • Info 列が「Application Data」 ばかりで、中身が解釈されていない(暗号化済み)
  • ポート番号が 443(HTTPS)

つまり、

クライアント(あなたのMac)→ ALB の間では

TLSハンドシェイクが完了して暗号化通信が始まっている状態です。

HTTP通信を見る(ALB→EC2)

Wiresharkのインターフェース選択画面で

SSH remote capture: sshdump を選択し、「設定」を開く。

https://www.wireshark.org/docs/man-pages/sshdump.html

  • Server: Remote SSH server: <EC2のPublic IP>
  • Authentication
    • Username: ec2-user
    • Private key: .pem ファイル
  • Capture Filter: port 80

別ターミナルで curl を再度実行します。

  • Protocol 列が「HTTP」(暗号化されていない)
  • Dst Port が 80(ALB から EC2 への平文HTTP)
  • Info 欄に GET / HTTP/1.1200 OK が見えている(中身が可視)

つまり、先ほどの「クライアント→ALB(443/TLS暗号化)」と対になる形で、ALBが復号してEC2へは平文HTTPを送っている 状況が完全に観察できています。

これでTLS終端構成の両側が見えました。

気になって調べたこと

Protocol欄にたくさんある「TCP」は何を意味してる?

画面の中央部分に、HTTPの他に、TCPのプロトコルが表示されているのが確認できます。

TCPは「Transmission Control Protocol」の略で、データを確実に順番通り相手に届けるための仕組みです。通信の途中でデータが失われたり順番が入れ替わったりしないよう制御しています。WiresharkでTCPが見えるのは、HTTPがこのTCPの上で動いているからです。TCP/IP参照モデル・OSI参照モデルのトランスポート層ですね。

https://ja.wikipedia.org/wiki/Transmission_Control_Protocol

TCPは、送信側と受信側が双方向の通信路(論理的なパイプライン)を張り合うようにして動作します。

それぞれの方向に独立したデータの流れがあり、どちらの側も「受け取った」「まだ届いていない」と確認しながら通信します。

Wiresharkでは、その様子がパケットのやり取りとして見えています。

最初にSYN、SYN/ACK、ACKという3つの通信でパイプラインを確立し(これが「ハンドシェイク」)、その後、実際のデータ(HTTPなど)がその上を流れます。

つまり、Wiresharkに見えているTCPパケットは、まさにその「確認し合いながら通信している」過程を記録したものです。

ビット フラグ名 説明 概要
1ビット目 CWR Congestion Window Reduced 混雑ウィンドウを減少させたことを通知する(送信側が輻輳制御の一環として使用)
2ビット目 ECE ECN-Echo Explicit Congestion Notification(明示的輻輳通知)を受信したことを示す
3ビット目 URG Urgent 緊急ポインタのフィールドが有効なことを表す
4ビット目 ACK Acknowledgment 受信データの連番フィールドが有効であることを表す(通常はデータが正常に届いたかを表す)
5ビット目 PSH Push flush動作で送信されたデータであることを表す(受信側に即座に転送するよう指示)
6ビット目 RST Reset 接続を強制終了する
7ビット目 SYN Synchronize 送信側と受信側で連番を確認しあう(接続の確立に使用)
8ビット目 FIN Finish 切断を表す(通信の終了を通知)
GET / HTTP/1.1 の HTTP/1.1って?

HTTPは1991年に登場して以来、1996年にHTTP/1.0、1997年にHTTP/1.1、2015年にHTTP/2、2022年にHTTP/3、と4度のバージョンアップが行われています。どのバージョンで接続するかは、クライアントとサーバーの設定次第で、やり取りの中で適切なプロトコルバージョンが選択されるそうです。
https://qiita.com/hirooka0527/items/13767855358f83db5e02

あとがき

HTTPのステータスコード(200や4xxなど)は以前から馴染みがありましたが、HTTPのバージョンについて考えたことがなかったのが発見でした。

トランスポート層のTCPについても

Gemcook Tech Blog
Gemcook Tech Blog

Discussion