【写経】vsftpd のバーチャルユーザを使ってみる

はじめに
----

とある目的のため、今更ながら vsftpd のバーチャルユーザを試します。
サーバ環境は [AWS - ELBはなんでもロードバランスできると聞いたのでFTPしてみる](http://qiita.com/koshigoe/items/7e4e9466e821df547192) にて作成したものを使用します。


pam_userdb (Berkeley DB)
----

### ユーザデータベースを作る

```
$ cat <<EOF > vsftpd-virtual-user.txt
user1
password1
user2
password2
EOF
$ sudo db_load -T -t hash -f vsftpd-virtual-user.txt /etc/vsftpd/vsftpd-virtual-user.db
```

### vsftpd の設定

```
$ sudo cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.orig
$ sudo vi /etc/vsftpd/vsftpd.conf
$ sudo diff -u /etc/vsftpd/vsftpd.conf.orig /etc/vsftpd/vsftpd.conf
--- /etc/vsftpd/vsftpd.conf.orig        2015-09-18 15:43:58.131379615 +0000
+++ /etc/vsftpd/vsftpd.conf     2015-09-19 02:20:40.951605554 +0000
@@ -114,7 +114,7 @@
 # Make sure, that one of the listen options is commented !!
 #listen_ipv6=YES

-pam_service_name=vsftpd
+pam_service_name=vsftpd.virtual
 userlist_enable=YES
 tcp_wrappers=NO

@@ -125,3 +125,16 @@
 pasv_max_port=60010
 use_localtime=YES
 force_dot_files=YES
+
+guest_enable=YES
+guest_username=ftp-test
+user_sub_token=$USER
+local_root=/home/ftp-test/$USER
+hide_ids=YES
+anon_upload_enable=YES
+anon_mkdir_write_enable=YES
+anon_other_write_enable=YES
+anon_world_readable_only=NO
+anon_umask=022
+virtual_use_local_privs=YES
+
```

#### PAM

```
$ cat <<EOF | sudo tee /etc/pam.d/vsftpd.virtual
#%PAM-1.0
auth       required     pam_userdb.so db=/etc/vsftpd/vsftpd-virtual-user
account    required     pam_userdb.so db=/etc/vsftpd/vsftpd-virtual-user
session    required     pam_loginuid.so
EOF
```

### chroot ディレクトリを作成

```
$ sudo install -d -o ftp-test -g ftp-test /home/ftp-test/{user1,user2}
```

### vsftpd を再起動

```
$ sudo /sbin/service vsftpd restart
```

### 接続確認

```
$ ftp user1@52.69.XXX.YYY
Connected to 52.69.XXX.YYY.
220 (vsFTPd 2.2.2)
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
229 Entering Extended Passive Mode (|||60008|).
150 Here comes the directory listing.
226 Directory send OK.
ftp> ls -al
229 Entering Extended Passive Mode (|||60003|).
150 Here comes the directory listing.
drwxr-xr-x    2 ftp      ftp          4096 Sep 19 02:24 .
drwxr-xr-x    2 ftp      ftp          4096 Sep 19 02:24 ..
226 Directory send OK.
ftp> put ~/test.txt ./test.txt
local: /Users/koshigoe/test.txt remote: ./test.txt
229 Entering Extended Passive Mode (|||60010|).
150 Ok to send data.
100% |****************************************************************************************************************************|     5       53.65 KiB/s    00:00 ETA
226 Transfer complete.
5 bytes sent in 00:00 (0.15 KiB/s)
```

### ユーザを追加する

```
$ cat <<EOF >> vsftpd-virtual-user.txt
user3
password3
EOF
$ sudo install -d -o ftp-test -g ftp-test /home/ftp-test/user3
$ sudo db_load -T -t hash -f vsftpd-virtual-user.txt /etc/vsftpd/vsftpd-virtual-user.db
```

```
$ ftp user3@52.69.XXX.YYY
Connected to 52.69.XXX.YYY.
220 (vsFTPd 2.2.2)
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -al
229 Entering Extended Passive Mode (|||60001|).
150 Here comes the directory listing.
drwxr-xr-x    2 ftp      ftp          4096 Sep 19 02:36 .
drwxr-xr-x    2 ftp      ftp          4096 Sep 19 02:36 ..
226 Directory send OK.
ftp> put ~/test.txt ./test.txt
local: /Users/koshigoe/test.txt remote: ./test.txt
229 Entering Extended Passive Mode (|||60010|).
150 Ok to send data.
100% |****************************************************************************************************************************|     5       32.33 KiB/s    00:00 ETA
226 Transfer complete.
5 bytes sent in 00:00 (0.15 KiB/s)
```

### まとめ

- chroot 用のディレクトリはユーザごとに事前に作成しておく必要があります
- chroot 用のディレクトリのパーミッションは `guest_username` で指定したユーザに対応させます
- FTP アカウントの追加はユーザデータベースを更新するだけでよく、vsftpd の再起動は不要でした

### 気になる

- データベースがローカルにあるファイルなあたり
- データベース更新タイミングで瞬断(エラー)が発生するのか
- データベースを NFS などで共有できたとして競合などは発生するのか


pam_mysql (MySQL)
----

### MySQL インストール

```
$ sudo yum install -y mysql mysql-server
$ sudo chkconfig mysqld on
$ sudo chkconfig --list mysqld
mysqld          0:off   1:off   2:on    3:on    4:on    5:on    6:off
$ sudo /sbin/service mysqld start
```

### pam_mysql インストール

```
$ sudo yum install --enablerepo=epel -y pam_mysql
```

### ユーザデータベース作成

```
mysql> CREATE DATABASE ftpusers;
Query OK, 1 row affected (0.00 sec)

mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER on ftpusers.* to ftpuser@localhost identified by '12345';
Query OK, 0 rows affected (0.00 sec)

mysql> USE ftpusers;
Database changed
mysql> CREATE TABLE users(
    ->     id INT AUTO_INCREMENT NOT NULL,
    ->     name CHAR(128) binary NOT NULL,
    ->     passwd CHAR(128) binary NOT NULL,
    ->     primary KEY(id)
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE logs (
    ->     msg VARCHAR(255),
    ->     user CHAR(128),
    ->     pid INT,
    ->     host CHAR(128),
    ->     rhost CHAR(128),
    ->     logtime TIMESTAMP
    -> );
Query OK, 0 rows affected (0.01 sec)
```

### PAM

```
$ cat <<EOF | sudo tee /etc/pam.d/vsftpd.mysql
auth       required     /lib64/security/pam_mysql.so user=ftpuser passwd=12345 host=localhost db=ftpusers table=users usercolumn=name passwdcolumn=passwd crypt=2 use_323_passwd=false sqllog=1 logtable=logs logmsgcolumn=msg logusercolumn=user logpidcolumn=pid loghostcolumn=host logrhostcolumn=rhost logtimecolumn=logtime
account    required     /lib64/security/pam_mysql.so user=ftpuser passwd=12345 host=localhost db=ftpusers table=users usercolumn=name passwdcolumn=passwd crypt=2 use_323_passwd=false sqllog=1 logtable=logs logmsgcolumn=msg logusercolumn=user logpidcolumn=pid loghostcolumn=host logrhostcolumn=rhost logtimecolumn=logtime
EOF
```

### vsftpd.conf

```
$ sudo cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.userdb
$ sudo vi /etc/vsftpd/vsftpd.conf
$ sudo diff -u /etc/vsftpd/vsftpd.conf.userdb /etc/vsftpd/vsftpd.conf
--- /etc/vsftpd/vsftpd.conf.userdb      2015-09-19 02:56:18.477864224 +0000
+++ /etc/vsftpd/vsftpd.conf     2015-09-19 03:08:23.835013951 +0000
@@ -114,7 +114,7 @@
 # Make sure, that one of the listen options is commented !!
 #listen_ipv6=YES

-pam_service_name=vsftpd.virtual
+pam_service_name=vsftpd.mysql
 userlist_enable=YES
 tcp_wrappers=NO

```

### FTP アカウント追加

```
$ mysql -u ftpuser -p
mysql> USE ftpusers;

Database changed
mysql> INSERT INTO users (name,passwd) VALUES('user4', PASSWORD('password4'));
Query OK, 1 row affected (0.00 sec)
```

### chroot ディレクトリを作成

```
$ sudo install -d -o ftp-test -g ftp-test /home/ftp-test/user4
```

### vsftpd を再起動

```
$ sudo /sbin/service vsftpd restart
```

### 接続確認

```
$ ftp user4@52.69.XXX.YYY
Connected to 52.69.XXX.YYY.
220 (vsFTPd 2.2.2)
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -la
229 Entering Extended Passive Mode (|||60005|).
150 Here comes the directory listing.
drwxr-xr-x    2 ftp      ftp          4096 Sep 19 03:12 .
drwxr-xr-x    2 ftp      ftp          4096 Sep 19 03:12 ..
226 Directory send OK.
ftp> put ~/test.txt ./test.txt
local: /Users/koshigoe/test.txt remote: ./test.txt
229 Entering Extended Passive Mode (|||60005|).
150 Ok to send data.
100% |****************************************************************************************************************************|     5       22.60 KiB/s    00:00 ETA
226 Transfer complete.
5 bytes sent in 00:00 (0.14 KiB/s)
```

### まとめ

- pam 用にユーザとデータベースとテーブルを用意すれば利用できます

### 気になる

- pam_mysql が mysql51-libs に依存していた点
- pam_mysql の設定に MySQL への接続情報を埋め込むあたり
- chroot 用にディレクトリを都度作るあたり


まとめ
----

- アカウントの追加を動的に行えることは分かりました
- chroot 用のディレクトリを事前に用意せずに済ませられるのか知りたいところです
- LDAP まで踏み込もうか迷いましたが、LDAP の知識がゼロであるため先送りにしました


参考
----

- [【linux】vsftpd 導入手順（バーチャルユーザー版） at softelメモ](https://www.softel.co.jp/blogs/tech/archives/2437)
- [Vsftpd FTP Server With Virtual Users ( Berkeley DB + PAM )](http://www.cyberciti.biz/tips/centos-redhat-vsftpd-ftp-with-virtual-users.html)
- [[CentOS6.x]vsftpd+MySQLでバーチャルユーザ運用 | ごった煮 - tips about programming and building a server](http://park1.wakwak.com/~ima/centos4_vsftpd0006.html)