wiz.code

FTPサーバーの設定

アクセス範囲の制限

FTPでルートが丸見え

FTPサーバーにはvsftpを使用しています。 初期の設定では、ログインしたユーザーのホームディレクトリが初期ディレクトリとなっており、そこからルートディレクトリまでさかのぼることが出来ます。 サーバーの保守としては便利ですがセキュリティ面ではよろしくないので、FTPでアクセスできる範囲を制限しようと思います。

一般的なレンタルサーバーのように、ログインすると役割ごとのディレクトリがあるほうが本格的っぽい。 例えば「public_html」は、Webサーバーで公開するデータ。 「data」は、Webサイトなどで使用する外部から直接アクセスできないデータ。 ログやデータベースのディレクトもあると便利です。

それぞれのディレクトリを一か所に集め、そこをFTP上の仮想ルートにすればよいのですが、データの種類によっては所定の場所を移動できないものもあります。 そこで、仮想ルート用のディレクトリを作り、そこへ各ディレクトリへのリンクを設置する方法で挑戦。

リンクの種類

仮想ルートに設置する各種ディレクトリへのリンク。 Linuxのlnコマンドはリンクを作成するコマンドです。 このコマンドでは「ハードリンク」と「シンボリックリンク」の2種類があります。 まずはこの2つの違いを把握。

ハードリンク
ファイルの実体を示すためのファイル情報(inode)の複製を作り、複数の場所からファイルを参照できるようにする
ディレクトリへのリンクは作成できない
リンク元のファイルを移動してもリンクが維持される
シンボリックリンク
ファイルやディレクトリの実体を示すためのパスを参照する
ディレクトリでもリンクを作成できる
リンク元のファイルやディレクトリを削除・移動するとリンクが切れる

なるほど。 ハードリンクはファイルシステムへ実際にエントリ(inodeと言うらしい)が作成される、ということですね。 プログラムからファイルにアクセスした場合、それがハードリンクであろうと実体であろうと、どちらもノードが存在しますから、ファイル内容を参照したり変更したりできるわけです。

一方のシンボリックリンクは、実体となるディレクトリやファイルへのパスを記憶するだけ。 プログラムからリンクを参照した場合、そこには実体がありません。 ファイルシステム内では、本来存在しない実体を、あたかもそこにあるかのように振舞っているわけです。

今回やろうとしていることは、ディレクトリのリンクですので、ハードリンクは使えません。 シンボリックリンクを使います。

FTPの仮想ルート

「仮想ルート」という言い方が一般的かは分かりませんが、要はFTPにログインしたとき、初めに表示されるディレクトリです。 初期値では、ユーザーのホームディレクトリになっていますが、Windowsのマイドキュメントみたいであまり恰好がよくありません。 ホームディレクトリに、FTP用のルートディレクトリ「ftproot」を作り、そこを仮想ルートとします。

FTP用の仮想ルートを作成

ホームにディレクトリを作ります。 root権限でなくてもよいので、ファイルマネージャで作っちゃいます。

ここに、Webデータを配置するためのディレクトリ「/var/www/」へのシンボリックリンクを作成します。 端末はroot化して、今作成した「ftproot」に移動してあります。

# cd ftproot
# ln -s /var/www/

リンク設置完了。 ひとまず今は、このディレクトリだけあればいいでしょう。

次に、FTPでログインしたときに、このディレクトリをルートとして表示するように設定します。

今回使用しているFTPサーバー「vsftp」では、vsftp.confで設定できるようです。 vsftp.confと同じ場所にディレクトリやファイルを作成するので、移動しておきましょう。

vsftpd.confを編集
# cd /etc/vsftp.d/
# vi vsftp.conf

101: chroot_list_enabled=YES
129: user_config_dir=/etc/vsftpd/user_config

ログインするユーザーごとに、ルートディレクトリを変更するには、101行目にある chroot_list_enable=YES のコメントを外して有効化します。

user_config_dirを追記

さらに、ユーザーごとに設定ファイルを使用できるように「user_config_dir」を指定します。 この項目はなかったので、ファイルの末尾に追記しました。

ユーザー別の設定を置くディレクトリ

ユーザー別の設定を保存するディレクトリを作成します。

# mkdir user_config
wiz用の設定ファイル

このディレクトリに、ユーザー名のファイルを作成し、仮想ルートとするディレクトリのパスを記述します。

# vi user_config/wiz
1: local_root=/home/wiz/ftproot
vsftpを再起動

ファイルを保存したら、vsftpを再起動します。

FTP接続失敗

