マルチテナントSFTPサーバを AWS で冗長化する
開発グループの uzuki です。
早速ですが、可用性と一貫性を担保する SFTP サービスにご興味はございませんか?
昨今様々なデータのやり取りが各サービス間で行われている中、ビッグデータの連携の主軸に FTP を利用しているものもあります。
そういったサービスとの連携を行うにあたり、可用性と一貫性を両立させた SFTP サービスを提供できるようにと思い、下記3要件を満たす SFTP サービスを構築してみました。
- SFTP インスタンスを冗長化することにより、可用性を担保
- 複数の SFTP インスタンスを運用しながら、どのインスタンスからも常に同じデータにアクセスできる一貫性を担保
- 利用者ごとに認証情報を個別にし、利用者ごとにアクセスするディレクトリを隔離することによりマルチテナント機能とファイルの機密性を担保
構成
プラットフォームには AWS を選択します。構成は下記の通り。
特に難しいことはせずに、Network Load Balancer 配下に EC2 インスタンスを複数設置します。
AWS S3 にデータ保管領域としてのバケットを用意し、そのバケットを SFTP インスタンスから s3fs を用いてマウントします。複数の SFTP インスタンスから同じバケットを同じファイルパスにマウントすることで、どのインスタンスからも常に同じデータにアクセスできるようになります。
※本サービス構築時点では EFS が東京リージョンにきていなかったので S3 をディスクとして利用しました。安定性や速度面から、新たに構築するのであれば EFS を利用することをおすすめします。
利用者からは SFTP インスタンスに対して、Network Load Balancer 経由で SFTP 接続をしてデータにアクセスしてもらいます。認証には公開鍵認証を用います
冗長化する方法
Network Load Balancer を利用すれば特に問題なく構築できます。また、複雑な設定は不要で、ターゲットインスタンスの指定とヘルスチェックポートの設定のみで設定は完了します。
SFTP の場合、そのプロトコル仕様により TCP コネクションが張りっぱなしとなるため、複数インスタンスでの確立済のセッション同期などの工夫は不要です。しかしながらインスタンスの異常停止や、メンテナンスで意図的にインスタンスを停止する場合には同時に TCP コネクションも切れてしまうため、クライアント側にリトライしてもらうか許容してもらう必要があります。
Network Load Balancer が受け付けるポート番号は、データ連携元の制約があればそちらに合わせるべきですが、そうでない場合は 22 や 115 など、いわゆる Well-known Port を避けておくのが無難でしょう。
SFTP インスタンスの構築
CentOS7 系で構築を行っています。他ディストリビューションを利用している場合は、適宜コマンドを置き換えてください。
まず、必要なグループ・ディレクトリの作成から行います。
# groupadd sftp-user -g 500
# install -d -o root -g root -m 750 /var/sftp
SFTP 通信を許可させるユーザを限定するため、sftp-user グループを作成しました。また s3fs のマウント先として /var/sftp ディレクトリを作成しました。
続いて SFTP アプリケーションの設定です。SFTP 専用のアプリケーションもありますが、シンプルに sshd を利用してサービス化します。通信ポートについてですが、22 番ポートを通常の SSH 接続用に残すことにすると、何かしら別のポートを利用する必要があります。以下では Network Load Balancer から 10022 番ポートで受け付けるようにしています。
# vi /etc/ssh/sshd_sftp_config
Port 10022 Protocol 2 SyslogFacility AUTHPRIV PermitRootLogin no PasswordAuthentication no ChallengeResponseAuthentication no PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys AllowTcpForwarding no UsePAM yes X11Forwarding no PidFile /var/run/sftp.pid AllowGroups sftp-users UseDNS no Subsystem sftp internal-sftp Match group sftp-users ClientAliveInterval 30 ForceCommand internal-sftp -l INFO ChrootDirectory /var/sftp/%u/
末尾の ChrootDirectory /var/sftp/%u/ が前述の「利用者ごとにアクセスするディレクトリを隔離する」部分となります。各利用者は /var/sftp/[user name]/ 以下のディレクトリのみアクセスが許可され、他の利用者のファイルの参照が行なえません。
この設定ファイルを用いて sshd を起動しても良いのですが、サービスファイルを作成することにより、簡単にサービス化が可能となります。
# vi /etc/systemd/system/sshd_sftp.service
[Unit] Description=OpenSSH server daemon only sftp After=syslog.target network.target auditd.service [Service] EnvironmentFile=/etc/sysconfig/sshd ExecStart=/usr/local/sbin/sshd_sftp -D -f /etc/ssh/sshd_sftp_config ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartSec=30s [Install] WantedBy=multi-user.target
# systemctl enable sshd_sftp
# systemctl start sshd_sftp
最後に、クライアントが保持する finger print による SSH 接続エラーの回避のため、サーバ側の鍵ペア(/etc/ssh/ssh_host_*)を各インスタンス間で同一になるよう、スナップショット(AWS では AMI)を取得してインスタンスのコピーを行うか、構成管理ツールで各インスタンスに同一の鍵ペアを設置するなどの工夫が必要です。
これをしないと、クライアントが最初に接続したインスタンスとは異なるインスタンスに接続した場合、最初に接続したインスタンスから取得した finger print とは異なる finger print であるためクライアント側で SSH 接続エラーが発生してしまう可能性があります。
利用者を追加する方法
以下は利用者が増えるごとに必要な作業となります。
利用者ごとにユーザアカウントを追加し、利用者ごとの認証情報を追加します。この方法は各インスタンスごとに同じ操作が必要となるため、スクリプトを用意したり、構成管理ツールを活用するなど、自動化するのがおすすめです。
・全インスタンスで必要な作業
# useradd -g sftp-user [user name]
# install -d -o [user name] -g [user name] -m 700 /home/[user name]/.ssh
# echo [公開鍵] > /home/[user name]/.ssh/authorized_keys
# chmod 600 /home/[user name]/.ssh/authorized_keys
# chown [user name]:[user name] /home/[user name]/.ssh/authorized_keys
最後に、S3 上にユーザごとのディレクトリを作成します。SFTP アプリケーションに sshd を利用するため、SFTP 用ルートディレクトリは root のみに作成権限を与えます。sshd では、SFTP 用ルートディレクトリに root 以外が書き込めるパーミションとなっているとサービス開始できないためです。ただし、それだけだと利用者がディレクトリ内にファイルを設置できないため、利用者のユーザアカウントで操作可能な何かしらのディレクトリを作成する必要があります。以下では data ディレクトリを作成しています
・1度の実行だけでOK (実質的に S3 の操作であるため)
# install -d -o root -g sftp-user -m 750 /var/sftp/[user name]
# install -d -o [user name] -g sftp-user -m 700 /var/sftp/[user name]/data
まとめ
上記の通り、特に難しいことはせずに可用性と一貫性を担保した SFTP サービスが構築できます。AWS を利用することにより、ロードバランサーの可用性担保・データの完全性担保が容易に行なえます。
この構成をミニマムで構築した場合、データ通信量を除けば費用は月1万円もかかりません。
SFTP サービス構築で悩んでいる方はぜひお試しください。
ディスカッション
コメント一覧
まだ、コメントがありません