サイトアイコン 協栄情報ブログ

AWS EC2でtcpdumpを使って解析

DNS FirewallがGoogleドメインをブロックする動作をAWS EC2でtcpdumpを使って解析

お世話になっております。yasuokaです。

本記事では、AWS EC2インスタンス上で tcpdump を使用し、AWS Route 53 DNS Firewall (DnsFW) がGoogleドメインをブロックしている様子をキャプチャする方法について解説します。

1. 事前準備:AWS EC2にログイン

a. AWS Systems Manager (SSM) を使ってEC2にログイン

AWS Systems Manager(SSM)を使用することで、SSH接続を使用せずにEC2インスタンスにログインできます。事前にEC2インスタンスに AmazonEC2RoleforSSM のIAMロールが付与されていることを確認してください。

手順:

  1. AWS マネジメントコンソールにログインし、Systems Managerを開きます。
  2. 左メニューから「セッションマネージャー」を選択します。
  3. セッションの開始」をクリックし、対象のEC2インスタンスを選択します。
  4. セッションの開始」ボタンをクリックすると、EC2インスタンスのシェルにアクセスできます。

DNSFWについては下記をご参照ください。

2. DNS Firewallの動作をtcpdumpでキャプチャ

a. 基本的なtcpdumpコマンド

tcpdump は、ネットワーク上のパケットをキャプチャし、リアルタイムで解析できるツールです。
ここでは、Googleドメインに関連するDNSトラフィックをキャプチャするため、DNSのポート(ポート53)をフィルタリングします。

コマンド例:

sudo tcpdump -i any -ttttv port 53

b. Googleドメインへのリクエスト確認

DNSFWがGoogleドメインをブロックしているかを確認するために、dig コマンドを使用してGoogleドメインに対してDNSリクエストを送信します。

コマンド例:

dig google.com

この際、tcpdump の出力にGoogleドメインへのDNSクエリが表示されるはずです。

出力例:

2024-10-09 15:30:00.123456 IP 192.168.1.100.12345 > 8.8.8.8.53: 12345+ A? google.com. (32)

3. DNS Firewallによるブロックの確認

DnsFWがGoogleドメインをブロックしている場合、NXDomain というエラーメッセージが返されることがあります。これは、リクエストされたドメインが存在しない、またはブロックされていることを意味します。

出力例:

2024-10-09 15:30:01.123456 IP 8.8.8.8.53 > 192.168.1.100.12345: 12345 NXDomain* 0/1/0 (92)

このようなエラーメッセージが表示された場合、GoogleドメインがDnsFWによってブロックされていることが確認できます。


4. tcpdumpの詳細と活用法

a. tcpdumpのオプション解説

b. ログファイルとして保存

リアルタイムでの監視だけでなく、キャプチャ結果をログファイルとして保存することも可能です。

コマンド例:

sudo tcpdump -i any -ttttv port 53 > dns_capture.log

これにより、後で結果を解析したり、チームで共有することができます。

5. まとめ

この記事では、AWS EC2インスタンス上で tcpdump を使用して、DNS FirewallがGoogleドメインをブロックしている様子をキャプチャする手順を紹介しました。

tcpdump は、ネットワークトラブルを迅速に特定し、原因を解析するための強力なツールです。

DNSFWのように特定ドメインをブロックする際、その動作を確認するには非常に有効です。

tcpdumpを活用して、ネットワークの監視やトラブルシューティングを効率的に行いたいと思います。

6. 追記

Tcpdumpのログから、以下の要件を満たす情報を抽出して表示するために、awkとgrepを使用してみます。

要件:

  1. タイムスタンプ
  2. 送信元IPアドレスとポート
  3. 受信先IPアドレスとポート
  4. プロトコル番号
  5. 特定のプロトコルやコマンドの抽出:
    • Traceroute
    • Ping
    • Telnet

awk –version
grep –version

方法:

  1. tcpdumpのログ形式を前提に、grepawkで必要な部分を抽出。
  2. 各プロトコルやツールに関連するパターンに合わせてフィルタリング。
  3. sedを使用して、抽出した情報を整形。

出力例を送信元と受信先で分けて、TimestampSource(送信元IPアドレス)、Destination(受信先IPアドレス)、Type(プロトコルの種類)、Protocol(プロトコル番号)を表示する形式に修正します。

以下は、awkgrepを使用して、TcpdumpのログからICMP、TCP、UDPの通信を抽出し、フォーマットするコマンドです。

