%%Title: IPfil について

%%Created: Mon Jun  2 07:48:36 1997
%%Updated:

最近の *BSD* にはportingされてる。

----------------------------------------------------------------------------
結局何が出来るか?

o 基本動作
  フィルタリング・ルールは複数設定出来る。
  ルール・リストの先頭から比較して最後にマッチしたものに従い処理を行なう。
  一つのフィルタリング・ルールは、以下で示すパターンを組み合わせて作成する。
  フィルタリング・ルールは、FLCで記述することが出来る。

o パターンの種類。
  - パケットの向き。
  - インターフェイス。
  - IPアドレス。
  - ポート番号。種々の演算子が使用可能。  
  - IPのペイロード部分のプロトコル。
  - フラグメントの種類。Tiny Fragment と Overlapping Fragment を指定可能。
  - IPオプションの種類。全体を指定する方法と、個別に指定する方法がある。
  - IPセキュリティクラスの種類。
  - TCPのフラグ。
  - ICMPのタイプとコード。

o マッチしたパケットに対して…
  - 叩き落す。
  - 通過させる。
  - ログを取る。
  - カウントする。
  - 指定したカーネル内関数を呼び出す。  
  - 指定したICMPパケットを返信する。
  - TCP-RSTパケットを返信する。
  - リストの以降のルールを無視する。
  - 指定したインターフェイスへコピーする。
  - 指定したインターフェイスのinbound(※)へ移動する。
  - セッションの情報を記録保持する(※)。
  - フラグメントされたパケットの情報を保持する(※)。

o ネットマスクの表記方法
  以下の方法をサポートしている。
  mynet/26
  mynet/255.255.255.192
  mynet mask 255.255.255.192
  mynet mask 0xffffffc0
  デフォルト、また指定しない場合は、255.255.255.255 or "/32"

o Packet state filtering
o Transparent Proxy Suppoer
o Transparent routing

o NAT
  ポート単位のNATが可能
  /sbin/ipf -E -Fa しとかないと ipnat は使えない。

----------------------------------------------------------------------------
o ツール
  ipf
    フィルタリング・ルールを設定・削除をする。
  ipfstat
    フィルタリングの統計情報を取得する。
    現在のルール・リストを取得する。
  ipftest
    フィルタリング・ルールのテストを行なう。
    入力パケットは、様々なフォーマットをサポートしているらしいが、
    少なくとも tcpdump の出力は動作しない。
  ipmon
    ログされた情報を読み出す。
  ipsend
    任意のIPパケットを生成送信する。
  ipresend
    tcpdump等の出力からIPパケットを生成し送信する
  iptest
    連続してIPパケットを送出する。
  ipfnat
    NATマップを設定・削除する。

