ちょっと話題の記事

【AWS】AWSでFTPサーバー立てる時に気をつけるべき2つのこと+α

2014.05.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは植木和樹です。本日はAWS環境にFTPサーバーを構築する際に軽く躓いてしまった事を備忘録を兼ねてまとめます。

FTPは言わずと知れたファイル転送プロトコルです。最近ではHTTPやssh(scp/sftp)が主流になり使う機会が随分と減りましたが、企業間でのファイルのやりとりの手段としていまだにFTPは健在です。

さてAWS環境にFTPサーバーを立てる際、通常は以下の設定を行います。

  1. EC2インスタンスを起動してFTPサーバーの設定を行い、EIPを割り当てる。
  2. EC2へのFTP(tcp/21)をセキュリティグループで許可する。

しかし上記の設定のみだとアクティブモードでは繋がりますが、パッシブモードで繋がりません。企業間でFTPを利用する際、多くは企業のファイアウォールを通ることになるためパッシブモードを利用するでしょう。今回はパッシブモードでも繋がるよう、この問題を解決したいと思います。

AWSでFTPサーバーを立てる際に設定すべき2点

今回利用したFTPサーバーソフトは vsftpd です。パッシブモードを利用可能にするにあたり2つの設定を入れましょう。

  1. pasv_addressにEIPのアドレスを設定し、データ通信でのクライアントからの接続先IPアドレスをグローバルIPにする。
  2. pasv_min_portpasv_max_portを設定し、データ通信で使用するポート番号の範囲を限定する。

順にご説明します。

データ通信でクライアントからの接続先IPアドレスをグローバルIPにする

パッシブモードでデータ通信する際は、FTPクライアント側からPASVというコマンドを投げると、FTPサーバーがデータ通信用の接続先「IPアドレス」と「ポート番号」を返します。

ftp> debug
Debugging on (ftp_debug=1).
ftp> ls
---> PASV
227 Entering Passive Mode (192,168,1,1,243,172). ★FTPサーバーのプライベートIPが返ってくる
---> LIST
150 Here comes the directory listing.
-rw-r--r--    1 10047    10047           0 May 10 01:02 README.txt
226 Directory send OK.

しかしAWS上のEC2は自身に割り当てられたEIP(グローバルIPへのアドレス変換)の存在を知らないため、PASVコマンドに対してプライベートIPアドレスを返してしまいます。当然FTPクライアントはプライベートIPアドレスに接続しにいこうとしてしまうため通信できません。「FTPでログインはできるけど、ディレクトリ/ファイル一覧が表示されない」という症状になります。

そこでpasv_addressを指定することで、PASVコマンドに対してグローバルIPアドレス(EIPのアドレス)を返すようにしてあげる必要があります。

/etc/vsftpd/vsftpd.conf

pasv_address=54.XXX.XXX.XXX

データ通信で使用するポート番号の範囲を限定する

パッシブモードで使用されるデータポートは1024番以上が使用されます。そのためセキュリティグループで1024〜65535までのTCP通信を許可してあげる必要があります。ポートを広く開けすぎですね。

通信元が限定されていれば接続元のIPアドレスを指定することですが、一般公開されているFTPサーバーや、セキュリティグループの設定上限(上限50)を超えてしまうケースの場合では、これだけ広いポートを開けるのは少々不安です。

そこでpasv_min_portpasv_max_portを指定して、ポート範囲を限定しましょう。どの程度のポートを開けるかは同時に接続するFTPクライアント数によりますが、ここでは分かりやすく65000〜65535の500ポート程にしています。セキュリティグループの許可ポートもこれにあわせて設定しておきましょう。

/etc/vsftpd/vsftpd.conf

pasv_min_port=65000
pasv_max_port=65535

ちなみに世の中にはALG(Application Layer Gateway)という機能をもったファイアウォールがあります。ALG機能はFTPの通信を監視し、PASVコマンドでFTPサーバーからポート番号が返されるとそのポートを動的に通信許可してくれます。残念ながらセキュリティグループにはALGの機能はありません。AWSで利用できるALG対応のファイアウォールってあるんでしょうか?

おまけ:FTPサーバーにインターネット経由でもVPN経由でも接続したい

企業間でFTPサーバーを用いてファイルのやりとりをするにあたり、協力会社はインターネット経由でFTPサーバーに接続し、自社はVPN経由でAWSに接続してFTPサーバーを利用するケースというのがあります。その場合はもう一工夫が必要です。

先ほど紹介したpasv_addressを設定すると、VPN(プライベートIP)経由のパッシブモードの際にもデータ通信でグローバルIPを返してしまいます。

$ ftp 192.168.1.1  ★プライベートIPアドレスに接続したのに・・・
ftp> debug
Debugging on (ftp_debug=1).
ftp> ls
---> PASV
227 Entering Passive Mode (54,XXX,XXX,XXX,243,172). ★グローバルIPが返ってきてしまう!

これを解決するためにはEC2に2つのIPアドレスを割り当て、vsftpdプロセスも2つ起動します。それぞれのvsftpdで担当(LISTEN)するIPアドレスを変えることで、一方のパッシブモードにはグローバルIPを返し、他方にはプライベートIPを返すようにします。

20140510_ftp01

設定手段は以下の通りとなります。

  1. ENI(仮想ネットワークインターフェース)を追加し、EC2にプライベートIPを2つ設定する。
  2. EIPを追加したENIに関連付ける。
  3. vsftpd.conf を local, global 2つの設定ファイルにわける。
  4. それぞれの設定ファイルでlisten_addressを設定し、LISTENするIPを指定する。
  5. global側の設定ファイルにはpasv_addressにEIPのアドレスを設定する。
  6. vsftpd サービスをrestartする。

Amazon Linuxでインストールされるvsftpd起動スクリプト(/etc/init.d/vsftpd)は、/etc/vsftpd/*.confというファイルの数分、複数のvsftpdプロセスを起動するようになっています。そのためグローバル用とプライベート用の2つの設定ファイルを用意するだけでOKです。

/etc/vsftpd/vsftpd.local.conf(変更部分のみ抜粋)

listen_address=192.168.1.1
pasv_min_port=65000
pasv_max_port=65535

/etc/vsftpd/vsftpd.global.conf(変更部分のみ抜粋)

listen_address=192.168.1.2
pasv_address=54.XXX.XXX.XXX
pasv_min_port=65000
pasv_max_port=65535

まとめ

EIPによるグローバルIPアドレスは、直接EC2に割り当てられているわけでなく単なるNATなわけで、EC2自身はグローバルIPアドレスを認識していないわけですね。これを失念しており、サーバー設定後の動作確認時にパッシブモードで繋がらない理由が分からず、少々ハマッてしまいました。

FTP自体は歴史も古く広く運用されているプロトコルなのですが、AWSとは少々相性が悪いと個人的には思っています。特にランダムにポートを使用するため、セキュリティグループでどうしてもポートを広く開けなければいけないのは正直いただけません。

データ通信の安全性や運用コストの安さ、データ保全の観点からも、今後は可能な限りS3を利用することをオススメしたいと思っています。