Old-School Networking / 2026 ・ No.12

いにしえのネットワーク入門

第12回(最終回) つながらない時の切り分け ── 下の層から、1段ずつ

公開

Wireshark の画面。PC の口で記録した ARP が 7 個並ぶ。1・2番はリゾルバー 198.51.100.53 の問い合わせと答え。3・4・5番は Who has 203.0.113.20? Tell 192.168.1.10 が 0.0003 秒、1.006 秒、2.029 秒と3回続き、答えはない。5番が選ばれ、明細の Address Resolution Protocol (request) に Target MAC address: 00:00:00:00:00:00、Target IP address: 203.0.113.20
申請サーバーの機械がいなくなったときの PC の口。「203.0.113.20 はだれ?」と3回尋ねても返事がなく、curl は 3.05 秒であきらめました。エラーの文面は「つながらない」だけでも、記録を見れば第2層で止まっているとわかります(筆者がクラウド上に作った練習用ネットワークで、2026年10月25日に記録したものを Wireshark 4.2.2 で開いて撮影。画面は英語のまま。ウインドウの上の帯と見出しは説明のために描き足したもの)

「申請ボタンを押しても、何も起きません」。最終回は、この一言から始まる調べ物です。
第9・10回の練習用ネットワークを、ケーブル、道、相手の機械、名前、番号、鍵、中身と、わざと1か所ずつ壊しました。そのたびに出たエラーの文面と、どの道具で、どの層で止まっているかを突き止める手順を、下の層から順に確かめます。

一

「何も起きません」

新井先輩、経理から電話です。「申請ボタンを押しても何も起きない」って。サーバーが落ちたんでしょうか。

古井落ちたかもしれないし、ケーブルが抜けたのかもしれないし、名前が引けないのかもしれない。いきなり答えに飛ぶな。

新井じゃあ、どこから?

古井下からだ。11回かけて作った地図を、指でなぞる。

全12回の路線図(いまここ:第12回)

1 全体図 2 物理層 3 データリンク層 4 IP アドレス 5 ルーター 6 TCP 7 UDP・ソケット 8 TLS 9 DNS 10 HTTP 11 開発者の網 12 切り分け いまここ 全体図 第1層 第2層 第3層 第4層 第5・6層 第7層 実践
  • 切り分けのはしご ── 層ごとに1つの質問と1つの道具。下から順に
  • 7通りに壊す ── ケーブル、道、相手の機械、名前、番号、鍵、nginx の向こう。そのたびの文面と時間(実測)
  • 断られたか、捨てられたか ── 0.041 秒の RST と、10 秒の時間切れ(実測と Wireshark)
  • 遅いとき ── curl で時間を名前・TCP・TLS・サーバーに分ける(実測)

練習用ネットワークは第9・10回と同じです。PC とプロバイダのリゾルバーが線の手前、DNS サーバーと申請サーバーが片道 20 ミリ秒のいたずら線の向こう。今回は申請サーバーの手前に nginx(80 番)も置きました。毎回1か所だけを壊し、記録を取ったら元に戻します。

二

切り分けのはしご

切り分けの第一歩は、第11回と同じく、どこから、どこの、何番へ送っているのかを1行で書くことです。今回なら「PC から、expenses.example の 3443 番へ、HTTPS で」。そのうえで、層ごとに1つずつ質問していきます。

層ごとに、1つの質問と1つの道具

層 確かめること 道具 中身(HTTP) 返事のステータスと、だれが返したか curl -v 鍵(TLS) 証明書は確かめられたか openssl s_client 番号(TCP) 断られたか、捨てられたか nc -vz 名前(DNS) 名前は住所に変わったか dig 住所と道(IP) 道はあるか、隣は答えるか ip route / ip neigh 線と口 口はつながっているか ip link 下から順に1段ずつ。通った段より下は、もう疑わなくてよい エラーの文面は、いちばん上の段で起きたことしか言わない(第3章)