----------------------------------------------------------------------------
フィルタ指定方法 [ipf(5)参照]

  基本ルール
    hexnumber
      0xを伴った16進数。
      hexnumber ::= "0x"hexstring .
      hexstring ::= hexdigit [ hexstring ] .
      hexdigit ::= digit | "a" | "b" | "c" | "d" | "e" | "f" .
    decnumber
      10進数。
      decnumber ::= digit [ decnumber ] .
      digit ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .
    ipaddr
      いわゆる IPアドレス形式。
      ipaddr ::= host-num "." host-num "." host-num "." host-num .
      host-num ::= [ digit [ digit [ digit ] ] ] .
    host-name
      ipaddr またはDNSで使用されるホスト名、または "any"
      "any" は、0.0.0.0/0 に等しい。
    addr ::= "any" | nummask | host-name [ "mask" ipaddr | "mask" hexnumber ] .
      ネットマスクの指定方法として "/" が使用可能。
      nummask ::= host-name [ "/" decnumber ] .
    port-comp
      TCP/UDPのポート番号に対して比較が指定可能。
      port-comp ::= "port" compare port-num .
        演算子には以下が使用可能。
        compare ::= "=" | "!=" | "<" | ">" | "<=" | ">=" | "eq" | "ne" |
                  "lt" | "gt" | "le" | "ge" .
        port-num には、/etc/services に定義された名前、
        または番号(decnumber)が使用可能。
        port-num ::= service-name | decnumber .
    port-range
      TCP/UDPのポート番号に対して範囲が指定可能。
      port-range ::= "port" port-num range port-num .
      範囲指定は以下が使用可能。
        range ::= "<>" | "><" .
        i.e.
          p1 <> p2  p1より小さく、p2より大きい
          p1 >< p2  p1より大きく、p2より小さい

  ルール設定
    filter-rule ::= [ insert ] action in-out [ options ] [ match ] [ keep ]

  insert ::= "@"decnumber .
    @n により、既存のルールのn番目の直後に挿入する。
    指定されない場合は、ルールの最後に挿入される。
    ※修正、削除は?

  action ::= block | "pass" | log | "count" | call .
    以下に示すキーワードを明示する。

    block ::= "block" [ "return-icmp"[return-code] | "return-rst" ] .
      マッチしたパケットをブロックする。
      "return-icmp" [ "("icmp-code")" ] .
        指定したコードのICMPを返送する。
        以下の文字列か番号(decnumber)を指定可能。
          "net-unr"
          "host-unr"
          "proto-unr"
          "port-unr"
          "needfrag"
          "srcfail"
          "net-unk"
          "host-unk"
          "isolate"
          "net-prohib"
          "host-prohib"
          "net-tos"
          "host-tos"
      "return-rst"
        TCPの場合、RSTフラグをセットしたパケットを返送する。

    "pass"
      マッチしたパケットについて、 フィルタを通過する。

    log ::= "log" [ "body" ] [ "first" ] [ "or-block" ] .
      マッチしたパケットについて、ipl(4)仮想デバイスへログする。
      body
        IPヘッダの先頭から128ビットをログする。
        ※本当にIPヘッダか?
      first
        ?? ※は?
      or-block
        ログに失敗した場合に block と同様な振舞をする。

    "count"
      マッチしたパケットをカウントする。ipfstat(8)で参照できる。

    call ::= "call" [ "now" ] function-name .
      マッチした場合、指定したカーネル内の関数をコールする。
      詳細は不定。
      now ※って何?

  in-out ::= "in" | "out" .
    actionの後に明示する。

    "in"
      interfaceからTCP/IPスタックへ渡される間に処理する。

    "out"
      TCP/IPスタックからinterfaceへ渡される間に処理する。

  options ::= [ log ] [ "quick" ] [ on ]
    複数指定する場合は、この順番で指定する。

    log
      上記参照。

    "quick"
      マッチしたパケットについて、以降のルールを適用しない。
      ※この時の適用されるルールはどれか?

    on ::= "on" interface-name [ dup ] [ froute ]
      インターフェイスを指定する。
      dup ::= "dup-to" interface-name [":"ipaddr]
        マッチしたパケットを指定したインターフェイスにコピーする。
        この時 Destinaion を指定したアドレスに変換可能。 
        off-host logging等に利用する。
        ※off-host loggingって? 
      froute ::= "fastroute" | "to" interface-name .
        マッチしたパケットを指定したインターフェイスへ移動する。
        ※実際の振舞は?inboundになるのか?その時ルールを最初から適用するのか?
        ※fastroute 使用時のインターフェイスは?

  match ::= [ tos ] [ ttl ] [ proto ] [ ip ] .
    複数指定する場合は、この順番で指定する。

    tos ::= "tos" decnumber | "tos" hexnumber .
      TOSを指定可能。

    ttl ::= "ttl" decnumber .
      TTLを指定可能。exactly matchのみ。

    proto ::= "proto" protocol .
      プロトコルを /etc/protocols に定義している名前か、
      番号(decnumber)で指定可能。
      TCPとUDPの両方にマッチする "tcp/udp" も使用可能。

    ip ::= srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] .
      
      srcdst ::= "all" | "from" object "to" object .
        object ::= addr [ port-comp | port-range ] .

      flags ::= "flags" flag { flag } [ "/" flag { flag } ] | "establish" .
        TCPのフラグを指定可能。
        ※"/" の使用意味は?
        flag ::= "F" | "S" | "R" | "P" | "A" | "U" .
          それぞれ FIN, SYN, RST, PUSH, ACK, URG
        "establish" は S/SA と同義。

      with ::= "with" | "and" .
      withopt ::= [ "not" | "no" ] opttype [ withopt ] .

        opttype ::= "ipopts" | "short" | "frag" | "opt" ipopts  .

          ipopts
            IPオプションが存在する場合にマッチする。

          short
            パケットが短くて、完全なIPヘッダを持っていない場合にマッチする。

          frag
            パケットがフラグメントされている場合にマッチする。

          "opt" ipopts
            ipopts ::= optlist | "sec-class" [ secname ] .
            optlist
              以下のIPオプションが指定可能。
              "nop"
              "rr"
              "zsu"
              "mtup"
              "mtur"
              "encode"
              "ts"
              "tr"
              "sec"
              "lsrr"
              "e-sec"
              "cipso"
              "satid"
              "ssrr"
              "addext"
              "visa"
              "imitd"
              "eip"
              "finn"

            "sec-class" [ secname ] .
              secname ::= seclvl [ "," secname ] .
              seclvl
                以下のセキュリティクラスを指定可能。複数指定はカンマで区切る。
                "unclass"
                "confid"
                "reserv-1"
                "reserv-2"
                "reserv-3"
                "reserv-4"
                "secret"
                "topsecret"

        optname   ::= ipopts [ "," optname ] .
          ※optlist の間違い?

      icmp ::= "icmp-type" icmp-type [ "code" decnumber ] .
        "icmp-type" icmp-type
          以下のICMPタイプを指定可能。番号(decnumber)でも指定可能。
          "unreach"
          "echo"
          "echorep"
          "squench"
          "redir"
          "timex"
          "paramprob"
          "timest"
          "timestrep"
          "inforeq"
          "inforep"
          "maskreq"
          "maskrep" 

        "code" icmp-code
          上記参照。

      keep ::= "keep state" | "keep frags" .
        ※記録してどうするの?

        keep state
          TCP,UDP,ICMP通信セッションの情報を保持する。

        keep frags
          フラグメントされたパケットの情報を保持する。

  keep
    上記参照。

