FTPの通信(アクティブモード)
FTP の通信には、PORT モード(アクティブモード)と PASVモード(パッシブモード)があります。ここでは、アクティブモードについて説明していきます。
アクティブモードは、多くの FTP ソフトウェアで、デフォルトの転送モードになっています。
このモードでは、データコネクションは、制御コネクションとは異なり、FTP サーバ側の20番ポートからクライアントの任意のポートに向けてコネクションが確立されます。
FTP サーバ側からコネクションを張るために、サーバはクライアントのIPアドレスとポート番号を知っている必要があります。これらは、制御コネクション時のPORTコマンドで、FTPサーバに通知されるようになっています。

ここで、注意が必要です。データコネクションの方向が、FTP サーバ側からクライアント方向になっています。これは、ファイルのダウンロード、アップロードにかかわらず、FTP サーバ側からコネクションが確立されるということです。
ファイルをアップロードする場合には、クライアントから通信が始まるのでは?
と疑問に思うかもしれませんが、アップロードも FTP サーバからコネクションが始まります。
このデータコネクションの方向が、いくつかの問題を引き起こします。
まずは、ファイアウォールのセキュリティの問題です。
クライアントのポート番号は、任意(1,024以上)である為、FTPで通信を行う為には、FTP サーバ側からのデータコネクションのポートをファイアウォールで開けておく必要があります。1,024以上のポートの全て開けておくということは非常にリスクが高くなります。
他にも、サーバからクライアント方向へデータコネクションを確立する際に、問題が発生します。
アクティブモードでは、ファイルのダウンロード、アップロードにかかわらず、下図のように FTP サーバ側からコネクションが確立されるようになっています。

データ転送時、クライアントは、PORT コマンドで、自分の接続を待ち受けるIPアドレスとポート番号をFTPサーバに通知します。
コマンド補足
PORTコマンドは、以下のように指定するようになっています。
PORT aaa,bbb,ccc,ddd,ee,ff
aaa,bbb,ccc,ddd ・・・ クライアントの待ち受けIPアドレスを指します。
ee,ff ・・・ クライアントの待ち受けポート番号を指します。
上の図のポート番号の場合のPORTコマンドは次のようになります。
PORT 192,168,1,1,11,185
ここで、疑問が生じてきます。なぜ、ポート番号の「3001」が、「11」と「185」になるのかです。
そのからくりは、このようになっています。
10進数の3001を16進数に変換すると下記のようになります。
(3001)10=(0BB9)16
16進数の(0BB9)16をオクテットに分割し、その各々を10進数に変換します。
(0B)16=(11)10
(B9)16=(185)10
また、(11)10は、8ビットシフト移動させたものなので、次のことが成り立ちます。
3001=11×256+185
アクティブモードのデータ転送の様子をもう少し詳しく見てゆくと、クライアントとサーバのシーケンスは、下表のようになります。
クライアント | 内容 | サーバ |
任意 | --> PORT aaa,bbb,ccc,ddd,ee,ff --> | 21 |
任意 | <-- PORT command successfull <-- | 21 |
任意 | --> RETR filename --> | 21 |
ee*256+ff | <-- ( SYN ) <-- | 20 |
ee*256+ff | --> ( SYN , ACK ) --> | 20 |
ee*256+ff | <-- ( ACK ) <-- | 20 |
任意 | <-- Opening ASCII mode data connection <-- | 21 |
ee*256+ff | ( ファイルのダウンロード ) ・ ・ ・ | 20 |
任意 | <-- Transfer complete. <-- | 21 |
アクティブモードはファイアウォールとNATとの相性が悪い
クライアントが、ファイアウォールの内側に位置する場合、アクティブモードの FTP は、失敗する場合がほとんどです。それは、多くのファイアウォールは、セキュリティの問題から外部からの SYN を拒否する設定を行っている場合があるからです。
また、クライアントがNATルータの配下にある場合も問題になってきます。
NAT や IPマスカレードでは、IPアドレスやポート番号が変換されます。そのため、PORT コマンドで渡される値も書換える必要があります。
その理由は、PORT コマンドで通知されるIPアドレスとポート番号では、クライアントと通信を行うことができないからです。変換される前の内部のIPアドレスとポート番号を使って通信することができません。NATで変換されるIPアドレスとポート番号で通信する必要があります。
そのため、PORTコマンドの引数を書き換える必要があります。PORTコマンドの引数は10進表記であり、IPアドレスとポート番号の値の文字列の長さが変わるので、チェックサムを書き換える必要も出てきます。
このような、複雑な処理が必要なため、PORTコマンドの書換えに対応していないNATルータも存在し、NATルータの配下にクライアントがある場合、FTP通信が行えないという問題があります。
FTPの通信(パッシブモード)
パッシブモードでは、制御コネクション、データコネクション共に全てクライアントから始まります。
アクティブモードでは、FWやNATにおいて、問題点がありました。パッシブモードは、クライアントが FW や NAT ルータ配下にいても通信ができるようにするために用意されたモードです。
アクティブモードでは、FTP サーバからデータコネクションが確立されましたが、パッシブモードのデータコネクションでは、アクティブモードとは逆に、クライアント側の任意のポートから FTP サーバの待ち受けポート方向にコネクションを確立します。
このモードでは、クライアントから FTP サーバへ制御コネクションでPASVコマンドを使用します。FTP サーバは、その応答に自身のIPアドレスと待ち受けポート番号を含めクライアントに通知します。
クライアントは、FTP サーバから通知されたIPアドレス、ポートに対して FTP サーバにデータコネクションの確立を行います。

