Ubuntuで固定IP設定時にハマった「デフォルトゲートウェイ消失」の罠と、ルート設定の正解

未分類

はじめに

Raspberry Piのubuntu上で、Pythonを使って外部APIやWebサイトに接続するアプリを開発していたところ、特定の外部サイトにまったく接続できないという不可解な事象に遭遇しました。

  • ブラウザは一部サイトが表示できる
  • sudo apt update は成功する
  • しかし Python(requestsなど)からの外部API通信は失敗する

「ネットワークは生きているのに、なぜ?」

調査の結果、原因は以前行った Ubuntuの固定IP設定(Netplan設定変更) にありました。

本記事では、

  • なぜ一部の通信だけ成功していたのか
  • gateway4削除の何が問題だったのか
  • 正しいルート設定の方法

を技術的に深掘りします。


トラブルの原因:gateway4の削除

Ubuntuでは Netplan を使ってネットワーク設定を行います。

以前はこのように gateway4 を書くのが一般的でした。

gateway4: 192.168.1.1

しかし現在は gateway4は非推奨 となり、routes セクションでの明示的な記述が推奨されています。

参考サイトを元に gateway4 を削除したものの、
default route(デフォルトゲートウェイ)をroutesで正しく設定していなかった ため、

外の世界への出口が消えていた

という状態になっていました。


そもそも「デフォルトゲートウェイ」とは?

Linuxで現在のルートを確認するには:

$ ip route

正常な状態では、以下のような表示があります。

default via 192.168.1.1 dev enp0s3

この default via がないと、

  • ローカルネットワーク外への通信
  • インターネットへの通信

が基本的にできません。


謎:なぜ apt は動いていたのか?

ここが今回一番面白いポイントです。

デフォルトゲートウェイが消えていたのに、
なぜ sudo apt update は成功していたのでしょうか?

考えられる理由は以下です。

1. IPv6が生きていた

IPv4のデフォルトゲートウェイは消えていたが、IPv6のルートは生きていた可能性があります。

多くのUbuntuミラーサイトはIPv6対応しているため、

  • apt → IPv6で通信成功
  • Pythonアプリ → IPv4で接続しようとして失敗

という差が発生していた可能性があります。

確認方法:

$ ping -4 google.com   # IPv4
$ ping -6 google.com   # IPv6

実施した結果がこれです。

$ ping -4 google.com
ping: connect: Network is unreachable
$ ping -6 google.com
PING google.com(lcnrta-ba-in-x0e.1e100.net (2404:6800:4004:816::200e)) 56 data bytes
64 bytes from lcnrta-ba-in-x0e.1e100.net (2404:6800:4004:816::200e): icmp_seq=1 ttl=113 time=8.28 ms
^C

やはりIPv6が生きている、が理由のようです。


2. LAN内プロキシの存在

その他考えられる要因として、企業ネットワークなどでは、

  • LAN内にHTTPプロキシがある
  • そのプロキシへのルートは生きている

というケースがあります。

この場合:

  • apt → プロキシ経由で成功
  • Pythonアプリ → 直接外部に出ようとして失敗

という挙動になります。

我が家の場合は自宅に置いてあるRaspberry Piですし、プロキシも通していませんので、この可能性はないです。


3. DNSキャッシュの影響

それ以外にも、systemd-resolved やキャッシュの影響で、名前解決だけ成功しているケースも考えられます。

ただし今回は「到達不能」だったため、本質的にはルート欠落が原因でした。


Pythonアプリが失敗した理由

Pythonの requests などは、接続先のDNS結果を元に

  • IPv4アドレスへ接続
  • OSのルーティングテーブルを参照

して通信します。

このとき、

default route が存在しない

と、IPv4外部通信は即失敗します。

つまり:

通信結果
apt成功(IPv6またはプロキシ)
Python外部API失敗(IPv4のみ)

という差が生まれていました。


正しいNetplan設定(routesでのdefault指定)

gateway4 を削除する場合、必ず routes で default を明示する必要があります。
記述は下記のようになります。

routes:
    - to: default
      via: 192.168.1.1

設定例:

/etc/netplan/99-custom.yaml

network:
  version: 2
  wifis:
    wlan0:
      dhcp4: false
      optional: true
      addresses:
        - 192.168.1.30/24
      routes:
        - to: default
          via: 192.168.1.1
      nameservers:
        addresses: [192.168.1.1]
      access-points:
        "アクセスポイントのSSID":
          password: "アクセスポイントのPSK-AES"

適用:

$ sudo netplan apply

確認:

$ ip route

必ず以下が表示されること:

default via 192.168.1.1 dev wlan0 proto static

Tips: netplan apply でパーミッションの警告が出たら

設定ファイルを編集(または新規作成)すると、権限が 644 などになってしまい、「Permissions are too open」と警告されることがあります。
このワーニングが出ると「何か間違えたか?」と焦りますが、これは「設定ファイルの権限(パーミッション)が緩すぎるよ!」というセキュリティ上の警告です。

ネットワーク設定ファイルは機密情報を含むため、

$ sudo chmod 600 /etc/netplan/*.yaml

で権限を絞っておくのが作法です。


今回の教訓

  • gateway4 を削除するなら routes: - to: default をセットで書く
  • 「一部の通信ができるから大丈夫」は危険
  • ネットワーク障害時は必ず ip route を確認する
  • IPv4 / IPv6 の違いを意識する

おわりに

今回の障害は単なる設定ミスですが、

なぜ一部の通信だけ成功していたのか?

を深掘りすることで、LinuxのルーティングやIPv6の挙動理解が一段深まりました。

ネットワーク系の不具合は「なんとなく動いている」が一番怖い。

同じように固定IP設定を触る方の参考になれば幸いです。

コメント

タイトルとURLをコピーしました