FTPクライアントで接続……できない。 サーバーから返されたエラー内容を見ると、chrootのリストファイルが読めない、と言ってます。 そりゃまぁ、そんなもの作ってませんからね…。 えっと…、参照しているパスは「/etc/vsftpd/chroot_list」ですね。

chroot_listファイルを作成
# vi chroot_list

1: wiz

このファイルは、単純にユーザー名を列挙すればいいようなので、名前を書いて保存します。

む、今度は"refusing to run with writable root inside chroot()"と言われた。 調べてみると、書き込み権限の設定をしなければならないらしい。 再び、vsftpd.confを開く。

chroot後のアクセス権を変更
# vi vsftp.conf

130: allow_writeable_chroot=YES

微妙にスペル間違ってる気がするけど…。 とりあえず、再起動してテスト。

シンボリックリンクが見えない

今度はログインできました。 が…、シンボリックリンクで作成した「www」が見えません…。 ちゃんと、ftprootを見てるのかなぁ。

ftprootにファイルを置いてみる

試しに、ftprootにファイルを作ってみよう。 これがFTPから見えれば…

見えてる~

あ、見えてますね。 ということは、wwwディレクトリの権限の問題かな。 一旦、wwwの所有者をwizに変更しましょう。

ディレクトリの所有者を変更
# chown wiz /var/www

リンクの鍵マークは消えたけど、まだ出てこない。 vsftpがシンボリックリンクを辿ることを許可してない、とか?

検索中...。

やはりその通り。 ただ、シンボリックリンクを辿れるようにするには、chrootを解除しなければならない! あちらを立てると、こちらが立たず…とはまさにこのコト。 Windows ServerのFTPだと、仮想ディレクトリというのがあって、目的のことがすんなり出来るんだけどなぁ…。

色々と検索していたら、ひとつだけ解決方法がありました。 mountコマンドを使って、特定のディレクトリを「デバイス化」し、ftprootディレクトリ内にマウントしてしまう、という方法。 結構な荒業に見えます。 Windowsで言うところの、substコマンド(任意のディレクトリをドライブ化するコマンド)みたいなものかな。 とにかくやってみましょう。 一旦リンクを除してからマウントします。

初めてのmountコマンド
# cd /home/wiz/ftproot
# rm www
# mount --bind /var/www www

ぐはっ。 ディレクトリが見つからない、とか言われたのでフルパスにしてもだめで、「www」はいらなかったか?と思ってやったら、「ftproot」=「/var/www」になってしまった。 ここは、「www」ディレクトリを作って、上記のコマンドを打てばよかったのか。

いったんマウント解除…。

初めてのumountコマンド...
# umount ./

その後、ディレクトリを作って、改めてmountコマンドを実行したら、wwwディレクトリの中にマウント先(/var/www)の中身が表示されました。 ふぅ…。 FTPクライアントで確かめます。

wwwは見えたけど…

むぅ…。 wwwディレクトリは見えるようになった。 ってか、ディレクトリが実態としてあるから当然だけど、その中身が表示されない。 アクセス権限や所有者を変えてみてもダメ。

あれ…? 詰んだ?

SELinuxを無効化

そういえば、SELinuxのコトを忘れていた。 一度無効にして…。

# setenforce 0
原因判明

あ、出てきた…。 SELinuxかぁ~…。

SELinux通知ブラウザ

SELinux Troubleshooterに通知が来ていました。 ASP.NETの時と同じように、setseboolコマンドで設定を変更する解決法が示されたので試してみます。

SELinuxの設定変更
# setsebool -P ftpd_full_access 1
# setenforce 1

設定変更後、SELinuxを稼働状態にします。 念のため、getenforceで稼働していることを確認し、再度FTPクライアントでアクセスしたところ、問題なくアクセスできました。

mountコマンドでディレクトリをマウントする方法は、少し強引でひっかかるところがあるけど、ひとまずよしとしましょう。

留意点

現時点では、各Webサイトのディレクトリはrootが所有していて、他のユーザーはアクセスのみが許可された状態。 そのため、ファイルをアップロードすることはできません。 権限を変えれば問題なくできるでしょうけど、ここはWebアクセス用のアカウントとグループを作る方法で後日対応します。 次章はFTPSに挑戦しようと思います。

この章のまとめ

  • リンクには「ハードリンク」と「シンボリックリンク」がある
  • ディレクトリのリンクは「シンボリックリンク」のみ
  • うまく動かない時はSELinuxを疑え(2回目)
  • chownコマンド:ディレクトリやファイルの所有者を変更する
  • mountコマンド:--bindオプションで任意のディレクトリを他のディレクトリの配下に置くことが出来る
  • umountコマンド:マウントを解除する

〔 この記事はここまでです。続きは後日公開します。 〕