普段からサーバー管理などで良く使うFTPですが、ひとえにFTPといっても内部的には2つの通信モード(アクティブモード(ポートモード)、パッシブモード)が存在しています。
この辺の問題に絡み、FTPを設定したけどサーバーとうまく通信ができないなどの問題が起きる可能性もでてきますので、どっちのモードで動かすのが良いのかを理解しておく必要が出てきます。
まず、FTPの通信には2つのコネクションが必要になります。
1. FTPのコマンドなどをやり取りする制御用のコネクション
2. FTPを用いてデータやサーバー情報を転送をするためのコネクション
このうち2.のデータ転送用のコネクションの扱い方が2つの通信モードによって異なってきます。
具体的に2つの通信モードにて、サーバーへのFTPコネクションの確立からサーバー情報の取得までの流れを見てみたいと思います。
今回確認する構成は、下記のようになっています。
クライアント(192.168.0.100) → サーバー(192.168.0.200)
※ いづれもLinux環境です。
パッシブモードによる通信
まずパッシブモードによって通信の流れを見てみます。
最近のFTPクライアントの多くは、デフォルトでパッシブモードの通信を採用してたりします。
# ftp ftp> open 192.168.0.200 Connected to 192.168.0.200. 220 (vsFTPd 1.2.1) 530 Please login with USER and PASS. 530 Please login with USER and PASS. KERBEROS_V4 rejected as an authentication type Name (192.168.0.200:root): foo 331 Please specify the password. Password: 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files.
デフォルトでパッシブモードの通信となるため明示的に指定はしていませんが、これでパッシブモードによるFTP接続ができました。
まず、このときの通信状況を見てみます。
# netstat -n Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 192.168.0.100:41900 192.168.0.200:21 ESTABLISHED
# netstat -n Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 192.168.0.200:21 192.168.0.100:41900 ESTABLISHED
クライアントからサーバーのポート21番へのコネクションが、制御用のコネクションです。
クライアントのポート番号は任意ですので接続のたびに変わります。
次に、クライアントからファイルをPUTしてみます。
ftp> put hoge.txt local: hoge.txt remote: hoge.txt 227 Entering Passive Mode (192,168,0,200,4,74) 150 Ok to send data.
このときの通信状況を見てみると
# netstat -n Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 95568 192.168.0.100:40886 10.100.0.240:1086 ESTABLISHED tcp 0 0 192.168.0.100:41900 10.100.0.240:21 ESTABLISHED
# netstat -n Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 192.168.0.200:1086 192.168.0.100:40886 ESTABLISHED tcp 0 0 192.168.0.200:21 192.168.0.100:41900 ESTABLISHED
いづれも下に表示されている21番ポートは先ほど接続している制御用コネクションですが、その上のサーバー側のポート1086番に接続しているのがデータ転送用のコネクションです。
クライアント側の40886番ポートは接続のたびに変わりますが、サーバー側の1086番ポートは、サーバー側の設定によりある範囲に固定することができます(後述)
パッシブモードを図示すると下記のようになります。
アクティブモード(ポートモード)による通信
次に、アクティブモードによる通信状況を同様に見てみます。
# ftp ftp> passive Passive mode off. ftp> open 192.168.0.200 Connected to 192.168.0.200. 220 (vsFTPd 1.2.1) 530 Please login with USER and PASS. 530 Please login with USER and PASS. KERBEROS_V4 rejected as an authentication type Name (192.168.0.200:root): foo 331 Please specify the password. Password: 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files.
このときの通信状況を見てみると
# netstat -n Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 192.168.0.100:46674 192.168.0.200:21 ESTABLISHED
# netstat -n Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 192.168.0.200:21 192.168.0.100:46674 ESTABLISHED
ここまではパッシブモードと状況は変わりません。
次に、同じようにファイルをPUTしてみます。
ftp> put hoge.txt local: hoge.txt remote: hoge.txt 200 PORT command successful. Consider using PASV. 150 Ok to send data.
この間の通信を見てみると
# netstat -n Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 95568 192.168.0.100:59660 192.168.0.200:33468 ESTABLISHED tcp 0 0 192.168.0.100:46674 192.168.0.200:21 ESTABLISHED
# netstat -n Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 192.168.0.200:33468 192.168.0.200:59660 ESTABLISHED tcp 0 0 192.168.0.200:21 192.168.0.200:46674 ESTABLISHED
サーバー側では59660番ポートを、クライアント側では33468番ポートを使ってデータを転送していることがわかります。
これらの状況からはわかりづらいですが、パッシブモードとアクティブモードとではどちら側から通信を開始するのか、という点が異なります。
FTPのアクティブモードの通信状況を図示すると下記のようになります。
この辺りの動作については、下記の記事がわかりやすく解説されています。
アクティブモードの場合は、クライアント側のIPやポートの情報をサーバーに伝え、サーバーから通信を開始してもらい、パッシブモードは逆でサーバーのIPやポート情報をもらって、クライアント側から再度データ転送用のコネクションを開始します。
アクティブモードは、サーバー側から通信を開始するためF/Wに引っかかったり、それを通す工夫をしようとしても使われるポートが不定の為、ACLを書きにくいというような問題があります。
そのために、パッシブモードというもう一つのモードが存在しています。
アクティブモードによるサーバー側の通信ポートの固定
サーバーとクライアントの通信ポートが接続のたびに変わるという状況は、色々不都合があります。
例えば、先の参考にさせていただいた記事の中で書かれているようなNAT環境での問題以外にも、F/WでFTPの通信を許可したいが、アクティブモードでは通信ポートがはっきりしないため、どこまでの範囲の穴を開けておけばよいかがわからないというような問題もあります。
極端に広い範囲で許可をしてしまうと、それはそれでセキュリティ上の問題にもなります。
vsftpdでは、アクティブモードによる通信のサーバー側の通信ポートを固定するオプションがあります。
connect_from_port_20=YES
このオプションを有効にすることでサーバー側のポートが20番に固定されます。
20番以外のポートを使いたい場合は、上記のオプションに加えて下記を指定します。(この場合、3000番ポートを使用)
ftp_data_port=3000
実際にFTPの通信状況を見てみると
tcp 0 0 192.168.0.100:33479 192.168.0.200:3000 ESTABLISHED
tcp 0 101360 192.168.0.200:3000 192.168.0.100:33479 ESTABLISHED
サーバー側のポートが3000番に固定されていることがわかります。
ただし、これは先ほど述べたように通信元のポート番号になるということに注意が必要です。
パッシブモードによるサーバー側の通信ポートの固定
次にパッシブモードの場合です。
パッシブモードの場合は、ポートをある範囲で受け付けるように指定します。
pasv_enable=YES pasv_min_port=1050 pasv_max_port=1100
上記の場合は、1050番から1100番の範囲のポートが使われます。
こちらは、アクティブモードとは違い、通信先のポート番号になります。
tcp 0 0 192.168.0.100:33486 192.168.0.200:1075 ESTABLISHED
tcp 0 134664 192.168.0.200:1075 192.168.0.100:33486 ESTABLISHED
FTPと言えども採用する通信モードによって、通信の方向と、使われるポート番号が異なるので、環境に応じて適切なモードで運用する必要が出てきます。
2010.01.18 追記
FTPパッシブモードとアクティブモードの通信状況の図を追加
[PR]
[PR]
関連記事
ftpやscp不要でターミナルエミュレータを通してファイル転送ができるlrzszパッケージ
[vsftpd] 特定の拡張子のファイルのアップロードを禁止する
OS上にいないバーチャルユーザーを使ってFTP接続する
[お名前.com] サービスを構築するまでに行ったサーバー設定作業もろもろ