「No route to host」の切り分け - ルーティングとファイアウォール

「No route to host」の切り分け - ルーティングとファイアウォール

「No route to host」とは何を示すのか?

結論: 相手ホストまでパケットを届ける経路が確立できない状態。カーネルまたは経路上の機器が「この宛先には到達できない」と判断した結果で、EHOSTUNREACH というエラーが返る。refused と同様に即座に失敗するのが特徴。

No route to host は、宛先までのパスのどこかで「届けられない」と判定されたときに出る。システムコールレベルでは connect()EHOSTUNREACH を返し、アプリはこれを「No route to host」と表示する。

$ ssh user@192.0.2.10
ssh: connect to host 192.0.2.10 port 22: No route to host
$ curl http://192.0.2.10/
curl: (7) Failed to connect to 192.0.2.10 port 80 after 2 ms: No route to host

判定が出る場所は 3 通りある。①自ホストのカーネルが「そもそも経路が無い」と判断する、②同一セグメントで相手が ARP に応答しない、③経路途中のルータやファイアウォールが ICMP host-unreachable / host-prohibited を返す。いずれも応答は数ミリ秒で返るため、無応答の timeout とは挙動が大きく異なる。

前提(対象環境)

  • OS: Ubuntu / 一般的な Linux(ip コマンド = iproute2)
  • 接続先: IP で到達したい任意のホスト
  • ルーティングテーブル・ARP テーブルを sudo 無しで参照できる前提

refused / timeout とどう違うのか?

結論: refused は「届いたがポートで拒否」、timeout は「届いたか不明・無応答」、No route to host は「そもそも届ける経路が無い / 相手に到達できない」。同じ接続失敗でも切り分けの起点がまったく異なる。

接続エラーは大きく 3 種類あり、原因の層が違う。最初にどれなのかを確定させる。

エラー 返ってくるもの 主な原因の層
Connection refused TCP RST(即時) サービス停止 / ポート(L4 アプリ)
Connection timed out 無応答(数十秒待つ) DROP / 経路の沈黙(L3〜L4)
No route to host ICMP unreachable 等(即時) 経路・ARP・REJECT(L2〜L3)
$ time curl -sS http://192.0.2.10/
curl: (7) Failed to connect to 192.0.2.10 port 80 after 2 ms: No route to host

real    0m0.012s

0.0xx 秒で No route to host が返れば、相手ホストの手前の経路で止まっている。サービス停止やポート閉塞なら Connection refused を、無応答で待たされるなら ポート疎通の確認 を参照。本記事は No route to host を扱う。

refused が「ホストは生きているがポートで断られた」なのに対し、No route to host は「ホストまでの道が無い・相手に届かない」。L4(ポート)の問題ではなく、L2〜L3(経路・到達性)の問題である点が決定的に違う。

なぜ No route to host が出るのか?

結論: 原因は「①ローカルの経路欠落 ②同一セグメントの ARP 解決失敗 ③経路途中のルータが ICMP 拒否 ④ファイアウォールの icmp-host-prohibited REJECT」の 4 つに整理できる。近い層(自ホスト)から順に潰すのが速い。

EHOSTUNREACH が返る経路を原因別に並べると次のとおり。

原因 起きやすい状況 確認の起点
ローカル経路が無い デフォルトゲートウェイ未設定 / route 削除 / IF down ip route get
ARP 解決の失敗 同一セグメントの相手が停止 / IP 重複 / L2 不通 ip neigh
経路途中のルータが拒否 ルータが ICMP host/network-unreachable を返す traceroute
ファイアウォールの REJECT reject-with icmp-host-prohibited 等が入っている nft list ruleset

切り分けは 自ホストに近い層から外へ 進める。まず「自分のルーティングテーブルにそもそも経路があるか」を見て、次に「同一セグメントなら相手と L2 で通信できるか」、最後に「経路の途中で拒否されていないか」の順だ。

