[Home] [Kuri] [Sysad] [Internet?] [Blog] [Java] [Windows] [Download] [Profile] [Flash] [+] |
ようやく、ファイアウォールマシンを FreeBSD から OpenBSD に変更できました。 OpenBSD では、IP Filter ではなく、PF というものになりました。
今回は、PF を使ったフィルタリング、NAPT およびポートフォワーディングの設定方法について書きました。
OS は OpenBSD 3.3 です。
設定ファイル /etc/pf.conf にルールを書き、pfctl コマンドで反映させます。 設定ファイルには、1行に1つのルールを書きます。 ルールは、IP Filter にそっくりです。 そっくりですが、マクロが使えたり、ルールをひとまとめにできたりします。 こっちの方が便利です。
action in-out [log] [quick] [on interface] [af] [proto protocol] [srcdist [flags flag] [state] ] |
それぞれの意味を以下に示します。
キーワード | 意 味 な ど |
---|---|
action | 許可は pass, 拒否は block |
in-out | 入ってくる時のチェックは in, 出ていく時は out |
log | ログに残す場合に指定 |
quick | 該当する場合移行のルールを見ずに適用させる場合に指定 |
on interface | 該当するインタフェースの指定 |
af | アドレスファミリの指定。inet か inet6. |
proto protocol | プロトコルの指定(icmp,tcp,udpなど) |
srcdist | 送信元および送付先の指定 (all もしくは from object to object) |
flags flag | TCP のフラグ指定(check/mask)。大抵は S/SA(SYN だけならマッチ) |
state | 状態が保存され、ポートや ACK# 等が一致すれば許可 (keep state,modulate state) |
object | IPアドレスおよびポートの指定(port = 110 や port > 1023 など) |
ここでは、単純に、外からから来るパケットのうち 22/tcp だけを通す設定をします。
こちらから出ていく分には、制限を設けません。
/etc/pf.conf の内容は、以下のようになります。
$lo_if = "lo0" $ex_if = "ne1" $ex_addr = "10.0.0.245" block log all pass quick on $lo_if all pass in quick on $ex_if proto tcp from any to $ex_addr port 22 flags S/SA modulate state pass in quick on $ex_if inet proto icmp from any to $ex_addr icmp-type echoreq keep state pass out quick on $ex_if proto { udp, tcp, icmp } from any to any keep state |
最初の3行はマクロです。
$lo_if は、ループバック・インタフェースです。
$ex_if は、LAN につながるインタフェースです。
$ex_addr は、$ex_if にアサインされたIPアドレスです。
マクロを使うと、環境が変わっても、ここの定義だけを書き換えればいいので、便利です。
4行目は、すべてをブロックするというルールです。
in-out を省略すると、両方が適用されます。
すべてのルールを見て、他に適用するルールがなければ、このルールが適用されます。
IP Filter と同様、デフォルトは通してしまいますので、これを書いておきます。
log をつけてあるので、これが適用されたパケットはログに残ります。
5行目は、ループバック・インタフェースに流れるパケットをすべて許可するというルールです。 quick がついていますので、該当すれば即適用されます。 チェックする必要のないインタフェースは、このように書いておけばいいと思います。
6行目は、$ex_if から来た 22/tcp 宛のパケットを許可するルールです。 これも quick がついていますので、該当すれば即適用されます。
7行目は、$ex_if から来た icmp echo request のパケットを許可するルールです。
8行目は、$ex_if から出ていく udp, tcp および icmp パケットをすべて許可するルールです。
これで、
ループバック・インタフェースを流れるパケットは無条件に許可。
外に出ていく udp, tcp および icmp のパケットは、無条件に許可。
外から入ってくるパケットのうち、22/tcp および icmp echo request は許可し、他は拒否。
という設定ができたことになります。
あとは、pfctl コマンドで適用させるだけです。
# pfctl -f /etc/pf.conf |
まずは、他のマシンからアクセスしてみます。
22/tcp と icmp echo request が通ることを、SSH と ping で確認します。
10.0.0.1# slogin 10.0.0.245 usu@10.0.0.245's password: ... 10.0.0.1# ping 10.0.0.245 PING 10.0.0.245 (10.0.0.245) 送信元 10.0.0.1 : 56(84) bytes of data. 64 バイト応答 送信元 10.0.0.245: icmp_seq=0 ttl=64 時間=675 マイクロ秒 64 バイト応答 送信元 10.0.0.245: icmp_seq=0 ttl=64 時間=631 マイクロ秒 64 バイト応答 送信元 10.0.0.245: icmp_seq=0 ttl=64 時間=599 マイクロ秒 --- 10.0.0.245 ping 統計 --- 送信パケット数 3, 受信パケット数 3, パケット損失 0% Round-Trip 最小/平均/最大/mdev = 0.599/0.635/0.675/0.031ミリ秒 |
通らなかったら、悩んでください。
そして、それ以外がつながらないことを、以下のように確認します。
10.0.0.1# telnet 10.0.0.245 Trying 10.0.0.245... (しばらく待つ) 10.0.0.1# telnet 10.0.0.245 80 Trying 10.0.0.245... (しばらく待つ) |
つながらなければ OK です。つながってしまったら、悩んでください。
ログは、/var/log/pflog に記録されます。ただしバイナリです。
tcpdump の形式なので、tcpdump で読めます。
# tcpdump -e -ttt -n -r /var/log/pflog ... Sep 11 05:49:40.158819 rule 0/0(match): block in on ne1: 10.0.0.1.4052 > \ 10.0.0.245.80: S 1414108234:1414108234(0) win 64240 |
-e オプションは、マッチしたルールなどの情報を出力するためのものです。
-ttt オプションは、月日を出力するためのものです。
-n オプションは、名前の解決をしないためのものです。
-r オプションで、ファイルを指定します。
上記は、先ほど telnet コマンドで 80/tcp にアクセスしたときの不正アクセス(!?)です。
NAPT の場合も、/etc/pf.conf に設定を書きます。
その前に、IP フォワーディングを有効にしておく必要があります。
コマンドラインで直接行うには、sysctl コマンドを使用します。
sysctl -w net.inet.ip.forwarding=1 |
OpenBSD 起動時に自動的に行わせるには、/etc/sysctl.conf に以下を追加します。
net.inet.ip.forwarding=1 |
「簡単な」書式は以下の通りです。
nat on ext_if [af] from src_addr [port src_port] to dst_addr [port dst_port] -> ext_addr |
それぞれの意味を以下に示します。
キーワード | 意 味 な ど |
---|---|
ext_if | 外部向けのネットワーク・インタフェース |
af | アドレスファミリ。inet か inet6 |
src_addr | 送信元の内部アドレス |
src_port | 送信元のポート |
dst_addr | 送信先のアドレス(といっても any でいいと思う) |
dst_port | 送信先のポート(といっても指定する必要はなさそう) |
ext_addr | 外部アドレス(src_addr がこのアドレスに変換される) |
設定を反映させるには、フィルタリングのときと同様に pfctl コマンドを使用します。
例えば、ne0 から出ていくパケットの送信元IPアドレス 10.0.0.0/8 を、 グローバルIPアドレス 1.2.3.4 に変換するには、以下のように記述します。
nat on ne0 from 10.0.0.0/8 to any -> 1.2.3.4 |
ne0 にアサインされたIPアドレスが 1.2.3.4 なら、以下のようにも書けます。
# ne0 にアサインされたアドレスに変換したい場合というべきでしょうか。
nat on ne0 from 10.0.0.0/8 to any -> ne0 |
さらにマクロを使えば、汎用性が増します。たぶん。
$ex_if = "ne0" nat on $ex_if from 10.0.0.0/8 to any -> $ext_if |
ne0 にアサインされるアドレスが DHCP などで動的に割り振られる場合は、
括弧で囲みます。
括弧で囲むと、アドレスが変更されても新しいアドレスを使ってくれます。
# 括弧で囲まないと、pfctl で適用したときのアドレス固定になります。
$ex_if = "ne0" nat on $ex_if from 10.0.0.0/8 to any -> ($ext_if) |
内部から、直接外部にアクセスしてみます。
% telnet www.yahoo.co.jp 80 Trying 210.81.150.5... Connected to www.yahoo.co.jp. Escape character is '^]'. HEAD / HTTP/1.0 HTTP/1.1 200 OK Date: Thu, 11 Sep 2003 13:59:33 GMT P3P: policyref="http://privacy.yahoo.co.jp/w3c/p3p.xml", ... ...後略 |
pfctl コマンドを -s state オプションつきで実行すると、 変換の具合を見ることができます。
# pfctl -s state ... tcp 10.0.0.11:1877 -> 1.2.3.4:64464 -> 211.14.15.5:80 FIN_WAIT_2:FIN_WAIT_2 |
いわずもがなですが、内部のマシンの特定のポートを、外から見えるようにできます。
「簡単な」書式は以下の通りです。
rdr on ext_if proto protocol from src_addr to dst_addr port dst_port -> in_addr [port in_port] |
それぞれの意味を以下に示します。
キーワード | 意 味 な ど |
---|---|
ext_if | 外部向けのネットワーク・インタフェース |
proto protocol | プロトコルの指定(icmp,tcp,udpなど) |
src_addr | 送信元のアドレス(any でいいと思う) |
dst_addr | 送信先の外部アドレス |
dst_port | 送信先のポート |
in_addr | 内部アドレス(dst_addr がこのアドレスに変換される) |
in_port | 送信先のポート(dst_port がこのポートに変換される) |
設定を反映させるには、フィルタリングのときと同様に pfctl コマンドを使用します。
ネットワーク・インタフェース ne0 から、 IPアドレス 1.2.3.4 の 22/tcp 宛に来たパケットを、 内部のマシン 10.0.0.245 のフォワードする設定は、以下のようになります。
rdr on ne0 proto tcp from any to 1.2.3.4 port 22 -> 10.0.0.245 |
プロトコルが同じであれば、複数をまとめられます。
22/tcp の他に、80/tcp, 443/tcp もフォワードする設定は以下の通りです。
rdr on ne0 proto tcp from any to 1.2.3.4 port { 22, 80, 443 } -> 10.0.0.245 |
さらに、マクロを使ったほうがすっきりします。(1つだけだと意味ないですが)
以下では、さらに 53/udp をフォワードしています。
$ex_if = "ne0" $ex_addr = "1.2.3.4" $in_addr = "10.0.0.245" $ex_tport = "{ 22, 80, 443 }" $ex_uport = "53" rdr on $ex_if proto tcp from any to $ex_addr port $ex_tport -> $in_addr rdr on $ex_if proto udp from any to $ex_addr port $ex_uport -> $in_addr |
外部からアクセスしてみます。
…例は割愛します。:-)
以下のような環境だとします。
1.2.3.4(ne0) 10.0.0.245(ne1) 10.0.0.1 INTERNET ---------------- [OpenBSD] ------------------------- [Server] <1.2.3.0/24> <10.0.0.0/8> |
…という条件にあう設定を作ってみました。
最初は、マクロやテーブルの設定です。
# 外向きのインタフェース、アドレス、ネットワーク $ex_if = "ne0" $ex_gw = "1.2.3.4" table <ex_net> { 1.2.3.0/24 } # 内向きのインタフェース、アドレス、ネットワーク $in_if = "ne1" $in_gw = "10.0.0.245" table <in_net> { 10.0.0.0/8 } # ループバック・インタフェース $lo_if = "lo0" # ホスト $in_sv = "10.0.0.1" $ex_sv = "1.2.3.3" # 公開するポート $sv_tport = "{ 22, 80, 443 }" $sv_uport = "53" $gw_tport = "{ 22, 25 }" |
まずは、NAPT の設定を記述してみます。
nat on $ex_if from <in_net> to any -> ($ex_if) |
次に、ポートフォワーディングの設定を記述してみます。
# 1.2.3.3 の 22/tcp, 80/tcp, 443/tcp を 10.0.0.1 へ。 rdr on $ex_if proto tcp from any to $ex_sv port $sv_tport -> $in_sv # 1.2.3.3 の 53/udp を 10.0.0.1 へ。 rdr on $ex_if proto ucp from any to $ex_sv port $sv_uport -> $in_sv |
そして、いよいよフィルタリングです。
ポートフォワーディングなどの設定をしている場合は、
変換後のアドレスを使う必要があります。
# IP Filter と同じですね。
# デフォルトはすべて拒否!!! block log all # ループバックと内部からは許可 pass quick on $lo_if all pass quick on $in_if all # 外部からは以下だけ許可 (他はデフォルト拒否だ!!) pass in quick on $ex_if proto tcp from any to $in_sv port $sv_tport flags S/SA modulate state pass in quick on $ex_if proto udp from any to $in_sv port $sv_uport keep state pass in quick on $ex_if proto tcp from any to $ex_gw port $gw_tport flags S/SA modulate state # ICMP echo request も許可 (気に入らなければコメントアウトしてください) pass in quick on $ex_if inet proto icmp all icmp-type echoreq keep state # 中から外は許可 pass out quick on $ex_if proto { udp, tcp, icmp } from any to any keep state |
IP Filter よりもずいぶんすっきりします。:-)
あと、石橋を叩くなら、外部から来るパケットで、
送信元がプライベートアドレスのパケットを拒否する設定でしょうか。
table <rfc1918_net> { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 } block in log quick on $ex_if from <rfc1918_net> to any |
ただし、INTERNET との接続が PPP や PPPoE などの場合はいいのですが、
普通に Ethernet でつながっている場合、
外部インタフェースにアサインされていないアドレスを使用する際には注意が必要です。
例えば上記の場合、ne0 のエイリアスに 1.2.3.3 をアサインしておくか、
arp コマンドで設定しておく必要があると思います。
# でないと、1.2.3.3 宛のパケットが OpenBSD に届きません。
[Home] [Kuri] [Sysad] [Internet?] [Blog] [Java] [Windows] [Download] [Profile] [Flash] [-] | |
usu@usupi.org | Last modified : Fri Sep 12 23:16:09 2003 |