[Home] [Kuri] [Sysad] [Internet?] [Blog] [Java] [Windows] [Download] [Profile] [Flash] [+]

IP Filter で フィルタリング、NAT

IPFW でもフィルタリングや NAT などができますが、IP Filter というもの を使ってもできます。また、IP Filter はいくつかの OS に対応しています ので、1度どれかに適用すると、他のマシン(OS)への設定が楽になります。

目次


1. 環境

OS は FreeBSD-3.2R および Solaris2.6,Solaris7 で行いました。
IP Filter のバージョンは、FreeBSD が OS についてくる 3.2.7 (だと思い ます)、Solaris が 3.3.1 です。少々古いかもしれません。

2. 前準備

2.1 インストール (Solaris2.x)

FreeBSD には IP Filter が標準でついてきますので、インストールの必要 はありません。(バグフィックス等でバージョンアップする場合などは別だ と思いますが…。)
インストール方法は、INSTALL.Sol2 に書いてある通りです。make solaris を実行してから、SunOS5 ディレクトリで make package を実行すると、 IP Filter のパッケージがインストールされます。

2.2 カーネルの再構築 (FreeBSD)

FreeBSD の場合、以下のオプションが含まれていない場合は、以下を追加 してカーネルの再構築を行う必要があります。

  options         IPFILTER                #kernel ipfilter support
  options         IPFILTER_LOG            #ipfilter logging

他にもオプションがあるかもしれませんが、私はこれだけ指定しました。 また、IPFILTER だけでもきっと動作すると思います。
Solaris2.x の場合は、IP Filter のカーネルモジュールを動的にロード させますので、このような作業は必要ありません。

2.3 reboot (FreeBSD)

FreeBSD の場合は、カーネルを入れ換えて再起動を行います。

3. 設定方法

Solaris2.x の場合、設定ファイルの位置が決まっています。フィルタリング の設定ファイルが /etc/opt/ipf/ipf.conf で、NAT,NAPT の設定ファイル が /etc/opt/ipf/ipnat.conf です。ただし IP Filter のバージョンに よっては異なるかもしれません。 これらは /etc/init.d/ipfboot で決まっていますので、念のため確認して ください。
FreeBSD の場合は自由に決められます。(Solaris も /etc/init.d/ipfboot を書き換えれば自由に決められますが…。) ここではそれぞれ /etc/ipf.conf および /etc/ipnat.conf としておきます。

3.1 フィルタリング

IPFW と同様、設定ファイル(ここでは ipf.conf)に、1行に1つのルールを に書いていきます。異なる点は、ルールを何も書かないとすべて通すこと になるということと、最後に該当したルールが適用されるということです。 「簡単な」書式は以下の通りです。
# BNF に詳しく書かれています。

action in-out [log] [quick] [on interface] [proto protocol] [srcdist [flags flags] [keep keep] ]

それぞれの意味を以下に示します。
プロトコルやフラグなどは、/ で複数指定ができます。(tcp/udp や S/SA など)

