【実務・中級編】 TCPベースtraceroute(tcptraceroute)の仕組みとファイアウォール透過性 – トラブルシューティング&ネットワーク運用監視実践ガイド

なぜ、pingやtracerouteが「嘘をつく」のか?——現場で鍛えられたTCPトレースの技術

ネットワーク障害の現場で最も恐ろしいのは、「問題が起きているのは確実なのに、標準的なツールが正常値を返してくる」という状況だ。

新人エンジニアがまず頼る ping(ICMP Echo)や traceroute(UDPまたはICMP)は、現代のデータセンターにおいて「全幅の信頼を置くには心許ない」ツールである。なぜなら、多くのファイアウォール(FW)やロードバランサーは、セキュリティ対策としてこれらを「不要なトラフィック」と見なし、ドロップしたり、優先度を極端に下げたりするからだ。

特に、Web APIの疎通確認や、複雑なマルチクラウド環境でのパケットロス調査において、標準の traceroute は何の役にも立たないことが多い。そこで我々シニアエンジニアが最終兵器として取り出すのが、tcptraceroute という選択肢だ。

—

1. なぜ「TCP」でトレースする必要があるのか?

標準的な traceroute は、UDPパケットやICMPパケットを用いて経路上のルーターから ICMP Time Exceeded メッセージを吐き出させることでホップを特定する。しかし、多くのステートフルFWは「許可されたTCPコネクション」以外のパケットを厳格に制限している。

一方で tcptraceroute は、宛先の特定のポート(例:80 や 443)に対して TCP SYN パケットを送りつける。

  • ステートフルFWの裏をかく: 多くのFWは 80 や 443 ポートへの SYN パケットを「アプリケーション通信の開始」と見なし、通過させる。
  • 経路上のデバイスをあぶり出す: TTL(Time To Live)を調整した SYN パケットを送ることで、経路上のルーターが「TTL期限切れ」を通知してくる挙動を逆手に取り、通常のTCP通信と同じ経路を通るノードだけを正確に可視化できる。

つまり、tcptraceroute は「Web APIが実際に通るはずの経路」をシミュレートできる唯一のツールなのだ。

—

2. 現場で使う tcptraceroute の実戦コード

まずは、Linux環境であれば tcptraceroute コマンドそのものを使うのが一番手っ取り早い。

# 宛先サーバーの443ポートへ向けてトレースを開始
# -n: DNS逆引きをスキップして高速化(現場では必須)
# -q 1: プローブ回数を減らして診断時間を短縮
sudo tcptraceroute -n -q 1 example.com 443

もしサーバーにツールをインストールできない環境であれば、hping3 や nmap を使って同様の挙動を再現することもできる。

# nmapを使ったTCPトレース(-sTでTCP接続、--tracerouteで経路表示)
sudo nmap -sT -p 443 --traceroute example.com

—

3. 実務応用:Pythonによる「カスタム・トレース」の自作

時には、特定のAPIエンドポイントに対して「毎分どれくらいのレイテンシがあるか」を計測し、ログに残す必要がある。そんな時は scapy ライブラリを使って、自分だけのカスタム・トレースツールを書いてみよう。

from scapy.all import IP, TCP, sr1

# 宛先情報
target_ip = "192.0.2.1"
target_port = 443

def custom_trace(target, port):
    for ttl in range(1, 30):
        # IPパケットにTTLをセットし、TCP SYNパケットを付与
        packet = IP(dst=target, ttl=ttl) / TCP(dport=port, flags="S")
        
        # パケットを送出し、応答を待つ(タイムアウト2秒)
        reply = sr1(packet, timeout=2, verbose=0)
        
        if reply is None:
            print(f"{ttl}: * (タイムアウト)")
        elif reply.type == 11:  # ICMP Time Exceeded
            print(f"{ttl}: {reply.src} (ルーター通過)")
        elif reply.haslayer(TCP): # 宛先に到達!
            print(f"{ttl}: {reply.src} (到達成功)")
            break

# 実行
custom_trace(target_ip, target_port)

このコードの肝は flags="S" だ。明示的に SYN を指定することで、FWに「Web接続ですよ」と認識させる。もし相手先が ACK を返してくれば、それは経路が完全に疎通していることの何よりの証拠だ。

—

4. シニアエンジニアからの教訓:運用上の注意点

この手法を使う際、たった一つだけ忘れてはならない注意点がある。それは「対象サーバーへの負荷とログ」だ。

  • ポートスキャンと誤認される: 短時間に大量の SYN パケットを投げると、相手先のIPS(侵入防止システム)が攻撃と判断し、自分のIPをブロックしてしまう可能性がある。診断時は q 1(プローブ数1回)に留めるのがマナーだ。
  • 隠蔽されたノード: 最近のクラウド(AWS/GCPなど)の内部ネットワークは、セキュリティのために ICMP Time Exceeded を返さない設定になっていることが多い。トレースの途中で * * * が続くからといって、必ずしも「そこが故障している」とは限らない。

最後に。ネットワークトラブルの9割は、ルーターの故障ではなく「設定ミス」か「FWのポリシールール」に起因する。tcptraceroute を使いこなせれば、パケットがどこで、なぜ止まっているのかを、勘ではなく「事実」として突き止めることができるはずだ。

さあ、コマンドラインを開いて、見えないパケットの流れを可視化してみよう。現場からは以上だ。

コメント

タイトルとURLをコピーしました