Linux技術 · 3 min read · Feb 03, 2026

UnionfsとChrootを使用してログイン時に安全なミラーに入る

UnionfsとChrootを使用してログイン時に安全なミラーに入る

1. はじめに

LinuxFromScratchのウェブサイトで「ヒント」を読んでいると、特にchrootとの組み合わせでのunionfsの特別な機能を発見しました。その後、Gentooのウィキサイトで、特別なスクリプトをシェルとして使用する際にchrootされたホームディレクトリに入る方法についてのHowToを読みました。この2つを組み合わせることで、特別なユーザーとしてログインする際に入るchrootされた環境を使用することになります。この環境は、作業しているシステムの正確なコピー(ミラー)です。実際のシステムの安全なコピーにいるため、好きなことができ、システムを変更することは決してありません。すべてはキャッシュ内に留まります(読み書きブランチ)。

リンク:
TRIP、LFS(および他のLinuxシステム)用のTRIvial Packager - LFSのウェブサイトでの元のヒント
Home_directory_jail - Gentooでchroot監獄を設定するためのガイド

2. 基本技術

好きなことをして、システムからファイルをインストール、変更、削除しても、何の害もありません。あなたの実際のシステムは手つかずのままです。これは魔法のように聞こえるかもしれませんが、実際にはLinux用に利用可能な技術を組み合わせることで可能です。
Unionfsファイルシステム、chroot、およびいくつかの適切に選択された再マウントされたディレクトリを使用することで、この仮想システムを設定できます。

2.1 Unionfs

最も重要な部分は、unionfsの使用です。Unionfsは、少なくとも2つの他のファイルシステムの和を作成する可能性を提供します。詳細についてはwww.unionfs.orgを参照してください。新しいファイルシステムを、元のファイルシステム(ルート)を読み取り専用モードで、そして一時的なファイルシステム(キャッシュ)を読み書きモードでの和にすることで、元のファイルシステムと全く同じように見えるファイルシステムを持つことができますが、元のシステムに何も変更を加えることなく、ファイルを修正、削除、または追加できます。これは、ルートが読み取り専用でマウントされているため不可能です。すべての変更はunionfsによってキャッシュに保存されます。
元のシステムと新しく作成されたシステムの唯一の違いはパスです:新しいシステムでは、常にunionのマウントポイントのパスから始まります。これが次のステップが必要な理由です。

特別な注意:今日[2007年6月]、unionfsがカーネルに含まれるようです。現在、unionfsは活発に開発されています。詳細についてはウェブサイトを確認してください。

ウェブサイトには、unionfsを有効にする方法が記載されています。最新のカーネル(2.6.19以降)にはカーネルソース用のパッチがあり、あまり最近でないカーネルには外部モジュールがあります。

2.2 (再)マウント

もう1つ行う必要があるのは、/dev、/proc、/sysなどのいくつかの重要なディレクトリを(再)マウントすることです。これは、unionファイルシステムが既存のマウントポイントを保持しないためです。
/tmpやソフトウェアを構築しているディレクトリなど、いくつかの特別なディレクトリを再マウントすることも推奨されます。

2.3 Chroot

このマウントポイントにchrootすることで、あなたのシステムの絶対的なコピーである環境に入ります。好きなことができ、重要なディレクトリやファイルを削除することさえできます。試してみてください!システムがフリーズする前にどこまで行けるか見てください。

2.4 この環境へのログイン

Home_directory_jailで説明されている概念のように、特別なログインシェルを作成することで、unionfsとchrootで作成された環境に入ることが可能です。
ここで説明されているアイデアは、特別なシェルを持つ特別なユーザーを作成することです。このシェルは、インタラクティブシェルに入る前に、unionファイルシステムをマウントし、いくつかの重要なディレクトリを再マウントし、chrootを行うなどの必要な手順を最初に実行します。

3. 準備

3.1 キャッシュパーティション

機能するのに十分なスペースを持つパーティションを開始します。これは物理的なパーティションである必要はなく、仮想ドライブでもかまいません。

このドライブを作成するには:

dd if=/dev/zero of=/mnt/cache.img bs=1M count=500  
mkfs.ext2 /mnt/cache.img  
mkdir /mnt/cache  
mount /mnt/cache.img /mnt/cache -o loop
chmod 777 /mnt/cache
mkdir /mnt/union

これにより、500Mの仮想パーティション(またはドライブ)が作成されます。

