Netassist Blog

mount –bind機能について

お久しぶりです。mnakamuraです。

ブログの当番が回ってきましたので、今回はmount --bindについてご説明致します。
linuxにおけるmountとは、HDDやDVD-ROM、USBメモリといったファイルシステムを、
指定した領域にアクセス可能な状態にするコマンドです。

一般的なWindowsのデスクトップPCで言えば、外付けのHDDをケーブルでPC本体に繋ぎ、
HDDへファイルを保存したり、取り出したり出来る状態を思い浮かべて頂ければ
分かりやすいのではないでしょうか。

そんなmountコマンドですが、実はオプションで『-B』もしくは『--bind』を付与すると、
特定のディレクトリを別のディレクトリにマウントする事も出来るのです。
(※カーネルが2.4.0以降の場合)

…そもそも、どういうシチュエーションで使うの?

というお話ですが、例えばWebサイトの制作をAの業者に任せているとします。
制作がある程度進んだ段階で、今度はBの業者にも作業を依頼しました。
BはAの領域の一部にアクセスして作業しなければならないが、
その一部領域以外のAの領域にはセキュリティ上アクセスして欲しくない…。

要するに、Bに『Aの一部の領域のみにアクセスする権利』を与えたい。
そんな時に便利な機能になります。

Aの業者のユーザを『TestUserA』、Bの業者のユーザを『TestUserB』として、
検証用のサーバで試してみましょう。
■1.検証用のユーザーを2つ用意
-----------------------------------------------------------------------------------------------------
[root@mnakamura ~]# useradd TestUserA
[root@mnakamura ~]# passwd TestUserA
ユーザー TestUserA のパスワードを変更。
新しいパスワード:
よくないパスワード: 辞書の単語に基づいています
新しいパスワードを再入力してください:
passwd: 全ての認証トークンが正しく更新できました。

[root@mnakamura ~]# useradd TestUserB
[root@mnakamura ~]# passwd TestUserB
ユーザー TestUserB のパスワードを変更。
新しいパスワード:
よくないパスワード: 辞書の単語に基づいています
新しいパスワードを再入力してください:
passwd: 全ての認証トークンが正しく更新できました。

[root@mnakamura ~]# id TestUserA
uid=510(TestUserA) gid=512(TestUserA) 所属グループ=512(TestUserA)

[root@mnakamura ~]# id TestUserB
uid=511(TestUserB) gid=513(TestUserB) 所属グループ=513(TestUserB)

[root@mnakamura ~]# ll -d /home/TestUserA
drwx------ 2 TestUserA TestUserA 4096 6月 8 16:26 2020 /home/TestUserA

[root@mnakamura ~]# ll -d /home/TestUserB
drwx------ 2 TestUserB TestUserB 4096 6月 8 16:26 2020 /home/TestUserB
-----------------------------------------------------------------------------------------------------

Webサイト制作業者のAとBのユーザがそれぞれ出来たと仮定します。
■2.TestUserAの領域にファイル設置ディレクトリ作成
--------------------------------------------------------------------------------------------------
[root@mnakamura ~]# mkdir /home/TestUserA/Files
[root@mnakamura ~]# touch /home/TestUserA/Files/Testfile1.txt
[root@mnakamura ~]# touch /home/TestUserA/Files/Testfile2.txt
[root@mnakamura ~]# touch /home/TestUserA/Files/Testfile3.txt
[root@mnakamura ~]# ll -A /home/TestUserA/Files
合計 0
-rw-r--r-- 1 root root 0 6月 8 16:30 2020 Testfile1.txt
-rw-r--r-- 1 root root 0 6月 8 16:30 2020 Testfile2.txt
-rw-r--r-- 1 root root 0 6月 8 16:30 2020 Testfile3.txt

[root@mnakamura ~]# chown -R TestUserA:TestUserA /home/TestUserA/

[root@mnakamura ~]# chmod -R 775 /home/TestUserA/

[root@mnakamura ~]# ll -d /home/TestUserA/
drwxrwxr-x 3 TestUserA TestUserA 4096 6月 8 16:30 2020 /home/TestUserA/

[root@mnakamura ~]# ll -AR /home/TestUserA/
/home/TestUserA/:
合計 16
-rwxrwxr-x 1 TestUserA TestUserA 18 3月 23 09:15 2017 .bash_logout
-rwxrwxr-x 1 TestUserA TestUserA 176 3月 23 09:15 2017 .bash_profile
-rwxrwxr-x 1 TestUserA TestUserA 124 3月 23 09:15 2017 .bashrc
drwxrwxr-x 2 TestUserA TestUserA 4096 6月 8 16:30 2020 Files
/home/TestUserA/Files:
合計 0
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile1.txt
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile2.txt
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile3.txt
--------------------------------------------------------------------------------------------------

