前の話で、ping の応答に3つの顔があることを腹に置いた。タイムアウトは沈黙、unreachable は拒否の声、部分応答は一部だけ返事。壊れている層が違うので、次に確認する場所も変わる。
けれど、タイムアウト(沈黙)を見たとき、何も返ってこないことだけはわかるが、その沈黙が経路のどこで起きているのか、ping だけでは特定できない。unreachable のときは応答に「From 」の出所がヒントとして付いてくる。部分応答のときは「N 件中 M 件成功」というロス率が手がかりになる。だが、沈黙のときは、沈黙以外に何も来ない。
途中の経路を、送信側からどう見にいけばいいのか。
L3 の規格に最初から組み込まれていた仕組みの中に手がかりがある。教科書では「無限ループ防止のためにある」と教わってきたカウンタ — TTL だ。各ホップで 1 ずつ減り、0 になったら廃棄される。
考えてみよう: TTL という名前は、L3 を学ぶときに必ず出てくる。「各ホップで 1 ずつ減って、0 になったら廃棄される」「無限ループ防止のため」 — そう習った。それでは聞きたい。0 になって廃棄されるとき、ルータは黙ってパケットを捨てているのだろうか。それとも、何かをしているだろうか。30秒だけ、自分で考えてみてほしい。もし誰かに何かを伝えているとしたら、それを使って、何が見えてきそうか。
tcpdump や運用ログで「ICMP time-to-live exceeded」「TTL exceeded」というメッセージを見たことがあるかもしれない。あのメッセージは、いつ、誰が出しているのだろうか。規格上、廃棄したルータが送信元へ何かを能動的に返しているのだとしたら — それを集めると、経路について何が見えてきそうか。
TTL は本来「無限ループ防止の安全装置」。だが、廃棄するとき、ルータは規格に従って送信元へ「時間切れの通知」を返している。これを逆手に取って、TTL を 1, 2, 3 ... と段階的に小さくしていけば、各ホップが順に名乗ってくれる。安全装置の副産物が、経路を測る道具に化ける発想の転換 — 応答が「廃棄通知」から「道しるべ」に変わる。


TTL という安全装置 — 各ホップで 1 ずつ減る、無限ループ防止のカウンタ
L3 を学んだとき、必ず出てくる名前がある。TTL — Time To Live。直訳すると「生存時間」だが、規格上の挙動は時間ではない。各ホップを通るたびに 1 ずつ減るカウンタ、つまり「ホップ数の上限」だ。送信側がパケットを送り出すとき、IP ヘッダにはあらかじめ初期値が入っている。値そのものは OS や送信種別で異なるが、ここで扱う粒度では具体的な数値の暗記は不要だ。「初期値があり、ある程度の余裕を持って始まる」 — それだけでよい。
そのパケットを受け取ったルータは、自分のルーティング処理で TTL の値を 1 デクリメントする。これが規格上の義務として定められている。次のルータも同じ。各ホップで TTL は 1 ずつ減っていく。経路が正常で、宛先がそれほど遠くなければ、TTL は正の値で残ったまま、最終的に宛先までパケットが届く。
問題は、経路がループしているときに起きる。
何かの異常で、ルーティングテーブルがループする経路を作ってしまった場合、パケットは行き先に着けない。同じ経路をぐるぐる回り続ける。ループは、ルーティングプロトコルの収束が遅れたり、設定の不整合があったりすると、現実に起こる。
何もブレーキがなければ、ループしたパケットは永遠に回り続け、回線とルータの処理を食い潰す。1つや2つのループならまだしも、これが何百、何千と並列に起きると、ネットワーク全体が立ち往生してしまう。
それを止めるための安全装置が、TTL だ。
各ホップで 1 ずつ減るカウンタが、ループを N 周しても必ずどこかで 0 になる。0 になったパケットは、規格に従ってその場で廃棄される。永遠の循環を断ち切る仕組みが、L3 の規格にあらかじめ組み込まれている。
「時間で消えるタイマー」ではなく「ホップ数の上限カウンタ」。「迷子になったパケットの自然消滅装置」ではなく「ルーティングループに対するハードブレーキ」。地味だが、L3 がスケールする上で、なくてはならない仕組みだ。
0 になったとき何が起きるか — ルータは黙って捨てているわけではない
TTL が 0 になって廃棄されるとき、ルータは黙ってパケットを捨てているのだろうか。それとも、何かをしているのだろうか。
L3 の規格を見ると、答えは「何かをしている」だ。ルータは TTL を 0 まで減らしてパケットを廃棄するとき、ICMP の規格に従って、送信元へ「時間切れの通知」というメッセージを能動的に返す。これは Time Exceeded(時間切れの通知)と呼ばれる、ICMP の応答メッセージの1つだ。
前話で出てきた Echo Reply(行きの依頼書への返事)や Destination Unreachable(届かないという拒否の声)とは別タイプの、規格上独立した応答メッセージとして定義されている。タイムアウトの「沈黙」とも、unreachable の「拒否の声」とも違う、第3の応答だ。
この応答は規格上の「義務」として定められている。最初は ICMP の原典で「廃棄したルータは送信元へ通知してもよい(may)」と書かれていたが、その後、ルータの規格として強化され、現在は「TTL=0 で廃棄したときには、送信元へ時間切れの通知を送らなければならない(MUST)」と定められている。
ルータベンダーの実装は、この義務に従って動いている。主要なルーティング実装でも、TTL=0 廃棄時に時間切れの通知を返す動作はデフォルトで広く見られる。設定でこの動作を絞ることもできるが、デフォルトでは規格に従って能動的に応答するのが一般的だ。
時間切れの通知を返したパケットの送信元 IP は、それを生成したルータ自身。Echo Reply のときも、Destination Unreachable のときも、応答の送信元 IP は応答を生成した機器自身だった。同じ規格上のルールが、ここでも貫かれている。
送信元から見ると、時間切れの通知を受け取ったとき、その応答の送信元 IP は「廃棄したルータがそこにいる」という情報になる。黙って捨てているわけではない。廃棄しつつ、規格に従って「私はここにいて、TTL が 0 になったのでこのパケットを捨てました」と能動的に通知している状態だ。


