Compnet

仕事とか遊びとか、日々折々

2019-05-03(金)

今さらだけど FTP サーバーを立てた

Posted by Nakane, R. in technical   

今更感が半端ないですが FTP サーバーを欲しいとの要望があったので、自身の記録がてら構築手順をここにまとめます。 ベースの OS は Debian 8 jessie です。 いつもの Ubuntu でなかったり、現状最新の stretch でなかったりする点については、詳しくは語れない大人の事情をお察しください。

FTP サーバー アプリケーションには Pure-FTPd を使います。 これの選定にあたっては、以下の条件を満たすように考慮しました。

  • FTP でログインするユーザーはシステム ユーザーとは別に管理する (仮想ユーザーだけにログインさせる)。
  • FTP でログインしたユーザー毎にホーム ディレクトリを指定し、そのディレクトリの親ディレクトリを参照させない (ホーム ディレクトリに chroot する)。
  • 設定手順を再現しやすい。

Pure-FTPd 以外にも ProFTPDvsftpd といった FTP サーバー アプリケーションがあり、それぞれ日本語での情報を散見しますが、設定変更をスクリプト化しにくかったり仮想ユーザーの登録・管理が面倒だったりで見送りました。

Pure-FTPD のインストール

まずは Pure-FTPd をインストールします。 Debian の公式リポジトリで提供されているので apt コマンドで以下のようにインストールします。

suso apt -y install pure-ftpd

続いて Pure-FTPd の設定を調整します。 Pure-FTPd の設定情報は、Debian では /etc/pure-fptd ディレクトリにまとめられており、一部の設定が /etc/default/pure-ftpd-common スクリプト ファイルに書かれています。

巷の情報では pure-ftpd.conf ファイル (Debian では /etc/pure-ftpd/pure-ftpd.conf ファイル) を編集するよう書いてあるものをよく見かけます。 しかし Debian ではこのファイルを直接編集するのでは無く、/etc/pure-ftpd/conf ディレクトリに Pure-FTPd の設定パラメーターの名前のファイルを作成してそのファイルにパラメーターの値を記述するのが作法のようです。 例えば、FTP の匿名ログインを禁止する NoAnonymous というパラメーターの値を yes にするのであれば、/etc/pure-ftpd/conf/NoAnonymous ファイルを作り、そこに yes の一行を書いて保存するというようにします。 なお、ユーザー認証に関する設定については /etc/pure-ftpd/conf に保存したファイルのシンボリック リンクを /etc/pure-ftpd/auth ディレクトリに作る必要があるようです。

仮想ユーザーの登録

さて、Pure-FPTd の設定を調整する前に、Pure-FTPd にログインできる仮想ユーザーを登録しておきます。 Pure-FTPd では /etc/passwd ファイルに記されているユーザー情報に基づく unix 認証、共通認証ライブラリを使った PAM 認証、Pure-FTPd 独自の DB である PureDB を参照する認証が使えます。 それ以外に MySQL や PostgreSQL の RDB を参照する認証や、LADP を参照する認証が使えます。

仮想ユーザーの管理には PureDB を使います。 今回は FTP でログインするユーザーをシステム ユーザーとは別にするという要件があるため、unix 認証は使えません。 MySQL や PostgreSQL を参照する認証は RDBMS をインストールが必要で、それなりの数のユーザーを管理するのでなねれば大形すぎますし、その作業も面倒です。 これについては LDAP を参照する場合も同様です。 また、最初にインストールしたパッケージには MySQL、PostgreSQL、LDAP を参照する機能が含まれておらず、別のパッケージ (pure-ftpd-mysql、pure-ftpd-postgresql、pure-ftpd-ldap) をインストールしなくてはなりません。

仮想ユーザーが FTP でログインしたときにそのユーザーにはユーザー ID とグループ ID が割り当てられますが、そのユーザー ID とグループ ID はシステム (OS) に予め登録されていなくてはなりません。 また、数字の小さいユーザー ID はセキュリティの観点からユーザーに割り当てないことが推奨されています。 同様にセキュリティの観点から、仮想ユーザーに割り当てるユーザー ID は FTP 以外の方法でのログインを許可しないのが望ましいといわれています。 このため、仮想ユーザーへの割り当てだけを目的にしたシステム ユーザーを新規に作成するのが一般的です。

