Zenn
🔖

アクティブモードで動作するFTPサーバをAWSに構築する

2025/03/22に公開

はじめに

FTPでファイル転送するIoT機器からメトリックを収集したい。
でもアクティブモードでしか通信できない。

といったとき、AWSでFTPサーバを構築する方法を検討してみました。

FTPのアクティブモードとパッシブモード

そもそもFTPのアクティブモードとは何か?ですが、FTPにはアクティブモードパッシブモードの二つの動作モードがあります。

アクティブモードとは、クライアントからサーバに接続した後にサーバからクライアントに対してデータ通信接続する通信モードです。
具体的にはクライアントからサーバのポート21に接続し、クライアントからPORTコマンドを使ってクライアントのIPアドレスとデータ通信用の待受ポート番号をサーバに通知します。サーバはPORTコマンドで受領したクライアントのIPアドレスとポート番号を使ってクライアントとデータ通信のコネクションを確立します。

ポイントは、サーバはクライアントがPORTコマンドで通知したIPアドレス宛にデータ転送のコネクションを確立する必要がある、という点です。

FTPアクティブモードシーケンス図

パッシブモードは、クライアントからサーバに接続した後にクライアントからサーバに対してデータ通信接続する通信モードです。
具体的にはクライアントからサーバのポート21に接続し、クライアントからPASVコマンドを使ってパッシブモードで動作することを通知し、サーバからの応答としてデータ通信用のIPアドレスとポート番号をクライアントに通知します。その後、クライアントはPASVコマンドで受領したサーバのIPアドレスとポート番号を使ってデータ通信のコネクションを確立します。

パッシブモードはアクティブモードと異なり、通信の起点は全てクライアントになります。

FTPパッシブモードシーケンス図

Transfer Familyの制限

AWSでFTP通信を実現するならAWS Transfer Familyを活用することだと思います。
しかしAWS Transfer FamilyのFTPサーバはパッシブモードのみサポートなので、アクティブモードで通信することができません。

アクティブモード非対応Q&A

https://aws.amazon.com/jp/aws-transfer-family/faqs/

FTPサーバ構築

AWS Transfer Familyが使えないとなると、自前でFTPサーバを構築・運用する必要があります。

Amazon Linux 2023をベースOSとして考えたときに、よく使われていて情報量が多いvsftpdを採用しました。
コンピュートインスタンスはECSでもEC2でもいいんですが、今回はサンプル実装をより構成をシンプルにするためにEC2で作りました。

https://github.com/shikira/aws-lab/blob/main/elb/ftp/lib/ftp-stack.ts#L1-L156

スケーリング

自前でAWS Transfer Familyの可用性を担保することは難しいのですが、可用性を考慮した設計にしておきたいので、マルチAZ + ロードバランサー構成にしました。
ただ、ALBはL7で動作するロードバランサーかつHTTP or HTTPSしかサポートしていないので、ALBを採用することができません。
NLBならL4ロードバランサーなのでFTPも扱うことができます。

AWSアーキテクチャ図

NLBを採用した場合、ポート21の制御接続はNLBを介します。
NLBの分散アルゴリズムはフローハッシュアルゴリズムで、接続中は単一のターゲットにルーティングする使用です。FTPの制御接続はログアウトするまで接続し続けるので、問題なく動作します。

NLB分散アルゴリズム

https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/userguide/how-elastic-load-balancing-works.html#request-routing

データ通信はFTPサーバとクライアントが直接通信することになります。なので、FTPサーバとクライアントが通信できるようセキュリティグループやルーティングを設計する必要があるので注意です。

おわりに

AWS上にパッシブモードで動作するFTPサーバを構築しました。
既存の機器では未だFTPが採用されているものはあるので、AWSさんがそういった環境もクラウドリフトさせたいと本気で考えるなら、アクティブモードをAWS Transfer Familyでサポートしてくれたらなと思います。
あとは、Transfer Familyは1インスタンス10,000セッションまでとかなので、Transfer Familyの負荷分散とか考えなきゃいけなくなるので辛いところ。

今回は記事の対象にしませんでしたが、IoT機器から送られてくる生データは一旦S3のデータレイクに蓄積し、ETL後にS3 Tablesなどに入れるといったときに、Mountpoint for S3やAmazon FSx for Lustre、lsyncdなど使ってS3との同期方式の検討が必要になります。
また、CPUや転送帯域などの指標で最適なスケールアウトの指標を検討するといったことも必要になってきます。
そういったこともマネージドであれば考えずに済むので、エンハンスを期待しつつ、終わりにしたいと思います。

GitHubで編集を提案

Discussion

ログインするとコメントできます