ModemManagerとNetworkManagerを使ったUbuntu Serverの4G/5G USBモデム自動フェイルオーバー設定

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

問題:深夜2時に光回線が落ちるとき

半年で3回、重要なサービスをホストするサーバーが、上流の光回線障害によってダウンした。ハードウェアの問題ではなく、解決に20分から4時間かかったISP側のトラブルだった。その度に、ユーザーが接続できない中、監視アラートが積み上がっていくのをただ見ていた。

3回目の障害のあと、Huawei E3372 USBモデムに4G SIMを挿し、週末を費やしてUbuntu 22.04での自動フェイルオーバーを実現させた。その後6ヶ月で、さらに7回の光回線障害が発生したが、アラートも手動対応も一切不要だった。これが目標だ:ログを確認するまでフェイルオーバーが起きたことに気づかないくらい、透明に動くこと。

このガイドでは、私が実際に行った手順を解説する:メイン回線が落ちたときにModemManagerとNetworkManagerが自動的に4G/5Gへ切り替え、回線が復旧したらスムーズに元に戻る設定だ。

基本概念:フェイルオーバーの仕組み

ModemManager — モデム抽象化レイヤー

ModemManagerは、USBおよびWWANモデムを管理するD-Busシステムサービスだ。モバイルブロードバンドハードウェアの複雑な現実――異なるATコマンドセット、USBモード、キャリア初期化シーケンス――を、NetworkManagerが扱いやすいクリーンなインターフェースに抽象化する。

ModemManagerなしでは、/dev/ttyUSB0に直接ATコマンドを送り、使用モデムのファームウェアが言うことを聞いてくれることを祈るしかない。ModemManagerがあれば、やりたいことを記述するだけでデーモンがハードウェアの詳細を処理してくれる。HiLinkモードのモデムは別で、USB Ethernetアダプターとして認識されるため、NetworkManagerが通常のネットワークインターフェースとして扱い、ModemManagerの出番はない。

NetworkManager — ルートメトリクスによるフェイルオーバー制御

NetworkManagerはルートメトリクスを使って、アウトバウンドトラフィックをどのインターフェースで処理するかを決定する。メトリクスが低いほど優先される。フェイルオーバーの仕組みはすべてこれに基づいている:

  • 光回線のメトリクスを100に設定(プライマリ、両方が有効なときに優先)
  • 4G回線のメトリクスを600に設定(バックアップ、プライマリが落ちたときのみ使用)

光回線が有効なとき、トラフィックはメトリクスの低いルートを流れる。光回線が落ちると、そのルートがルーティングテーブルから消え、トラフィックは4Gルートに切り替わる。光回線が復旧すると、低いメトリクスのルートが戻り、再び優先される。スクリプト不要。cronジョブ不要。手動対応不要。

ハードウェアの選択

すべてのUSBモデムが同じように動作するわけではない。私が試した3つのモデルを紹介する:

  • Huawei E3372 (HiLinkモード) — 最もシンプルな設定で入手しやすく、中古で約3,000〜4,500円。USB Ethernetとして認識されるためModemManager不要。
  • ZTE MF833usb_modeswitchでUSBモードを切り替えれば動作するが、設定がやや複雑。
  • Sierra Wireless EM7455 — Linuxサポートが優秀でエンタープライズグレードだが、価格はかなり高い。

本番環境ではHiLinkモードのE3372を使っている。モデムパラメータの細かい制御は失われるが、フェイルオーバー目的には完璧だ――挿せばインターフェースが現れ、メトリクスを設定するだけで完成する。

実践:4G自動フェイルオーバーの設定

ステップ1:必要なパッケージのインストール

sudo apt update
sudo apt install -y modemmanager network-manager usb-modeswitch

# ModemManagerを有効化して起動
sudo systemctl enable ModemManager
sudo systemctl start ModemManager

最小構成のサーバーインストールでは、デフォルトでNetworkManagerが起動していないことがある。動作確認:

systemctl status NetworkManager

ステップ2:モデムの検出

USBモデムを挿し、ModemManagerが認識しているか確認する:

mmcli -L

期待される出力:

/org/freedesktop/ModemManager1/Modem/0 [Huawei Technologies Co., Ltd.] E3372

HiLinkモードのモデムはここに表示されないが、これは正常だ。代わりにnmcli device statusを確認し、新しいethernetインターフェースを探す。ハードウェアの認識確認:

lsusb | grep -i huawei
ip link show
nmcli device status

モデムがCD-ROMドライブ(ストレージモード)として表示される場合、usb_modeswitchが再挿入時に自動で切り替える。たいていはそれだけで解決する。

ステップ3:4G接続の設定

通常のモデムモード(HiLinkではない)のモデムには、GSM接続を作成する:

nmcli connection add \
  type gsm \
  ifname "*" \
  con-name "4g-failover" \
  apn "your.carrier.apn" \
  -- \
  connection.autoconnect yes \
  connection.autoconnect-priority -100

your.carrier.apnを実際のAPNに置き換える。多くのキャリアではinternetまたはwebが使われている。不明な場合はキャリアのドキュメントを確認しよう。日本のキャリア:SoftBankはsmile.world、IIJmioはiijmio.jpを使用する。

ethernetインターフェースとして表示されるHiLinkモードのモデムは、NetworkManagerが自動的にDHCP接続を作成する。接続名を確認しておこう:

nmcli connection show

ステップ4:フェイルオーバー優先度のルートメトリクス設定

