純規の暇人趣味ブログ

首を突っ込んで足を洗う

vsftpdのセキュリティ対策

      HimaJyun

Webサーバでコンテンツを管理するために導入されているFTP

そのFTP用のサーバとして利用されているvsftpd、どうすればこれをより安全に出来るか、自分の知り得る方法をいくつか紹介してみようと思います。

まずは基本

一応Ubuntu 16.04として説明を進めますが、設定の話なのでCentOSでもそう変わらないでしょう。

パスワードの強化

もはやFTP云々は関係ないですが、やはりパスワードが強力である事に越した事はありません。

「0000」なんて以ての外ですよ、サーバなんですから12桁くらいはあった方が良いでしょう。

(もちろん、パスワードが強ければ完璧と言う訳ではありませんが……)

パスワード変更のコマンドは「passwd」です。

SSLの有効化

せっかくのよいパスワードであっても通信のやり取りが暗号化されてなければ全くの無意味です。

FTPでもSSLを利用できるように設定しましょう。

まずは設定ファイルを開きます。

sudo editor /etc/vsftpd.conf

以下を参考に設定を変更します。

# YESにしてSSLを有効化
ssl_enable=YES
# SSLv2とv3は脆弱性があるので使わない
ssl_sslv3=NO
ssl_sslv2=NO
ssl_tlsv1=YES
# FileZillaが対応していない事がある(らしい)のでHIGHにしておく
ssl_ciphers=HIGH
# ローカルの接続にSSLの使用を強制するか
# 当然ながらYESの方が安全、基本SSLの有無はクライアントで選べるのでYESでもNOでも問題はない
force_local_logins_ssl=YES
force_local_data_ssl=YES
# 使用する証明書、snakeoilはUbuntuインストール時に自動で用意されるオレオレ証明書
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key

FTPSとSFTP

FTPは暗号化されていないので論外だとして、FTPSとSFTPを混同している方が案外多い様なので念のため説明しておきます。

FTPSは「SSLで暗号化したFTP」、対してSFTPは「SSHで暗号化したファイル転送

これらの2つはまず第一に根本的に違う物です、同じ様な名前で同じ様な事が出来るってだけで全く異なる仕組みです。

FTPSは1つの規格として決まっている物ですが、SFTPは単にSSHサーバの機能の1つとして提供されているだけなので規格などはありません。

鍵認証を使えると言う点ではSFTPの方がより安全かも知れませんが、WordPressを利用したければほぼ必然的にFTPSになるかと思われます。

WordPressも実はSFTPが使えるのですが、秘密鍵と公開鍵の両方をサーバ上に置くとか言うクソお察し実装なので、WordPressを使う予定があるのであればFTPSでよいでしょう。(もう少しマシな実装のプラグインもありますが、FTPSで間に合う物をSFTPにするためにプラグインを使うってのもちょっと)

匿名アカウントのログインを拒否

FTPにはファイル配布に使うためのアノニマスFTPと言う物があります。

これは、FTPに必要なユーザ認証の際にユーザ名を「anonymous」にする(パスワードは慣習的に自分のメールアドレスにする)事で誰でもログイン出来る様にする機能です。

今でもアノニマスFTPで配布されている事は多々ありますが、それらはほぼ大抵多くの場合同時にHTTPでも配布されています。(昨今のコンピュータや回線などは非常に発達しているのでHTTPで配信しても十分間に合う)

が、その仕組みはよほど特殊な用途に限られます、普通に使う分には誰でもログイン出来る危険性を孕むデメリット以外の何物でもないので無効化してしまいましょう。

先程同様「/etc/vsftpd.conf」を開いて、以下の様に設定します。

anonymous_enable=NO

普通はデフォルトでNOだとは思いますが、一応確認しておきましょう。

ftpd_bannerも一応変更

FTPでは接続時にサーバからウェルカムメッセージとやらを送信するのですが、vsftpdではデフォルトでご親切にバージョンを自白する様になっています。

