暗号化通信があたりまえの昨今ですが、いまだにFTPが利用される場面が少なくありません。
しかしご存じの通りFTPはNAT環境ではトラブルの元となります。
そこで、FTP絡みのトラブルシューティングに備えてFTPプロトコルの動きについてまとめようと思います。
FTPの通信
FTPにはコントロール通信とデータ通信の2種類の通信があります。
コントロール通信
FTPコマンドのやり取りはコントロール通信で行います。サーバーはTCP21番ポートで待ち受けています。
FTPログインの様子
FTPログインはコントロール通信で行います。FTPクライアントがFTPサーバーのTCP21番ポートへ接続に成功すると次のようなやり取りでログインします。

FTPログインのやり取り
ログインに成功するとディレクトリの一覧(LIST)表示やディレクトリの移動(CWD)、アスキーモードへの変更(TYPE A)などFTPサーバーが対応しているコマンドを実行できます。
実行できるコマンドはHELPコマンドで確認可能です。
コントロール通信はコマンドの実行要求と応答で利用されます。しかし一部のコマンドについてはデータ通信を併用するものがります。たとえばLISコマンドはUnixの”ls”コマンドに相当するものですが、このコマンドの実行結果はデータ通信でおこないます。
そのため「ログインはできるが”ls”コマンドを実行すると失敗する」という場合はデータ通信で問題が発生しています。
データ通信
アクティブモードとパッシブモード
データ通信には「アクティブモード」と「パッシブモード」という2種類の通信モードがあります。
通信モードの違いはFTPクライアントとサーバー間でどのようにデータ転送するかというものです。
アクティブモードとは
アクティブモードはFTPサーバーからFTPクライアントへ向けてデータ通信のための接続を開始します。
このときFTPクライアントは接続するべきデータ通信用のポート番号をFTPサーバーへ通知します。
以下はアクティブモードで mytext.txt というファイルをダウンロードする際のフロー図です。破線がデータ通信をおこなっている箇所です。

アクティブモードでのデータ転送
FTPクライアントがPORTコマンドでIPアドレスとポート番号を通知する
アクティブモードではFTPクライアントがPORTコマンドで接続するべきIPアドレスとポート番号をFTPサーバーへ通知します。
PORT 192,168,0,203,199,239
このコマンドは最初の「192,168,0,203」がIPアドレスとなります。
192,168,0,203 → 192.168.0.203
残りの「199,239」がポート番号です。ポート番号は次のように計算します。
199 x 256 + 239 = 51183
最初の「199」に256を掛けて、残りの「239」を足した結果が「51183」となります。FTPサーバーはポート20番(FTP-DATA)からFTPクライアントのポート51183へ向けてTCPコネクションを張りデータ転送を行います。
パッシブモードとは
パッシブモードはFTPクライアントからFTPサーバーへ向けてデータ通信のための接続を開始します。
アクティブモードとは反対にFTPサーバー側が接続するべきデータ通信用のポート番号をFTPクライアントへ通知します。
以下はパッシブモードで mytext.txt というファイルをダウンロードする際のフロー図です。破線がデータ通信をおこなっている箇所です。

パッシブモードでのデータ転送
FTPサーバーがIPアドレスとポート番号を通知する
パッシブモードではFTPクライアントがFTPサーバーへPASVコマンドでパッシブモードへの移行を要求します。
FTPサーバーが了承するとFTPサーバーは接続するべきIPアドレスとポート番号をFTPクライアントへ通知します。
227 Entering Passive Mode(192,168,0,101,79,42)
アクティブモードのときと同様に接続するべきポート番号を計算できます。
79 x 256 + 42 = 20266
アクティブモードではFTPクライアントがFTPサーバーのポート20266へ向けてTCPコネクションを張りデータ転送を行います。
FTPのトラブル
FTPはトラブルが発生する事が多いプロトコルです。特に通信経路上でアドレス変換やポート変換をしているとFTPのデータ通信で問題が発生します。
ログインできるがタイムアウトする
もっとも単純なケースはFTPログインした後に”ls”コマンドを実行するとタイムアウトしてしまうものです。
これはパソコンで発生することが多く、外から内への通信を問答無用で遮断するようなファイアウォール設定になっている場合に発生します。原因はアクティブモードでデータ通信をしようとした際にFTPサーバーからFTPクライアントへ接続する通信が遮断されてしまうためです。
解決方法としては、FTPクライアント側でFTPサーバー発信の通信をファイアウォールで許可するかパッシブモードを利用する必要があります。
そのほかにネットワーク機器のACLでデータ通信を許可する設定を入れていない場合も同様にデータ通信が失敗します。アクティブモードとパッシブモードとではACL設定がまったく異なるので、事前にどちらのモードで通信するのか決めておいた方が良いでしょう。
アドレス・ポート変換でトラブルが起きる
問題が発生するのはNAT環境が極めて多いです。
単純にアドレス変換のみおこなった場合、FTPのデータ通信は失敗します。これはアドレス変換後のIPアドレスとPORTコマンドで通知するIPアドレスが異なるためです。
ネットワーク機器の中にはNATする際に賢くFTPデータ通信用のIPアドレスとポート番号を書き換えてくれるものがありますが、そのような機能がない場合はFTPのデータ通信に失敗します。
また、ネットワークのIPアドレスの整合性を保つためにコッソリとNATしている場合があります。そのような場合は原因の特定が難しくなるかも知れません。
FTPデータ通信が失敗する場合はACLやNATを疑い設定箇所を見直していくことになるでしょう。最終的にはパケットキャプチャしてPORTコマンドでのやり取りを調査することになるかも知れません。
まとめ
FTPは前時代的なプロトコルですが、いまだに新規構築でFTPを採用することがあります。
これは顧客の要望もあり仕方がないことなので、インフラエンジニアの方はトラブルシューティングのためにもFTPプロトコルについて最低限の知識を持っていた方が良いかと思います。
できればtcpdumpやWireSharkでFTP通信がどのようにおこなわれているのか実際に目で見ておくとトラブルシューティングの際に役立つこと間違いありません。