1. Ping (ICMP)

grep "ICMP" /path/to/tcpdump.log | grep -E "echo request|echo reply" | \
awk '{
    split($3, src, "\\."); 
    src_ip=src[1]"."src[2]"."src[3]"."src[4];

    if ($NF == "echo" && $(NF-1) == "request") {
        print "Timestamp: " $1, $2 ", Source: " src_ip ", Type: ICMP Echo Request, Protocol: 1";
    } else if ($NF == "echo" && $(NF-1) == "reply") {
        print "Timestamp: " $1, $2 ", Source: " src_ip ", Type: ICMP Echo Reply, Protocol: 1";
    }
}'

このコマンドは、tcpdumpでキャプチャされたICMP通信(特に「echo request」と「echo reply」)をフィルタし、フォーマットされた形で表示するものです。それぞれの部分の意味と動作を以下で詳しく説明します。

1. grep "ICMP" /path/to/tcpdump.log

2. grep -E "echo request|echo reply"

3. awk '{...}'

split($3, src, "\\.");

src_ip=src[1]"."src[2]"."src[3]"."src[4];

if ($NF == "echo" && $(NF-1) == "request") {...}

print "Timestamp: " $1, $2 ", Source: " src_ip ", Type: ICMP Echo Request, Protocol: 1";

else if ($NF == "echo" && $(NF-1) == "reply") {...}

print "Timestamp: " $1, $2 ", Source: " src_ip ", Type: ICMP Echo Reply, Protocol: 1";

全体の流れ

  1. grepでICMPのパケットをフィルタリング。
  2. さらにgrepで「echo request」や「echo reply」を持つ行を選び出す。
  3. awkで、タイムスタンプ、送信元IPアドレス、通信のタイプを抽出してフォーマットし、出力。

意図

2. Traceroute (UDP)

grep "UDP" /path/to/tcpdump.log | \
awk '{
    split($3, src, "\\."); 
    split($5, dest, "\\.");
    src_ip=src[1]"."src[2]"."src[3]"."src[4];
    dest_ip=dest[1]"."dest[2]"."dest[3]"."dest[4];

    print "Timestamp: " $1, $2 ", Source: " src_ip ", Destination: " dest_ip ", Type: UDP, Protocol: 17";
}'

3. Telnet (TCP)

grep "TCP" /path/to/tcpdump.log | grep ":23 " | \
awk '{
    split($3, src, "\\."); 
    split($5, dest, "\\.");
    src_ip=src[1]"."src[2]"."src[3]"."src[4];
    dest_ip=dest[1]"."dest[2]"."dest[3]"."dest[4];

    print "Timestamp: " $1, $2 ", Source: " src_ip ", Destination: " dest_ip ", Type: TCP, Protocol: 6";
}'

出力例

実行結果は以下のように表示されます。

Timestamp: 2024-10-11 10:00:00, Source: 192.168.1.10, Type: ICMP Echo Request, Protocol: 1
Timestamp: 2024-10-11 10:00:01, Source: 192.168.1.20, Type: ICMP Echo Reply, Protocol: 1
Timestamp: 2024-10-11 10:00:02, Source: 192.168.1.10, Destination: 192.168.1.20, Type: TCP, Protocol: 6
Timestamp: 2024-10-11 10:00:03, Source: 192.168.1.10, Destination: 192.168.1.20, Type: UDP, Protocol: 17

ICMPの出力例は、以下のようになります。

ICMP Echo Request(Pingのリクエスト)

Timestamp: 2024-10-11 10:00:00, Source: 192.168.1.10, Type: ICMP Echo Request, Protocol: 1

ICMP Echo Reply(Pingのリプライ)

Timestamp: 2024-10-11 10:00:01, Source: 192.168.1.20, Type: ICMP Echo Reply, Protocol: 1

このように、ICMPプロトコルでは「Echo Request(リクエスト)」と「Echo Reply(応答)」が主要な通信タイプで、プロトコル番号は常に 1 です。

上記例の背景:

これらのログは、ICMPの通信内容を表しており、Pingコマンドの結果をtcpdumpなどのネットワークパケットキャプチャツールで解析したときに見られる情報です。

AWKを使わないで、grepsedだけで同様のICMPのログを整形する方法を以下に示します。この場合、grepsedを組み合わせて情報を抽出し、必要な情報を整形します。

追記の追記 ICMPのgrepsedを使った例

コマンド例

