IP Filter + NAT

FreeBSD 4.2R に用意されている IPF(IP Filter) を使ってみました。

ipf.gif nat-config.gif

IP Filter とは?

パケットフィルタです
IPFW よりも細かく制御できます
NAT 機能付き
ルールのテストができます
IPFW では最初にマッチしたルールが適用されますが、 IP Filter は最後にマッチしたルールが適用されます(quick を指定すると、その場で適用されます)

マシンの設定

FreeBSD 4.2R の Kern-Developer というセットをインストールします
カーネルを作り直します

   #options        INET6            <= IPv6 を使わないなら不要
   #options        NFS              <= 有効にしてはいけない
   #pseudo-device   bpf             <= 有効にしてはいけない
   options         IPFILTER               
   options         IPFILTER_LOG
   options         IPFILTER_DEFAULT_BLOCK
   # 以下は必須ではありません(LINT を参照)
   options         ICMP_BANDLIM     <= ICMP パケットの帯域を制限
   options         TCP_RESTRICT_RST <= RST フラグの制限
   options         TCP_DROP_SYNFIN  <= SYN+FIN フラグの TCP パケットを落す

/etc/rc.conf を編集します

   ipfilter_enable="YES"
   ipfilter_rules="/etc/ipf.rules"
   ipfilter_flags=""
   ipmon_enable="YES"               <= ログを取る
   ipmon_flags="-D /var/log/ipflog" <= ログファイルを指定
   ipnat_enable="YES"               <= NAT を有効にする
   ipnat_rules="/etc/ipnat.rules"   <= NAT の設定ファイルを指定
   gateway_enable="YES"             <= 2つのインターフェイス間にパケットを流す
   portmap_enable="NO"
   tcp_restrict_rst="YES"     <= TCP_RESTRICT_RST を有効にする
   tcp_drop_synfin="YES"      <= TCP_DROP_SYNFIN を有効にする

最も簡単な /etc/ipf.rules はこうです

   pass in all
   pass out all

/etc/ipnat.rules はこう書きます(外側のインターフェイスは xl0)
auto でうまく動作しなかったら、25000:40000 と指定して下さい)

   map xl0 192.168.0.0/24 -> 1.2.3.4/32 portmap tcp/udp auto
   map xl0 192.168.0.0/24 -> 1.2.3.4/32

ルールの設定

IP Filter 付属の mkfilters で基本となるルールを作成できます (mkfilters は 4.2R の contrib ソースに含まれています)

   % perl mkfilters > ipf.simple
	  
   # ipf.simple の内容
   # Internet 側のインターフェイスが xl0 の場合で、
   # その IP アドレスを 1.2.3.4 とする
   # 内部のインターフェイスは xl1 で、IP は 192.168.0.1/24 とする
   block in log quick from any to any with ipopts
   block in log quick proto tcp from any to any with short
   pass out on xl0 all head 250
   block out from 127.0.0.0/8 to any group 250
   block out from any to 127.0.0.0/8 group 250
   block out from any to 1.2.3.4/32 group 250
   pass in on xl0 all head 200
   block in from 127.0.0.0/8 to any group 200
   block in from 1.2.3.4/32 to any group 200
   block in from 192.168.0.1/0xffffff00 to any group 200
   pass out on xl1 all head 350
   block out from 127.0.0.0/8 to any group 350
   block out from any to 127.0.0.0/8 group 350
   block out from any to 192.168.0.1/32 group 350
   pass in on xl1 all head 300
   block in from 127.0.0.0/8 to any group 300
   block in from 192.168.0.1/32 to any group 300
   block in from 1.2.3.4/0xffffff00 to any group 300

このルールを設定してみます

   # ipf -Fa -Z -f ipf.simple

ルールの確認は ipfstat で行ないます

   # ipfstat -i
   # ipfstat -o

これで分かるように、IP Filter のルールは入力用と出力用に分かれています
ipfstat を作り直して、-t オプションを有効にすると便利です

ルールのテスト

ipftest コマンドでパケットがパスするかブロックされるかをテストすることができます
テストデータには tcpdump や etherfind のダンプも使用できます
手で記述する場合は、こんな風に書きます

   # ipf.test
   # 1.2.3.4 は Internet 側のアドレス
   in on xl0 tcp 123.123.123.123,2000 1.2.3.4,80

テストします

   # ipftest -r ipf.simple -i ipf.test
   in on xl0 tcp 123.123.123.123,2000 1.2.3.4,80
   input: on xl0 ...
   pass ip 40(20) ...    <= ルール通過

NAT の設定

例えば、/etc/ipnat.rules というファイルを用意します

   map xl0 192.168.0.0/24 -> 1.2.3.4/32 portmap tcp/udp auto
   map xl0 192.168.0.0/24 -> 1.2.3.4/32

このファイルを ipnat コマンドで設定します

   # ipnat -CF -f /etc/ipnat.rules  <= 設定

NAT を使用している様子もモニタできます

   # ipnat -l
   List of active MAP/Redirect filters:
   map xl0 ...
   map xl0 ...
   List of active sessions:
   MAP 192.168.xxx.zzz  1521 <- -> 1.2.3.4 25035 [207.46.131.137 80]

上の例は、192.168.xxx.zzz のクライアントから、1.2.3.4 を経由して 207.46.131.137 のポート 80 にアクセスしていることを示します