(注:ループバックデバイスは、カーネルでサポートされている必要があります。ほとんどのディストリビューションのカーネルはそうです。)

3.2 特別なログインシェル

必要な手順をすべて実行するchroot-unionというシェルスクリプトを作成します:

/binのchroot-unionスクリプト:

#!/bin/bash
function mount_unionfs {
# 一時ファイルシステムをマウント
if [ -z "$(mount -t unionfs | grep -w /mnt/union )" ]; then
    sudo /bin/mount -t unionfs -o dirs=/mnt/cache:/=ro unionfs /mnt/union
    
fi
if [ -n "$(mount -t unionfs | grep -w /mnt/union )" ]; then
    # 基本システムマウント
    if [ -z "$(mount | grep -w /mnt/union/dev)" ]; then
    sudo /bin/mount --bind /dev /mnt/union/dev 2> /dev/null
    fi
    
    if [ -z "$(mount -t devpts | grep -w /mnt/union/dev/pts)" ]; then
    sudo /bin/mount -t devpts devpts /mnt/union/dev/pts 2> /dev/null
    fi
    if [ -z "$(mount -t tmpfs | grep -w /mnt/union/dev/shm)" ]; then
    sudo /bin/mount -t tmpfs shm /mnt/union/dev/shm 2> /dev/null
    fi
    
    if [ -z "$(mount -t sysfs | grep -w /mnt/union/sys)" ]; then
    sudo /bin/mount -t sysfs sysfs /mnt/union/sys 2> /dev/null
    fi
    
    if [ -z "$(mount -t proc | grep -w /mnt/union/proc)" ]; then
    sudo /bin/mount -t proc proc /mnt/union/proc 2> /dev/null
    fi
    if [ -z "$(mount | grep -w /mnt/union/tmp)" ]; then
    sudo /bin/mount --bind /tmp /mnt/union/tmp 2> /dev/null
    fi
    
    
else
    echo "Mount of /mnt/union failed."
    
    exit 2
fi
    
}
function umount_unionfs {
#
# /tmpをアンマウント
#
if [ -n "$(mount | grep -w /mnt/union/tmp)" ]; then
    sudo /bin/umount /mnt/union/tmp 2> /dev/null
fi
#
# /procをアンマウント
#
if [ -n "$(mount -t proc | grep -w /mnt/union/proc)" ]; then
    sudo /bin/umount /mnt/union/proc 2> /dev/null
fi
#
# /sysをアンマウント
#
if [ -n "$(mount -t sysfs | grep -w /mnt/union/sys)" ]; then
    sudo /bin/umount /mnt/union/sys 2> /dev/null
fi
#
# /dev/shmをアンマウント
#
if [ -n "$(mount -t tmpfs | grep -w /mnt/union/dev/shm)" ]; then
    sudo /bin/umount /mnt/union/dev/shm 2> /dev/null
fi
#
# /dev/ptsをアンマウント
#
if [ -n "$(mount -t devpts | grep -w /mnt/union/dev/pts)" ]; then
    sudo /bin/umount /mnt/union/dev/pts 2> /dev/null
fi
#
# /devをアンマウント
#
if [ -n "$(mount | grep -w /mnt/union/dev)" ]; then    
    sudo /bin/umount /mnt/union/dev 2> /dev/null
fi
if [ -n "$(mount | grep -w /mnt/union )" ]; then  
    sudo /bin/umount /mnt/union 2> /dev/null
fi
}
mount_unionfs
# chrootに入る
sudo /usr/sbin/chroot /mnt/union /bin/su --shell /bin/bash --login $USER
# 一時ファイルシステムをアンマウント
umount_unionfs
EOF

新しいログインシェルを/etc/shellsファイルに追加します。これは、PAMがシェルをチェックする際に必要です。

3.3 ユーザーとグループの作成。

このスクリプトをシェルとして持つ新しいグループとユーザーを作成します:

groupadd -g 27 uniongroup  
useradd -c "Test user for chrooted union." -d /home/unionuser \  
-m -s /bin/chroot-union -g uniongroup -u 27 unionuser  
passwd unionuser

3.4 ユーザーに十分な権限を与える

新しいユーザーにsudoでより多くの権限を与えます。sudoの設定ファイル/etc/sudoersに次の行を追加します:


unionuser ALL=(ALL) ALL

注:このユーザーに権限を与える他の方法もあります。私は現在それらを検討しています。

注:これらの完全な権限を与えることは、通常のユーザーには多すぎます。しかし、ソフトウェアをインストールし、システムを変更するユーザーには必要です。