/home/TestUserA/Files が、
Aの業者が作成しているWebサイトのファイル置き場と仮定しましょう。
Testfileは実際のWebサイトの構成ファイルだと考えて下さい。
■3.TestUserBの領域にmount用のディレクトリを作成
--------------------------------------------------------------------------------------------------
[root@mnakamura ~]# mkdir /home/TestUserB/MountPoint
[root@mnakamura ~]# chown -R TestUserB:TestUserB /home/TestUserB/
[root@mnakamura ~]# chmod -R 775 /home/TestUserB/

[root@mnakamura ~]# ll -d /home/TestUserB/
drwxrwxr-x 3 TestUserB TestUserB 4096 6月 8 17:13 2020 /home/TestUserB/

[root@mnakamura ~]# ll -AR /home/TestUserB/
/home/TestUserB/:
合計 16
-rwxrwxr-x 1 TestUserB TestUserB 18 3月 23 09:15 2017 .bash_logout
-rwxrwxr-x 1 TestUserB TestUserB 176 3月 23 09:15 2017 .bash_profile
-rwxrwxr-x 1 TestUserB TestUserB 124 3月 23 09:15 2017 .bashrc
drwxrwxr-x 2 TestUserB TestUserB 4096 6月 8 17:13 2020 MountPoint
/home/TestUserB/MountPoint:
合計 0
--------------------------------------------------------------------------------------------------

新しい業者Bがプロジェクトに参入。Aの /home/TestUserA/Files の
領域にアクセスしたいですが、/home/TestUserA/ にはA社の機密ファイルがあるので、
そこを経由せずにピンポイントでアクセスする為に、
Bの領域 /home/TestUserB/ の配下にmount用の領域である
/home/TestUserB/MountPoint を作成します。
■4.mount前の状態を比較
--------------------------------------------------------------------------------------------------
[root@mnakamura ~]# ll -A /home/TestUserA/Files
合計 0
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile1.txt
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile2.txt
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile3.txt

[root@mnakamura ~]# ll -A /home/TestUserB/MountPoint
合計 0
--------------------------------------------------------------------------------------------------
mount前は当然、Webサイトの構成ファイルは /home/TestUserA/Files
にのみ置かれています。 /home/TestUserB/MountPoint は空です。
■5.mount --bind実行
--------------------------------------------------------------------------------------------------
[root@mnakamura ~]# mount --bind /home/TestUserA/Files /home/TestUserB/MountPoint
--------------------------------------------------------------------------------------------------
マウント元とマウント先を指定し、mount --bindします。
■6.再度マウント先とマウント元のディレクトリを比較
--------------------------------------------------------------------------------------------------
[root@mnakamura ~]# ll -A /home/TestUserA/Files
合計 0
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile1.txt
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile2.txt
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile3.txt

[root@mnakamura ~]# ll -A /home/TestUserB/MountPoint
合計 0
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile1.txt
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile2.txt
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile3.txt
--------------------------------------------------------------------------------------------------
すると… /home/TestUserB/MountPoint にアクセスすると、
/home/TestUserA/Files の中身が見えるではありませんか。
mountした事で、ピンポイントで中身が見えるようになったんですね。

では、実際にBの業者の立場になって、
TestUserBでサーバにアクセスしてみましょう。
■7.TestUserBに切り替えてmountしたディレクトリを見てみる
--------------------------------------------------------------------------------------------------
[root@mnakamura ~]# su - TestUserB
[TestUserB@mnakamura ~]$ whoami
TestUserB
[TestUserB@mnakamura ~]$ pwd
/home/TestUserB
[TestUserB@mnakamura ~]$ ll -A
合計 16
-rwxrwxr-x 1 TestUserB TestUserB 18 3月 23 09:15 2017 .bash_logout
-rwxrwxr-x 1 TestUserB TestUserB 176 3月 23 09:15 2017 .bash_profile
-rwxrwxr-x 1 TestUserB TestUserB 124 3月 23 09:15 2017 .bashrc
drwxrwxr-x 2 TestUserA TestUserA 4096 6月 8 16:30 2020 MountPoint

[TestUserB@mnakamura ~]$ cd MountPoint/

