ネットの海の片隅で

技術ネタの放流、あるいは不法投棄。

Net::FTPでNAT越えする

解決したいこと

  • FTPはActiveモードを使った時にデフォルトでNATを越えられない。
  • NAT越えのためにはFTPのPORTコマンドを適切に使用する必要がある。
  • RubyのNet::FTPにはPORTコマンドあるいは似たようなオプションが無い。
  • RubyアプリケーションでNAT越えのFTP通信(EC2から外向き)ができない。

無いなら作る

Net::FTP#portを生やして、設定したアドレスとポートを元に通信するためのgemを書いた。

使い方

基本的にはGitHubの方に書いてある通り。

require 'net/ftp'
require 'net/ftp/port_command'

ftp = Net::FTP.new("exmaple.com", "username", "password")
ftp.port("203.0.113.5", 10020) # サーバ側からのデータコネクションを待ち受けるアドレスとポート
ftp.list # => ["foo.txt", "bar.txt"]

一度設定したアドレスとポートは明示的に解除されるまでずっと有効*1

ftp.port(nil, nil) # デフォルトの動作に戻す

さいごに

Net::FTPとその周辺のコードを読むのには苦労したけど、読み終わってからの設計・実装はすぐにできた。

コードも実質10行くらいしかないけど、少なくとも自分にとって非常に役に立つ10行になるはずだし、今までで一番良いgemを書いたと思っている。

関連記事

EC2からactive modeでFTP通信ができない件 - ネットの海の片隅で

*1:このあたりはFTPのPORTと違うところ。