ここでも以下のコマンドで仮想ユーザーに割り当てるシステム ユーザーを、システムにログインできないようにホーム ディレクトリを /dev/null で、ユーザー シェルを /usr/sbin/nologin で指定して新たに作ります。 このユーザーの名前は分かりやすいように ftp-user に、グループ ID は既に作成済みの www-data にします。

sudo useradd -c 'for FTP user' -d /dev/null -g www-data -s /usr/sbin/nologin ftp-user

仮想ユーザーを区分けして別のユーザー ID を割り当てたいときは、必要な数のシステム ユーザーを同様に作成しておきます。

仮想ユーザーに割り当てるユーザー ID を用意したら、実際に仮想ユーザーを登録します。 PureDB にユーザーを登録したり修正したりするときは pure-pw コマンドを使います。 仮想ユーザーの名前を user1、ホーム ディレクトリを /var/www/html にして、先ほど作った ftp-user のユーザー ID を割り当てるには以下のようにします。

sudo pure-pw useradd user1 -d /var/www/html -u $(id -u ftp-user)

このコマンドを実行すると /etc/pure-fptd/pureftpd.passwd ファイルにユーザー情報が追加され、/etc/pure-fptd/pureftpd.passwd ファイルが作成・更新されます。 なお上記のようにホーム ディレクトリを -d オプションで指定すると親ディレクトリ (この場合は /var/www/html) の参照をさせません (/var/www/html に chroot します)。 親ディレクトリの参照を許可したいときは -d オプションではなく -D オプションでホーム ディレクトリを指定します。

必要な数の仮想ユーザーを登録したら以下のコマンドで /etc/pure-fptd/pureftpd.passwd ファイルから /etc/pure-fptd/pureftpd.pdb ファイルを生成します。

sudo pure-pw makedb

Pure-FPTd の PureDB は pure-pw makedb コマンドで変換したファイルしか参照できないので、仮想ユーザーを登録したときは pure-pw makedb コマンドの実行を忘れないようにしてください。

以下のように -m オプションを付けて pure-pw useradd コマンドを実行すると、/etc/pure-fptd/pureftpd.passwd ファイルへのユーザー登録と同時に /etc/pure-fptd/pureftpd.pdb ファイルも生成・更新できます。

sudo pure-pw useradd user2 -d /var/www/html -u $(id -u ftp-user) -m

なお、登録した仮想ユーザーの数がある程度以上になると pdb ファイルの生成・更新にもそれなりの時間が掛かります。 一度に登録する仮想ユーザーの数が多いときは、ユーザーを登録するときの pure-pw useradd コマンドに毎回 -m オプションを付けてその都度 pdb ファイルの生成・更新するのではなく、仮想ユーザーをすべて登録した後に pure-pw makepd コマンドを実行する方がいいでしょう。

Pure-FTPd の設定

Debian の場合は Pure-FTPd の設定で本当に基本的な部分は初期値のままでほぼ問題ないので、ユーザー認証の設定だけを行います。 仮想ユーザーを PureDB のファイル (/etc/pure-fptd/pureftpd.pdb ファイル) に登録したので、PureDB で /etc/pure-fptd/pureftpd.pdb ファイルを参照した認証を行うようにします。 さらに unix 認証と PAM 認証は無効にして、PureDB だけで認証するようにします。 これを設定するために以下のコマンドを実行します。

(
  PARAMS=(
    "UnixAuthentication:no"
    "PAMAuthentication:no"
    "PureDB:/etc/pure-ftpd/pureftpd.pdb"
  )
  for PARAM in "${PARAMS[@]}"; do
    echo "${PARAM#*:}" | sudo tee "/etc/pure-ftpd/conf/${PARAM%%:*}" >/dev/null
  done
)

これらの設定項目は /etc/pure-fptd/conf ディレクトリに作成しましたが、すべてユーザー認証に関するもののため /etc/pure-fptd/auth ディレクトリに保存しないと有効になりません。 そこでこれらのファイルのシンボリック リンクを /etc/pure-fptd/auth ディレクトリに作ります。 /etc/pure-fptd/conf/UnixAuthentication と /etc/pure-fptd/conf/PAMAuthentication のふたつのファイルはすでにシンボリック リンクが /etc/pure-fptd/auth ディレクトリに作られているので、残る /etc/pure-fptd/conf/PAMAuthentication/PureDB ファイルのシンボリック リンクを以下のコマンドで作ります。

