せらぴんブログ

サークル「せらぴん」のうのはな透です。やっぱり眼鏡っ娘が好き!!

【FTP】パッシブモードと見せかけてアクティブモード

「クライアントからサーバにパッシブモードでファイルを転送しようとしたが、途中で425エラーが出てきてしまう」という話があった。
この時クライアントのファイアウォールをOFFにすると、なぜか転送に成功する。

ソースは以下のとおり。

package testProject;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.SocketException;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;

public class FTPsender {
  private static FTPClient client = new FTPClient();

  public static void main(String[] arg) throws SocketException, IOException {
    client.connect("127.0.0.1");
    client.login("user", "pass");

    client.pasv();
    client.setFileType(FTP.ASCII_FILE_TYPE);

    FileInputStream is = new FileInputStream("C:\\tmp.txt");
    client.storeFile("/ftproot/tmp.txt", is);
    is.close();

    client.logout();
    client.disconnect();
  }
}

「なんでだろう……なんでだろう……」と思ってパケットをキャプチャしてみる*1

f:id:yuphiel:20140207233950j:plain

あれ? PASVコマンドが出た後でPORTコマンドが出ている……。パッシブモードで送ったつもりなのに、実際はアクティブモードで送っていたのだ。失敗して当たり前である!!

結論から言うと、client.pasv()の部分が間違い。FTP#pasv()でなくFTPClient#enterLocalPassiveMode()を使わないと、storeFile内で勝手にアクティブモードになってしまうようだ。

f:id:yuphiel:20140207234009j:plain

正しくパッシブモードになっていれば、STORコマンドを送る前にデータコネクションが確立する。

それにしても狐につままれるような感じだなぁ。

教訓

  • コネクション周りの不具合は、パケットをキャプチャしないとわからない。
  • 現場のエンジニアの勘より、パケットキャプチャを信じろ。

*1:SSは別環境での再現なのでエラーは発生してない