初めに #
Linuxサーバーを複数人で運用している場合、「SSHでのログインは許可したいが、操作できる範囲は制限したい」といった場面がよくあります。
そのような場合に有効な手段が Chroot を利用した SSH ユーザーの隔離となります。
Chroot を利用する事で、SSH でログインしたユーザーを特定のディレクトリ配下に閉じ込め、他の領域へアクセスできない安全な環境を構築する事ができます。
これにより、操作ミスによるトラブルを防ぎ、万が一アカウントが不正に利用された場合でも被害を最小限に抑えることができます。
本記事では、AlmaLinux 10 にて Chroot を利用したSSHユーザー隔離環境を構築する方法について初心者向けにご紹介いたします。
Chrootとは? #
Chroot は、Linux カーネルが提供する機能のひとつで、特定のプロセスやユーザーから見えるルートディレクトリを別の場所に変更する仕組みとなっています。
一般的な構成の Linux 環境にて SSH ログインを行った場合、ユーザーはルートディレクトリを起点とした以下のようなファイルシステム構造を認識する事ができます。
実際にアクセスできるかどうかは権限(パーミッション)によって管理されているため、この構成自体が必ずしも危険というわけではありません。
/
├── bin
├── etc
├── home
│ ├── user1
│ └── user2
├── usr
└── var
例えばサーバーの / 直下に隔離用の jail ディレクトリを作成し、その中に Chroot 環境を構築するとします。
/
├── bin
├── etc
├── home
├── usr
├── var
└── jail(Chroot環境)
├── bin
├── lib
├── lib64
└── home
└── user1
└── user2
この状態で /jail を起点とし Chroot 機能を有効化すると 各ユーザーからは次のように見えるようになります。
/ (実際には /jail となっている)
├── bin
├── lib
├── lib64
└── home
└── user1
└── user2
このように、制限されたユーザーからは /jail の中がサーバーのすべてであるかのように見えます。
これは、Chroot によってサーバーのルートディレクトリ(/)の起点が /jail に変更されるためです。
その結果、実際のルートディレクトリに存在する /etc や /var などの本来のシステム領域は、ユーザーから認識できなくなり、参照や操作ができなくなります。
Chroot環境の構築 #
ここからは、実際に Chroot を利用した SSH ユーザーの隔離環境を構築していきます。
今回はユーザーが最低限のコマンドを実行できるよう、Chroot 環境内にはコマンド本体や必要なライブラリも配置します。
構築するChroot環境のディレクトリ構成は以下の通りとなります。
/ (ホストOSのルート)
├── bin, etc, lib, usr... (ホストのシステムファイル)
├── home
│ ├── user1 -> /jail/home/user1 (SSH認証用のシンボリックリンク)
│ └── user2 -> /jail/home/user2 (SSH認証用のシンボリックリンク)
└── jail <-- 【Chrootのルートディレクトリ】
├── bin (コマンドファイル)
├── dev (仮想デバイスファイル)
├── etc
│ ├── passwd (必要アカウントのみを抽出し記載)
│ ├── group (必要グループのみを抽出)
│ ├── bashrc (共通設定用)
│ └── profile (共通設定用)
├── home
│ ├── user1 (ユーザー1のホームディレクトリ)
│ └── user2 (ユーザー2のホームディレクトリ)
├── lib, lib64 (コマンド実行に必要な共有ライブラリ)
└── usr (追加のバイナリ・ライブラリ)
Chroot用ディレクトリの作成 #
初めに Chroot 環境の土台となるディレクトリを作成します。
以下のコマンドを実行し必要ディレクトリを作成してください。
mkdir -p /jail/{bin,lib,lib64,home,dev,usr,etc}
mkdir -p /jail/usr/bin
デバイスファイルの配置 #
次に Chroot 環境内で bash シェルなどを正常に動作させるための、基本的なデバイスファイルを作成します。
以下のコマンドを実行しデバイスファイルを作成してください。
mknod -m 666 /jail/dev/null c 1 3
mknod -m 666 /jail/dev/zero c 1 5
mknod -m 666 /jail/dev/random c 1 8
mknod -m 666 /jail/dev/tty c 5 0
上記のコマンドを実行すると、以下のようにキャラクタデバイスが作成されます。
ls -al /jail/dev/
total 0
drwxr-xr-x. 2 root root 55 Dec 21 17:08 .
drwxr-xr-x. 7 root root 64 Dec 21 17:08 ..
crw-rw-rw-. 1 root root 1, 3 Dec 21 17:08 null
crw-rw-rw-. 1 root root 1, 8 Dec 21 17:08 random
crw-rw-rw-. 1 root root 5, 0 Dec 21 17:08 tty
crw-rw-rw-. 1 root root 1, 5 Dec 21 17:08 zero
シェルと基本コマンドの複製 #
次に、Chroot 環境内でユーザーがログインした際に操作できるよう、bash シェルおよび基本的なコマンドを隔離ディレクトリ内へ複製します。
本記事では、ユーザーを隔離することを最優先の目的としているため、コマンドやライブラリの最小化は行わず、通常の Linux 環境で使用されるファイル一式をそのまま配置します。
以下のコマンドを実行しコマンドやライブラリを隔離ディレクトリに複製してください。
cp -avL /bin/. /jail/bin/
cp -avL /usr/bin/. /jail/usr/bin/
cp -avL /lib/. /jail/lib/
cp -avL /lib64/. /jail/lib64/
ユーザーの作成 #
基本コマンドやライブラリの設置が完了したら実際に使用するユーザーの作成を進めます。
以下のコマンドを実行し共通グループを作成してください。
このグループは、後ほど隔離対象となるユーザーをまとめるために利用します。
groupadd users
次に以下のコマンドを実行し user1 および user2 のアカウントを作成してください。
ここで使用するユーザー名は例となっております。
要件に合わせて任意の名前を指定する事が可能です。
useradd -m -g users user1
useradd -m -g users user2
作成後にディレクトリを確認すると、以下のように表示されます。
ls -al /home/
total 0
drwxr-xr-x. 4 root root 32 Dec 21 17:40 .
drwxr-xr-x. 8 root root 75 Dec 21 17:25 ..
drwx------. 2 user1 users 62 Dec 21 17:40 user1
drwx------. 2 user2 users 62 Dec 21 17:40 user2
ユーザー領域の移動 #
次に先ほど作成したユーザーのホームディレクトリを /jail 配下へ移動させます。
mv /home/user1 /jail/home/user1
mv /home/user2 /jail/home/user2
移動後にディレクトリを確認すると、以下のように表示されます。
ls -al /jail/home/
total 0
drwxr-xr-x 4 root root 32 Dec 21 22:51 .
drwxr-xr-x 9 root root 86 Dec 21 22:46 ..
drwx------ 2 user1 users 62 Dec 21 22:48 user1
drwx------ 2 user2 users 62 Dec 21 22:48 user2
SSHデーモンは、ログイン時の処理としてユーザーの認証を実施した後に Chroot による隔離を行います。
そのため、公開鍵認証を利用する場合は ユーザー本来の領域にある公開鍵 (/home/user1/authorized_keys) が必要となります。
このパスの不整合を解消するために、今回がシンボリックリンクを利用します。
以下のコマンドを実行しシンボリックリンクを作成してください。
ln -s /jail/home/user1 /home/user1
ln -s /jail/home/user2 /home/user2
これにより、SSHデーモンが鍵を読み取る際、自動的に /jail/home 配下の実体ファイルを参照するようになります。
システムファイル複製 #
Chroot 環境ではシステムの /etc/passwd や /etc/group は利用する事はできません。
しかしユーザーが利用するプログラムや一部のコマンドではこのようなシステムファイルを利用するケースがあります。
そのため、最低限必要な情報のみを抽出し複製しておきます。
grep -E '^(user1|user2):' /etc/passwd > /jail/etc/passwd
grep '^users:' /etc/group > /jail/etc/group
これにより、Chroot 内でも正しいユーザー名やグループ名が表示されるようになります。
次に bash 関連の設定ファイルを複製します。
これにより bash の共通設定の読み込みが正常に行われるようになります。
cp -a /etc/bashrc /jail/etc/bashrc
cp -a /etc/profile /jail/etc/profile
複製後の /jail/etc の構成は次の通りとなります。
ls -al /jail/etc
total 16
drwxr-xr-x 2 root root 62 Dec 21 23:11 .
drwxr-xr-x 9 root root 86 Dec 21 22:46 ..
-rw-r--r--. 1 root root 2709 Nov 29 2023 bashrc
-rw-r--r-- 1 root root 13 Dec 21 22:48 group
-rw-r--r-- 1 root root 80 Dec 21 22:48 passwd
-rw-r--r--. 1 root root 1982 Nov 29 2023 profile
SElinuxの無効化 #
今回の Chroot 構成では、SELinuxのセキュリティポリシーが干渉してしまうため無効化を行います。
初めに以下のコマンドを実行し現在の状態を確認してください。
getenforce
Enforcing と表示される場合は SELinux が有効となっており、Disabled と表示される場合は無効となっています。
既に無効となっている場合は本対応は不要となります。
有効となっている場合は以下の手順にて無効化を行なってください。
vi /etc/selinux/config
以下の設定を記載の内容に修正してください。
# 修正前
SELINUX=enforcing
# 修正後
SELINUX=disabled
無効化が完了したら反映を行うためにサーバーの再起動が必要となります。
以下のコマンドにて再起動を実施してください。
reboot
要件などによりサーバーの再起動が難しい場合は、以下のコマンドを実施しSELinuxを一時的に無効化する事が可能となっております
setenforce 0
ご利用の環境に合わせて対応方法を検討してください。
SSHの設定変更(Chrootの適用) #
次に SSH サーバーの設定を編集し先ほど作成した一般ユーザーグループ users に対して Chroot を有効化します。
初めに以下のコマンドを実行しバックアップを取得してください。
cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config_bk
次に以下のコマンドを実行し編集を行なってください。
vi /etc/ssh/sshd_config
ファイルの末尾に以下の内容を記述してください。
Match Group users
ChrootDirectory /jail
X11Forwarding no
AllowTcpForwarding no
今回記述した設定は以下の通りとなっております。
| ディレクティブ名 | 設定値 | 説明 |
|---|---|---|
ChrootDirectory |
/jail |
ルートディレクトリ / として扱うディレクトリを指定。 |
X11Forwarding |
no |
SSH での X11 転送を設定。 `今回は不要なため無効化 |
AllowTcpForwarding |
no |
TCP ポートフォワーディングの有無を設定。 `今回は不要なため無効化 |
最後に設定した内容を反映させるため SSH デーモンをリロードしてください。
systemctl reload sshd
動作確認 #
設定がすべて完了したら、実際に外部から SSH 接続を行い、意図した通りにディレクトリが制限され操作環境が整っているかを確認してください。
1. ログインと環境の確認 #
問題なくSSHができたら以下のように表示されます。
Last login: Sun Dec 21 23:11:22 2025 from XX.XXX.XXX.XXX
[user1@ホスト名 ~]$
次に、現在地が正しいホームディレクトリであることを確認してください。
$ pwd
/home/user1
次に ls コマンドが正常に利用できるか確認してください。
$ ls -al
total 16
drwx------ 3 user1 users 95 Dec 21 14:11 .
drwxr-xr-x 4 0 0 32 Dec 21 14:05 ..
-rw------- 1 user1 users 45 Dec 21 14:36 .bash_history
-rw-r--r-- 1 user1 users 18 Oct 29 2024 .bash_logout
-rw-r--r-- 1 user1 users 144 Oct 29 2024 .bash_profile
-rw-r--r-- 1 user1 users 522 Oct 29 2024 .bashrc
drwx------ 2 user1 users 29 Dec 21 14:06 .ssh
2. ルートディレクトリの隔離確認 #
次に、システム全体のルート(/)を確認してくさい。
$ ls -al /
total 76
drwxr-xr-x 9 0 0 86 Dec 21 13:46 .
drwxr-xr-x 9 0 0 86 Dec 21 13:46 ..
dr-xr-xr-x. 2 0 0 20480 Dec 21 12:40 bin
drwxr-xr-x 2 0 0 55 Dec 21 13:46 dev
drwxr-xr-x 2 0 0 62 Dec 21 14:11 etc
drwxr-xr-x 4 0 0 32 Dec 21 14:05 home
dr-xr-xr-x. 32 0 0 4096 May 28 2025 lib
dr-xr-xr-x. 39 0 0 20480 May 28 2025 lib64
drwxr-xr-x 3 0 0 17 Dec 21 13:47 usr
ここには /jail 配下に用意した最小限のファイル群のみが表示されます。
本来システム構成として存在しているはずの /var, /proc, /run, /boot などのディレクトリも、ユーザー視点では「存在すらしない」状態になっている事が確認できます。
$ ls -al /var
ls: cannot access '/var': No such file or directory
$ ls -al /proc
ls: cannot access '/proc': No such file or directory
$ ls -al /run
ls: cannot access '/run': No such file or directory
$ ls -al /boot
ls: cannot access '/boot': No such file or directory
この結果からホストOSの本来のルートディレクトリとは完全に隔離されていることがわかります。
以上ので Chroot 環境の構築はすべて完了となります。