- ブラウザURL入力今ここ
- DNS名前→IP今ここ
- ルータ経路選択今ここ
- ロードバランサ振り分け
- Nginx受け口
- アプリ処理今ここ
- DB保存
第2期の最終回です。特定の段を学ぶのではなく、ここまでの全段を「どこで止まっているかを突き止める順序」として並べ直します。地図全体が今回の対象です。
まず結論
「つながらない」という報告は、それ自体では何も特定していません。第14週から積み上げてきた層は、ここで「どの段まで生きているかを下から順に確かめる」という手順に変わります。
そして観測には、観測器ごとの見える範囲があります。tcpdump はホストと網の境界を、strace はプロセスとカーネルの境界を記録します。どちらも「境界を通るものを全件書き出す」道具で、境界の外側で起きたことは原理的に映りません。
traceroute の出力の途中に `* * *` という行が並んでいました。ここから確実に言えることはどれでしょうか。
当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。
「つながりません」は、何も言っていない
第2期の最終回です。新しい層は出てきません。ここまで積み上げた層を、実務の手順に組み直します。
現場で最も多く聞く報告は「つながりません」です。この一文は、状況の説明としては何も特定していません。名前が引けていないのか、相手まで届いていないのか、届いたが拒否されたのか、届いて受理されたがアプリが応答を返していないのか。どれでも同じ見え方をします。
ここで層が効いてきます。層とは第14週で見たとおり入れ子の一段一段でした。入れ子であるということは、内側の段は外側の段が生きていなければ絶対に成立しないということです。逆向きに読めば、下から順に確かめていけば、生きている範囲と死んでいる範囲の境目が必ずどこかに1つ見つかります。
- ・下の段が死んでいれば、上の段は必ず失敗する
- ・だから下から潰すと、一段ごとに原因の範囲が狭まる
DNSだけは順序が特殊です。 名前解決は特定の段の中の仕事ではなく、通信を始める前段で全体に効きます。名前が間違って引けていれば、そもそも見当違いの相手に対して以降の全段が正常に動いてしまう——つまりすべてが正常に見えるのに目的を達しないという、最もたちの悪い形になります。だから先に確認します。
段ごとに、何を打つか
型として並べると次のようになります。コマンドを覚えることが目的ではなく、各段で何を問うているかが要点です。
段 何を問うているか 代表的なコマンドDNS(先に) 名前は正しく引けているか digリンク層 隣の機器と話せているか ip link / ip neighIP層 相手のホストまで届くか ping / tracerouteトランスポート層 そのポートは開いているか ss -tan / nc -vzアプリ層 アプリは応答を返すか curl -v
これらは第15週から第25週で扱ってきた段そのものです。学んだ順序が、そのまま確かめる順序になっています。
ただし、ここに落とし穴があります。各段の「確かめる」コマンドは、期待した答えを返さないことがあり、しかもそれが異常とは限らないのです。
「ping が返ってこない」という事実から、宛先ホストが停止していると結論できますか。
沈黙は、故障の証拠ではない
最もよくある誤読が「ping が通らない = 故障」です。
ping が確かめているのは「相手が生きているか」ではありません。「相手が ICMP Echo に応答を返してくれるか」です。応答を返さない方針の機器は珍しくないので、沈黙から到達不能を結論することはできません。
同じことが traceroute にも起きます。traceroute は TTL を1ずつ増やしながらパケットを送り、TTL を使い切った機器が送り返す ICMP Time Exceeded(Type 11) を手がかりに、経路上の機器を手前から順に明らかにします。ここで、Time Exceeded を返さない方針の機器に当たると、その行は * になります。
もう一点、traceroute については用語の誤りが広く流通しています。「traceroute は ICMP を使う」は無条件には正しくありません。
環境 既定で送るものLinux traceroute UDP(ポート33434から1ずつ増やす)macOS/BSD traceroute UDP(同上)Windows tracert ICMP Echo Request─────────────────────────────────────────────Linux は -I で ICMP、-T で TCP に切り替わる
返ってくる Time Exceeded が ICMP であることと、送る側が何を使うかは別の話です。ここが混ざると「ICMP を止めているのに traceroute が動く/動かない」の理由が説明できなくなります。なお「Linux は UDP 固定」と覚えるのも誤りで、オプションで変わります。
tcpdump — ホストと網の境界
自分のホストとネットワークの間を通るパケットを記録します。アプリが何のライブラリを使っていようと、暗号化していようと、線に出る以上は境界を通るので記録されます。逆に、別のインタフェースから出ていった通信や、そもそもホストの外に出なかった通信は映りません。
境界の内側 自分のホスト(アプリもカーネルも含む)境界そのもの ネットワークインタフェース ← ここを記録境界の外側 網の先で起きること────────────────────────────────────────映らない例 別インタフェース経由 / フィルタ式に外れた通信
strace — プロセスとカーネルの境界(第13週)
第13週で見たとおり、プロセスがカーネルに出す依頼を記録します。アプリが何の言語で書かれていようと、ファイルを読むならカーネルに頼むしかないので記録されます。逆に、カーネルに入らない処理は映りません。vDSO 経由の呼び出しが strace に出ないのは、この境界を越えていないからでした。
境界の内側 プロセス(ユーザーモード)境界そのもの システムコール ← ここを記録境界の外側 カーネルの内部で起きること────────────────────────────────────────映らない例 vDSO経由の呼び出し(カーネルに入らない)
tcpdump と strace。見ているものはまったく違いますが、道具としての性格は同型です。共通する構造は何でしょうか。そして、その構造から必ず生じる限界は何でしょうか。
「何を全件記録できるのか」と「何が原理的に記録できないのか」を、それぞれについて言葉にしてから比べてください。
tcpdump に目的の通信が1行も出てきませんでした。「パケットが送られていない」と断定できますか。
同じ語が、別のものを指している
切り分けの最中に用語を取り違えると、確かめたつもりの事実が事実でなくなります。第2期で何度も出てきた主題が、最後にもう一度現れます。
IPの TTL と DNSの TTL は、同じ略語ですが働きが違います。
IPヘッダの TTL DNSレコードの TTL実質の単位 ホップ数(規格上は秒) 秒数減るきっかけ ルータを1つ越えるごと 時間の経過0になると パケットが捨てられ、 キャッシュを捨ててTime Exceeded が返る 引き直す
どちらも Time To Live の略で「寿命」という発想は共通していますが、片方の感覚でもう片方を読むと必ず誤ります。 「TTL が 300 なので5分でルータを越えられなくなる」といった説明が出てきたら、2つが混ざっています。
用語が一致していることと、意味が一致していることは別だ——第14週で RFC 1122 の層名について見たこと、第25週で DNS の語彙について見たことと、同じ構造です。
第2期が残したもの
第14週で「層とは入れ子の一段のこと」から始め、下から順に一段ずつ登ってきました。最後にそれが、不具合を切り分ける手順という形に変わりました。
- ・各段には「何を問うているか」が対応している
- ・観測器には見える範囲がある。範囲の外は「無い」ではなく「分からない」
第2期を通して繰り返してきた問い返しは、一貫して同じものでした。「それはどの文書に、どう書かれているか」、そして**「その観測器は、何を見ていて、何を見ていないか」**。
* * * を経路断と読むのも、空のキャプチャを「通信していない証拠」と読むのも、straceに出ないことを「呼ばれていない証拠」と読むのも、すべて同じ誤りの形をしています。観測されなかったものを、存在しなかったことにしているのです。
この章のまとめ
- 「つながらない」は何も特定していない。層は原因の範囲を下から順に狭めるための区切りとして使う。
- 順序は 名前解決(DNS)を先に → リンク層
ip link/ip neigh→ IP層ping/traceroute→ トランスポート層ss -tan/nc -vz→ アプリ層curl -v。DNSは層の外側で全体に効く。 pingが通らない = 故障ではない。 応答を返さない方針の機器がある。- traceroute の途中の
* * *は経路断ではない。 Microsoft 公式が「一部のルータは Time Exceeded を返さず invisible」と明記し、公式の出力例でも14〜16ホップ目が*のまま17ホップ目で到達している。 - ICMP Time Exceeded は Type 11(Type 3 は Destination Unreachable)。
- 「traceroute は ICMP」は無条件には誤り。 Linux/BSD の既定は UDP(33434から)、Windows tracert は ICMP Echo。Linux も
-I/-Tで変わるので「UDP固定」も誤り。 - tcpdump と strace は同型の観測器。前者はホスト/網の境界、後者はプロセス/カーネルの境界を全件記録する。どちらも境界の外は原理的に映らないので、出力が空でも「起きていない」の証明にはならない。
- IPの TTL は実質ホップ数の上限(規格上の単位は秒)、DNSの TTL は秒数。 同じ略語でも働きが違う。
- tcpdump の出力例は暗記しない。版やプロトコルで変わるので、自分の環境で1行取り、その環境の man ページと突き合わせる。
自分の現場で確かめる
読んだだけでは身につきません。手元の環境で実際に見てみてください。
理解度チェック
読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。
「traceroute は ICMP を使って経路を調べるコマンドである」——この説明の評価として最も適切なのはどれですか。
用語集(6語)
- TTL (IPヘッダ)
- パケットが通過してよいルータの残り数。ルータを1つ越えるごとに1減り、0になったパケットは捨てられ、捨てたルータが ICMP Time Exceeded を送り返す。規格上の単位は秒だが(RFC 791)、ルータは必ず1以上減らすので実質はホップ数の上限として働く(RFC 1812 §5.3.1)。
- TTL (DNSレコード)
- そのレコードをキャッシュに保持してよい秒数。IPの TTL と同じ略語だが単位も意味も異なる。
- ICMP Time Exceeded
- TTL を使い切ったパケットを捨てたことを送信元へ知らせる ICMP メッセージ。Type 11(Code 0 が transit 中の TTL 超過)。Type 3 の Destination Unreachable とは別のメッセージ。
- traceroute / tracert
- TTL を1ずつ増やしながら送り、返ってくる Time Exceeded で経路上の機器を手前から明らかにするツール。Linux/BSD の traceroute は既定で UDP(ポート33434から)、Windows の tracert は ICMP Echo を使う。Linux でも -I で ICMP、-T で TCP に変えられる。
- tcpdump
- 観測しているインタフェースを通過するパケットを記録するツール。ホストと網の境界を通るものを全件書き出すが、記録できるのはそのインタフェースを通ったものに限られる。
- 切り分け
- 不具合の原因がありうる範囲を、確かめられる事実によって段階的に狭めていく作業。層はその区切りとして使える。
出典(一次ソース)
- RFC 792 — ICMP(Time Exceeded は Type 11) ↗
- tracert — Microsoft 公式ドキュメント(応答しないルータと `*` の説明) ↗
- traceroute(8) — Linux man-page(既定のUDP・ポート33434) ↗
- tcpdump(1) — man-page(出力形式は各自の環境の版で確認する) ↗
- strace(1) — Linux man-page ↗
- RFC 791 — Internet Protocol(TTL: The time is measured in units of seconds) ↗
- RFC 1812 §5.3.1 — Time to Live(effectively a hop count limit) ↗