【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。
あれ? PASVコマンドが出た後でPORTコマンドが出ている……。パッシブモードで送ったつもりなのに、実際はアクティブモードで送っていたのだ。失敗して当たり前である!!
結論から言うと、client.pasv()の部分が間違い。FTP#pasv()でなくFTPClient#enterLocalPassiveMode()を使わないと、storeFile内で勝手にアクティブモードになってしまうようだ。
正しくパッシブモードになっていれば、STORコマンドを送る前にデータコネクションが確立する。
それにしても狐につままれるような感じだなぁ。
教訓
- コネクション周りの不具合は、パケットをキャプチャしないとわからない。
- 現場のエンジニアの勘より、パケットキャプチャを信じろ。
*1:SSは別環境での再現なのでエラーは発生してない