バージョンが入ってるくらい(きちんとアップデートしていれば)実際どうって事ないのですが、Webサーバ基準で考えると「メッセージにバージョンが含まれるなんて論外だZe!!(言い過ぎ?」がデフォなので一応同じようにバージョンを自白しないように変更しておこうと思います。

と言っても簡単、「/etc/vsftpd.conf」の「ftpd_banner」に適当な文字を設定するだけです。

ftpd_banner=AIEEEEE!!

(やらない方が良いとは思いますが)一応日本語でも行けるみたいですよ、少なくとも手元のFileZiilaでは……

更にセキュアに

ここから少しややこしくなって来ますが頑張って付いてきてくださいね~

ポート番号を変更

FTPで使用するポート番号をデフォルト以外の物に変えるだけでもかなりの効果があるようです。

例によって「/etc/vsftpd.conf」に以下の様に追記します。

listen_port=10021

10021の所は何番でも良いですが、基本1024~49151番を使うのが良いでしょう。

0~1023番はウェルノウンポートで重複の可能性が高いので使わない方が良いです。

また、49152~65535番はどちらかと言うとクライアントが接続のために使うポートとしての利用が多いでしょうから、やはりあまり使わないかと

ここはオフトピックなので詳しい説明はWikipediaに投げるとして、早い話他のサービスと被りさえしなければ良いのです。

FTPクライアントを利用する際には変更したポート番号を指定するのを忘れずに……

ログイン出来るユーザを制限

普通は管理者ユーザとWebサイト用ユーザは分ける物です。

なので、今回の場合Webサイト用ユーザのみがログイン出来れば良い訳であって、それ以外のユーザはログインさせる必要がありません(それこそ、管理者ユーザは鍵認証のSFTPを使う、などの使い分けを行えばよいのです。)

「/etc/vsftpd.conf」に以下の様に追記してユーザリストを利用することで実現できます。

# ユーザリストを利用する
userlist_enable=YES
# YES/NOで挙動が変わるので要注意
# NO->リストに記載されたユーザのみがログインできる(ホワイトリスト)
# YES->リストに記載されたユーザがログイン出来なくなる(ブラックリスト)
userlist_deny=NO
# ユーザリストのファイルを指定
userlist_file=/etc/vsftpd/user_list

次に「userlist_file」で指定したファイルにログインを許可するユーザを記載して行きます。

1行に1ユーザずつ記載して行きます、例として「hoge」と「fuga」ユーザのログインを許可する場合は以下の様になります。

hoge
fuga

こうする事で不必要なユーザがログイン出来なくなり、意図しないユーザでログインされる可能性をなくせます。

特定のディレクトリしか操作出来ないようにする

複数人でバーチャルホストを利用して別々のサイトを公開している、とかでもない限り、Webサイトのコンテンツは「/var/www」とかにあると思います。

Webサイトを管理するユーザが「/var/www」より上のディレクトリ(/varとか)を操作出来る必要はありません。

しっかり制限して不必要なファイルを触られないようにしましょう、そうすればもし仮にアカウントを乗っ取られたとしてても被害を抑える事が可能です。

# chrootを利用する
chroot_local_user=YES
# ディレクトリが書き込み可能でもchrootを利用する
allow_writeable_chroot=YES
# chrootの例外リストを利用する
chroot_list_enable=YES
# chrootの例外リストの場所
chroot_list_file=/etc/vsftpd/chroot_list

「chroot_list_file」で指定したファイルに記載されているユーザは例外的にchrootの対象から外すことが出来ます。

例として「fuga」と「piyo」ユーザを例外にする場合の設定です。

fuga
piyo

ユーザ別にchrootのディレクトリを変更する場合

「hoge」ユーザのコンテンツは「/var/www/hoge」に、「fuga」ユーザのコンテンツは「/var/www/fuga」にある場合にchrootを活用したい場合はuser_configが役に立ちます。

「/etc/vsftpd.conf」に「user_config_dir」を追記しましょう。

user_config_dir=/etc/vsftpd/user_conf

「user_config_dir」で指定した場所にディレクトリを作成します。

sudo mkdir -p /etc/vsftpd/user_conf

そしてその中にユーザ名と同じ名前のファイルを作成し、上書きする設定を書いていきます。

例として、「hoge」ユーザのlocal_rootを「/var/www/hoge」に変更する場合は、まず最初にhogeファイルを作成して

sudo editor /etc/vsftpd/user_conf/hoge

その中に上書きしたい設定を書き込みます。

local_root=/var/www/hoge

chroot+WordPressの注意点

WordPressの更新などでFTPを利用する際にchrootが有効になっていると、WordPress(PHP)の取得するパスとFTP上でのパスに相違が発生します。

これはwp-config.phpに以下の3つの設定を加えることで解決できます。

define('FTP_BASE', '/wp/');
define('FTP_CONTENT_DIR', '/wp/wp-content/');
define('FTP_PLUGIN_DIR', '/wp/wp-content/plugins/');

ここで指定するパスは「FTPから見たWordPressのパス」です、早い話が「実際のパスからchroot分を取り除いたパス」です。

え?分かりづらいって?、WordPressが「/var/www/wp」にあって、chroot(local_root)のパスが「/var/www」なら「/wp/」を指定するのですよ。

FTP専用ユーザにする

普通は管理者ユーザとWebサイト用ユーザは分ける物です。(2回目)

Webサイト用ユーザはFTPでしかログインされない事が分かり切っています。

それではどうするか、そのユーザをFTP以外でログイン出来なくすれば良いのです。

ログイン出来るシェル、出来ないシェル

vsftpdはそのユーザがログイン出来るか否かを設定されたデフォルトシェル(多くの場合/bin/bashになっている)で判別します。

ユーザのデフォルトシェルが「/etc/shells」と言うファイルに記載されていればログイン可能、されていなければ不可能、となります。

ユーザをFTP専用にする

CentOSとかだと/sbin/nologinが/etc/shellsに含まれていて、デフォルトシェルにこれを指定するだけで良いみたいです。

Ubuntuの場合は含まれておらず、また、daemonによって/bin/falseだったり/sbin/nologinだったりを使用しているので、どちらか片方を/etc/shellsに追加するのは抵抗があります。

なので、ここでは一目でFTP専用だと分かる「ftponly」シェルを作成、追加してFTP専用ユーザを作成しようと思います。

まずは適当な場所(/usr/local/bin/ftponly)にファイルを作成します。

sudo editor /usr/local/bin/ftponly

中身はFTPしか使えない事を示すテキストをechoしてやれば十分でしょう。

#!/bin/sh
/bin/echo "This user can be only ftp login."
exit 0

で、これに実行権限を与えて……

sudo chmod +x /usr/local/bin/ftponly

/etc/shellsに追加してやる、と

echo "/usr/local/bin/ftponly" | sudo tee -a /etc/shells

FTP専用にするユーザのデフォルトシェルにこれを指定します。(SSHにはログイン出来なくなるので間違えてもサーバの管理者ユーザを指定しないように)

sudo usermod -s /usr/local/bin/ftponly ユーザ名

最後に

一通りの設定が終わったら再起動しましょう。

sudo systemctl restart vsftpd

あくまで僕の知っている手法をいくつか掲載しただけですが、セキュリティ対策としては十分使える手法だと思います。

あと、どうでも良いですが、vsftpdは「Very Secure FTP Daemon」の略ですよ、なので稀に「vsFTPd」と記載されている事があるのです。

(更にどうでも良いですが、daemonとdemonは厳密には微妙に異なるのですよ、ざっと説明するとdaemonは守護天使とかの意味です。)

 - サーバ運営