google 等の検索エンジンからこのページへ来た方へ
お手数ですがトップページの 注意書きをお読み下さい。
IP アドレス、ドメイン名等は全て仮のものです。

前ふり
最近の ADSL の普及で、 24 時間常時接続なんて環境がごく身近な物になってました。
こういう状況になると、恐いのが「クラッキング」というやつです。
自分のマシンがクラックされるのもそうですが、 「踏み台」にされて人様に迷惑をかけたなんてなると目も当てられません。
そうならないためにも、 パケットフィルタリングの設定はきちんとしておきましょう。


IPFW と IP Filter
FreeBSD にはパケットフィルタリングのシステムとして、 IP Firewall (IPFW) と IP Filter の 2 種類が用意されています。
調べてみると IPFW は FreeBSD 独自のシステムであり、 IP Filter は Linux, Solaris, IRIX などでも使えるようです。
今回は資料が手元にあった IPFW を使ってみました。


natd
ネットワーク構成で見たように、 LAN 側の IP アドレスはプライベート IP アドレスを使っています。
このままでは LAN 側のマシンはインターネットにアクセスできません。
そこで NAT (Network Address Translation) を使って、 プライベートアドレスをグローバルアドレスに変換します。
これは natd デーモンが処理します。
また、natd は IPFW と協調して動作します。
IPFW には divert と呼ばれるソケットが用意されていて、 この divert ソケットに転送されたパケットを natd デーモンで処理して、 アドレスを書き換えて NAT 機能を実現します。
アドレスが書き換えられたパケットは、 IPFW がフィルタリングルールにマッチするかどうかチェックします。


フィルタルングの方針
あらかじめ、パケットフィルタルングの方針を決めておきます。
今回は次の方針でフィルタリングのルールを作ります。


カーネルの再構築と rc.conf の設定
ここから先は ローカルコンソールで行なって下さい。
理由は後述します。

最近の FreeBSD なら /etc/rc.conf に firewall_enable="YES" と書いておけば、 再起動した時にカーネルモジュールを読み込んでくれます。
しかし、 デフォルトではログが取れない状態になっています。
ログが取れないと、いつどのようなアクセスがあったかが分らなくなります。
IPFW のログを有効にするにはカーネルの再構築か、 カーネルモジュールの再コンパイルのどちらかが必要となりますが、 今回はカーネルの再構築を行ないます。

まず、server01 の カーネルコンフィグレーションファイル (ここでは /usr/src/sys/i386/conf/SERVER01) を編集します (もちろん root で)。
    # cd /usr/src/sys/i386/conf
    # vi SERVER01
ここで次の 3 行を加えて下さい。
    options         IPFIREWALL          # IPFW を有効にする
    options         IPFIREWALL_VERBOSE  # IPFW のログを有効にする
    options         IPDIVERT            # divert ソケットを有効にする
編集が終わったらカーネルを再構築します。
    # rm -rf ../../compile/SERVER01
    # config SERVER01
    # cd ../../compile/SERVER01
    # make depend && make
    # make install
これが全て正常に終了したらリブートします。
これで IP Firewall が有効になります。
ここで、注意しなくちゃならないのは、 IP Firewall のデフォルトは 全てのパケットの通過を禁止します。
実は、カーネルのインストールまではリモートからでもできます。
しかし、 この状態でリブートしてしまうと、 以後リモートから操作できなくなります。
このマシンがすぐ近くにあれば問題ありませんが、 九州のマシンを北海道から操作しているときにうっかりこれをやってしまうと 目も当てられない悲惨な状況になります。


設定ファイルを書く
/etc/rc.conf に以下を追加します。
    gateway_enable="YES"                  # 複数インターフェース間でのパケット転送
    natd_enable="YES"                     # natd を起動
    natd_interface="if1"                  # 変換先アドレスを持つインターフェース
    natd_flags=""                         # natd 起動時のオプション
    firewall_enable="YES"                 # IPFW を有効にする
    firewall_script="/etc/firewall.local" # IPFW のルール設定用スクリプト
    firewall_logging="YES"                # IPFW のログ機能を有効にする
IPFW のルール設定用スクリプト /etc/firewall.local を作ります。
113 番ポートへのルールは "deny" ではなく "reject" にします。
調べてみると、接続クライアントが何者かを認証するために ident (113 番ポート) というサービスがあるそうです。
これを deny にすると、 タイムアウトまたは規定回数の試行を繰り返すのを待つので、 ftp などで接続が遅くなるそうです。
reject にすると相手側のサーバが諦めてくれるのでこの問題は解決します。

2003/01/26 追記
Auth/IDENT (TCP/113, RFC 1413) は SMTP サーバとの通信などで、 そのセッションを張ったのは誰かを特定するのに使用されます。
しかしこの特定ができなくても、通信は実施されます。

ipfw での reject (unreach host と同義) は ICMP の destination unreach の host unreachable を返します。
ただし、host unreachable を返すと、すでに確立されていたそのホストとの connection が切られてしまうことがあります。
この問題は host unreachable ではなく port unreachable (ipfw のルールで reject ではなく unreach port) を返すようにすれば良いのですが、古い TCP/IP の実装 (4.3BSD tahoe 等) では port unreachable の概念が無いそうです。