内側のマシンが外部から直接アクセスできるようにするには、rdr というルールを追加します
例えば、内部に web サーバを配置する場合(この構成は危険です)は、こう書きます

   rdr xl0 0.0.0.0/0 port 80 -> サーバアドレス port 80

設定例

IPFW + NAT と同じルールです

#  IPF+NAT 用のルールファイル(静的ルール)

# 2月13日 修正

# (group を指定していないルールはグループ 0)
# IP オプションが指定されたもの、断片化されたもの、
# 短いパケットなどはここで破棄
block in log quick from any to any with ipopts frag
block in log quick proto tcp from any to any with short

############################################
# 外部(Internet)からの入力(グループ 100)

pass in on xl0 all head 100

# アドレス偽装防止
block in from 127.0.0.0/8 to any group 100
block in from 1.2.3.4/32 to any group 100
block in from 192.168.0.1/24 to any group 100

# プライベートアドレスやマルチキャストなどの破棄
block in from 10.0.0.0/8 to any group 100
block in from 172.16.0.0/12 to any group 100
block in from 192.168.0.0/16 to any group 100
block in from 0.0.0.0/8 to any group 100
block in from 169.254.0.0/16 to any group 100
block in from 192.0.2.0/24 to any group 100
block in from 224.0.0.0/4 to any group 100
block in from 240.0.0.0/4 to any group 100

# NetBIOS (port 137-139)
block in quick from any port 136 >< 140 to any group 100
block in quick from any to any port 136 >< 140 group 100

# UDP パケットをデフォルトで拒否
block in proto udp all group 100

# 接続された TCP パケットを許可
pass in quick proto tcp all flags A/A group 100

# 外部からの SSH 接続開始を許可
pass in quick proto tcp from any to any port = 22 flags S/SA group 100

# 外部からの SMTP 接続開始を許可
pass in quick proto tcp from any to any port = 25 flags S/SA group 100
# IDENT には答えない
block return-rst in quick proto tcp from any to any port = 113 group 100

# DNS サーバを立てている場合
pass in quick proto tcp from any to any port = 53 flags S/SA group 100
pass in quick proto udp from any to any port = 53 group 100

# WWW サーバを立てている場合
pass in quick proto tcp from any to any port = 80 flags S/SA group 100

# それ以外の外部からの TCP 接続を拒否し、ログに残す
block in log quick proto tcp all flags S/SA group 100

# 外部の DNS に問い合わせた帰りのパケット
pass in proto udp from any port = 53 to any group 100

# NTP の帰り
pass in proto udp from any port = 123 to any group 100

# 内部から外部への ping のみ許可
block in proto icmp all group 100
pass in proto icmp all icmp-type 0 group 100

# RFC2979
pass in proto icmp all icmp-type 3 group 100

############################################
# 外部への出力(グループ 200)

pass out on xl0 all head 200

# アドレス偽造防止
block out from 127.0.0.0/8 to any group 200
block out from any to 127.0.0.0/8 group 200
block out from any to 1.2.3.4/32 group 200

# プライベートアドレスやマルチキャストなどの破棄
block out from any to 10.0.0.0/8 group 200
block out from any to 172.16.0.0/12 group 200
block out from any to 192.168.0.0/16 group 200
block out from any to 0.0.0.0/8 group 200
block out from any to 169.254.0.0/16 group 200
block out from any to 192.0.2.0/24 group 200
block out from any to 224.0.0.0/4 group 200
block out from any to 240.0.0.0/4 group 200

# NetBIOS (port 137-139)
block out from any port 136 >< 140 to any group 200
block out from any to any port 136 >< 140 group 200

# 接続された TCP パケットを許可
pass out proto tcp all flags A/A group 200

# 外部の DNS サーバへの問い合わせを許可
pass out from any to any port = 53 group 200

# 外部への接続開始を許可
pass out proto tcp all flags S/SA group 200

# 外部の NTP サーバへの問い合わせを許可
pass out proto udp from any to any port = 123 group 200

# 内部から外部への ping のみ許可
block out proto icmp all group 200
pass out proto icmp all icmp-type 8 group 200

############################################
# 内部から来るパケット(グループ 300)

pass in on xl1 all head 300
block in from 127.0.0.0/8 to any group 300
block in from 192.168.0.1/32 to any group 300
block in from 1.2.3.4/0xffffff00 to any group 300

############################################
# 内部へ出ていくパケット(グループ 400)

pass out on xl1 all head 400
block out from 127.0.0.0/8 to any group 400
block out from any to 127.0.0.0/8 group 400
block out from any to 192.168.0.1/32 group 400 

############################################
# ループバックへのルール(グループ 0)
# (最後にあっても OK)
pass in quick on lo0 all
pass out quick on lo0 all

プロキシとの併用

外部からのアクセスを受け付ける場合、FWTK などと併用すると良いでしょう

まとめ

   [good] ipftest でルールのテストができる 
   [good] IPFW よりも厳密な設定ができる 
   [good] 内部のユーザにはルータの様に見えるので、壁を(ほとんど)意識しないで済む 
   [good] マシンのリソースをほとんど消費しない(カーネルのみ) 
   [good] パケット処理が高速

添付ファイル: filenat-config.gif 2273件 [詳細] fileipf.gif 2392件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2004-10-29 (金) 14:31:12 (5494d)