はしごは下からのぼります。上の段は下の段の上に乗っているので、口がつながっていなければ名前は引けず、名前が引けなければ TCP は始まらず、TCP がなければ TLS も HTTP もありません。逆に、ある段が通れば、それより下は全部動いている証拠です。もう疑わなくてかまいません。

三

エラーの文面にだまされない

まず、ケーブルを抜きました(練習では、線の向こう側の口を落としました)。

# ケーブルを抜いた(線の向こう側の口を落とした)
pc$ curl https://expenses.example:3443/api/expenses
    curl: (6) Could not resolve host: expenses.example   (6.025 s)
# まず自分の口を見る
pc$ ip -br link show eth0
    eth0   DOWN   <NO-CARRIER,BROADCAST,MULTICAST,UP>
pc$ ping -c2 198.51.100.53
    2 packets transmitted, 0 received, 100% packet loss

curl の文面は「Could not resolve host」、名前が引けない、でした。6.02 秒待たされたあとです。でも DNS は何も壊れていません。curl が最初にしようとしたのが名前引きで、そこで止まったので、そう書いただけです。エラーの文面は、いちばん上で起きたことしか言いません。はしごを下から見れば、ip link の NO-CARRIER(向こうに相手がいない)で一目瞭然です。

POINT

「DNS が悪い」と言う前に、自分の口と、リゾルバーまでの ping を見ます。Wi-Fi のつかみそこね、ケーブルの抜け、VPN の切れ目は、名前引きの失敗として現れることがよくあります。

四

住所と道

次は第3層です。まず、203.0.113.0/24 への道(経路)を消しました。

# 203.0.113.0/24 への道(経路)を消した
pc$ curl -v https://expenses.example:3443/api/expenses
    *   Trying 203.0.113.20:3443...
    * Immediate connect fail for 203.0.113.20: Network is unreachable
    curl: (7) Failed to connect … after 0 ms: Couldn't connect to server
pc$ ip route get 203.0.113.20
    RTNETLINK answers: Network is unreachable

道がなければ、パケットは PC から出ることすらできません。0 ミリ秒で「Network is unreachable」。ip route get で、その住所への道があるかを直接たずねられます。

今度は道はあるが、相手の機械がいない場合です。申請サーバーの住所 203.0.113.20 を外しました。

# 相手の機械がいない(203.0.113.20 を外した)
pc$ curl https://expenses.example:3443/api/expenses
    curl: (7) Failed to connect … after 3053 ms: Couldn't connect to server
# 隣の住所(MAC)が引けたか
pc$ ip neigh show 203.0.113.20
    203.0.113.20 dev eth0 FAILED
pc$ ping -c3 203.0.113.20
    3 packets transmitted, 0 received, 100% packet loss

curl は 3.05 秒待って「つながらない」。表紙の写真が、そのときの PC の口です。第3回の ARP で「203.0.113.20 はだれ?」と3回尋ね、返事がないまま終わっています。ip neigh の FAILED は「隣の宛名(MAC)が引けなかった」という記録で、相手の機械が止まっているか、住所の設定が違うかを疑います。

五

名前

名前の段は、2通りに壊しました。リゾルバーを止めたときと、名前を打ち間違えたときです。

# ① リゾルバーが止まった
pc$ curl https://expenses.example:3443/api/expenses
    curl: (6) Could not resolve host: expenses.example
pc$ dig expenses.example
    ;; communications error to 198.51.100.53#53: connection refused
# ② 名前の打ち間違い(exmaple)
pc$ curl https://expenses.exmaple:3443/api/expenses
    curl: (6) Could not resolve host: expenses.exmaple
pc$ dig expenses.exmaple
    ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN
# 正しい名前なら
pc$ dig +short expenses.example
    203.0.113.20

curl の文面は、どちらも「Could not resolve host」で区別がつきません。dig なら違いがはっきりします。リゾルバーが止まったときは「communications error」(そもそも答えをもらえない)、打ち間違いは status: NXDOMAIN(ちゃんと答えをもらえて、その答えが「そんな名前はない」)。前者は第3層までかリゾルバーの問題、後者は名前そのものの問題です。

