夜中の3時。データセンターの監視モニターに赤々と浮かび上がる「API応答遅延アラート」。
「おい、また海外リージョンからのレイテンシが跳ね上がってるぞ。IX(インターネットエクスチェンジ)のどこかでパケットが詰まってるのか?」
インフラエンジニアやWeb APIの設計・運用に携わっていると、こうした夜間トラブルに遭遇することは少なくありません。アプリケーション層のログだけを見つめていても、「データベースが遅いのか」「クラウドプロバイダーの内部ネットワークが揺らいでいるのか」の根本原因にはたどり着けません。
そんな時、私たちネットワークエンジニアが真っ先に手に取る武器が traceroute です。単に「パケットの通る道を見るコマンド」だと思っていませんか? 実は traceroute の挙動を深く理解し、ホップごとの応答遅延(RTT)やAS(Autonomous System)経路情報を読み解くことができれば、地球の裏側で起きているルーティングループやISP間のトラフィック渋滞をも一撃で特定できるようになります。
今回は、数々の修羅場をくぐってきたNOC(ネットワークオペレーションセンター)のシニアエンジニアである私から、traceroute を極めるための実践的なノウハウを余すところなく伝授しましょう。
—
1. tracerouteの裏側:TTLとICMP/UDPが織りなすパケットの旅
traceroute がどのように動いているか、そのパケットの挙動を正しく理解しています。教科書的には「TTL(Time to Live)を1ずつ増やしながらパケットを投げる」と説明されますが、現場のトラブルシューティングでは、その背後にあるプロトコル仕様の癖を知っておく必要があります。
RFCが定めるTTLの寿命とICMP Time Exceeded
IPパケットのヘッダーには TTL(IPv4)または Hop Limit(IPv6)というフィールドが存在します。ルーターはこの値を経由するたびに1ずつデクリメント(減算)し、値が 0 になった瞬間にそのパケットを破棄します。そして、パケットを破棄したルーターは、送信元に対して ICMP Time Exceeded(Type 11, Code 0) というエラーメッセージを泣きながら送り返します。
traceroute はこの仕組みをハックしています。
1. TTL=1 のパケットを送信する $\rightarrow$ すぐ隣のルーター(ホップ1)で破棄され、ICMPが返ってくる。これでホップ1のIPアドレスと遅延がわかる。
2. 次に TTL=2 のパケットを送信する $\rightarrow$ 2つ先のルーター(ホップ2)で破棄され、ICMPが返ってくる。
3. これを宛先に届くまで繰り返す。
実務で知るべきUDP版とICMP版の罠
実は、OSやツールによってデフォルトの送信方式が異なります。
- Linux系(iputils traceroute): デフォルトではUDPパケットを宛先の高位ポート(通常33434〜)に向けて送信します。
- Windows(tracert): デフォルトではICMP Echo Request(pingと同じ)を送信します。
- 現代のベストプラクティス: ファイアウォール(FW)やセキュリティグループでUDPや特定のICMPが厳しくフィルタリングされている環境では、TCP(SYN)を用いた
traceroute(例:tcptracerouteやnmap --traceroute)の利用が必須となります。
—
2. 実践!CLIによる遅延解析とAS経路情報の読み方
それでは、実際に実務でよく使われるコマンドと、その出力結果のリアルな読み解き方を解説します。ここでは、AS(Autonomous System)情報まで同時に引いてくれる賢いツール mtr や、拡張オプションを駆使した traceroute を用います。
ホップごとの応答遅延(RTT)の波形を読み解く
まずは、標準的な traceroute の実行例と、そこに隠されたメッセージを見てみましょう。
# 宛先サーバーに対してUDPベースのtracerouteを実行(AS情報を付加)
$ traceroute -A 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
1 gw.internal.net (192.168.1.1) 0.412 ms 0.389 ms 0.355 ms
2 core1.tokyo.isp.example.jp (203.0.113.1) [AS65001] 1.210 ms 1.150 ms 1.102 ms
3 ix-tyo.net.example (198.51.100.42) [AS65000] 2.890 ms 2.812 ms 2.798 ms
4 * * *
5 74.125.50.61 [AS15169] 12.450 ms 12.310 ms 12.400 ms
6 dns.google (8.8.8.8) [AS15169] 11.980 ms 12.010 ms 11.950 ms
この出力から、何が読み取れるでしょうか?
1. ホップ1〜3: 社内ゲートウェイからISPのコアネットワーク、そしてIX(Internet Exchange)に至るまで、RTTは正常かつ安定(数ミリ秒以内)しています。
2. ホップ4(* * *): パケットが消えています。「おや、障害か?」と身構えるかもしれませんが、実務ではルーターのコントロールプレーンの負荷対策として、ICMP Time Exceededの生成レートリミット(Rate Limiting)をかけているだけであることが多々あります。後続のホップ5で正常に応答が返っているため、ここは単なる「ルーターの仕様による無応答」と判断してスルーするのが正解です。
3. ホップ5以降: GoogleのAS(AS15169)に入り、RTTが一気に12ms程度に跳ね上がっていますが、これは物理的な伝搬遅延(東京からGoogleのネットワークへの移動)として極めて正常な範囲です。
IX(インターネットエクスッチェンジ)における遅延増加箇所の特定
ISP間の接続点であるIXや、異なるTier(ティア)を持つキャリア間のトランジット回線では、しばしばトラフィックの輻輳(コンジェスト)が発生します。
ここで重要になるのが、「特定のホップ以降で急激に遅延が増加し、かつパケットロス(パロス)が発生しているか」の切り分けです。
# リアルタイムでパケットロスと遅延の統計を取るMTRの実行例
$ mtr --report --report-cycles=100 8.8.8.8
もし、あるIXのルーターを境に、それ以降のすべてのホップで遅延が数百度msに跳ね上がり、さらにパケットロスが10%を超えているような場合、それは間違いなくそのIXのインターフェース、あるいはトランジット回線でボトルネック(帯域枯渇)が発生しています。このデータを添えてISPやクラウドベンダーにチケット(問い合わせ)を起票すれば、向こうのNOCエンジニアも「こいつ、分かってるな」と迅速にルーティングの再最適化や帯域増強の調査を行ってくれます。
—
3. ルーティングループの検知とトポロジーの罠
ネットワーク構築のミスや、BGP(Border Gateway Protocol)の設定不備(プレフィックスの漏洩や誤った経路広告)によって発生するのがルーティングループです。パケットが無限にぐるぐると回り続けるこの現象は、APIサーバーのCPU負荷を高騰させ、ネットワーク帯域を食いつぶす最悪の障害の一つです。
ルーティングループのtracerouteパターン
ルーティングループに陥った宛先に対して traceroute を打つと、以下のような特徴的な出力が得られます。
$ traceroute 198.51.100.99
traceroute to 198.51.100.99 (198.51.100.99), 30 hops max, 60 byte packets
1 gw.internal.net (192.168.1.1) 0.500 ms 0.480 ms 0.452 ms
2 router-A.carrier.net (203.0.113.10) 2.100 ms 2.050 ms 2.010 ms
3 router-B.carrier.net (198.51.100.1) 5.400 ms 5.350 ms 5.310 ms
4 router-A.carrier.net (203.0.113.10) 5.800 ms 5.750 ms 5.710 ms
5 router-B.carrier.net (198.51.100.1) 9.100 ms 9.050 ms 9.010 ms
6 router-A.carrier.net (203.0.113.10) 9.500 ms 9.450 ms 9.410 ms
... (30ホップ上限までこれが繰り返される)
見事に router-A と router-B の間でパケットがピンポン玉のように行き来しています。TTLが尽きるまでこれが繰り返されるため、インフラのレイヤーでは深刻なトラフィック増を引き起こします。この兆候を見つけたら、即座に該当キャリアのnocへ連絡し、BGPの静的ルートやASパスの確認を依頼する必要があります。
—
4. アプリケーション層からのネットワーク診断:Pythonによる自動監視の実装
「障害が発生した時に、人間が手動で traceroute を叩く」のでは、モダンなSRE(Site Reliability Engineering)の現場としては失格です。APIのヘルスチェックや外形監視システムの中に、ネットワーク経路の揺らぎを検知する仕組みを組み込んでおきましょう。
ここでは、Pythonを用いて外部APIへの経路遅延やホップ数の変化を簡易的にモニタリングするスクリプトの例を紹介します。実務では、これをPrometheusのカスタムExporterなどに組み込んで時系列メトリクスとしてグラファイトやGrafanaで可視化します。
import subprocess
import re
import sys
def analyze_traceroute(destination: str):
"""
指定された宛先に対してtracerouteを実行し、
ホップ数と最終的な到達遅延を解析して標準出力に返す関数
"""
print(f"[*] Tracing route to {destination}...")
# Linux環境を想定し、tracerouteコマンドを実行(最大ホップ数15に制限して高速化)
try:
result = subprocess.run(
["traceroute", "-m", "15", "-q", "1", destination],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=True
)
except subprocess.CalledProcessError as e:
print(f"[!] Traceroute failed: {e.stderr}", file=sys.stderr)
return
hops = result.stdout.strip().split("\n")[1:] # ヘッダー行を除外
hop_count = len(hops)
print(f"[+] Total hops to {destination}: {hop_count}")
# 各ホップの情報をパースして表示
for line in hops:
# ホップ番号とIPアドレス、応答時間を正規表現で抽出
match = re.match(r"^\s*(\d+)\s+(.+)", line)
if match:
hop_num = match.group(1)
hop_detail = match.group(2)
print(f" Hop {hop_num}: {hop_detail}")
# 実務的なTips: ここで特定のホップのレイテンシが閾値を超えていないか判定し、
# 超過していればアラート用メトリクス(Prometheusカウンター等)をインクリメントする処理を入れる
if __name__ == "__main__":
# テストとしてGoogle Public DNSをターゲットにする
target_host = "8.8.8.8"
analyze_traceroute(target_host)
—
5. シニアエンジニアからの実務的アドバイス:パケットの「声」を聞け
ネットワークのトラブルシューティングにおいて、ツールはあくまで道具にすぎません。「なぜそのパケットがそこで破棄されたのか」「なぜそのパスが選ばれたのか」というネットワーク全体の意思決定(ルーティングポリシーや物理的トポロジー)を脳内に描き出すことが最も重要です。
最後に、現場で役立ついくつかの鉄則をまとめます。
1. 片方向の経路(Asymmetric Routing)を疑え: 行きと帰りで通るルートが違うのはインターネットの基本です。往路の traceroute が正常でも、復路でパケットがドロップしているケースは多々あります(その場合は逆方向からの traceroute や mtr が必要です)。
2. クラウド環境(AWS/GCP/Azure)の仮想ルーターの挙動を知れ: クラウドのVPC内から外部へ traceroute を打つと、セキュリティグループやNATゲートウェイの仕様によって、予期せぬアスタリスク(*)や遅延のジャンプが見られます。クラウド特有のアーキテクチャを理解した上でパケットを解釈してください。
ネットワークは生き物です。パケットが光の速度で世界中のルーターを駆け抜け、あなたの手元にあるAPIサーバーへとたどり着くまでのドラマを想像しながら、日々の監視とデバッグを楽しんでください。あなたのインフラライフが、より堅牢でスムーズなものになることを応援しています!
コメント