【写経】ProFTPDでバーチャルユーザ

TL;DR
----

- とある用件で前知識が必要になったので、雑に検証する事が主目的
- ProFTPD 一つで FTP/SFTP を提供できる事が分かった
- ProFTPD は chroot するホームディレクトリを自動で作れる事が分かった
- ProFTPD はデータベースにレコードを追加するだけで FTP/SFTP アカウントを発行できることが分かった


目標
----

ProFTPD を使って PostgreSQL で管理するバーチャルユーザで FTP と SFTP できる様にします。
運用に耐えられる設定になっているかは問題としません(棚上げ)。


インストール
----

Amazon Linux を使って EC2 インスタンスを用意します。

```
$ sudo yum install --enablerepo=epel -y proftpd postgresql94 proftpd-postgresql
```


PostgreSQL の準備
----

### サーバ

RDS を利用するので省略。

### アカウントテーブル

```
=> CREATE TABLE ftp_users (
  user_id VARCHAR(20) NOT NULL,
  passwd VARCHAR(20) NOT NULL
);
=> INSERT INTO ftp_users VALUES('user1', 'password');
```

### DB接続ユーザ

```
=> CREATE USER nobody PASSWORD 'password';
=> GRANT SELECT ON ftp_users TO nobody;
```


ProFTPD と mod_sql
----

### 設定

```
$ sudo cp /etc/proftpd.conf /etc/proftpd.conf.orig
$ sudo vi /etc/proftpd.conf
$ sudo diff -u /etc/proftpd.conf.orig /etc/proftpd.conf
--- /etc/proftpd.conf.orig      2015-09-19 08:42:17.080279438 +0000
+++ /etc/proftpd.conf   2015-09-19 10:40:17.947791730 +0000
@@ -19,7 +19,7 @@

 # Use pam to authenticate (default) and be authoritative
 AuthPAMConfig                  proftpd
-AuthOrder                      mod_auth_pam.c* mod_auth_unix.c
+# AuthOrder                    mod_auth_pam.c* mod_auth_unix.c
 # If you use NIS/YP/LDAP you may need to disable PersistentPasswd
 #PersistentPasswd              off

@@ -46,6 +46,25 @@
 LogFormat                      default "%h %l %u %t \"%r\" %s %b"
 LogFormat                      auth    "%v [%P] %h %t \"%r\" %s"

+MasqueradeAddress 54.65.XXX.YYY
+PassivePorts 60001 60010
+LoadModule mod_sql.c
+LoadModule mod_sql_postgres.c
+<IfModule mod_sql_postgres.c>
+    SQLAuthenticate   users
+    SQLAuthTypes      Plaintext
+    SQLBackend        postgres
+    SQLConnectInfo    proftpd@proftpd.cpc1qsv2t7us.ap-northeast-1.rds.amazonaws.com:5432 nobody password
+    SQLLogFile        /var/log/proftpd/sql.log
+    SQLUserInfo       ftp_users user_id passwd Null Null Null Null
+    SQLDefaultUID     500
+    SQLDefaultGID     500
+    SQLDefaultHomedir "/home/ec2-user/"
+    CreateHome        on
+    RequireValidShell off
+    AuthOrder         mod_sql.c
+</IfModule>
+
 # Dynamic Shared Object (DSO) loading
 # See README.DSO and howto/DSO.html for more details
 #
```

### 起動

```
$ sudo /sbin/service proftpd start
```

### 接続

```
ftp user1@54.65.XXX.YYY
Connected to 54.65.XXX.YYY.
220 FTP Server ready.
331 Password required for user1
Password:
230 User user1 logged in
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -al
229 Entering Extended Passive Mode (|||60006|)
150 Opening ASCII mode data connection for file list
drwx------   3 user1    500          4096 Sep 19 10:44 .
drwx------   3 user1    500          4096 Sep 19 10:44 ..
-rw-r--r--   1 user1    500            18 Mar  4  2015 .bash_logout
-rw-r--r--   1 user1    500           176 Mar  4  2015 .bash_profile
-rw-r--r--   1 user1    500           124 Mar  4  2015 .bashrc
-rw-------   1 user1    500           658 Sep 19 09:49 .psql_history
drwx------   2 user1    500          4096 Sep 19 08:29 .ssh
226 Transfer complete
ftp> put ~/test.txt ./test.txt
local: /Users/koshigoe/test.txt remote: ./test.txt
229 Entering Extended Passive Mode (|||60007|)
150 Opening BINARY mode data connection for ./test.txt
100% |****************************************************************************************************************************|     5       38.75 KiB/s    00:00 ETA
226 Transfer complete
5 bytes sent in 00:00 (0.28 KiB/s)
```


SFTP
----

### 設定