POINT

第9回のとおり、dig は hosts を見ません。アプリだけ様子がおかしいときは getent hosts(Mac なら dscacheutil)でも引いて、hosts の書き置きを疑います。

六

番号:断られたか、捨てられたか

第4層でいちばん大事なのは、断られたのか、捨てられたのかの区別です。サーバーのプログラムを止めたときと、相手の防火壁に黙って捨てさせたときを比べました。

# ① サーバーのプログラムが止まった(その番号で待つ者がいない)
pc$ curl https://expenses.example:3443/api/expenses
    curl: (7) Failed to connect … after 41 ms: Couldn't connect to server
pc$ nc -vz expenses.example 3443
    … port 3443 (tcp) failed: Connection refused
srv$ ss -ltn 'sport = :3443'
    (なし)
# ② 相手の防火壁が、黙って捨てる(DROP)
pc$ curl --connect-timeout 10 https://expenses.example:3443/api/expenses
    curl: (28) Failed to connect … after 10002 ms: Timeout was reached
pc$ nc -vz -w 3 expenses.example 3443
    … port 3443 (tcp) timed out: Operation now in progress

即答の RST と、返事のない SYN

断られる PC サーバー 捨てられる PC サーバー SYN RST 0.041 s 相手まで届いている。 Connection refused 防火壁 0.0 × 1.0 × 2.0 × 3.1 × 4.1 × 5.1 × 7.1 × Timeout 10 s 即答の「断られた」は相手まで届いた証拠。待たされての「時間切れ」は途中で消えている
Wireshark のパケット一覧を2つ縦に並べたもの。上は、PC から 203.0.113.20 の 3443 番への SYN に、0.040679 秒で RST, ACK が返っている。下は、SYN を 0、1.01、2.03、3.06、4.08、5.11、7.12 秒と送り直していて、返事はひとつもない
上はサーバーのプログラムを止めたとき、下は相手の防火壁が黙って捨てるとき。同じ「つながらない」でも、上は相手まで届いて断られ、下は途中で消えています(筆者がクラウド上に作った練習用ネットワークで、2026年10月25日に記録したものを Wireshark 4.2.2 で開いて撮影。画面は英語のまま。ウインドウの上の帯と見出しは説明のために描き足したもの)

プログラムが止まっていると、相手の OS が「その番号ではだれも待っていない」と RST で即答します。0.041 秒は、いたずら線のちょうど1往復です。相手の機械までは届いているので、見るべきは相手側でプログラムが動いているか(ss -ltn)、番号が合っているかです。

防火壁が捨てると、何も返ってきません。PC は第6回で見たとおり SYN を送り直し、curl は 10 秒で時間切れ。こちらは途中のどこかで消えているので、防火壁、セキュリティグループ、途中の道を疑います。

七

鍵

TCP がつながっても、TLS の段で止まることがあります。練習用の CA を curl に教えずに、HTTPS で送りました。

# 練習用の CA を知らないまま HTTPS で
pc$ curl https://expenses.example:3443/api/expenses
    curl: (60) SSL certificate problem: unable to get local issuer certificate
# 相手が見せた証明書を、openssl で直接見る
pc$ openssl s_client -connect expenses.example:3443 -servername expenses.example
    subject=CN = expenses.example
    issuer=CN = Kiji Practice Root CA
    Verify return code: 21 (unable to verify the first certificate)
# CA を教えれば
pc$ openssl s_client … -CAfile ca.pem
    Verify return code: 0 (ok)

openssl s_client は、相手が見せた証明書を直接のぞく道具です。「だれの証明書か(subject)」「だれが発行したか(issuer)」と、確かめの結果(Verify return code)が見えます。CA を教えれば 0(ok)。第8回の4つの場面(発行元を知らない、名前が違う、期限切れ、自己署名)のどれかを、ここで見分けます。直し方は、正しい CA を教えるか、証明書を直すこと。-k で確かめを切るのは、直したことになりません。

八

中身:だれが返した 5xx か

