WSL 2にRootless Dockerをインストールしようとしていましたが、ip_tablesカーネルモジュールがWSL 2にはないのでちょっと手間でした。 k-hyoda.hatenablog.com
そこで、今回は自分でip_tables.koカーネルモジュールとそれを読み込むことができるカーネルを用意してRootless Dockerを他のLinux OSと同じようにインストールできるようにしました。
注意事項
- 自己責任です。
- ip_tables.koを認識するところまでは確認しましたがRootless Dockerのインストールまでは確認していません。
動作環境
- Windows 10 Home 64bit 1909 18363.1082
- Windows Subsystem for Linux 2
- Ubuntu 20.04
- Linux kernel 4.19.128-microsoft-standard
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
やること
具体的な手順
- カーネルビルドに必要なパッケージをインストールする
- GitHubからMicrosoftがカスタマイズしたLinuxカーネルのソースコードをcloneする
- 現在のカーネルバージョンに合わせてブランチを切り替える
- ビルドに必要なファイルをコピーする
- ビルドしたいカーネルモジュールを指定する
- ビルドする
- ビルドしたカーネルをWSL 2のカーネルに指定しWSL 2を再起動する
- 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
すると次のような映像が表示されます。
ここで、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
引数を渡すほうが楽だと思いました。