他の手として、 TCP RST を返せば相手側はタイムアウトまで待たずに諦めてくれます。
FreeBSD の ipfw には reset というルールがあります。
これはパケットを破棄して、TCP パケットであれば、 相手に TCP RST を送信しようとします。
こちらの方が無難かと思います。
追記ここまで

ルール設定用スクリプトを書いた後、リブートすれば全て終了です。
LAN 側からインターネットにアクセスできるか確認して下さい。
以下のルールで大丈夫なはずですが、 動作がおかしい場合はログを見てルールの追加や削除をして下さい。
ログは /var/log/security に記録されます。

ルール設定用スクリプト /etc/firewall.local の例です。
ただしプロバイダとの関係もあり、 管理人の実際の設定とは若干異なる部分があります。
このスクリプトでの動作検証はしていないので、 実際にこのスクリプトを使うときは十分注意して下さい。
    # IPFW のコマンド
    fwcmd="/sbin/ipfw -q"

    # 外側インターフェースの IP アドレス、ネットワークアドレス
    oif="if0"
    oip="1.2.3.x"
    onet="1.2.3.0"
    omask="255.255.255.0"

    # 内側インターフェースの IP アドレス、ネットワークアドレス
    iif="if1"
    iip="192.168.0.1"
    inet="192.168.0.0"
    imask="255.255.255.0"

    # 全てのルールのクリア
    ${fwcmd} -f flush

    # アドレス詐称パケットの破棄
    ${fwcmd} add deny ip from ${inet}:${imask} to any in via ${oif}
    ${fwcmd} add deny ip from ${onet}:${omask} to any in via ${iif}

    # Net-BIOS の破棄
    ${fwcmd} add deny udp from any to any 137-139
    ${fwcmd} add deny udp from any 137-139 to any

    # プライベートアドレスやマルチキャストの破棄 (外→内)
    ${fwcmd} add deny ip from any to 10.0.0.0/8 via ${oif}
    ${fwcmd} add deny ip from any to 172.16.0.0/12 via ${oif}
    ${fwcmd} add deny ip from any to 192.168.0.0/16 via ${oif}
    ${fwcmd} add deny ip from any to 0.0.0.0/8 via ${oif}
    ${fwcmd} add deny ip from any to 169.254.0.0/16 via ${oif}
    ${fwcmd} add deny ip from any to 192.0.2.0/24 via ${oif}
    ${fwcmd} add deny ip from any to 224.0.0.0/4 via ${oif}
    ${fwcmd} add deny ip from any to 240.0.0.0/4 via ${oif}

    # NAT
    ${fwcmd} add divert natd all from any to any via ${oif}

    # プライベートアドレスやマルチキャストの破棄 (内→外)
    ${fwcmd} add deny ip from 10.0.0.0/8 to any via ${oif}
    ${fwcmd} add deny ip from 172.16.0.0/12 to any via ${oif}
    ${fwcmd} add deny ip from 192.168.0.0/16 to any via ${oif}
    ${fwcmd} add deny ip from 0.0.0.0/8 to any via ${oif}
    ${fwcmd} add deny ip from 169.254.0.0/16 to any via ${oif}
    ${fwcmd} add deny ip from 192.0.2.0/24 to any via ${oif}
    ${fwcmd} add deny ip from 224.0.0.0/4 to any via ${oif}
    ${fwcmd} add deny ip from 240.0.0.0/4 to any via ${oif}

    # ident パケットの破棄
    ${fwcmd} add reset tcp from any to any 113

    # ループバックの設定
    ${fwcmd} add allow ip from any to any via lo0
    ${fwcmd} add deny ip from any to 127.0.0.0/8

    # 内側から外側への接続の許可
    ${fwcmd} add allow tcp from any to any established
    ${fwcmd} add allow tcp from ${inet}:${inet} to any setup
    ${fwcmd} add allow tcp from ${oip} to any via ${oif} setup
    ${fwcmd} add allow udp from ${inet}:${inet} to any keep-state
    ${fwcmd} add allow udp from ${oip} to any via ${oif} keep-state
    ${fwcmd} add allow ip from any to any frag

    # 外側から WWW サーバへの接続の許可
    ${fwcmd} add allow tcp from any to ${oip} 80 setup

    # 内→外へ通常の (Passive モード以外) の FTP を許可
    # 20 番ポートへのコネクションはサーバ側から張る
    ${fwcmd} add allow tcp from any 20 to ${oip} setup

    # 外側から Mail サーバ (SMTP, POP) への接続を許可
    ${fwcmd} add allow tcp from any to ${oip} 25 in via ${oif} setup
    ${fwcmd} add allow tcp from any to ${oip} 110 in via ${oif} setup

    # DNS サーバへの接続を許可
    ${fwcmd} add allow tcp from any to ${oip} 53 via ${oif} setup
    ${fwcmd} add allow udp from any to ${oip} 53 via ${oif} 

    # 動的ルール集合に対するパケットのチェック
    ${fwcmd} add check-state

    # 内側から外側への ping とその応答の許可
    ${fwcmd} add allow icmp from any to any via ${iif}
    ${fwcmd} add allow icmp from any to any out via ${oif} icmptype 8
    ${fwcmd} add allow icmp from any to any in via ${oif} icmptype 0

    # 上記以外のパケットは破棄し、ログを取る
    ${fwcmd} add deny log ip from any to any

    # カウンタのリセット
    ${fwcmd} zero


Top Top へ戻る