最後の段は HTTP です。申請サーバーの手前に nginx を置き、その向こうを2通りに壊しました。新しい版(/v2/)のアプリを起動し忘れたときと、アプリが遅すぎるときです。

# 申請サーバーの手前に nginx(80 番)。/v2/ の先(4000 番)は起動し忘れ
pc$ curl http://expenses.example/api/expenses
    → 200  (0.089 s)
pc$ curl http://expenses.example/v2/api/expenses
    → 502 Bad Gateway  (0.083 s)
pc$ curl 'http://expenses.example/api/report?ms=3000&n=1'
    → 504 Gateway Time-out  (2.085 s)
# nginx の記録(error.log、一部)
    connect() failed (111: Connection refused) while connecting to upstream,
      upstream: "http://127.0.0.1:4000/api/expenses"
    upstream timed out (110: Connection timed out) while reading response header
      from upstream, upstream: "http://127.0.0.1:3000/api/report?ms=3000&n=1"

5xx を返したのは手前の nginx。悪いのはその裏

PC nginx :80 アプリ 127.0.0.1:3000 v2(起動し忘れ) 127.0.0.1:4000 3 秒かかる × 502 / 504 5xx を返したのは、PC の目の前の nginx。悪いのはその裏 502=裏につながらない、504=裏が時間内に答えない 原因は nginx の error.log に、裏の住所つきで書いてある
Wireshark の画面。表示フィルター http で6つに絞った一覧。4番 GET /api/expenses に6番 200 OK、14番 GET /v2/api/expenses に16番 HTTP/1.1 502 Bad Gateway、24番 GET /api/report?ms=3000&n=1 に26番 HTTP/1.1 504 Gateway Time-out(2.28 秒)。16番の明細に Server: nginx/1.24.0 (Ubuntu)、Content-Length: 166
nginx の向こうが動いていないときの返事。502 を返したのは、Server ヘッダーのとおり nginx です。アプリが返したのではありません(筆者がクラウド上に作った練習用ネットワークで、2026年10月25日に記録したものを Wireshark 4.2.2 で開いて撮影。画面は英語のまま。ウインドウの上の帯と見出しは説明のために描き足したもの)

返事が来た、ということは、下の5段はすべて通っています。見るべきはだれが返したかです。502 と 504 は、どちらも PC の目の前の nginx が返しました(写真の Server: nginx)。502 は「裏につなごうとしたら断られた」、504 は「裏が 2 秒以内に答えなかった」。原因は nginx の error.log に、裏の住所つきで書いてあります。4xx なら頼み方(第10回)、5xx ならサーバー側、そのうち 502・504 なら「サーバーの、さらに裏」です。

九

遅いとき

「つながらない」の親戚が「遅い」です。遅いときは、時間を段ごとに分けます。curl の -w は、名前引き・TCP・TLS・最初の1バイトが届くまでの時刻を、始まりから数えて教えてくれます。

# 300 ミリ秒かかる報告を、リゾルバーの記憶を消してから2回(curl -w で時間を分解)
pc$ curl -w 'dns %{time_namelookup} tcp %{time_connect} tls %{time_appconnect}
        first-byte %{time_starttransfer} total %{time_total}\n' …
    1回目    dns 0.166  tcp 0.206  tls 0.252  first-byte 0.595  total 0.595
    2回目    dns 0.002  tcp 0.043  tls 0.090  first-byte 0.434  total 0.434

0.595 秒の内訳(実測)

1回目 0.166 0.344 0.595 s 2回目 0.345 0.434 s 名前(DNS) TCP の握手 TLS の握手 サーバーの処理 どこで時間を使ったかがわかれば、見る層が決まる ここでは毎回約 0.34 秒がサーバー側。1回目だけ名前引きに 0.166 秒

差を取ると、1回目は名前 0.166 秒、TCP の握手 0.041 秒、TLS の握手 0.045 秒、サーバーの処理と返事 0.344 秒。2回目は名前が 0.002 秒に縮みました(第9回のキャッシュ)。どちらも、いちばん長いのはサーバー側の約 0.34 秒(300 ミリ秒の処理+1往復)で、ネットワークのせいではありません。「ネットワークが遅い」と言う前に、まずこの分解を見ます。