TTL を段階的に切らせて各ホップを順に名乗らせる — 安全装置の副産物が経路測定の手立てに化ける
普通に使う限り、TTL は安全装置として機能するだけだ。経路がループしたときに、パケットが永遠に回り続けるのを止める。送信側からすれば、稀に時間切れの通知が返ってくるが、それは「自分のパケットがどこかでループに巻き込まれて廃棄された」という事故の通知として読まれる。
TTL を意図的に 1 に設定して送ると、最初のルータは受け取ったパケットの TTL を 1 デクリメントして 0 にする。0 になったので規格に従って廃棄し、送信元へ時間切れの通知を返す。応答の送信元 IP は廃棄したルータ自身 — 送信元には最初のホップのルータの IP が返ってくる。
TTL=2 で送ると、最初のルータは TTL を 1 デクリメントして 1 にする。0 ではないので転送する。次のルータは TTL を 1 デクリメントして 0 にする。0 になったので廃棄し、送信元へ時間切れの通知を返す。送信元には 2 番目のホップのルータの IP が返ってくる。
TTL=3 で送れば 3 番目のルータが廃棄して名乗る。TTL=4 なら 4 番目。順に繰り返せば、経路上の各ホップが順に名乗ってくれる。


安全装置が動いた瞬間に「廃棄したルータが送信元へ通知する」という規格上のルールがあらかじめ組み込まれていた。本来の目的とは別の、規格化された応答メカニズムだ。TTL を 1 で送れば最初のホップが名乗る。2 で送れば 2 番目が名乗る。順に繰り返せば、経路の各ホップの IP が並んで返ってくる。
これまで、tcpdump や運用ログで「ICMP time-to-live exceeded」「TTL exceeded」を見ても、廃棄された痕跡としてしか読めなかったかもしれない。同じメッセージは、規格に従って能動的に返された応答であり、応答の送信元 IP は応答を返したルータ自身。「そのルータが、そのとき、そこにいた」という情報だ。沈黙ではなく道しるべとして読める。
TTL という安全装置は、規格を作った人たちがルーティングループを止めるために用意したものだ。規格にはループを終結させると明示されている。TTL=0 廃棄時にルータが送信元へ通知を返す仕組みを能動的に使うと、設計者が想定していなかった用途が、規格にあらかじめ含まれていた応答メカニズムを通じて運用の道具に化ける。本来の目的のために用意した仕組みが、副作用として別の用途に使われる — 設計と運用の境目で、このような転化が起きる。
ping ではできなかったことが、TTL の規格上の応答を逆手に取ると、できるようになる。沈黙の場所を、送信側から測りにいける。TTL=1, 2, 3 と順に送って各ホップの IP を集めれば、経路の長さがわかる。
tcpdump の Time Exceeded は、廃棄通知ではなく各ホップの名乗りとして読める
ping の沈黙だけでは経路のどこで消えたか読めなかった。TTL の廃棄通知を段階的に集める発想で、送信側から各ホップの IP を順に引き出せる。tcpdump や show ログの Time Exceeded も、廃棄の痕跡ではなく各ルータの名乗りとして読める。
ただし、現実は理想通りには進まない。各ホップが毎回同じように名乗ってくれるとは限らない。
次の話では、その差に向き合う。発想を実際に使ったときに、何が起きるのかに踏み込み、観測の最初の目線を仕上げに行く。