[TestUserB@mnakamura MountPoint]$ ll -A
合計 0
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile1.txt
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile2.txt
-rwxrwxr-x 1 TestUserA TestUserA 0 6月 8 16:30 2020 Testfile3.txt
--------------------------------------------------------------------------------------------------
上記の通り、TestUserBの領域から、TestUserAの領域を参照出来るようになりました。
但し、このままだと普通にFTPクライアントソフトで
TestUserAのディレクトリには移動出来てしまいます。
なので、chroot設定等で移動出来ないようにしましょう。
■8.FTPクライアントソフト上で、他のTestUserA所有領域への移動制限
--------------------------------------------------------------------------------------------------
今回はFTPでの接続を想定し、vsftpd.confの設定を変えて、chrootを利かせます。

[root@mnakamura ~]# grep -v -e '^\s#' -e '^\s$' /etc/vsftpd/vsftpd.conf
anonymous_enable=YES
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
listen=YES
pam_service_name=vsftpd
userlist_enable=YES
tcp_wrappers=YES

[root@mnakamura ~]# cp -ip /etc/vsftpd/vsftpd.conf{,.$(date +%Y%m%d)}

[root@mnakamura ~]# ll -A /etc/vsftpd/vsftpd.conf{,.$(date +%Y%m%d)}
-rw------- 1 root root 4599 3月 22 21:14 2017 /etc/vsftpd/vsftpd.conf
-rw------- 1 root root 4599 3月 22 21:14 2017 /etc/vsftpd/vsftpd.conf.20200610

[root@mnakamura ~]# vsftpd -v
vsftpd: version 2.2.2

vsftpdのバージョンが2.3.5以降の場合、
エラーが発生する可能性があります。その場合は
allow_writeable_chroot=YES
も追加するようにしましょう。

[root@mnakamura ~]# vi /etc/vsftpd/vsftpd.conf
[root@mnakamura ~]# diff /etc/vsftpd/vsftpd.conf{,.$(date +%Y%m%d)}
96,97c96,97
< chroot_local_user=YES
< chroot_list_enable=YES
chroot_local_user=YES
chroot_list_enable=YES
99c99
< chroot_list_file=/etc/vsftpd/chroot_list
chroot_list_file=/etc/vsftpd/chroot_list

[root@mnakamura ~]# vi /etc/vsftpd/chroot_list
[root@mnakamura ~]# cat /etc/vsftpd/chroot_list
TestUserA

TestUserAは規制対象外にしておきましょう。
vsftpdを再起動します。

[root@mnakamura ~]# service vsftpd status
vsftpd (pid 29573) を実行中…
[root@mnakamura ~]# service vsftpd restart
vsftpd を停止中: [ OK ]
vsftpd 用の vsftpd を起動中: [ OK ]
[root@mnakamura ~]# service vsftpd status
vsftpd (pid 29640) を実行中…

FTPクライアントソフトはFileZillaを使用してみましょう。

すると…
TestUserAでFTP接続すると、/homeディレクトリが見えるので、
ここを経由して色々と移動出来ますが…

TestUserA.jpg

TestUserBでFTP接続すると、/homeディレクトリが見えないので、
mount --bindされた領域以外のTestUserA領域へは移動出来ません。
これで作業用のMountPointディレクトリしかアクセス出来ない状況が完成しました。

TestUserB.jpg
--------------------------------------------------------------------------------------------------
その他、
chgrpによる所属グループの変更…
chmodによるパーミッション変更…
等を利用して柔軟に制限をかける事が可能です。
望み通りの環境を作る為に、状況に応じて調整しましょう。

但し、mount --bindした状態でusermod等で対象ユーザの所属グループを変更すると、
mount --bindされた配下領域の所属グループも変更されたりする場合があるので、
そこは注意が必要です。

尚、通常のmount設定と同様、サーバを再起動するとmountが外れてしまうので、
再起動した際に自動的にmountされるようにしたい場合には、fstabに記載しましょう。
■ex.再起動しても自動的にmountされるようにする
--------------------------------------------------------------------------------------------------
[root@mnakamura ~]# vi /etc/fstab
[root@mnakamura ~]# tail -1 /etc/fstab
/home/TestUserA/Files /home/TestUserB/MountPoint/ none bind 0 0
--------------------------------------------------------------------------------------------------

ちょっと記事が長くなってしまったので、
他にも色々紹介したい事はありますが割愛します。
今回はここまでで。またお会いしましょう。