[ -e /etc/pure-ftpd/auth/60puredb ]  || sudo ln -s ../conf/PureDB /etc/pure-ftpd/auth/60puredb

/etc/pure-fptd/auth ディレクトリにあるファイル (シンボリック リンク) はファイル名の順に読み込まれ、その順に認証が行われるので、他のふたつ (65unix と 70pam) のファイルよりも前に読み込まれるようにファイル名を決めています。 実際には他のふたつ (65unix と 70pam) のファイルはどちらも no であり、これらの認証を使わない設定になっているため、読込順序を気にする意味はありません。

以上の設定を行ったら、Pure-FTPd を再起動して設定を読み込ませます。

systemctl -q is-active pure-ftpd && sudo systemctl restart pure-ftpd || sudo systemctl start pure-ftpd

<おまけ> パッシブモードでつかうポート範囲を制限

この FTP サーバーは AWS の EC2 に Debian 8 jessie を入れて、そこに Pure-FPTd サーバーをインストーして構築しています。 AWS の EC2 なので、インターネットからみたときには NAT-Masquerade の内側であり、セキュリティ グループによるアクセス制限の対象です。 もちろんサーバー用途なので、EIP を割り当ててグローバル IPv4 アドレスが変動しないような措置を採ってあります。

AWS の EC2 で FTP サーバーを構築してインターネットに公開するときは、セキュリティ グループでインバンドの通信を許可しないと行けません。 アウトバウンドの通信の許可も必要ですが、すべてアウトバンドへの通信が初期値で許可されているのでここでは考えません。 また、インターネット側からアクセスするときの IP アドレスと、EC2 自身の持つ IP アドレスが異なることにも留意が必要です。

インバウンドの通信で許可が必要なポートは、制御コネクションで使うポートとパッシブ モードのデータ通信で使うポートです。 このうちの制御コネクションは TCP の 21 番ポートに決まっていますが、パッシブ モードのテータ通信では毎回度ポート番号がランダムに決まります。 ポート番号がランダムに決まるということは、セキュリティ グループでこれを設定するにはすべてのポートを許可せざるをえないということでもありますが、そんなことはセキュリティ的には避けるべきです。 そこでパッシブ モードのデータ通信で使うポートを制限して、セキュリティ グループではその範囲だけを許可すればいいようにします。

また、FTP サーバーはパッシブ モードでの通信要求 (PASV コマンド) に自身のアドレスを返す仕様になっています。 ただし、ここでいう自身のアドレスとは FTP クライアントからの接続先のアドレス、つまり FTP サーバーに接続するためのグローバル アドレスでなくてはなりません。 EC2 は NAT-Masquerade の内側なので、これは EC2 に割り当てている EIP のアドレスを返すようにする必要があります。 そこで、Pure-FTPd に PASV コマンドに対して EIP のアドレスを返すように設定します。

以上を設定するために以下のコマンドを実行します。

(
  PARAMS=(
    "PassivePortRange:30000 30099"
    "ForcePassiveIP:$(curl http://169.254.169.254/latest/meta-data/public-ipv4)"
  )
  for PARAM in "${PARAMS[@]}"; do
    echo "${PARAM#*:}" | sudo tee "/etc/pure-ftpd/conf/${PARAM%%:*}" >/dev/null
  done
)

ここではパッシブ モードのデータ通信に TCP の 30000 番から 30099 番の範囲のポートを使うように設定しています。 AWS の該当するセキュリティ グループで TCP の 21 番宛に加えて、TCP の 30000 番から 30099 番宛のインバウンドの通信を許可するのを忘れないようにしてください。 また PASV コマンドに対しては curl http://169.254.169.254/latest/meta-data/public-ipv4 コマンドで得られる、この EC2 に割り当てたグローバル IP アドレスを返すように設定しています。

設定を行ったら、Pure-FTPd を再起動してこれを読み込ませます。

systemctl -q is-active pure-ftpd && sudo systemctl restart pure-ftpd || sudo systemctl start pure-ftpd

次の記事ではここで構築した Pure-FTPd を FTPs に対応させます。

Comments