FTPの通信

 FTPは、「File Transfer Protocol」の略で、ファイル転送プロトコルとも呼ばれます。ネットワークでファイルの転送を行うための通信プロトコルで、インターネットの初期の頃から存在するインターネット上で最もよく利用されているファイル転送用プロトコルとなっています。

 ファイル転送用プロトコルは、他にも、NetBIOSやNFSなどがあります。こちらは、OSのファイルシステムを利用して外部のファイルシステムに対して仮想的にマウントすることでファイル転送を実現しています。

 FTPでは、相手先のコンピュータにログインした上でFTPサーバにファイルをアップロードしたり、FTPサーバからダウンロードを行うことができます。しかし、その際にやり取りするユーザ名とパスワードは暗号化されずに平文で送信されてしまうために、盗聴されてしまう恐れがあります。

 セキュアなFTP通信を行いたい場合は、FTPS(FTP over SSL/TLS)やSFTP(SSH FTP)でファイル転送を行う必要があります。

 FTPでのファイル転送は、コマンドベースで行うことになりますが、現在は、Windows環境においても、Linux環境においても、GUIで操作できるFTP専用ソフトが充実しています。GUIツールでは、コマンドを意識することなくファイル転送を行えるようになっています。

 FTPでは、制御用とデータ転送用の2つのコネクションを使って通信を行います。制御用には21番ポート(FTP)を、データ転送用には20番ポート(FTP-DATA)が使用されます。

 まず、最初に制御コネクションを張り、ユーザ認証が行われます。ユーザ認証に成功したら、制御用コネクションが確立されます。これは、FTPサーバへ、クライアント側から要求することで確立されます。クライアントは空いている任意のポートを使って、サーバの21番へ接続します。

 制御コネクションの確立が終わったら、データコネクションを確立します。このように、FTPでは、データの送受信とは別に制御用のコネクションを確立することで、データ転送中であっても、停止命令など他の命令が出せるようになっています。

 データコネクションは、制御コネクションで渡されるコマンドによって、その都度生成され、データの転送が終了したら切断されます。データコネクションは、1回のFTP通信の間に何回も接続と切断を繰り返しながら、ファイルが転送されることとなります。

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以上)を通すようにファイアウォールを設定しておかなければならないことです。

 サーバの送信元ポート番号は、ランダムであるためかなり広い範囲を指定しておく必要があり、ファイアウォールの穴が大きくなってしまいます。静的フィルタリング型のファイアウォールでは、常に穴が開いた状態となるため、外部からの侵入経路となるため、危険にさらされることとなります。