よく似たエラーに Network is unreachableENETUNREACH)がある。これは宛先ネットワークへの経路が無いケース(デフォルトルートすら無い等)で出やすい。No route to host(EHOSTUNREACH)は「ネットワークへの経路はあるが、その先のホストに届かない」寄りのニュアンス。どちらもローカル経路の確認から始める点は同じ。

ローカルの経路を確認するには?

結論: ip route get <宛先IP> で「カーネルがどの経路・どの出口 IF・どのゲートウェイを使うか」を一発で確認する。ここでエラーが出るなら原因は自ホストのルーティングテーブルに確定する。

まず、カーネルがその宛先へどう送ろうとするかを問い合わせる。

$ ip route get 192.0.2.10

経路が正常なら、出口インターフェースとゲートウェイ(または直結)が表示される。

192.0.2.10 via 10.0.0.1 dev eth0 src 10.0.0.42 uid 1000
    cache

経路が無い場合は、その場でエラーになる。

$ ip route get 192.0.2.10
RTNETLINK answers: Network is unreachable

このときはルーティングテーブルとデフォルトゲートウェイを確認する。

$ ip route
$ ip route show default
default via 10.0.0.1 dev eth0 proto static
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.42

default via ... の行が無ければデフォルトゲートウェイが未設定で、ローカルネットワーク外の宛先はすべて到達不能になる。インターフェース自体が down していないかも併せて確認する。

$ ip -br link
$ ip -br addr
eth0   UP   52:54:00:11:22:33 <BROADCAST,MULTICAST,UP,LOWER_UP>

IF が DOWN なら sudo ip link set eth0 up、IP やゲートウェイの恒久設定は netplan / NetworkManager 等の設定ファイルで行う。

ip route get は実際にパケットを送らずにカーネルの経路選択だけを再現する。宛先がどの IF・どの GW に向かうかを副作用なく確認できるため、切り分けの最初の一手として最適。

同一セグメントの ARP 解決を確認するには?

結論: 宛先が同一サブネット内なら、通信には ARP による MAC 解決が必須。相手が応答しないと近傍テーブルが FAILED になり No route to host が返る。ip neigh で状態を確認する。

ip route get の出力で via <GW> が無く dev eth0 src ...(直結)と出た場合、宛先は同一セグメントにある。このときは ARP(IPv6 では NDP)で相手の MAC を解決できるかが鍵になる。

$ ping -c1 -W1 192.0.2.10
$ ip neigh show 192.0.2.10

相手が応答していれば REACHABLESTALE で MAC が入る。応答が無いと FAILED になる。

192.0.2.10 dev eth0 FAILED

FAILED は「同一セグメントに居るはずだが ARP に誰も答えない」状態。相手ホストの停止、IP の打ち間違い、IP アドレスの重複、スイッチ/VLAN/ケーブルといった L2 の問題を疑う。同セグメントの他ホストとの ARP が通るかを比較すると、自分側か相手側かを切り分けやすい。

$ ip neigh
10.0.0.1 dev eth0 lladdr 52:54:00:aa:bb:cc REACHABLE
192.0.2.10 dev eth0 FAILED

ゲートウェイ(10.0.0.1)が REACHABLE なのに目的の相手だけ FAILED なら、自ホストの L2 は正常で、相手ホストまたはその経路に問題がある。

ARP テーブルは時間で状態が変わる。FAILED を見たら数秒おいて再度 ip neigh を確認するか、ping で能動的に解決を試みてから状態を読むと誤判定を避けられる。

経路途中のルータが原因の場合は?

結論: 別ネットワーク宛で No route to host が出るなら、経路途中のルータが ICMP host/network-unreachable を返している可能性が高い。ping の応答元と traceroute でどのホップで止まるかを特定する。

別サブネット宛でローカル経路もゲートウェイも正常なのに失敗する場合、判定は経路の途中で起きている。ping を打つと、ルータが代理で unreachable を返すことがある。

