Gemcook Tech Blog
🦈

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

に公開

この記事を書いた背景

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

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

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

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

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

この記事でやること

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

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

その後、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)
      • 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 python3 -m http.server 80

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

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

③Route53でドメインを取得

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

④ACMで証明書を発行

HTTPS通信のためにACMでSSL証明書を発行します。この証明書は、Amazon Trust Servicesという認証局(CA)によってデジタル署名された公開鍵証明書です。

手順は以下の記事と同じなので詳細は割愛します。

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は公式サイトからダウンロードできます。

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

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

Wiresharkの基本的な使い方は、以下の記事がわかりやすかったです。

https://qiita.com/OtsukaTomoaki/items/eb22bc2b8869fcd81600

HTTPS通信を覗いてみる(port 443)

tcp port 443でキャプチャフィルタをかけたあと、ブラウザにてドメインにアクセスします。

するとWiresharkの画面にはキャプチャがばばばっとたくさん表示されています。

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

つまり、ClientからALBの通信の間ではTLSハンドシェイクが完了して、暗号化通信が始まっている状態であることがわかります。

HTTP通信を覗いてみる(port 80)

ALBからEC2へのHTTP通信(port 80)はローカルから直接見えないため、sshdumpを使います。sshdumpはSSH経由でEC2上のtcpdumpを実行し、その結果をWiresharkに転送して内部通信を可視化する仕組みです。

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

Wiresharkのインターフェース選択画面でSSH remote capture: sshdump を選択し、設定で以下を入力します。

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

設定が終わったら、ブラウザにてドメインにアクセスします。

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

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

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

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

Protocol 列に、HTTPのほかに「TCP」がたくさん並んでいます。

TCPは「Transmission Control Protocol」の略で、トランスポート層に位置し、データを確実に順番通り相手に届けるための仕組みです。通信の途中でデータが失われたり順番が入れ替わったりしないよう制御しています。

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

通信の最初には、接続を確立するために SYN → SYN/ACK → ACK の3つのパケットがやり取りされます。これは3ウェイハンドシェイクと呼ばれる処理です。

Wiresharkでは、このハンドシェイクやデータの送受信確認など、TCPが通信の信頼性を維持するために行っている制御パケットが表示されています。

HTTP通信はこのTCPの上で動いているため、HTTPのパケットとあわせて多くのTCPパケットが並んで見えわけですね。

https://ja.wikipedia.org/wiki/3ウェイ・ハンドシェイク

GET / HTTP/1.1 の HTTP/1.1って?

HTTP/1.1は、HTTPのバージョンを表しています。

HTTPは1991年に登場して以来、1996年にHTTP/1.0、1997年にHTTP/1.1、2015年にHTTP/2、2022年にHTTP/3、と4度のバージョンアップが行われています。

どのバージョンで接続するかは、クライアントとサーバーの設定次第で、やり取りの中で適切なプロトコルバージョンが選択されるそうです。
https://qiita.com/hirooka0527/items/13767855358f83db5e02

まとめ

ひとまずWiresharkを使ってパケットキャプチャなるものをできて満足です。

ネットワークに関することは、本や記事を読んでいるだけでは「ふ〜んそうなんだ」で終わりがちなので、こうして実際に通信の流れを追いかけてみると理解が深まりそうだと思いました。

Wiresharkでこんな面白いことできるよ、というアイデア募集中。

Gemcook Tech Blog
Gemcook Tech Blog

Discussion