十

早見表と、自分の PC で

この連載で実際に出会ったエラーの文面と、最初に疑う段の早見表です。

文面(例)まず疑う段最初の一手
Could not resolve host名前。ただし、その下もip link と dig
Network is unreachable道(経路がない)ip route get 住所
数秒待ってつながらない(ARP に答えなし)相手の機械、住所の設定ip neigh
Connection refused番号(届いたが、だれも待っていない)相手で ss -ltn
Timeout was reached途中で捨てられている防火壁、nc -vz
SSL certificate problem鍵(第8回の4場面)openssl s_client
502 / 504手前のサーバーの、さらに裏手前の error.log
CORS のエラーブラウザの番人(第10・11回)API の返すヘッダー
ECONNREFUSED 127.0.0.1localhost の取り違え(第11回)どこから送っているか

はしごの道具は、OS ごとに名前が少し違います。

段MacWindowsLinux
線と口ifconfigipconfig /allip -br link
道netstat -rnroute printip route get 住所
隣arp -aarp -aip neigh
名前dig 名前Resolve-DnsName 名前dig 名前
番号nc -vz 名前 番号Test-NetConnection 名前 -Port 番号nc -vz 名前 番号
鍵・中身curl -v https://名前/

結 — 全12回の一枚まとめ

申請ボタンの1回の通信を、下から上までたどった12回

12 切り分け 下から順に、1段ずつ 11 開発者の PC localhost、Docker、プロキシ 10 HTTP 申請の中身。ステータスとヘッダー 9 DNS 名前から住所を引く 8 TLS(第5・6層) 鍵をかけ、相手を確かめる 6・7 TCP・UDP 番号で届け分け、送り直す 4・5 IP・ルーター 住所と、道の選び方 2・3 物理・データリンク 電気と電波、隣どうしの宛名 申請は下から上へ 第1回の全体図に、11回分の中身が入った
  1. まず1行で書く。どこから、どこの、何番へ。
  2. はしごは下から。通った段より下は疑わない。
  3. エラーの文面は、いちばん上で起きたことしか言わない。ケーブルが抜けても「Could not resolve host」。
  4. 断られた(すぐ)は相手まで届いた証拠、時間切れ(待たされる)は途中で消えた証拠。
  5. 名前は dig で。止まったリゾルバーと NXDOMAIN を分ける。
  6. 鍵は openssl s_client で。確かめを切らずに直す。
  7. 5xx はだれが返したかを見る。遅いときは時間を段ごとに分ける。

新井経理さんの件、ip link から順に見たら、無線の切りかえで線が切れていました。サーバーは元気でした。

古井上出来だ。12回分の地図があれば、どこで止まっても迷子にならない。

新井次は、この申請を受け取るサーバーの中を知りたいです。

古井いいね。網の旅はここまで。続きは、サーバーの中でやろう。

参考

記録は、筆者がクラウド上の Linux(Ubuntu 24.04、カーネル 6.18)にネットワーク名前空間で作った練習用ネットワークで、2026年10月25日に取ったものです。構成は第9・10回と同じ(リゾルバー Unbound 1.19.2、DNS サーバー NSD 4.8.0、申請サーバー Node.js 22.23)で、申請サーバーの手前に nginx 1.24.0 を置き、PC 側は curl 8.5.0、OpenSSL 3.0 です。名前と住所はすべて説明用に予約されたもの、または練習用に作ったものです。PC とサーバーの間は、第6回のいたずら線(片道 20 ミリ秒)です。表の数字や出力はすべて、この記録とそのときのコマンドの出力から読んだ実際の値です(長い出力は一部を省いています)。登場人物は架空の人物です。全12回を読んでくださって、ありがとうございました。

いにしえのネットワーク入門 第12回 — つながらない時の切り分け / 2026.10

← 記事一覧へ