$ ping -c2 192.0.2.10
From 10.0.0.1 icmp_seq=1 Destination Host Unreachable
From 10.0.0.1 icmp_seq=2 Destination Host Unreachable

応答元(From 10.0.0.1)が宛先ではなくルータになっている点が重要だ。これは「ゲートウェイまでは届いたが、その先で相手に到達できない」ことを示す。どのホップで途切れるかは traceroute / mtr で追う。

$ traceroute -n 192.0.2.10
 1  10.0.0.1   0.4 ms   0.3 ms   0.3 ms
 2  10.0.0.1  !H  *  !H

!H(host unreachable)が出たホップが拒否の発生源。!N ならネットワーク到達不能、!X は管理的に通信禁止(後述のファイアウォール拒否)を表す。ここまで来たら、原因は自ホストではなく経路上の機器・対向側の設定にある。

traceroute の末尾記号は切り分けの近道。!H=ホスト到達不能 / !N=ネットワーク到達不能 / !X!A=管理的に禁止(フィルタ)。!X 系が出たら次のファイアウォールセクションへ進む。

ファイアウォールが原因の場合(icmp-host-prohibited)

結論: ファイアウォールが reject-with icmp-host-prohibited(または icmp-host-unreachable)で拒否すると、クライアントには No route to host が出る。tcp-reset なら refused になるため、REJECT の種別が症状を決める。

REJECT は「何を返して拒否するか」を選べる。返す ICMP の種類で、クライアント側の表示が変わる。

REJECT の種別 クライアントに出る症状
icmp-host-prohibited No route to host
icmp-host-unreachable No route to host
icmp-net-unreachable Network is unreachable
icmp-port-unreachable(既定) Connection refused
tcp-reset Connection refused

つまり No route to host が出ていて、かつローカル経路・ARP・traceroute に問題が無いなら、icmp-host-prohibited 系の REJECT ルールを疑う。多くのディストリの初期 iptables ルールにはこの種別が含まれることがある。

# nftables のルール確認
$ sudo nft list ruleset | grep -i -E 'reject|prohibit'

# iptables を使う環境
$ sudo iptables -L -n -v --line-numbers
Chain INPUT (policy ACCEPT)
num  target  prot  ...  destination
8    REJECT  all   ...  reject-with icmp-host-prohibited

上記のように reject-with icmp-host-prohibited が該当トラフィックにマッチしていれば、それが発生源だ。サーバ側・経路上のいずれにあるかは traceroute の !X 位置と合わせて判断する。ufw 環境での許可ルール確認と復旧は ufw でSSHが繋がらない時 を参照。

ファイアウォールのルール変更は、適用順序を誤ると自分自身の接続(SSH 等)を切る危険がある。リモートでルールを編集する際は、一定時間後に自動で元に戻すスケジュール(at での復旧予約など)を併用し、締め出しを防ぐ。

それでも直らないときのチェックリスト

結論: No route to host は「経路・到達性の問題」が確定した状態。ローカル経路 → ARP → traceroute → REJECT ルールの順に、自ホストから外へ向かって潰せば原因はこの 4 層のどこかに収束する。

  • [ ] エラーは No route to host(即時)か timed out(待たされる)か区別したか
  • [ ] ip route get <宛先> で経路・出口 IF・ゲートウェイを確認したか
  • [ ] ip route show default にデフォルトゲートウェイの行があるか
  • [ ] 出口インターフェースは UP か(ip -br link
  • [ ] 同一セグメント宛なら ip neighFAILED になっていないか(ARP 解決)
  • [ ] ping の unreachable 応答元は宛先かルータか(From <GW> なら経路途中)
  • [ ] traceroute でどのホップに !H / !N / !X が出るか
  • [ ] nft list ruleset / iptables -Licmp-host-prohibited 系の REJECT が無いか

次に読む