```
$ sudo cp /etc/proftpd.conf /etc/proftpd.conf.psql
$ sudo vi /etc/proftpd.conf
$ sudo diff -u /etc/proftpd.conf.psql /etc/proftpd.conf
--- /etc/proftpd.conf.psql      2015-09-19 10:47:04.221939858 +0000
+++ /etc/proftpd.conf   2015-09-19 10:55:37.965440674 +0000
@@ -65,6 +65,17 @@
     AuthOrder         mod_sql.c
 </IfModule>

+LoadModule mod_sftp.c
+<IfModule mod_sftp.c>
+    SFTPEngine on
+    SFTPLog /var/log/proftpd/sftp.log
+
+    SFTPAuthMethods password
+    SFTPHostKey /etc/ssh/ssh_host_rsa_key
+    SFTPHostKey /etc/ssh/ssh_host_dsa_key
+    Port 2222
+</IfModule>
+
 # Dynamic Shared Object (DSO) loading
 # See README.DSO and howto/DSO.html for more details
 #
```

### 再起動

```
$ sudo /sbin/service proftpd restart
```

### 接続

```
$ sftp -P 2222 user1@54.65.XXX.YYY -vvvv
user1@54.65.XXX.YYY's password:
Connected to 54.65.XXX.YYY.
sftp> ls
test.txt
sftp> put test.txt a.txt
Uploading test.txt to /a.txt
test.txt                                                                                                                               100%    5     0.0KB/s   00:00
```


おまけ：ホームディレクトリ
----

### ホームディレクトリカラムを追加

```
=> ALTER TABLE ftp_users ADD COLUMN homedir VARCHAR(255);
=> UPDATE ftp_users SET homedir='/home/ec2-user/user1' WHERE user_id='user1';
=> ALTER TABLE ftp_users ALTER COLUMN homedir SET NOT NULL;
```

### 設定

```
$ sudo cp /etc/proftpd.conf /etc/proftpd.conf.sftp
$ sudo vi /etc/proftpd.conf
--- /etc/proftpd.conf.sftp      2015-09-19 11:04:48.908558616 +0000
+++ /etc/proftpd.conf   2015-09-19 11:14:46.145880479 +0000
@@ -56,7 +56,7 @@
     SQLBackend        postgres
     SQLConnectInfo    proftpd@proftpd.cpc1qsv2t7us.ap-northeast-1.rds.amazonaws.com:5432 nobody password
     SQLLogFile        /var/log/proftpd/sql.log
-    SQLUserInfo       ftp_users user_id passwd Null Null Null Null
+    SQLUserInfo       ftp_users user_id passwd Null Null homedir Null
     SQLDefaultUID     500
     SQLDefaultGID     500
     SQLDefaultHomedir "/home/ec2-user/"
```

- ディレクトリがなければ作る設定 `CreateHome on` は先の手順で設定済み
- ホームディレクトリ用カラム `homedir` を使う様に `SQLUserInfo` の該当欄を `Null` から `homedir` に変更した

### 確認

```
$ sftp -P 2222 user1@54.65.XXX.YYY
user1@54.65.XXX.YYY's password:
Permission denied, please try again.
user1@54.65.XXX.YYY's password:
Connected to 54.65.XXX.YYY.
sftp> ls -al
drwx------    2 user1    500          4096 Sep 19 11:14 .
drwx------    2 user1    500          4096 Sep 19 11:14 ..
```

```
[ec2-user@ip-172-31-12-219 ~]$ ls /home/ec2-user
a.txt  test.txt  user1
```


まとめ
----

- PostgreSQL で FTP/SFTP のアカウントを管理する事ができました
- ProFTPD で FTP/SFTP を利用する事ができました
- chroot するディレクトリを自動で作らせる事ができました


棚上げした課題
----

- FTP と SFTP でアカウントが同一になっている
- ProFTPD の設定に PostgreSQL の接続情報を埋め込んでいる
- ユーザテーブルに平文パスワードを保存している
- chroot するホームディレクトリのパーミッションまわりが適当
- アカウントの UID/GID が適当
- SFTP のポート番号の設定場所が適当(バーチャルホストで分けてない)
- SFTP のホスト鍵が適当
- ディレクトリの自動作成はセキュリティ的にどう考えるべき　なのか


参考
----

- [ProFTPD module mod_sql](http://www.proftpd.org/docs/contrib/mod_sql.html)
- [ProFTPD module mod_sftp](http://www.proftpd.org/docs/contrib/mod_sftp.html)
- [ProFTPDとPostgresqlの連携](http://www.gside.org/Gentoo/proftpd/proftpd_postgresql.html)
- [mod_sftpでProFTPDをSFTPサーバとして動かす - 黒糖々日記/kokutoto diary](http://d.hatena.ne.jp/kokutoto/20100727/p1)