昨日は動作していたトンネルが、更新後の再起動を境にインターフェースが上がらなくなりました。WireGuard を外部モジュールとしてビルドするシステムでは、通常の原因は、ディスク上のモジュールが現在実行中のカーネルリリースとは別のリリースに属していることです。同じマシン上に似た名前のヘッダーがあっても、その一致を証明するものではありません。決め手になるのはリリース文字列だけです。

実行中のカーネルか、インストール済みのカーネルか

更新は新しいカーネルパッケージをインストールし、マシンが再起動するまで古いものをディスクに残します。再起動後は実行中のリリースが変わり、以前のリリース向けにビルドされたモジュールは、ファイルが残っていても使えなくなります。このずれが、再起動前は正常で再起動後に壊れたというよくある報告を、間に設定変更もないまま説明します。ヘッダーの再インストールで直るように見えるときと見えないときがある理由も、これで説明できます。

インストールするヘッダーパッケージは、実際に起動したカーネルではなく最新のカーネルパッケージに対応していることがあり、パッケージ名からはその区別がつかず、区別するのはリリース文字列だけです。何がインストールされているかを見る前に、何が動いているかを見てください。

再ビルド前の三つの確認

最初の確認は、どのカーネルが動いているかです。二つ目は、そのリリース向けのモジュールが存在し、見つけられるかどうかです。三つ目は、カーネルがすでにそれを読み込んでいるかどうかです。四つ目の問い、インターフェースを作れるかどうかは、モジュールではなく権限を試すものなので、この一覧ではなく再ビルドの後に置くべきです。

以下のコマンドは何も変更せずに最初の三つに答えます。答えごとに除外される修理が違うので、先へ進む前に各結果を読んでください。

uname -r
ls -l /lib/modules/$(uname -r)/build
modinfo wireguard
lsmod | grep wireguard

二行目がパスは存在しないと報告したら、実行中カーネルのビルド環境がなく、コンパイルしたものはどれも一致しません。パスがあるのに modinfo が失敗するなら、モジュールがまったくインストールされていない可能性があり、実装をツリー内で提供するカーネルでは普通のことです。modinfo が成功し lsmod が何も表示しないなら、モジュールは存在するが読み込まれておらず、これはビルドではなく読み込み時の問題です。結果ごとに進む先が違うので、コマンドそのものより読解のほうが重要です。

実行中のリリースに対してビルドする

外部モジュールは準備済みのカーネルツリーに対してコンパイルされ、カーネルの外部モジュールガイドは、最も高いバージョン番号を持つディレクトリではなく、実行中カーネルに属するビルドディレクトリを使うよう説明しています。そのビルドディレクトリはカーネルパッケージが管理するシンボリックリンクなので、現在起動しているリリースのツリーを指します。この間接性こそが要点で、間違えやすい選択を一つ取り除いてくれます。明示的に指定すれば、対象は曖昧でなくなります。

ツリーが完全にビルドされておらず準備だけされている場合、一つ注意点があります。準備ターゲットは、一部の外部ビルドが必要とするシンボルバージョンファイルを生成しないため、ヘッダーで満たされたツリーが自動的に完全なビルド環境になるわけではありません。シンボル不足でビルドが失敗したら、まずそのファイルを見てください。

sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules_install
sudo depmod -a

パッケージされたヘッダーが遅れる場合

自前のカーネルをパッケージするディストリビューションやシングルボードコンピューターでは、ヘッダーがリリースより数日あるいは数週間遅れることがあります。ヘッダーパッケージは名前は正しくても中身が古いことがあり、その場合ビルドは通っても読み込み時に失敗し、コンパイル時に失敗するのではありません。提供元を混ぜるとさらに悪化し、サードパーティのリポジトリのヘッダーを持つディストリビューションのカーネルや、汎用ヘッダーを持つベンダーのカーネルは、きれいにコンパイルできても、設定が異なるために実行中カーネルに拒否されることがあります。バージョン番号だけではそれを解決できません。

マシンが実験的なカーネルチャネルを追っているなら、対応するビルド成果物とともにそこにとどまるのか、サポート対象のパッケージ群に戻るのかを意識的に決めてください。更新を繰り返して部品が揃うことを願うのは、同じ不一致が毎回再現するので計画ではありません。

再ビルド後にインターフェースを確認する

インストールに成功したら、インターフェースを作ることが重要なテストで、その後にカーネルが実際に何を読み込んだか、拒否した場合はログが何と言っているかを読みます。読み込まれるモジュールと作成できないインターフェースは、原因の異なる別の失敗です。以下の三つのコマンドがそれを切り分けます。

sudo ip link add wg9 type wireguard
lsmod | grep wireguard
sudo dmesg | tail -5

モジュールが読み込みを拒否する場合、カーネルログが理由を示し、バージョンの不一致は可能性の一つにすぎません。同じビルドをもう一度実行しても同じ十分を費やして同じ拒否になるだけなので、再ビルドの前にその行を読んでください。その後で使い捨てのインターフェースを削除し、次のテストがきれいな状態から始まるようにしてください。

関連記事