パッシブモードでは、制御コネクション、データコネクション共に全てクライアント側から確立されることになります。
PASV コマンドに対する応答の中に FTP サーバのIPアドレスと待ち受けポート番号が記述されることにますが、NAT や IP マスカレードでの変換対象にならないので問題になりません。
パッシブモードでは、一見、NAT問題を解決できそうに思えますが、FTP サーバが NAT ルータ配下である場合に、同様な問題が起こります。
パッシブモードでは、ファイルのダウンロード、アップロードにかかわらず、下図のようにクライアント側からコネクションが確立されるようになっています。

パッシブモードのデータ転送のクライアントとサーバのシーケンスは、下表のようになります。
クライアント | 内容 | サーバ |
任意 | --> PASV --> | 21 |
任意 | <-- Entering Passive mode (aaa,bbb,ccc,ddd,ee,ff) <-- ※コマンド補足を参照 | 21 |
任意 | --> ( SYN ) --> | ee*256+ff |
任意 | <-- ( SYN , ACK ) <-- | ee*256+ff |
任意 | --> ( ACK ) --> | ee*256+ff |
任意 | --> RETR filename --> | 21 |
任意 | <-- Opening ASCII mode data connection <-- | 21 |
任意 | ( ファイルのダウンロード ) ・ ・ ・ | ee*256+ff |
任意 | <-- Transfer complete. <-- | 21 |
クライアントは、PASV コマンドをサーバに送信して、パッシブモーとでデータを転送するように要求します。サーバは、この応答として、データ転送で使用するサーバ側のポート番号を送信します。この応答を受け取ったクライアントは、クライアントの任意のポートからサーバの指定ポートに向けて、コネクションを張ります。
コマンド補足
aaa,bbb,ccc,ddd ・・・ クライアントの待ち受けIPアドレスを指します。
ee,ff ・・・ クライアントの待ち受けポート番号を指します。
上図のポート番号が「3001」の場合、eeが「11」、ffが「185」となります。
そのからくりは、このようになっています。
10進数の3001を16進数に変換すると下記のようになります。
(3001)10=(0BB9)16
16進数の(0BB9)16をオクテットに分割し、その各々を10進数に変換します。
(0B)16=(11)10
(B9)16=(185)10
パッシブモードとファイアウォール、NATとの相性
パッシブモードでは、内部からの SYN を送信して、コネクションを確立するので、外部からの SYN を拒否するように設定されたファイアウォールのフィルタリングにブロックされることはありません。
また、送信元IPアドレスと送信元ポート番号は、アクティブモードと同様に記述されますが、これはサーバ側から内部へのパケットであるため、送信元IPアドレスと送信元ポート番号を書き換える必要がありません。そのため、NAT や IP Masquerade で問題が生じることがなくなります。
パッシブモードで通信を行うと、ファイアウォールやNATとのトラブルがなくなりますが、注意するべき点があります。それは、パッシブモードでは、サーバの送信元ポート番号(1024以上)を通すようにファイアウォールを設定しておかなければならないことです。
サーバの送信元ポート番号は、ランダムであるためかなり広い範囲を指定しておく必要があり、ファイアウォールの穴が大きくなってしまいます。静的フィルタリング型のファイアウォールでは、常に穴が開いた状態となるため、外部からの侵入経路となるため、危険にさらされることとなります。