可能なこと

通常のユーザーのための安全で安全な環境

この構造は、信頼できないゲストユーザーに非常に適しています。私が試した最初のことは、グラフィカルセッションを開始することでした。問題はありませんでした。

このユーザーとしてソフトウェアをインストール

このユーザーとしてソフトウェアをインストールすることも可能です。これは次のように行うことができます:

  • このユーザーとしてソフトウェアをインストールします。特別な構造のため、すべての変更はキャッシュに行きます。
  • ログアウト後、キャッシュの内容と実際のシステムを比較します。
  • 管理ユーザー(root)は、キャッシュの内容をルートに移動することで、実際のインストールを行う選択肢があります。

例えば、小さなパッケージaudiofile-0.2.6のコンパイルとインストールを考えます。ソースが/tmpにあると仮定します。最初にログインします:

[root@hostname ]# login  
hostname login: unionuser  
Password:  
Last login: Wed Jun 20 19:58:32 CEST 2007 on pts/0  
[unionuser@hostname ]$

今、パッケージをコンパイルしてインストールします:

[unionuser@hostname ]$ cd /tmp/audiofile-0.2.6
[unionuser@hostname ]$ ./configure –prefix=/usr
[unionuser@hostname ]$ make
[unionuser@hostname ]$ sudo make install

セッションを終了し、キャッシュの内容を確認します:

[unionuser@hostname ]$exit
[root@hostname ]# cd /mnt/cache
[root@hostname ]# ls -Al
drwxr-xr-x 3 root root 1024 2007-06-05 17:32 home
drwxr-xr-x 6 root root 1024 2007-06-05 17:37 usr
drwxr-xr-x 3 root root 1024 2007-06-05 17:32 var
[root@hostname ]#

ホームディレクトリはここに表示されます。なぜなら、シェルBashがファイル.bash_historyを変更するからです。varディレクトリは、ファイル/var/run/utmpとディレクトリ/var/run/sudoの変更により表示されます。これは、期待通りに機能していることを証明します。

次に、ソフトウェアをインストールした/usrディレクトリの変更を確認すると:

[root@hostname ]# find usr -type f
usr/lib/pkgconfig/audiofile.pc
usr/lib/libaudiofile.la
usr/lib/libaudiofile.a
usr/lib/libaudiofile.so.0.0.2
usr/include/audiofile.h
usr/include/aupvlist.h
usr/include/af_vfs.h
usr/bin/audiofile-config
usr/bin/sfconvert
usr/bin/sfinfo
usr/share/aclocal/audiofile.m4
[root@hostname ]# find usr -type d
usr
usr/lib
usr/lib/pkgconfig
usr/include
usr/bin
usr/share
usr/share/aclocal

ご覧のとおり、すべてが/mnt/cache/usrディレクトリにあります。

これをバックアップすることができます:

[root@hostname ]# find usr | sort -u > /tmp/filelist-audiofile-0.2.6  

[root@hostname ]# tar --create --files-from=/tmp/filelist-audiofile-0.2.6 \  
                  --file=/tmp/install-audiofile-0.2.6.tar --directory=/mnt/cache \  
                  --no-recursion --absolute-names --preserve-permissions

上書きされるすべてのファイルのバックアップを作成することも非常に可能です:

[root@hostname ]# for installfile in $(cat /tmp/filelist-audiofile-0.2.6); do \  
                    if [ -e "/$installfile ]; then \  
                      echo "/$installfile" >> /tmp/backup-audiofile-0.2.6 \  
                    fi \  
                  done  
[root@hostname ]# tar --create --files-from=/tmp/backup-audiofile-0.2.6 \  
                  --file=/tmp/backup-audiofile-0.2.6.tar --directory=/mnt/cache \  
                  --no-recursion --absolute-names --preserve-permissions

次に、すべてのファイルをルートにコピーして実際のインストールを行います:

[root@hostname ]# for installfile in $(cat /tmp/filelist-audiofile-0.2.6); do \  
                    cp --verbose --force --recursive --parents --no-dereference \  
                      --preserve --target-directory=/ $installfile \  
                  done

注:上記のコマンドはアイデアを説明するためのものです。バックアップ、チェック、インストールを行うスクリプトを作成しており、非常に良好に機能しています。

Share: X/Twitter LinkedIn

新しい投稿を受信箱で受け取る

スパムはありません。いつでも購読を解除できます。