[AWS] EC2をFTPサーバーとして構築 + FTPの色々な設定をしてみた

# はじめに
AWSのファイルストレージサービスであるEFSにローカルからファイルを転送するため、題名の構築が必要でした。
EC2にファイルをFTP接続で設置できるように、FTPサーバーとして構築します。

# 事前準備
・EC2を事前に設置
インターネットゲートウェイやサブネットも作成済み
[こちらを参考にしました](https://qiita.com/MayForBlue/items/c96674fb6aac5852a978)

・EC2のインバウンドのセキュリティーグループはこちらの設定にしてください。
「ポート21」はFTP通信でFTPサーバー接続用
「ポート22」はSSH接続でEC2サーバー接続用
「ポート60001-60010」はファイルを置く時に使用するポート。複数ポートを確保することで、接続時、負荷を分散できます。
<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/a73ac045-f5dd-ba25-1a47-d0afc6b54edb.png">


# 流れ
①EC2をFTPサーバーとして構築
②rootユーザーでFTP接続する
③rootユーザーの使用を禁止し、別のユーザーを作成する
④作成したユーザーが他のディレクトリにアクセスしファイル転送する方法
⑤FTPユーザごとにホームディレクトリを指定する
⑥接続したユーザーのホームディレクトリより上の階層に対してアクセスを禁止する
⑦接続したユーザーのホームディレクトリより上の階層に対してアクセスをできるようにする
⑧ユーザーごとに表示できるディレクトリを制限する
⑨ファイルの説明
⑩ログファイルの見方

# EC2をFTPサーバーとして構築

まずEC2にSSH接続します

```
$ ssh -i ~/.ssh/ec2-key.pem ec2-user@✕✕.✕✕✕.✕✕✕.✕✕
```
[詳しい方法はこちら](https://qiita.com/holdout0521/items/7010ab2401c813d67d0f#ssh%E6%8E%A5%E7%B6%9A%E6%96%B9%E6%B3%95)

アップデート実行

```
$ sudo yum update -y
```
FTPクライアントをインストール

```
$ sudo yum install -y ftp
```
vsftpdをインストール

```
$ sudo yum install -y vsftpd
```
vsftpdの起動と自動起動設定をします。設定することでサーバーが再起動すると、vsftpdも自動で起動します。

```
$ sudo systemctl enable vsftpd
$ sudo systemctl start vsftpd
$ sudo systemctl status vsftpd
● vsftpd.service - Vsftpd ftp daemon
   Loaded: loaded (/usr/lib/systemd/system/vsftpd.service; enabled; vendor preset: disabled)
   Active: active (running) since 
```
起動していることが確認できました。

vsftpd.confを編集していくのですが、その前に、デフォルト設定を`vsftpd.conf.org`というファイル名でコピーしておきます。こちらは編集しません。

```
$ cd /etc/vsftpd/
$ sudo cp -a vsftpd.conf  vsftpd.conf.org
```
`vsftpd.conf`を編集します。

```
$ sudo vim vsftpd.conf
```
以下の5行を`vsftpd.conf`の一番下に追加し、保存します。

```vsftpd.conf
pasv_address=XX.XXX.XXX.XXX  #EC2のパブリックIPアドレス（SSH接続時のアドレスと同じ）
pasv_enable=YES  #パッシブモードON
pasv_addr_resolve=YES  #パッシブモードの接続先IPアドレスをホスト名から取得
pasv_min_port=60001　　#接続時の最小ポート番号
pasv_max_port=60010  #接続時の最大ポート番号
```
[vsftpd.confファイルのの詳しい内容を知りたいかたはこちら](https://qiita.com/dogyear/items/289b314db9af42e15cfa)

`vsftpd.conf`を編集しましたので、再起動します。

```
$ sudo service vsftpd restart
```
# rootユーザーでFTP接続する
「ftpuser」と「user_list」ファイルを編集します。
それぞれのファイルの`root`をコメントアウトして`#root`に修正します。

```
$ sudo vim /etc/vsftpd/user_list 
```

```/etc/vsftpd/user_list:/etc/vsftpd/user_list
# root
```

```
$ sudo vim /etc/vsftpd/ftpusers
```

```/etc/vsftpd/ftpusers:/etc/vsftpd/ftpusers
# root
```

**「user_list」**は、userlist_deny=YES もしくは記述が無い場合、接続禁止リストとして機能します。
つまり、「このリストに記述されているユーザーは FTP 接続ができない」ということになります。

**「ftpusers」**は、アクセスを禁止するためのリストです。
user_listよりも優先順位が高いので、user_listで許可されているユーザーであっても、このリストにユーザー名を書かれてしまうとアクセスできません。

rootユーザーのパスワードを設定します

```
$ sudo passwd root
ユーザー root のパスワードを変更。
新しいパスワード:
新しいパスワードを再入力してください:
passwd: すべての認証トークンが正しく更新できました。
```
FTPサーバーに接続できるか確認します。

```
$ ftp
ftp> open xxx.xxx.xx.xx(パブリックipアドレス)
Connected to xxx.xxx.xx.xx (xxx.xxx.xx.xx).
220 (vsFTPd 3.0.2)
Name (xxx.xxx.xx.xx:ec2-user): root
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
```
FTP接続できると確認できましたので、FileZillaなどのツールで確認します。
<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/18962422-5d8c-d17e-19f5-edabaee7eacb.png">


# rootユーザーの使用を禁止し、別のユーザーを作成する
rootだとEC2サーバー内の全てのディレクトリとファイルにアクセスする権限がありますので、rootを使用できないよう`rootユーザーのログインを拒否`することができます。
先程の/etc/vsftpd/ftpusersの`#root`のコメントアウトを消すとログインできません。

新規でユーザーを作成します。
ユーザー名：ftp-user、パスワード：hogehogepasswordの設定でユーザーを作成します。

```
$ sudo useradd ftp-user

$ sudo passwd ftp-user
ユーザー ftp-user のパスワードを変更。
新しいパスワード:
新しいパスワードを再入力してください:
passwd: すべての認証トークンが正しく更新できました。
```

# 作成したユーザーが他のディレクトリにアクセスしファイル転送する方法

ただし、ftp-userユーザーは、EC2内の`/home/ftp-user`配下しかファイルが転送できません。
もし、EC2内の`/mnt`や`/var/www/html`にアクセスしてファイルを転送したい場合、ディレクトリの所有者を変更する必要があります。

```
$ ls -la /mnt
合計 0
drwxr-xr-x  2 root root   6 10月  1 13:50 .
dr-xr-xr-x 18 root root 257 10月  1 12:55 ..
```
/mntは、ユーザー所有権とグループ所有権がrootであると分かります。
そのため、ユーザー所有権とグループ所有権をftp-userに変えることで/mntへアクセスできるようにします。

```
$ sudo chown ftp-user:ftp-user /mnt
$ ls -la /mnt
合計 0
drwxr-xr-x  2 ftp-user ftp-user   6 10月  1 13:50 .
dr-xr-xr-x 18 root     root     257 10月  1 12:55 ..
```
[chownコマンドの詳しい内容についてはこちら](https://webkaru.net/linux/chown-command/)
/mntにアクセスし、ファイルの転送できることを確認しました。
AWSのファイルストレージサービスであるEFSを用いて、EC2の/mntディレクトリ配下とEFSをマウントすることがありますので、使う場面はありますね。
[こちらの記事では、EFSをEC2にマウントさせる方法を記載しています。](https://qiita.com/holdout0521/items/8564791feed63a39ad2f)


# FTPユーザごとにホームディレクトリを指定する
ftp-userは、ログイン時、`/home/ftp-user`がホームディレクトリになります。
ログイン時、`/home/ftp-user`ではなく`/mnt`がホームディレクトリになるよう設定します。

```
$ cd /etc/vsftpd/
$ ls
chroot_list  ftpusers  user_list  vsftpd.conf  vsftpd.conf.org  vsftpd_conf_migrate.sh

$ sudo vim vsftpd.conf
```
vsftpd.confの設定に下記の内容を記載します。
ユーザごとの設定ファイルを参照する為のパスを記載します。

```vsftpd.conf
user_config_dir=/etc/vsftpd/vsftpd_user_conf
```

vsftpd_user_confディレクトリを作成します。

```
$ sudo vim /etc/vsftpd/vsftpd_user_conf/ftp-user
```

`vsftpd_user_confディレクトリ配下`にftp-userファイルを作成し、ホームディレクトリを設定します。

```/etc/vsftpd/vsftpd_user_conf/ftp-user:/etc/vsftpd/vsftpd_user_conf/ftp-user
local_root=/mnt
```

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/5625602f-5108-8c1b-d9df-9e06c021d5f5.png">



/mntにchrootされました！






# 接続したユーザーのホームディレクトリより上の階層に対してアクセスを禁止する

vsftpd.confに以下の内容を記入し、再起動すると、接続したユーザーのホームディレクトリより上の階層に対してアクセスを禁止できる

```vsftpd.conf
chroot_local_user=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list
allow_writeable_chroot=YES
```
**chroot_local_user=YES**:`ログイン後にユーザーのホームディレクトリにchrootする`

**chroot_list_enable=YES**:`chrootをしても例外的に上の階層にアクセスできるユーザーをリスト管理する`

**chroot_list_file=/etc/vsftpd/chroot_list**:`↑↑のリストであり、ここに書かれたユーザーは上の階層にアクセスできる`
(chroot_listは作成する必要がある)

**allow_writeable_chroot=YES**:`chroot先での書き込みを許可する(ない場合、ホームディレクトリ先が書き込み権限がないとアクセスできなくなる)`

```
$ sudo service vsftpd restart
```

ftp-userは、ホームディレクトリより上の階層に、アクセスできなくなりました！

# 接続したユーザーのホームディレクトリより上の階層に対してアクセスをできるようにする
結論から言うと、先程`chroot_list_file=/etc/vsftpd/chroot_list`と設定しましたが、`chroot_list`ファイルを作成し、そこにホームディレクトリより上の階層に対してアクセスをできるようにしたいユーザーを記入する。

```
$ sudo vim chroot_list
```

```chroot_list:chroot_list
# ここに記載されたユーザーは、ホームディレクトリより上の階層に対してアクセスをできる
ftp-user
```

ftp-userは、ホームディレクトリより上の階層に対してアクセスをできるようになりました！

# ユーザーごとに表示できるディレクトリを制限する

mntディレクトリ配下に、`efs`・`efs2`・`efs3`・`efs3`ディレクトリがあります。

```
mnt/
├ efs
├ efs2
├ efs3
└ efs4
```
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/af042d08-00c9-cb03-7ef9-54524e1af0e0.png">

ftp-userには、`efs2`・`efs3`ディレクトリを操作してほしくないので、`efs2`・`efs3`が表示されない設定をしていきたいと思います。

vsftpd.confファイルに以下の設定がされているか確認します。されていなければ、設定します。

```
$ sudo vim /etc/vsftpd/vsftpd.conf
```

```/etc/vsftpd/vsftpd.conf
chroot_local_user=YES
user_config_dir=/etc/vsftpd/vsftpd_user_conf
```

そして、`/etc/vsftpd/vsftpd_user_conf/ftp-user`　のファイルがなければ作成します。

```
$ sudo vim /etc/vsftpd/vsftpd_user_conf/ftp-user
```
ftp-userファイルに表示したくないファイルやディレクトリを記載します。

```/etc/vsftpd/vsftpd_user_conf/ftp-user
deny_file={efs2,efs3}
hide_file={efs2,efs3}
```
ftp-userでログインすると、`efs2`・`efs3`ディレクトリが表示されなくなりました！
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/c55a6111-1b51-01d6-a52d-4e76ea4b3433.png">


# ファイルの説明

現在、`/etc/vsftpd`配下には以下のファイルとディレクトリがあります。


```
/etc/vsftpd/
 ├ chroot_list
 ├ user_list
 ├ ftpusers
 ├ vsftpd.conf
 ├ vsftpd.conf.org
 └ vsftpd_user_conf - ftp-user
```

一つ一つ説明していきます。

## chroot_listファイル

vsftpd.confの設定で有効な場合、制限をかけたいユーザーを設定できます。
設定したユーザーは上位ディレクトリへの移動ができなくなります。
chroot_list_enableをYESにした場合、chroot_list_fileで指定したchroot_listファイルは必須になります。
ファイルが存在しない場合、全てのユーザがログインできなくなるので、ユーザいない場合でも、空のファイルを作る必要があります。

```
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list
```

## user_listファイル
ユーザーのアクセスを禁止、許可する制御ファイルです。

vsftpd.confの下記の設定内容によって意味が変わります。

### `「user_listファイルに追加したユーザーのアクセスを禁止する場合」`

```vsftpd.conf
userlist_enable=YES
userlist_deny=YES #もしくは記述が無い場合
```

```user_list:user_list
root #rootユーザーはアクセスできない
```


### `「user_listファイルに追加したユーザーのみアクセスを許可する場合」`

```vsftpd.conf
userlist_enable=YES
userlist_deny=NO
```

```user_list:user_list
root #rootユーザーのみアクセスできる
```

## ftpusersファイル
ユーザーのアクセスを禁止するためのリストです。
user_listよりも優先順位が高いので、user_listで許可されているユーザーであっても、このリストにユーザー名を書かれてしまうとアクセスできません。




## vsftpd.confファイル
FTPサーバーの設定ファイルです。

## vsftpd.conf.orgファイル
FTPサーバーの設定のデフォルトファイルです。
基本的には触りません。


## vsftpd_user_confディレクトリ
ユーザーごとにファイルを作成し、ユーザーごとの設定をすることができるディレクトリです。

```vsftpd_user_conf/ftp-user:vsftpd_user_conf/ftp-user
# ホームディレクトリを指定
local_root=/mnt

# 表示したくないディレクトリ
deny_file={efs2,efs3}
hide_file={efs2,efs3}
```

# FTP接続エラー
以下のように、接続拒否されることがあります。

```
$ ftp
ftp open [ec2のパブリックip]
ftp> ls
227 Entering Passive Mode (0,0,0,0,234,99).
ftp: connect: Connection refused
```

vsftpd.confファイルに以下の設定を加えると、接続できる場合があります。

```/etc/vsftpd/vsftpd.conf
# スタンドアロンモード(デーモン)で起動するかどうか(YES/NO)
listen=YES
# スタンドアロンモード(デーモン)で起動するかどうか(IPv6で待ち受ける)
listen_ipv6=NO
```

# ログファイルの見方
`/etc/vsftpd/vsftpd.conf`に以下の設定をすることで、ログを取得できます。

```/etc/vsftpd/vsftpd.conf
# ログ取得の有無(YES/NO)
xferlog_enable=YES

# ログファイルのファイル名を設定する
xferlog_file=/var/log/xferlog

# ログをxferlogのフォーマットにするかの設定する
xferlog_std_format=YES
```
`/var/log/xferlog`では、以下のようなログが取得できます。

```/var/log/xferlog:/var/log/xferlog
Tue Oct 26 18:08:07 2021 1 xx.xxx.xxx.xx 237796 /hoge/test.html b _ i r ec2-user ftp 0 * c
```

|設定  |意味|
|---|---|
| Tue Oct 26 18:08:07 2021 | アクセス日時 |
| 1 |  転送時間、秒|
| xx.xxx.xxx.xx |  アクセス元リモートホストのIP|
| 237796 |  転送されたバイト数|
| /hoge/test.html |  転送されたファイル名|
| b | 転送モード　a: ascc, b: binary |
| _ | 加えられたアクション C: ファイルは圧縮された, U: ファイルは解凍された, T: ファイルは tar された, _: なにも行われていない |
| i | 転送の向き o: 出て行く方向, i: 入ってくる方向 |
| r |  ユーザーのアクセスモード a: 匿名のゲストユーザ, g: パスワード設定されたゲストユーザ, r: ローカルで認証されたユーザ|
| ec2-user | ユーザー名 |
| ftp |  このサービスの名前：FTP|
| 0 |  認証方式 0: none, 1: RFC931|
| * | 認証時に返されるユーザーID, ユーザーIDが不可の場合は、* |
| c | 転送の状態  c：転送完了、i：転送未完了 |

http://manpages.ubuntu.com/manpages/bionic/ja/man5/xferlog.5.html

### ファイル転送エラーしたときのログ
転送が未完了になっており、転送されたバイト数が0になっていることが分かります。

```
Thu Nov 11 16:27:47 2021 1 xx.xxx.xxx.xxx 0 /testtest/wp-config.php b _ i r ec2-user ftp 0 * i
```

# FTP のすべての要求と応答をログに出力する
`log_std_format`を無効化し、`log_ftp_protocol`をYESに設定すると、すべての要求と応答をログに出力されす

```diff_conf:/etc/vsftpd/vsftpd.conf
# ログをxferlogのフォーマットにするかの設定する
- #xferlog_std_format=YES

# FTP のすべての要求と応答を記録
+ log_ftp_protocol=YES
```
あとは、再起動するだけです。
```
$ sudo service vsftpd restart
```

`/var/log/xferlog`は、ログが出力されなくなり、
`/var/log/vsftpd.log`に、ログが出力されるようになります。

```log:/var/log/vsftpd.log
FTP command: Client "xx.xx.xx.xx", "PASV"
FTP response: Client "xx.xx.xx.xx", "227 Entering Passive Mode (xx,xx,xx,xx,xx)."
```

http://park12.wakwak.com/~eslab/pcmemo/linux/vsftpd/vsftpd5.html

http://www.pasokuma.net/linux/server/ftpd/vsftpd/vsftpdconf.html

# 同時接続数とパッシブポートを増やす
同一IPからの同時接続数はデフォルトで50ですが、ファイルの転送数が多い場合など、エラーになった場合以下のように修正してみます。
- 同時接続数を50から`200`
- パッシブポートを「60001-60010」→「60001-60050」

まず、セキュリティーグループを「60001-60010」→「60001-60050」に修正します。

その後、`vsftpd.conf`を修正して、再起動すると反映完了です、
```terminal
$ sudo su
# vim /etc/vsftpd/vsftpd.conf
```
```diff_conf:/etc/vsftpd/vsftpd.conf
pasv_min_port=60001
- pasv_max_port=60010
+ pasv_max_port=60050

+ max_per_ip=200
```
```terminal
# sudo service vsftpd restart
Redirecting to /bin/systemctl restart vsftpd.service
```

# 参考
・[[AWS] EC2でFTPを使いたい](https://qiita.com/Yuki_BB3/items/deeb84c360c6f3c37f51#%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97)
・[【備忘録】FTPサーバーをAWSで立てる](https://qiita.com/moonbass630/items/5776f5e37c0de077dd35)
・[【AWS】閉域網のEC2にFTPサーバーを構築](https://www.hanatare-papa.jp/entry/technology-aws-ftp-1)
・[Linux：FTPユーザごとにホームディレクトリを指定する(vsftpd)](http://raining.bear-life.com/linux/ftp%E3%83%A6%E3%83%BC%E3%82%B6%E3%81%94%E3%81%A8%E3%81%AB%E3%83%9B%E3%83%BC%E3%83%A0%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8Bvsftpd)
・[vsftpdで上位ディレクトリへのアクセスを禁止するには](https://teratail.com/questions/237254)

FTPではなく、SFTPサーバーの設定はこちらを参照するとできます。
・[EC2をSFTPサーバー設定](https://dev.classmethod.jp/articles/file-upload-to-s3-from-ec2-using-sftp/)