チラシの裏からうっすら見える外枠の外のメモ書き

新聞に挟まってる硬い紙のチラシの裏からうっすら見える外枠の外に走り書きされたようなものです。思いついたときにふらふらと。

WSL 2にip_tables.koカーネルモジュールを入れる方法

WSL 2にRootless Dockerをインストールしようとしていましたが、ip_tablesカーネルモジュールがWSL 2にはないのでちょっと手間でした。 k-hyoda.hatenablog.com

そこで、今回は自分でip_tables.koカーネルモジュールとそれを読み込むことができるカーネルを用意してRootless Dockerを他のLinux OSと同じようにインストールできるようにしました。

注意事項

  • 自己責任です。
  • ip_tables.koを認識するところまでは確認しましたがRootless Dockerのインストールまでは確認していません。

動作環境

user@MACHINE:~$ uname -a
Linux MACHINE 4.19.128-microsoft-standard #1 SMP Tue Jun 23 12:58:10 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

やること

  1. Linuxカーネルソースコードをダウンロードする
  2. 必要な機能をモジュールに設定してビルドする
  3. ビルドで出てきたカーネルをWSL 2で使用する
  4. modprobeコマンドで読み込む

具体的な手順

  1. カーネルビルドに必要なパッケージをインストールする
  2. GitHubからMicrosoftがカスタマイズしたLinuxカーネルソースコードをcloneする
  3. 現在のカーネルバージョンに合わせてブランチを切り替える
  4. ビルドに必要なファイルをコピーする
  5. ビルドしたいカーネルモジュールを指定する
  6. ビルドする
  7. ビルドしたカーネルをWSL 2のカーネルに指定しWSL 2を再起動する
  8. ip_tablesをロードする

手順

カーネルモジュールのビルド手順については以下の記事を参考にしています。 contentsviewer.work

1. カーネルビルドに必要なパッケージをインストールする

カーネルのビルドには必要となるパッケージがいくつかあるので、それをインストールします。

sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool

2. GitHubからMicrosoftがカスタマイズしたLinuxカーネルソースコードをcloneする

WSL 2ではMicrosoftがカスタマイズしたLinuxカーネルを使用しているので、そのカーネルソースコードを入手する必要があります。このソースコードOSSとしてGitHubで公開されているので、誰でも入手することができます。 github.com このソースコード/usr/srcに今使用しているカーネル4.19.128-microsoft-standardディレクトリ名でcloneします。

sudo git clone https://github.com/microsoft/WSL2-Linux-Kernel.git /usr/src/4.19.128-microsoft-standard

3. 現在のカーネルバージョンに合わせてブランチを切り替える

cloneしたソースコードはおそらく現在使用しているカーネルのバージョンよりも新しいものなので、ソースコードのバージョンを現在使用しているカーネルのバージョンに合わせる必要があります。

例えば、この環境ではカーネル4.19.128-microsoft-standardなので、4.19.128のブランチへ切り替えます。gitのタグ名はこのカーネルGitHubリポジトリにあるReleaseで確認するほうが見やすいと思います。 github.com

cd /usr/src/4.19.128-microsoft-standard
sudo git checkout refs/tags/linux-msft-4.19.128

4. ビルドに必要なファイルをコピーする

現在のカーネル設定を引き継ぐため、/proc/config.gzにあるconfigデータをカーネルソースコードディレクトリへコピーします。また、menuconfigが読み込めるように.configにリネームします。

sudo cp /proc/config.gz ./
sudo gunzip config.gz
sudo mv config .config

5. ビルドしたいカーネルモジュールを指定する

menuconfigを実行し、カーネルモジュールを選択します。

sudo make menuconfig

すると次のような映像が表示されます。 f:id:k-hyoda:20200922113257p:plain ここで、ip_tablesをモジュールに設定します。矢印キーとEnterキーを使用し、[*] Networking support --->Networking options --->[*] Network packet filtering framework (Netfilter) --->IP: Netfilter Configuration --->を選択します。間違えて他の項目に入ってしまった場合はEscキーを2回押すか、Tabキーで<Exit>を選択してEnterキーを押せば前の項目に戻ることができます。

そして、IP: Netfilter Configurationの項目にある<*> IP tables support (required for filtering/masq/NAT)を選択し、スペースキーを何回か押して<*>の箇所が<M>になるようにしてください。これでモジュールとしてビルドする設定ができます。あとはTabキーを操作してSaveを選択して保存します。.configに保存していいかという確認画面が出ますが、そのまま< Ok >をEnterキーで選択して構いません。あとはEscキーなどを連打してmenuconfigを終了します。

6. ビルドする

カーネルモジュールをカーネルとともにビルドします。次のコマンドでビルドを行います。

sudo make -j 5 && sudo make modules_install -j 5 && sudo make install -j 5

このとき、-j 5は並列ジョブ数を指定しています。コア数+1が推奨されているので、それぞれコンピュータに合わせて指定してください。今回は4コアのコンピュータと仮定しています。 ビルドにはしばらくかかるので気長に待ちます。

7. ビルドしたカーネルをWSL 2のカーネルに指定しWSL 2を再起動する

エラーもなく正常にビルドが終わるとカーネルが生成されているので、それを任意のディレクトリに移します。今回はWindowsのユーザーディレクトリに移します。

sudo cp vmlinux /mnt/c/Users/user/

そして、C:\Users\userディレクトリに.wslconfigファイルを作成し次の内容を書きカーネルを指定します。

kernel=C:\\Users\\user\\vmlinux

その後、PowerShellなどからWSL 2をシャットダウンします。

wsl --shutdown

8. ip_tablesをロードする

再びWSL 2を起動すると、カーネルが変わっていることがわかります。

user@MACHINE:~$ uname -a
Linux MACHINE 4.19.128-microsoft-standard+ #2 SMP Tue Sep 22 10:56:28 JST 2020 x86_64 x86_64 x86_64 GNU/Linux

ここで、modprobeコマンドを使用してip_tablesをロードします。

sudo modprobe ip_tables

エラーもなく実行でき、またlsmodコマンドでロードされていることが確認できます。

lsmod
Module                  Size  Used by
ip_tables              24576  0

また、/lib/modules/4.19.128-microsoft-standard+/kernel/net/ipv4/netfilter/の中にip_tables.koが入っていることも確認できます。

ls /lib/modules/4.19.128-microsoft-standard+/kernel/net/ipv4/netfilter/ | grep ip_tables.ko
ip_tables.ko

感想

正直カーネルモジュールをビルドするのは手間なので、おとなしくDockerコンテナ起動時に--net=host引数を渡すほうが楽だと思いました。