labunix's blog

labunixのラボUnix

debian Wheezyにセキュアなvsftpdを導入する

■debian Wheezyにセキュアなvsftpdを導入する

 余計なことを言うと、sshでsftpが許可されているのであれば、余り使わない。
 それでもセキュアなFTPが欲しいなら、以下のような設定を行うべき。

 匿名ログインを無効、ローカルログイン可能に変更
 「/etc/ftpusers」に記載されたユーザはログイン出来ない。
 PAMをカスタマイズ、「/etc/ftpgroup」に記載されたsudoグループを許可
 「/etc/ftpusers」を使って、sudoグループの中でも拒否ユーザを指定
 待ち受けIPの制限
 apache2と同じ自己署名証明書と秘密鍵をvsftpd用に1ファイルにしたSSL対応とcurlで一覧表示
 apache2と同じ自己署名証明書と秘密鍵をそのまま使うSSL対応とcurlで一覧表示
 SSLv2の無効
 ローカルログイン時はSSLを使わない設定

 なお、「/etc/hosts.allow」や「/etc/hosts.deny」、
 「xinetd」や「inetd」の説明はFTPのみの話題では無いので省略する。
 また、私の場合、FTPはファイアウォールを通さない(同じセグメントのみ)で
 良いという考えなのでスルーします。

■apache2の自己署名証明書

 Wheezy+openssl+apache2で使える自己署名証明書を作成する
 http://d.hatena.ne.jp/labunix/20130514

$ sudo apt-get install -y vsftpd
$ grep "^listen\|pem" /etc/vsftpd.conf 
listen=YES
rsa_cert_file=/etc/ssl/private/vsftpd.pem

$ sudo ls -l /etc/ssl/private/vsftpd.pem
ls: /etc/ssl/private/vsftpd.pem にアクセスできません: そのようなファイルやディレクトリはありません

$ dpkg -L vsftpd | grep bin/
/usr/sbin/vsftpd

■匿名ログインを無効、ローカルログイン可能に変更

$ sudo grep "^local\|^#anony" /etc/vsftpd.conf 
#anonymous_enable=YES
local_enable=YES
local_umask=022

$ sudo /etc/init.d/vsftpd restart

$ ftp localhost
ftp: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
220 (vsFTPd 2.3.5)
Name (localhost:labunix): labunix
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> quit
221 Goodbye.

■rootユーザはログイン出来ない。
 「/etc/ftpusers」に記載されたユーザはログイン出来ない。

$ sudo grep root /etc/ftpusers 
root
$ ftp localhost
ftp: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
220 (vsFTPd 2.3.5)
Name (localhost:labunix): root
331 Please specify the password.
Password:
530 Login incorrect.
Login failed.
ftp> quit
221 Goodbye.

■「/etc/ftpusers」に記載されたユーザがログイン出来ないルールは
 「/etc/pam.d/vsftpd」に記載されている。

$ sudo grep -v "^#\|^\$" /etc/pam.d/vsftpd 
auth	required	pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed
@include common-account
@include common-session
@include common-auth
auth	required	pam_shells.so

■上記を参考にログイン出来るユーザを「sudo」グループに限定する。

$ echo "sudo" | sudo tee /etc/ftpgroup
sudo

$ grep pam_listfile /etc/pam.d/vsftpd 
auth    required	pam_listfile.so item=group sense=allow file=/etc/ftpgroup
auth	required	pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed

$ id toor
uid=1001(toor) gid=1001(toor) groups=1001(toor)

$ ftp localhost
ftp: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
220 (vsFTPd 2.3.5)
Name (localhost:labunix): toor
331 Please specify the password.
Password:
530 Login incorrect.
Login failed.
ftp> quit
221 Goodbye.

$ id labunix | tr ',' '\n' | grep sudo
27(sudo)

■「toor」ユーザを「sudo」に追加。

$ sudo usermod -a -G sudo toor
$ id toor | sed s/" \|,"/"\n"/g | grep sudo
27(sudo)

■toorユーザがsudoグループユーザとしてログインできるようになった。

$ ftp localhost
ftp: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
220 (vsFTPd 2.3.5)
Name (localhost:labunix): toor
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> quit
221 Goodbye.

■「toor」ユーザが「sudo」グループを取得したとしてもログイン出来ないようにする。

$ echo "toor" | sudo tee -a /etc/ftpusers
toor

$ ftp localhost
ftp: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
220 (vsFTPd 2.3.5)
Name (localhost:labunix): toor
331 Please specify the password.
Password:
530 Login incorrect.
Login failed.
ftp> quit
221 Goodbye.

■「sudo」グループでもログインできないことを確認したので、
 「toor」ユーザから「sudo」グループ権限を剥奪する。

$ id -G toor
1001 27

$ sudo usermod -G 1001 toor
$ id toor
uid=1001(toor) gid=1001(toor) groups=1001(toor)

■待ちうけIPを制限する。

$ netstat -an | grep "\:21"
tcp        0      0 0.0.0.0:21              0.0.0.0:*               LISTEN

$ grep listen_address /etc/vsftpd.conf
listen_address=127.0.0.1

$ netstat -an | grep "\:21"
tcp        0      0 127.0.0.1:21            0.0.0.0:*               LISTEN

$ grep listen_address /etc/vsftpd.conf
listen_address=192.168.45.11

$ netstat -an | grep "\:21"
tcp        0      0 192.168.45.11:21        0.0.0.0:*               LISTEN

■apache2のために用意した自己署名証明書を使う。
 ※よくある公開鍵と秘密鍵を一緒にしたファイル版

$ sudo grep ^- /etc/ssl/certs/lpic303.test.local.pem 
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----

$ sudo grep ^- /etc/ssl/private/lpic303.test.local.key
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----

$ openssl s_client -connect lpic303.test.local:443 | grep SSL
depth=0 C = JP, ST = Tokyo, L = Virtual City, O = Paper Company, OU = Test Unit,
 CN = lpic303.test.local, emailAddress = root@lpic303.test.local
verify error:num=18:self signed certificate
verify return:1
depth=0 C = JP, ST = Tokyo, L = Virtual City, O = Paper Company, OU = Test Unit,
 CN = lpic303.test.local, emailAddress = root@lpic303.test.local
verify return:1
SSL handshake has read 1849 bytes and written 510 bytes
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-GCM-SHA384
SSL-Session:
GET / HTTP/1.0

$ grep "SSL.*lpic303" /etc/apache2/sites-available/vhost-ssl
        SSLCertificateFile    /etc/ssl/certs/lpic303.test.local.pem
        SSLCertificateKeyFile /etc/ssl/private/lpic303.test.local.key

$ sudo cat /etc/ssl/certs/lpic303.test.local.pem /etc/ssl/private/lpic303.test.local.key | \
  sudo tee /etc/ssl/private/vsftpd.pem > /dev/null

$ sudo grep "^ssl\|^rsa_cert" /etc/vsftpd.conf
ssl_enable=YES
ssl_tlsv1=YES
rsa_cert_file=/etc/ssl/private/vsftpd.pem

$ sudo /etc/init.d/vsftpd restart
Stopping FTP server: vsftpd.
Starting FTP server: vsftpd.

■暗号化を要求されるようになった。

$ sudo grep "^ssl\|^rsa_cert" /etc/vsftpd.conf
ssl_enable=YES
ssl_tlsv1=YES
rsa_cert_file=/etc/ssl/private/vsftpd.pem
labunix@lpic303:~$ ftp 192.168.45.11
Connected to 192.168.45.11.
220 (vsFTPd 2.3.5)
Name (192.168.45.11:labunix): labunix
530 Non-anonymous sessions must use encryption.
Login failed.
ftp> quit
421 Service not available, remote server has closed connection

■SSL対応FTPクライアントを導入。
 ftpクライアントとコンフリクトするので入れ替え。

$ apt-cache search "ftp client" | grep SSL
ftp-ssl - The FTP client with SSL or TLS encryption support

$ apt-cache show ftp-ssl | grep Conf
Conflicts: ftp (>= 0.10)

$ sudo apt-get install -y ftp-ssl
$ dpkg -L ftp-ssl | grep bin/
/usr/bin/ftp-ssl
/usr/bin/pftp

$ dpkg -L ftp-ssl | grep bin/
/usr/bin/ftp-ssl
/usr/bin/pftp

$ netstat -an | grep "\:21\|\:990\|\:989"
tcp        0      0 192.168.45.11:21        0.0.0.0:*               LISTEN

$ ftp-ssl 192.168.45.11
Connected to 192.168.45.11.
220 (vsFTPd 2.3.5)
Name (192.168.45.11:labunix): labunix
234 Proceed with negotiation.
[SSL Cipher DES-CBC3-SHA]
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> quit
221 Goodbye.

■ユーザ名、パスワード認証を必要とするので、「s_client」は使えない。

$ openssl s_client -connect 192.168.45.11:21
CONNECTED(00000003)
3074435224:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:766:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 320 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---

■apache2と同様、公開鍵と秘密鍵を分けて記述する方式に変更。
 ※SSL証明書の更新の度に、わざわざvsftpd.pemというファイルを用意しなくて済む。

$ grep /ssl/ /etc/vsftpd.conf
#rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_cert_file=/etc/ssl/certs/lpic303.test.local.pem
rsa_private_key_file=/etc/ssl/private/lpic303.test.local.key

$ netstat -an | grep "\:21\|\:990\|\:989"
tcp        0      0 192.168.45.11:21        0.0.0.0:*               LISTEN

■ディレクトリ一覧には、curlが使える。

$ curl --ftp-ssl --insecure --user labunix:XXXXX ftp://192.168.45.11
dr--------    2 0        0            4096 May 14 18:56 1368525346
...

$ echo "Hello World" | tee test
Hello World
$ curl --ftp-ssl --insecure --user labunix:XXXXX ftp://192.168.45.11/test
Hello World

■SSLv2の無効

$ grep sslv2 /etc/vsftpd.conf
ssl_sslv2=NO

$ sudo /etc/init.d/vsftpd restart

■ローカルユーザのユーザ認証、データ転送時のSSL無効化。
 通常のFTP認証ではSSLが無いので失敗する。
 但し、これはSSL自己署名証明書の不具合に備えたコメントアウトにとどめるべきだと思う。

$ curl --user labunix:XXXXX ftp://192.168.45.11 | head -1
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0curl: (67) Access denied: 530

$ sudo grep force /etc/vsftpd.conf
force_local_logins_ssl=NO
force_local_data_ssl=NO

$ sudo /etc/init.d/vsftpd restart

$ curl --user labunix:XXXXX ftp://192.168.45.11 | head -1
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0  3337    0     0  14626      0 --:--:-- --:--:-- --:--:-- 15031
dr--------    2 0        0            4096 May 14 18:56 1368525346