ここが実際のフェイルオーバーロジックの核心だ。4Gのメトリクスを高く設定することで、プライマリが落ちたときのみ使用される:

# 4Gバックアップ接続に高いメトリクスを設定
nmcli connection modify "4g-failover" ipv4.route-metric 600
nmcli connection modify "4g-failover" ipv6.route-metric 600

# プライマリ光回線に低いメトリクスを設定
# "Wired connection 1"を実際の接続名に置き換える
nmcli connection modify "Wired connection 1" ipv4.route-metric 100
nmcli connection modify "Wired connection 1" ipv6.route-metric 100

変更を適用する:

nmcli connection up "4g-failover"
nmcli connection up "Wired connection 1"

ステップ5:ルーティングテーブルの確認

ip route show table main | grep default

両方の接続が有効な場合、2つのデフォルトルートが表示されるはずだ:

default via 192.168.1.1 dev eth0 proto dhcp metric 100
default via 192.168.8.1 dev eth1 proto dhcp metric 600

光回線ルートが優先される(metric 100)。これが消えると、トラフィックは自動的に4Gルートに切り替わる(metric 600)。

ステップ6:接続確認機能の有効化

リンク状態だけでは不十分だ。光回線インターフェースがアップしていても、ISPのルーティングが完全に壊れていることがある。接続確認機能でこれを検知する:

sudo nano /etc/NetworkManager/conf.d/connectivity.conf
[connectivity]
uri=http://connectivity-check.ubuntu.com/
interval=60
response=NetworkManager is online
sudo systemctl restart NetworkManager

この設定により、物理リンクが有効でもインターネット到達性の喪失を検知し、フェイルオーバーをトリガーする。私の環境では、フェイルオーバー検知時間が約45秒から20秒未満に短縮された。より包括的なエンドポイント監視が必要な場合は、Prometheus Blackbox ExporterでHTTP・TCP・ICMPをエージェントなしで能動監視する方法も参考になる。

ステップ7:本番投入前のテスト

別のマシンからサーバー上のサービスへの継続的なpingを開始し、光回線障害をシミュレートする:

# サーバー上で光回線障害をシミュレート
sudo ip link set eth0 down

# すぐにルーティングを確認
ip route show table main | grep default
# 4Gルートのみが表示されるはず

# 光回線を復元
sudo ip link set eth0 up

# プライマリルートが戻ることを確認
ip route show table main | grep default

リモートマシンからのpingを観察する。フェイルオーバー中は15〜45秒の中断が予想される――これが検知と再ルーティングの時間だ。多くのワークロードでは許容範囲内だ。

ステップ8:フェイルオーバーイベントの監視

イベント発生後にNetworkManagerのログを確認する:

journalctl -u NetworkManager --since "1 hour ago" | grep -E "(up|down|default|route|connectivity)"

小さなcronスクリプトで毎分アクティブなインターフェースをログに記録し、フェイルオーバー履歴を簡単に確認できるようにする:

#!/bin/bash
# /usr/local/bin/check-failover.sh
DEFAULT_IFACE=$(ip route show default | awk 'NR==1{print $5}')
DEFAULT_GW=$(ip route show default | awk 'NR==1{print $3}')
echo "$(date '+%Y-%m-%d %H:%M:%S') - デフォルト: $DEFAULT_IFACE 経由 $DEFAULT_GW" >> /var/log/failover.log
chmod +x /usr/local/bin/check-failover.sh
echo "* * * * * root /usr/local/bin/check-failover.sh" | sudo tee /etc/cron.d/failover-monitor

月末にgrep eth1 /var/log/failover.log | wc -lを実行するだけで、システムが4Gで過ごした正確な分数がわかる。vnStatを使った長期ネットワーク帯域幅モニタリングと組み合わせると、ISPの信頼性や月々のデータ使用量をより詳しく追跡できる。

6ヶ月の本番運用で学んだこと

設定前に知っておきたかったことをいくつか紹介する:

  • フェイルオーバー時間は15〜45秒。接続確認機能が有効なら、通常は速い方になる。ステートフルな接続――SSHセッション、データベース接続――はこの間に切断され、再接続が必要になる。
  • フェイルバックはクリーンで自動的だ。光回線が復旧すると、NetworkManagerは数秒以内に低メトリクスのルートを再追加する。手動対応不要、間違ったインターフェースに固定されたセッションもない。
  • データ使用量に注意しよう。私のSIMは6ヶ月のフェイルオーバーイベントで約800MBを消費した。容量制限のあるプランでは、長時間の障害がすぐに積み上がる。
  • 自動であっても、フェイルオーバー時にはアラートを送るべきだ。対応は不要でも、発生を知ることで再発前に根本原因を調査できる。監視スクリプトからTelegramやメール通知を設定しておこう。
  • フェイルオーバーにはHiLinkモードの方がシンプルだ。モデムが対応していれば、ModemManagerを完全にスキップして2つのethernetインターフェースを管理するだけでいい。設定が少なく、問題が起きたときのデバッグも楽だ。

20秒未満のフェイルオーバーが必要なら、BGPマルチホーミングマルチパスTCP(MPTCP)によるアクティブ-アクティブ負荷分散が必要になる――別次元の複雑さだ。ほとんどの小規模サーバーやホームラボでは、このメトリクスベースの設定がちょうどよいバランスを保っている:自動回復、最小限のハードウェアコスト、一度動かせばメンテナンス不要。

Share: