【実務・中級編】 tracerouteのTCPオプションを用いた高度な経路診断とフィルタリング回避 – トラブルシューティング&ネットワーク運用監視実践ガイド

「なぜPingは通るのにアプリは繋がらない?」──TCP Tracerouteで魔境のネットワークを暴く

現場で働いていると、一度はこんな事態に遭遇するはずだ。「監視ツールは正常と言っているのに、特定のWeb APIだけがタイムアウトする」。Pingを打てば応答はある。だが、肝心のサービスポートが死んでいるのか、それとも途中のファイアウォール(FW)がL7レベルで遮断しているのか。標準的な traceroute(UDP)や ping(ICMP)だけでは、今の「セキュリティがガチガチに固められた境界」を突破して真実を突き止めることはできない。

今日は、百戦錬磨のインフラエンジニアが最後に行き着く、TCP SYN Traceroute を用いた泥臭い経路診断術を伝授しよう。

—

1. なぜ標準のtracerouteでは「見えない壁」があるのか

標準的な traceroute は、デフォルトでUDPパケット(Linux系)やICMP Echo Request(Windows系)を使用する。しかし、現代のデータセンターやクラウド環境において、これらは「真っ先にドロップされる対象」だ。

  • UDP traceroute: 宛先ポートが(たまたま)開いていない限り、途中のルーターはICMP Time Exceededを返すが、FWがUDPのインバウンドを全遮断していれば、ただ「* * *」と表示されるだけの虚無が待っている。
  • ICMP ping: 多くのFWはセキュリティポリシーとして「外部からのPing応答」を無効化している。

ここで真の味方となるのが、TCP SYN Traceroute だ。

—

2. TCP SYN Tracerouteのロジック:パケットの「擬態」

TCP SYN Tracerouteは、宛先ポート(例えば 80 や 443)に向けて、あたかも正規のコネクションを確立しようとするかのように SYN パケットを送りつける。

1. TTLの仕掛け: 各ホップ(ルーター)に対して、TTL(Time To Live)を 1 から順にインクリメントしながらパケットを投げる。
2. 中間ノードの反応: TTL が尽きたノードは、ICMP Time Exceededを返してくる。
3. 最終目的地: 宛先に到達すると、ターゲットサーバーは「接続していいよ」と SYN/ACK を返してくる(またはポートが閉じているなら RST を返す)。

この「正規の通信に見える」という性質が、FWのフィルタリングをすり抜ける最大の武器になるのだ。

—

3. 実践:最強のツール tcptraceroute を使いこなす

Linux環境であれば、tcptraceroute をインストールしておくのが鉄板だ。

# Ubuntu/Debian系の場合
sudo apt install tcptraceroute

# 実行例:Webサーバーの443番ポートに向けて経路を追跡
# -n: 名前解決をせずIPで表示(DNS待ちのロスを防ぐ)
# -p 443: TCP 443番ポートを指定
# -q 3: 各ホップで3回送信(パケットロス確認のため)
sudo tcptraceroute -n -p 443 192.168.1.100 80

もし tcptraceroute が入っていない環境でも、traceroute コマンド自体が -T オプション(TCPモード)をサポートしていることが多い。

# 標準のtracerouteコマンドでTCPモードを使用
traceroute -T -p 443 192.168.1.100

—

4. プログラミングで「自作」する経路監視

APIの疎通が断続的に途切れるような嫌な障害の場合、定期的に経路を記録しておくスクリプトがあると便利だ。Pythonの scapy を使えば、生のTCPパケットを自由に操作できる。

from scapy.all import *

# 宛先ターゲット
target = "192.168.1.100"
dest_port = 443

# TTLを1から順に増やす
for i in range(1, 20):
    # TCP SYNパケットを作成
    pkt = IP(dst=target, ttl=i) / TCP(dport=dest_port, flags="S")
    
    # 送信して応答を待つ
    reply = sr1(pkt, timeout=2, verbose=0)
    
    if reply is None:
        print(f"{i}: * (Timeout)")
    elif reply.type == 11: # ICMP Time Exceeded
        print(f"{i}: {reply.src} (Route node)")
    elif reply.haslayer(TCP): # 宛先に到達
        print(f"{i}: {reply.src} (Target reached!)")
        break

—

5. 現場のシニアからの警告:注意すべき「罠」

この手法は強力だが、注意点が一つだけある。「DoS攻撃と誤認される」リスクだ。

特に、SYN パケットを短時間に大量に投げるようなスクリプトを走らせると、相手側のIDS(侵入検知システム)が「SYN Flood攻撃だ!」と判断し、あなたの送信元IPを自動的にブラックリストへ放り込んでしまうことがある。

  • Tips: 調査を行う際は、必ず -q 1 (試行回数を1回)にするか、送信間隔(--wait や sleep)を十分に空けること。特に本番環境のクリティカルなサーバーに対して行う場合は、監視担当者に一声かけるのがプロの流儀だ。

—

まとめ:ネットワークの深淵を覗くために

「パケットは嘘をつかない」。これは私が新人の頃、師匠に教わった言葉だ。CLI画面に表示される * * * の羅列に絶望するのではなく、どのレイヤーで、どのポートで、どのようなフラグが弾かれているのかを論理的に分解すれば、必ずボトルネックは特定できる。

次にAPIが繋がらない時は、慌ててログを見る前に tcptraceroute を叩いてみてほしい。君の目の前にある「見えない壁」の正体が、きっと姿を現すはずだ。

コメント

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