grep "ICMP" /path/to/tcpdump.log | grep -E "echo request|echo reply" | \
sed -E 's/([0-9-]+ [0-9:]+)\..* IP ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) > .*, (ICMP echo request|ICMP echo reply).*/Timestamp: \1, Source: \2, Type: \3, Protocol: 1/'

コマンドの詳細な説明

  1. grep "ICMP" /path/to/tcpdump.log

    • 目的: tcpdumpのログファイルから「ICMP」に関連するパケットを含む行を抽出します。
    • 動作: tcpdump.logの中で「ICMP」が含まれている行のみをフィルタリングします。
  2. grep -E "echo request|echo reply"

    • 目的: ICMPパケットの中でも、特にecho requestまたはecho replyの行をフィルタします。
    • 動作: -Eは正規表現をサポートし、「echo request」または「echo reply」を含む行だけを選びます。
  3. sed -E 's/([0-9-]+ [0-9:]+)\..* IP ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) > .*, (ICMP echo request|ICMP echo reply).*/Timestamp: \1, Source: \2, Type: \3, Protocol: 1/'

    • 目的: フィルタされたログの各行を整形し、指定されたフォーマットで出力します。
    • 動作:
      • sed -Eは拡張正規表現を有効にします。
      • s/sedの置換コマンドです。s/パターン/置換/の形式でマッチした部分を置換します。
      • ([0-9-]+ [0-9:]+)はタイムスタンプ部分(2024-10-11 10:00:00の形式)を抽出。
      • ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)は送信元IPアドレスを抽出。
      • (ICMP echo request|ICMP echo reply)はICMPのタイプ(リクエストまたはリプライ)を抽出。
      • .*でその後の不要な情報を無視します。
      • \1, \2, \3は、それぞれ正規表現でキャプチャした部分(タイムスタンプ、IPアドレス、ICMPタイプ)を置換時に使用します。
      • Protocol: 1は固定値(ICMPのプロトコル番号)として追加します。

実行結果の例

もし、tcpdump.logに以下のようなICMPのパケットが含まれていた場合:

2024-10-11 10:00:00.123456 IP 192.168.1.10 > 192.168.1.20: ICMP echo request, id 1, seq 1, length 64
2024-10-11 10:00:01.123456 IP 192.168.1.20 > 192.168.1.10: ICMP echo reply, id 1, seq 1, length 64

上記のコマンドを実行すると、以下のような出力が得られます。

Timestamp: 2024-10-11 10:00:00, Source: 192.168.1.10, Type: ICMP Echo Request, Protocol: 1
Timestamp: 2024-10-11 10:00:01, Source: 192.168.1.20, Type: ICMP Echo Reply, Protocol: 1

この方法では、grepでログから必要な行を抽出し、sedでその行を整形して出力します。AWKを使わずに、sedの正規表現を使って行を処理することで、簡潔にデータを整形することが可能です。

1. ツールの目的と機能

2. データの操作

例: AWK vs sedの処理の違い

AWKでの操作:

awk '{
    split($3, src, "\\.");
    src_ip=src[1]"."src[2]"."src[3]"."src[4];

    if ($NF == "echo" && $(NF-1) == "request") {
        print "Timestamp: " $1, $2 ", Source: " src_ip ", Type: ICMP Echo Request, Protocol: 1";
    } else if ($NF == "echo" && $(NF-1) == "reply") {
        print "Timestamp: " $1, $2 ", Source: " src_ip ", Type: ICMP Echo Reply, Protocol: 1";
    }
}'

sedでの操作:

sed -E 's/([0-9-]+ [0-9:]+)\..* IP ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) > .*, (ICMP echo request|ICMP echo reply).*/Timestamp: \1, Source: \2, Type: \3, Protocol: 1/'

3. 複雑な処理

AWKの複雑な処理例:

例えば、AWKでは次のように複数の条件を組み合わせてデータ処理が可能です。

awk '{
    split($3, src, "\\.");
    split($5, dst, "\\.");
    src_ip=src[1]"."src[2]"."src[3]"."src[4];
    dst_ip=dst[1]"."dst[2]"."dst[3]"."dst[4];

    if ($NF == "echo" && $(NF-1) == "request") {
        print "Timestamp: " $1, $2 ", Source: " src_ip ", Destination: " dst_ip ", Type: ICMP Echo Request, Protocol: 1";
    }
}'

これは、送信元と受信先のIPアドレスを取り出し、if文で複雑な条件分岐を行っています。

4. 学習曲線

まとめ

モバイルバージョンを終了