なぜchrootは数十年の時を経てもなお、強力な「武器」であり続けるのか?
Dockerを設備が整ったマンションに例えるなら、chrootは最も素朴なレンガの壁のようなものです。1979年に登場したchroot(change root)は、プロセスに対して仮想的なルートディレクトリを変更することを可能にします。ここに「閉じ込められた」アプリケーションは、そのディレクトリをファイルシステム全体(/)として認識します。外の世界については一切知ることができません。
2年前、私はPHP 5.6を使用するレガシーなアプリケーションを実行しているCentOS 7サーバー群を管理していました。脆弱性修正のためにメインシステムをアップグレードする必要がありましたが、古いPHP 5.6のライブラリ群が競合を引き起こし、大きな負担となっていました。仮想マシン(VM)ごとに512MBのRAMを追加で消費する代わりに、私はchrootを使って古いライブラリ群を隔離しました。その結果、アプリケーションは安定して動作し、リソースを節約でき、何よりメインのOSを汚さずに済みました。
隔離だけでなく、chrootはLinuxが起動できなくなった時の「サバイバル」スキルでもあります。GRUBの設定を誤ったり、rootパスワードを忘れたりした場合、Live USB from 故障したシステムにアクセスするための唯一の手段がchrootです。
アプリケーションのための「新しい家」を準備する
chrootコマンドはcoreutilsパッケージに含まれているため、追加のインストールは不要です。難しいのは環境の準備です。空のchrootパーティションには、lsやcdコマンドさえも存在しません。
bash用の最小限েরサンドボックス環境を作成してみましょう:
# ディレクトリ構造を作成する
sudo mkdir -p /home/jail/{bin,lib,lib64}
実行ファイル/bin/bashをそこにコピーしただけでは、すぐにエラーになります。なぜでしょうか?それは、Linuxがコマンドを実行するために共有ライブラリ(.so)を必要とするからです。ここで、lddコマンドが強力な助っ人になります。
ldd /bin/bash
画面には4〜5つのライブラリパスが表示されます。これらのファイルを、/home/jail内の正しいディレクトリ構造に正確にコピーする必要があります。この作業は少し手間がかかりますが、Linuxにおける依存関係(dependencies)の本質を理解するのに役立ちます。
二つの実戦的な活用シナリオ
1. 隔離環境(Jail)の作成
ユーザーにシステムをいじらせたいけれど、実際のデータには触れさせたくないとしましょう。bashとlsに必要なライブラリをすべてコピーしたら、「投獄」を実行します:
sudo chroot /home/jail /bin/bash
ls /を実行してみると、先ほど作成したディレクトリだけが表示されるはずです。しかし、油断は禁物です。chrootは鉄壁のセキュリティ層ではありません。Jail内でroot権限でプロセスが実行されている場合、double chrootというテクニックを使って脱出される可能性があります。黄金律:Jail内でのアプリケーション実行は、常に一般ユーザーで行いましょう。
2. システムレスキュー(レスキューモード)
これは、私が直近の四半期で物理サーバーのダウンを処理するために10回以上使用したシナリオです。サーバーがログイン画面まで起動できない場合は、レスキューUSBを使用して、次の3つのステップを実行します:
ステップ1: ハードディスクを一時ディレクトリにマウントします。
sudo mount /dev/sda1 /mnt
ステップ2: USBからのハードウェアリソースを古いハードディスクにリンクします。このステップを忘れると、aptやgrub-installなどのコマンドが完全に機能しなくなります。
for i in /dev /dev/pts /proc /sys /run; do sudo mount -B $i /mnt$i; done
ステップ3: 故障したシステムに入ります。
sudo chroot /mnt
これで、あなたは壊れたオペレーティングシステムの中心に立っています。passwdでパスワードを変更したり、update-grubでブートローダーの修復を行ったりできます。修正が終わったら、exitしてアンマウントし、再起動すれば、すべてが再びスムーズに動作するはずです。
チェックのコツと実戦で得た教訓
プロセスが「閉じ込められて」いるかどうかをどうやって判断するのでしょうか?実機から/procディレクトリを確認します。各プロセス(PID)には、そのルートディレクトリを指すrootリンクがあります。
# 特定のPIDのルートディレクトリを確認する
sudo ls -ld /proc/[PID]/root
結果が/ではなく/home/jailと表示されていれば、それは隔離されていることを意味します。パフォーマンスに関しては、chrootは仮想マシンのようにハードウェアをエミュレートする必要がないため、オーバーヘッドはほぼゼロです。
重要な注意点:レスキューの際、システムに独立した/bootパーティションがある場合は、GRUB修復コマンドを実行する前に必ずそれをマウントしてください。忘れてしまうと、空のディレクトリにデータを更新しているだけになり、再起動後もエラーが解消されないままになります。
Dockerがコンテナの世界を支配していますが、chrootを理解しておくことは依然として大きな強みです。パフォーマンスに関しては、仮想マシンのようにハードウェアをエミュレートする必要がないため、オーバーヘッドはほぼゼロです。
Dockerがコンテナの世界を支配していますが、chrootを理解しておくことは依然として大きな強みです。サーバーが起動できないような「最悪の事態」の対処や、超軽量なテスト環境が必要な時に役立ちます。