----------------------------------------------------------------------------
NAT指定方法 [ipnat(5)参照]
  ipnat(1)を使用しマップを定義する。
  ポート単位のNATが定義可能。
  ※対応するプロトコルは?

  マップ定義
  ipmap ::= mapit ifname ipmask "->" ipmask [ mapport ] .

  mapit ::= "map" | "rdr" .

    "map"
      outbound のパケットに対してルールを適用する。

    "rdr"  
      inbound のパケットに対してルールを適用する。

    ifname ::= 'A' - 'Z' { 'A' - 'Z' } digit .
      インターフェイス名を指定する。
      ※大文字だけが使用可能か?  => そんなことはない。

    ipmask ::= ip "/" bits | ip "/" mask | ip "netmask" mask .

    mapport ::= "portmap" tcpudp portnumber ":" portnumber .
      tcpudp ::= "tcp" | "udp" | "tcp/udp" .
      portnumber ::= digit { digits } .

----------------------------------------------------------------------------
実際の動作

  o ipftest
  
  tcpdump -ntqi


o sample
x - B - a

ipnat.rules:
rdr ef1 202.249.27.7/32 port 110 -> 10.21.0.2 port 110

ipfile.rules:
pass in quick on ef1 from 203.178.141.128/25 to 202.249.27.7 port = 110

proxy arp:
arp -s 202.249.27.7 00:60:97:97:39:88 pub

o ipmon
	# ipmon -Ds
	/var/log/messages にログを出力する。

----------------------------------------------------------------------------
o ip_fil 3.1.11 を BSD/OS 2.1p27 へインストールする

  ipfil-bsdi.patchの作成

  プログラムの make
  - /usr/share/man/man[145]を作っておく。
  - Makefile, BSD/Makefile を適当に書き換える。
  - root になって make install-bsdi

  カーネルの remake
  - BSDOS/kinstall を適当に書き換える。 
    インストールするパス(/sys) を適当に書き換える。
    下方の awk のスクリプトを訂正する。
  - config ファイルに追加
      options IPFILTER
      options IPFILTER_LOG

  /dev/ipl の作成
  - mknod /dev/ipl c 37 0