キーワード意 味 な ど
action 許可は pass, 拒否は block
in-out 入ってくる時のチェックは in, 出ていく時は out
log ログに残す場合に指定
quick 該当する場合移行のルールを見ずに適用させる場合に指定
on interface 該当するインタフェースの指定
proto protocol プロトコルの指定(icmp,tcp,udpなど
srcdist 送信元および送付先の指定 (all もしくは from object to object)
flags flags TCP のフラグ指定(F,S,R,P,A,U および establish でそれぞれ FIN, SYN, RST, PUSH, ACK, URG および S/SA に該当)
keep 状態が保存され、ポートや ACK# 等が一致すればリストを参照せずに許可 …だと思う(state,frag)
object IPアドレスおよびポートの指定(port = 110 や port > 1023 など)

例えば、rules/example3 について説明します。(コメントを差し替えました。)
特定のホストからの通信のみ許可するような設定になっているようです。

  #
  # 最初に、入ってくる方向のルールが書いてあります。
  #
  # IPFW とは異なり、最初にすべて拒否を入れておきます。
  # 後の pass ルールに該当すれば、許可され、それ以外の許可されていない
  # パケットを拒否するためです。
  block in from any to any
  #
  # localhost 同士は許可します。on lo0 がある方がいい気もします。
  pass in from 127.0.0.1/32 to 127.0.0.1/32
  #
  # 10.1.3.1 などのホストからのパケットを許可します。
  pass in from 10.1.3.1/32 to any
  pass in from 10.1.3.2/32 to any
  ... (中略)
  #
  # 次に、出ていく方のパケットに対するルールです。
  # あとは同様ですので、コメントは割愛します。
  #
  block out from any to any
  #
  pass out from any to 127.0.0.1/32
  #
  pass out from any to 10.1.3.1/32
  pass out from any to 10.1.3.2/32
  ... (後略)

次に、IPFW のところで書いた
ルールと 同様のものを書いてみます。

  block in from any to any
  pass in from 127.0.0.1/32 to 127.0.0.1/32
  pass in from any to 192.47.224.211 port = 80 keep state
  pass in from any to 192.47.224.211 port = 21 keep state
  pass in from 192.47.224.211 to any

quick を使うと、IPFW と同様の並びになります。

  pass in quick from 127.0.0.1/32 to 127.0.0.1/32
  pass in quick from any to 192.47.224.211 port = 80 keep state
  pass in quick from any to 192.47.224.211 port = 21 keep state
  pass in quick from 192.47.224.211 to any
  block in from any to any

3.2 NAPT(IP masquerade)

設定ファイル(ipnat.conf)に、1行1ルールを書きます。
「簡単な」書式は以下の通りです。
# 詳しくは ipnat(5) に書かれています。

map ifname ipmask -> ipmask [portmap tcpudp portrange]

それぞれの意味を以下に示します。

キーワード意 味 な ど
ifname 外に出ていく時のインタフェースを指定
ipmask 適用するパケットのアドレス(およびネットマスク)の指定
portmap ポートの書き換えを行う場合に指定
tcpudp tcpあるいはudpの指定(もしくは両方(tcp/udp))
portrange ポート番号の範囲指定(port : port)

例を示します。

  map ed0 10.0.0.0/8 -> 1.2.3.0/24

出ていくパケットに対して、送信元の(プライベートアドレスである)10.x.x.x を 1.2.3.y に書き換えます。もちろん逆方向は逆に戻してくれます。
しかし、クラスAのアドレスはクラスCにおさまりきるとは思えません。 そこで、以下のようにします。

  map ed0 10.0.0.0/8 -> 1.2.3.0/24 portmap tcp/udp 10000:40000

こうすると、送信元のポートを 10000〜40000 内の空いているポート に書き換えてくれます。ただしこれらは TCP/UDP にしか有効ではありませ ん。
よって、通常は、以下のように両方を記述する必要があると思います。

  map ed0 10.0.0.0/8 -> 1.2.3.0/24 portmap tcp/udp 10000:40000
  map ed0 10.0.0.0/8 -> 1.2.3.0/24

TCP/UDP に対しては前者の、ICMP などは後者のエントリが適用されます。

3.3 Port forwarding

設定ファイルは NAPT と同様です(ipnat.conf)。
「簡単な」書式は以下の通りです。

rdr ifname ipmask port port -> ipmask port port [udp]

それぞれの意味を以下に示します。

キーワード意 味 な ど
ifname 外から入ってくるインタフェースを指定
ipmask 適用するパケットのアドレスを指定
udp デフォルトでは tcp なので、udp の場合は指定

例を示します。

  rdr ed0 1.2.3.80/32 port 80 -> 192.168.0.80 port 80
  

1.2.3.80 のポート80 のパケット(TCP)が来たら、宛先を 192.168.0.80 に 変更します。
注意しないといけないところは、-> の後のアドレスで、ネットマスクを 指定すると叱られます。
また、フォワード先が実在しないマシンの場合、例えば 1.2.3.80 が存在 しない場合は、あらかじめ以下を実行しておく必要があります。

  arp -s 1.2.3.80 ed0のMACアドレス pub

こうしないと、ルータが 1.2.3.80 宛のパケットを誰に届ければいいか わからなくて捨てられてしまうからです。
後述の起動スクリプトに書いておけばいいと思います。

3.4 起動スクリプトなど

Solaris2.x の場合は、/etc/init.d/ipfboot がありますので、インストール 後に OS 再起動をせず設定を行った場合は、/etc/init.d/ipfboot start と実行すれば、IP Filter が動き出します。
FreeBSD の場合も、同様のスクリプトでいいと思います。必要最低限の内容 ですが、以下を /usr/local/etc/rc.d/ipf.sh などという名前で置いておけ ば、OS 起動時に IP Filter が動き出します。

  #!/bin/sh
  PATH="/usr/sbin:/usr/bin:/sbin"
  export PATH

  # ARP エントリの追加
  #  - 必要なければ %%ARPEND%% までコメントアウトすべし
  IF="ed0"
  MACADDR="`ifconfig $IF|grep ether|awk '{print $2}'`"
  arp -s www $MACADDR pub
  arp -s ftp $MACADDR pub
  ...
  # %%ARPEND%%

  # IP Filter の起動(というか設定を読み込ませる)
  if [ -f /etc/ipf.conf ]; then
    ipf -IFa -f /etc/ipf.conf > /dev/null && echo -n ' ipf' && $IPF -s
  fi
  if [ -f /etc/ipnat.conf ]; then
    ipnat -CF -f /etc/ipnat.conf > /dev/null && echo -n ' ipnat'
  fi


4. 動作確認

4.1 フィルタリング

中や外からいろいろアクセスして、確認します。 その後、ipfstat で状況を確認します。

  # ipfstat -ih
  0 pass in quick on lo0 from any to any
  12491 pass in quick on hme0 from any to any
  0 pass in quick on hme1 from any to 192.168.0.1/32
  15259 pass in quick on hme1 from any to 192.168.0.2/32
  ...

-i オプションは in に対するルールの出力を示しています。逆に out の 場合は -o です。また、-h はルールが適用されたパケット数の出力を示し ています。
許可(あるいは拒否)しているところにアクセスし、該当するルールの数 を確認してみてください。 設定が間違っている場合は修正し、
前述の起動スクリプト の ipf を起動している箇所を再度実行します。
# Solaris なら /etc/init.d/ipfboot reload で結構です。

4.2 NAPT,NAT

中や外からいろいろアクセスして、確認します。NAPT の場合は、WWW サー バにアクセスしてみて、WWW サーバのアクセスログを見て、有効なアドレス になっていることを確認するのが比較的楽です。
また、ipnat で状況を確認できます。

  # ipfstat -ls
  mapped  in      5902    out     6929
  added   123     expired 114
  inuse   21
  rules   27
  List of active MAP/Redirect filters:
  map hme1 172.16.0.0/16  -> 1.2.3.2/32  portmap tcp/udp 10000:40000
  map hme1 172.16.0.0/16  -> 1.2.3.2/32
  rdr hme1 1.2.3.73/32 port 23 -> 172.16.0.73 port 23 tcp
  ...

  List of active sessions:
  MAP 172.16.0.211   1058  <- -> 1.2.3.2   10023 [4.3.2.1 23]
  RDR 172.16.0.73      23  <- -> 1.2.3.73  23    [4.3.2.85 32806]
  ...

設定が間違っている場合は修正し、 前述の起動スクリプト の ipnat を起動している箇所を再度実行します。
# Solaris なら /etc/init.d/ipfboot reload で結構です。

5. 捕捉

5.1 ログ

ipmon を使用すれば、ログを syslog に飛ばしたりできます。
当方では、ipfboot を以下のように変更して、OS起動時に ipmon が起動 されるようにしています。

  *** ipfboot.0	Thu Aug  5 02:30:48 1999
  --- ipfboot	Wed May 23 11:17:12 2001
  ***************
  *** 16,22 ****
                  modload /usr/kernel/drv/ipf
                  [ -r ${IPFILCONF} ] && ipf -Fa -f ${IPFILCONF}
                  [ -r ${IPNATCONF} ] && ipnat -CF -f ${IPNATCONF}
  ! #             ipmon -sn &
                  ;;
    
          stop)
  --- 16,22 ----
                  modload /usr/kernel/drv/ipf
                  [ -r ${IPFILCONF} ] && ipf -Fa -f ${IPFILCONF}
                  [ -r ${IPNATCONF} ] && ipnat -CF -f ${IPNATCONF}
  !               ipmon -Ds
                  ;;
    
          stop)

