[前に戻る: 性能] [目次] [次に進む: authpf: 認証ゲートウェイ用 ユーザシェル]
FTP はふたつの方法、受動的接続 (passive) か能動的接続 (active) のうちのいずれかの方法で 使用することができます。一般的に active か passive かの選択は、ファイアウォールでの FTP の使用に問題があるかどうかで決定されます。現実的には、ユーザが幸せになるために、 両方の方法をサポートすべきでしょう。
FTP の能動的接続モードでは、ユーザがリモートの FTP サーバに接続して 情報やファイルを要求する際に、要求されたデータを転送するために FTP サーバからクライアントに対して新しい接続を行います。これは データ接続 (data connection) と呼ばれる接続です。FTP クライアントは、 この接続を受信するためのランダムな空ポートを選択します。FTP クライアントは、 選択したポート番号を FTP サーバに送信し、そのポートで FTP サーバからの 接続の着信を待ちます。そして、FTP サーバは、クライアントのアドレスの 選択されたポートに対して接続を開始し、データ転送を行います。しかし、これは、 NAT の向う側にある FTP サーバからの接続を、ユーザが受信しようとする場合に 問題となります。NAT がどのように働くのかという理屈を考えるとわかりますが、 FTP サーバは NAT ゲートウェイの外部アドレスの選択されたポートに対して接続して、 データ接続を開始しようとするからです。そして、NAT マシンがこの接続を受信しますが、 NAT マシンはその状態テーブルにパケットのマッピングを持っていないので、 このパケットは廃棄され、それがクライアントに配信されることはないのです。
FTP の受動的接続モード (これは OpenBSD の href="http://www.openbsd.org/cgi-bin/man.cgi?query=ftp&sektion=1&manpath=OpenBSD+3.4" >ftp(1) クライアントのデフォルトのモードです) では、クライアントがサーバに データ接続を待ち受けるためのランダムなポートを選択するよう、要求を出します。 サーバはクライアントに選択したポートの情報を伝え、クライアントはそのポートに接続して データ転送を行います。不運にも、FTP サーバの手前にあるファイアウォールが、着信する データ接続をブロックしてしまうかも知れませんので、これは常に可能だったり、 期待できたりするわけではありません。OpenBSD の ftp(1) クライアントは、受動的接続モードを デフォルトで使用しますが、強制的に能動的接続モードで FTP を使用するには ftp に -A フラグを指定するか、"ftp>" プロンプトで "passive off" コマンドを 発行することで、受動的接続モードを "off" に設定するかのいずれかの方法で可能です。
パケットフィルタ (PF) は、FTP プロキシサーバを通過する FTP のトラフィックを リダイレクトすることで、このような状況に対する解決策を用意しています。 この処理は、NAT ゲートウェイやファイアウォールを通過する FTP トラフィックを 「案内」するように動作します。OpenBSD と PF で使用される FTP プロキシは、 ftp-proxy(8) です。これを有効化するには、pf.conf の NAT セクションに以下のような行を追加します。
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 \
port 8021
この行の記述は、「内部インターフェイス上のトラフィックは、 ポート 8021 をリスンする、このマシン上で実行されている プロキシサーバにリダイレクトする」という意味になります。
できれば、プロキシサーバが OpenBSD を実行するマシン上で動作するようにしたいのではないでしょうか。 これは、以下のような行を /etc/inetd.conf に 追加することで可能になります。
127.0.0.1:8021 stream tcp nowait root /usr/libexec/ftp-proxy \
ftp-proxy
そして、システムをリブートするか、HUP シグナルを inetd(8) に送信するかのどちらかを実行してください。HUP シグナルを送信するには以下のようにします。
kill -HUP `cat /var/run/inetd.pid`
ftp-proxy がポート 8021 をリスンし、同じポートを上記の rdr 命令文が FTP トラフィックを送信しているということに注意する必要があるでしょう。ポート 8021 の選択は任意のものですが、8021 は他のいかなるアプリケーションによっても 定義されていないので、これは良い選択であると言えるでしょう。
ftp-proxy(8) は、PF フィルタの背後の FTP クライアントを助けるためのものであって、PF フィルタの背後の FTP サーバを扱うために使用するものではないということに注意してください。
pass in on $ext_if proto tcp from any to any port 21 keep state
pass in on $ext_if proto tcp from any to any port > 49151 \
keep state
もし、その必要性があれば、これらのポートの範囲を大幅に厳しくすることができます。 OpenBSD の ftpd(8) プログラムの場合、これは sysctl(8) の変数 net.inet.ip.porthifirst および net.inet.ip.porthilast を使用して制御することができます。
以下は、この目的を達成するためのルールのサブセットの例です。
ftp_server = "10.0.3.21"
rdr on $ext_if proto tcp from any to any port 21 -> $ftp_server \
port 21
rdr on $ext_if proto tcp from any to any port 49152:65535 -> \
$ftp_server port 49152:65535
# in on $ext_if
pass in quick on $ext_if proto tcp from any to $ftp_server \
port 21 keep state
pass in quick on $ext_if proto tcp from any to $ftp_server \
port > 49151 keep state
# out on $int_if
pass out quick on $int_if proto tcp from any to $ftp_server \
port 21 keep state
pass out quick on $int_if proto tcp from any to $ftp_server \
port > 49151 keep state
[前に戻る: 性能] [目次] [次に進む: authpf: 認証ゲートウェイ用 ユーザシェル]