はじめに (対象読者・この記事でわかること)
この記事は、Ubuntu 20.04/22.04、Debian 11/12 などのDebian系ディストリビューションで「サーバーを運用中に突然デフォルトゲートウェイが書き換わり、通信が不通になる」という症状に見舞われた方、あるいはその予兆を感じている方向けです。
読み進めることで、以下のことがわかります。
- ルーティングテーブルがなぜ「自動」で変更されるのか
netplan、systemd-networkd、NetworkManager、dhclientのどれが元凶なのかを特定する方法- 設定ファイルをどう修正すれば、再起動やDHCPリース更新後もデフォルトルートが固定されるのか
私自身、業務でマルチNIC構成のサーバーを構築した直後に「プライマリゲートウェイが突然消える」「想定外のNICがデフォルトゲートウェイになる」という現象に何度も遭遇し、原因調査に丸一日を費やした経験があります。この記事はその教訓をまとめたものです。
前提知識
ip routeコマンドでルーティングテーブルを読める/etc/netplan/*.yamlまたは/etc/network/interfacesで静的IPを設定した経験があるsystemctl statusでサービスの状態を確認できる
なぜ「勝手にルーティングが変わる」のか
Debian系OSでは、複数のデーモンが同時にネットワーク設定を触るため、「最後に設定を書き込んだものが勝つ」状態になります。代表的な例を挙げると:
netplan→systemd-networkd経由でLAN側NICにDHCPを有効にしている- DHCPオファーにデフォルトゲートウェイ情報(option routers)が含まれている
- その情報が既存のデフォルトルートを上書きしてしまう
このとき、netplanのYAMLでdhcp4: trueとしているだけでgateway4を明示していないと、DHCPサーバーから届いたゲートウェイが優先されてしまうのです。
事象を再現・特定するまでの道のり
ステップ1:現在のルーティングと由来を確認する
まず、変更前の状態をメモルーティングテーブルと、どのデーモンがルートを注入したかを確認しましょう。
Bash# ルーティングテーブル ip route show # 例: # default via 192.0.2.1 dev eno1 proto dhcp metric 100 # default via 198.51.100.1 dev eno2 proto static metric 200 # ルートの出所を確認 ip route get 8.8.8.8
proto dhcpとあるものはDHCPクライアントが付与したルート、proto staticはnetplanや/etc/network/interfacesで明示した静的ルートです。
ステップ2:ログを追って「誰が書き換えたか」を特定
Debian 11以降では、systemd-networkdまたはNetworkManagerのいずれかが実質的なネットワーク管理を行います。ログを絞り込みます。
Bash# systemd-networkdのログ journalctl -u systemd-networkd -f # DHCPクライアントのログ(旧システム) journalctl -u dhclient -f # NetworkManagerのログ(DesktopやNM有効時) journalctl -u NetworkManager -f
GATEWAYやdefault routeキーワードでgrepしてやると、次のようなメッセージが見つかります。
systemd-networkd[1234]: eno1: DHCP: Received gateway 192.0.2.1
systemd-networkd[1234]: eno1: Configuring default route with gateway 192.0.2.1
これで「DHCP応答がルートを上書きしている」ことが特定できます。
ステップ3:設定ファイルを修正してDHCPの上書きを回避
netplanを使っている場合、dhcp4-overridesでuse-routes: falseを指定します。
Yaml# /etc/netplan/01-netcfg.yaml network: version: 2 renderer: networkd ethernets: eno1: # LAN(DHCPクライアントとして動作) dhcp4: true dhcp4-overrides: use-routes: false # ← これがポイント eno2: # 外向け(静的ルート) addresses: [198.51.100.10/24] gateway4: 198.51.100.1 nameservers: addresses: [8.8.8.8, 1.1.1.1]
use-routes: falseにすると、DHCPサーバーからゲートウェイ情報が降ってきても無視します。これでeno2側の静的なデフォルトゲートウェイが常に優先されます。
ifupdown(/etc/network/interfaces)を使っている場合は、dhcp-optionsで拒否できます。
allow-hotplug eno1
iface eno1 inet dhcp
# DHCPでルートを受け取らない
supersede routers 0.0.0.0
ステップ4:即時反映と永続化
変更後は以下で即座に反映させます。
Bashsudo netplan apply # netplan利用時 # または sudo ifdown eno1 && sudo ifup eno1
そして再起動を一度行い、ip routeが変わらないことを確認しましょう。
ハマった点:metric値の競合
私の環境では、eno1側のDHCPルートがmetric 100、eno2側の静的ルートがmetric 200だったため、DHCPルートの方が常に優先されていました。netplanで明示的にroutes:を書いてmetricを下げても、DHCP側が100のままでは意味がないので、DHCP側のルート注入を完全に無効化する方が確実です。
解決策まとめ
- DHCPでルートを受け取りたくないNICでは
use-routes: falseまたはsupersede routers 0.0.0.0 - 複数NICでゲートウェイを使い分ける場合は、受け側と送り側を明確に分離してYAML/インターフェースを記述
- 設定適用後は必ず
reboot→ip routeで再現試験を行う
まとめ
本記事では、Debian系OSで「DHCP応答によってデフォルトゲートウェイが意図せず上書きされる」現象の調査手順と、それを防ぐためのnetplan/interfaces設定を紹介しました。
- DHCPが配布する
option routersはuse-routes: falseで無効化できる systemd-networkdのログを追うことで、誰がルートを注入したかが一目でわかる- マルチNIC環境では、「どのNICで外向けゲートウェイを使うか」を明確に設計してから設定を書き始める
これで、再起動やDHCPリース更新後も「突然通信が途切れる」という恐怖から解放されます。
次回は、同じ問題をAnsibleで大規模サーバー群に一括適用する方法と、障害時に自動でルートを戻す仕組みを紹介する予定です。
参考資料
- man systemd.network (dhcp选项の overrides セクション)
- netplan.io Reference - dhcp4-overrides
- Debian Wiki - NetworkConfiguration