-D オプションは、daemon として起動させるために必要です。
-s オプションを指定すると、syslog の local0 にログを送信してくれ ます。ですので、/etc/syslog.conf に以下のようなエントリを追加して おく必要があると思います。

  local0.info			/var/log/ipflog

ただし、出力されるログはけっこうな量になります。
これをいちいち見ていられないとお嘆きの貴兄に、お勧めのスクリプトが あります。(
→こちら)

5.2 FTP

前述の NAPT の設定だけですと、外部の ftp サーバにアクセスするには PASV モードにする必要があります。
ただし、内部のマシンが1つだけでしたら、PORT も通すように設定する ことが可能です。rules/ftp-proxy などにも書かれていますが、内部マシン の IP アドレスが 172.16.0.1, 外部の FTP サーバを 1.2.3.4/32 とします と、以下の項目を ipnat.conf に追加します。

  map hme1 172.16.0.1/32  -> 1.2.3.4/32 proxy port ftp ftp/proxy
  

最初、

  map hme1 172.16.0.0/16  -> 1.2.3.0/24 proxy port ftp ftp/proxy
  

と書いていたのですが、設定後最初に接続した内部マシンのみ PORT が 通り、他の内部マシンは以前と同様 PORT が使えませんでした。
ただ、外部の ftp サーバに対しては、1.2.3.0/24 の範囲内でしたら どのマシンへも PORT が有効でした。それでは、

  map hme1 172.16.0.1/32  -> 1.2.3.0/24 proxy port ftp ftp/proxy
  

こうすれば、内部マシンは固定ですが、1.2.3.0/24 にあるマシンへの ftp の使い勝手がよくなると思ったのですが、なぜかつながらなくなり ました。
(ちゃんとソースを眺めて理解しないといけませんね…。> 自分)

Powered by Apache PostgreSQL Usupi Logo Kuri Logo
[Home] [Kuri] [Sysad] [Internet?] [Blog] [Java] [Windows] [Download] [Profile] [Flash] [-]
usu@usupi.org Last modified : Tue May 14 00:46:03 2002