オンラインソフトで実現する完全無欠のセキュリティ

「第11回 PktFilter」


NetworkWorld 2003年6月号


本文書は、NetworkWorld誌に寄稿した記事の原稿を、IDGジャパン編集部殿の許可を得た上で掲載したものです。




PktFilterとは


PktFilterは、Windows 2000/XP上で動作するIPv4パケットのフィルタリングソフトウェアである。Jean-Baptiste Marchand氏によって開発され、BSDライセンスのもとで無償配布されている。

パケットフィルタリングソフトウェアは、コンピュータとネットワークとの間の通信を、一定のルールに従って許可あるいは拒否する。一般的にパケットフィルタリングの方式は、大きく以下の二つに分けることができる。

  1) ステートレス・フィルタリング
  2) ステートフル・フィルタリング
ステートレス・フィルタリングは非常に単純で、個々のIPパケットをそれぞれ単独でルールと比較し、通過させるかどうかを判断する。例えばコンピュータAからコンピュータBに対して、TCP/80の接続を許可したい場合を考えてみよう。ステートレス・フィルタリングではパケットの往復それぞれについてルールを記述する必要があるため、

  AからBへのTCP/80に対する往きのパケットを許可する
  BからAへのTCP/80からの戻りのパケットを許可する
のように設定しなければならない。

一方ステートフル・フィルタリングは比較的高度な処理を行っており、通信の接続に関する状態(ステート)を考慮しながら通過パケットを決定する。つまり、

  AからBへのTCP/80に対する接続を許可する
というルールを設定してやれば、往きのパケットの情報に基づいて、戻りのパケットは自動的に判断して通過させてくれる。パケットフィルタ型のファイアウォール製品は、ほとんどの場合、ステートフル・フィルタリング機能を持っている。

今回紹介するPktFilterは、前者、すなわちステートレス・フィルタリングを行うためのソフトウェアである。

Windows 2000やXP Proに標準で備わっているパケットフィルタリング機能には、TCP/IPフィルタリング(TCP/IP詳細設定のオプション)、RRASフィルタリング、およびIPSecフィルタリングがある。このうちRRASフィルタリングとIPSecフィルタリングは十分実用的ではあるものの、ルールの設定方法に融通性がなかったりする。Windows XPからはステートフル・フィルタリングを行うICF(インターネット接続ファイアウォール)が新たに導入されたが、ICFにはインバウンド(ネットワークからコンピュータへ)の通信しか制御できないという短所がある。

これらに比較してPktFilterは、柔軟なルール設定や双方向のフィルタリングが可能で、しかもフィルタリングに特化したサービスのためコンパクトに作られているという特長を持つ。最新のバージョンでは拒否パケットのロギング機能もサポートしている。




PktFilterのインストール


PktFilterの最新版(原稿執筆時点ではv0.06-beta2)は以下のサイトからダウンロードすることができる。

  http://www.hsc.fr/ressources/outils/pktfilter/index.html.en
PktFilterの使用方法については、ダウンロードファイルに詳細なドキュメントが付属しているので、必要に応じて参照していただきたい。ここではまずインストール方法について説明する。

なお、以下の手順を実行するには基本的に管理者権限が必要なので、Administratorsグループのユーザでログインすることを忘れずに。

● ダウンロードファイルの展開

ダウンロードファイルは、ソースコードファイル、実行モジュール、およびドキュメントがZIPによりアーカイブされた状態で提供されるので、まずダウンロードファイルを適当なディレクトリに展開する。ここではシステムドライブの「Program Files」ディレクトリの下に、「PktFilter」というディレクトリを作って展開することとしよう。

すると、以下の三つのディレクトリが展開されるはずだ。

  - doc       ... ドキュメント
  - pktctl    ... pktctl.exeと関連するソースコードファイルおよびルールファイル
  - pktfltsrv ... pktfltsrv.exeと関連するソースコードファイル
pktctl.exeはPktFilterを制御するコマンドラインプログラムである。これについては特別なインストール操作は必要ない。pktctlコマンドについては後で説明する。

● サービスのインストール

PktFilter本体はWindowsのサービスとして動作する。サービスの実体はpktfltsrv.exeで、このプログラムを以下のように「-i」オプションを付けて実行することにより、サービスとしてインストールされる。

  pktfltsrv -i ルールファイル ログファイル
「ルールファイル」には、フィルタリングルールを記述したテキストファイル名をフルパスで指定する。また「ログファイル」にはドロップしたパケットを記録するログファイル名を、同じくフルパスで指定する。(ちなみにPktFilterサービスをアンインストールするには、「-u」オプションでpktfltsrvを実行すればよい)

図1にPktFilterサービスのインストールの実行例を示す。ここではルールファイルとしてデフォルトルールファイルの「C:\Program Files\PktFilter\pktctl\rules.txt」を、ログファイルとして「C:\Program Files\PktFilter\pktctl\PktFilter.log」を指定している。


図1 PktFilterサービスのインストール例


● サービスの「スタートアップの種類」を変更

PktFilterサービスは、インストールした時点では「スタートアップの種類」が「手動」になっている。つまりサービスを開始させるためには「net start」コマンド等を用いて、手動で起動しなければならない。Windows起動時に自動的にPktFilterサービスを開始させるためには、このサービスの「スタートアップの種類」を「自動」に変更する必要がある。

図2は「コントロールパネル」の「管理ツール」から「サービス」を実行し、PktFilterサービス(表示名は「Stateless Packet Filtering」)のプロパティ「スタートアップの種類」を「自動」に変更したところを表している。


図2 PktFilterサービスが自動的に起動するように変更





フィルタリングルール


前述のとおり、PktFilterはルールファイル(テキストファイル)に記述されたフィルタリングルールに基づき、IPパケットのフィルタリングを行う。(注:ルール指定はpktctlコマンドを用いてインタラクティブに行うことも可能である)

ルールを記述する際に常に気をつけなければならないのが、そのルールを適用するネットワークインターフェイス名の指定である。PktFilterでは、個々のネットワークインターフェイスについて独自のインターフェイス名で表記する。そのためルール記述に先立ち、そのコンピュータにどのようなネットワークインターフェイスが存在するか、またそれらのインターフェイス名は何かを知らなければならない。

● ネットワークインターフェイス名を調べる

ネットワークインターフェイスとそれに対応するインターフェイス名の一覧を表示するには、pktctlコマンドに「-I」オプションを付けて実行する。

  pktctl -I
実行例を図3に示す。ここで「eth0」と表示されているのがPktFilterで使用するインターフェイス名である。つまりネットワークインターフェイス「AMD PCNET Family Ethernet Adapter」に対してルールを記述する場合は、インターフェイス名に「eth0」を指定することになる。複数のネットワークインターフェイスを持つ場合は特に注意が必要だ。


図3 ネットワークインターフェイスの一覧表示でインターフェイス名を調べる


さてそれではPktFilterのルールの設定方法について説明しよう。PktFilterのルールは、以下の3つに分類することができる。

  - グローバルオプション
  - デフォルトルール
  - フィルタリングルール
なお、ルールファイルの中で「#」で始まる行はコメントとして取り扱われる。

● グローバルオプション

グローバルオプションは、ネットワークインターフェイスの各種動作を設定する。ルールファイルには、まず先頭にグローバルオプションを記述する。現時点で設定可能なグローバルオプションは、細かくフラグメント化されたIPパケットを通さない「small_frags」オプションのみである。以下の例では「eth0」インターフェイスに対して「small_frags」オプションを設定している。

  option small_frags on eth0
細かくフラグメント化されたパケットは、しばしばサービス妨害攻撃で用いられるため、基本的にはすべてのネットワークインターフェイスに対して「small_frags」オプションを指定することが推奨される。

● デフォルトルール

次に、各ネットワークインターフェイスのデフォルトの振る舞いを設定するために、デフォルトルールを記述する。デフォルトルールには、

  - デフォルトですべての通信を拒否する(blockキーワードを指定)
  - デフォルトですべての通信を許可する(passキーワードを指定)
の二種類の考え方がある。前者はデフォルトをすべて拒否にしておき、許可したい通信のルールを追加していく方法、後者はデフォルトをすべて許可にしておき、拒否したい通信のルールを追加していく方法である。通常は安全性を第一に考え、デフォルトルールは拒否に設定することが一般的である。

デフォルトルールは各ネットワークインターフェイスごとに、インバウンド方向(ネットワークからコンピュータへの通信、「in」で指定)とアウトバウンド方向(コンピュータからネットワークへの通信、「out」で指定)の二つについて設定する。以下の例では「eth0」インターフェイスに対して、インバウンド方向およびアウトバウンド方向のすべての通信をデフォルト拒否に設定している。

  block in on eth0 all
  block out on eth0 all

● フィルタリングルール

デフォルトルールの記述に引き続き、個々のフィルタリングルールを設定する。フィルタリングルールは図4に示すとおり、アクション、方向、インターフェイス名、プロトコル、ソース、ディスティネーション、およびオプションといった要素で構成される。


図4 フィルタリングルールの構成要素


    ・アクション

    デフォルトルールを「拒否」に設定している場合、個々のフィルタリングルールは通過させるパケットのルールを記述するため、アクションには「pass」を指定する。逆にデフォルトが「許可」の場合は、フィルタリングルールのアクションには「block」を指定する。

    ・方向

    インバウンド方向のルールでは「in」を、アウトバウンド方向のルールには「out」を指定する。

    ・インターフェイス名

    ルールを設定したいインターフェイス名を、「on eth0」のように指定する。

    ・プロトコル

    許可あるいは拒否したいプロトコルについて、以下のように指定する。
      - proto tcp  ... TCPプロトコル
      - proto udp  ... UDPプロトコル
      - proto icmp ... ICMPプロトコル
      - proto 番号 ... プロトコル番号によるプロトコル指定
      - (指定なし) ... すべてのプロトコル
    

    ・ソース

    ソースIPアドレスを指定する。プロトコルがTCPやUDPの場合は必要に応じてソースポート番号を指定することができる。ソース指定には以下のような形式を用いる。
      - from any                     ... すべてのIPアドレス
      - from 192.168.183.1           ... 特定のIPアドレス
      - from 192.168.183.0/24        ... 特定のサブネット
      - from 192.168.183.1 port = 53 ... 特定のIPアドレスとポート番号
    
    なおポート番号の指定形式は以下のとおりである。
      - port = 53         ... ポート番号が53番
      - port >= 1024      ... 1024以上のポート番号
      - port > 1023       ... 1023より大きいポート番号
      - port <= 1023      ... 1023以下のポート番号
      - port < 1024       ... 1024より小さいポート番号
      - port 1000 >< 2000 ... 1000より大きく2000より小さいポート番号
    

    ・ディスティネーション

    ソースと同様の形式で、ディスティネーションIPアドレスおよび、必要に応じてポート番号を指定する。ただしディスティネーションでは「from」の代わりに「to」キーワードを使用する。

    ・オプション

    プロトコルがTCPの場合、オプションに「established」キーワードを指定することができる。「established」キーワードはTCPパケットのうち、コネクション開設用のSYNパケット以外を通過させたいケースに用いる。つまり、TCP接続の「戻り」のパケットを通過させるためのルール設定だと考えていただければよい。 またプロトコルがICMPの場合、以下の形式でICMPタイプおよびICMPコードを指定することができる。
      - icmp-type タイプ
      - icmp-type タイプ code コード
    
    ここで「タイプ」は以下のいずれかのキーワードもしくはICMPタイプ番号を指定する。また「コード」はICMPコード番号を指定する。
      - echorep     ... echo reply
      - unreach     ... destination unreachable
      - squench     ... source quench
      - redir       ... redirect
      - echo        ... echo request
      - router_adv  ... router advertisement
      - router_sol  ... router solicitation
      - timex       ... time exceeded
      - paramprob   ... parameter problem
      - timest      ... timestamp request
      - timestrep   ... timestamp reply
      - inforeq     ... information request
      - inforep     ... information reply
      - maskreq     ... address mask request
      - maskrep     ... address mask reply
    



ルールの設定例


それでは実際にルールを設定してみよう。

前述のインストール例では、ルールファイルとしてPktFilterに標準添付されている「rule.txt」を指定している。「メモ帳(notepad.exe)」等のテキストエディタでこのファイルを開くと、図5のような内容が表示される。


図5 PktFilter添付の標準ルールファイル


先頭が「#」で始まるコメント行を除くと、このファイルには以下のルールが記述されている。

  option small_frags on eth0 ... eth0に対するグローバルオプション

  block in on eth0 all       ... eth0のインバウンド方向のデフォルトルール(拒否)
  block out on eth0 all      ... eth0のアウトバウンド方向のデフォルトルール(拒否)
つまりデフォルト状態で、インターフェイス「eth0」を通過するすべてのIPパケットが拒否されていることがわかる。このファイルに、通過させる必要のあるパケットのルールを追加していけばよい。

なおインターフェイス名が「eth0」でない場合は、前述の「ネットワークインターフェイス名を調べる」を参考にして適宜変更しなければならない。また複数のネットワークインターフェイスがある場合、それぞれのインターフェイスについて、ルールのセットを記述する必要がある。

さてここではWebサービスを提供するWebサーバを例として考えてみる。ネットワークアクセスのポリシーは以下のとおりとする。

  1) すべてのIPアドレスからのTCP/80へのアクセスを許可する
  2) 名前解決のためDNSサーバとの間のUDP/53通信を許可する
  3) すべてのIPアドレスからのICMPエコーを許可し、エコーリプライを返す
  4) その他の通信はすべて拒否する
ちなみにこの例では当該WebサーバのIPアドレスを「192.168.183.130」、DNSサーバのIPアドレスを「192.168.183.254」としている。

まず1)のポリシーを実現するためには、このコンピュータ(192.168.183.130)に対するTCP/80の通信を許可するとともに、戻りのTCPパケットを許可するためのルールを記述しなければならない。つまり、

  pass in on eth0 proto tcp from any to 192.168.183.130 port = 80
  pass out on eth0 proto tcp from 192.168.183.130 port = 80 to any established
の2つのルールが必要になる。ここで2行目に指定している「established」オプションに注意していただきたい。この指定がない場合は、当該コンピュータからソースポート80番の外向きのTCP接続を無制限に許可してしまうことになる。

次に2)では、DNSサーバ(192.168.183.254)に対するUDP/53の通信と、その戻りの通信の2つのルールを記述する。UDP/53へのアクセスは通常ソースポートが1024以上となるため、このルールでもアウトバウンドのソースポートおよびインバウンドのディスティネーションポートをそのように指定している。

  pass out on eth0 proto udp from 192.168.183.130 port > 1023 to 192.168.183.254 port = 53
  pass in on eth0 proto udp from 192.168.183.254 port = 53 to 192.168.183.130 port > 1023
3)は、ネットワーク上のコンピュータからのpingに対して応答するためのものである。すべてのIPアドレスからのICMPエコーリクエストを受け入れ、ICMPエコーリプライを戻すことができるように、次の2つのルールを記述する。

  pass in on eth0 proto icmp from any to 192.168.183.130 icmp-type echo
  pass out on eth0 proto icmp from 192.168.183.130 to any icmp-type echorep
4)のポリシーは、デフォルトルールとして各フィルタリングルールに先立ち、以下の2つを記述する必要がある。

  block in on eth0 all
  block out on eth0 all
これはインストールされた「rule.txt」に標準で書かれているため、それをそのまま使えばよい。実際にこれらのルールを記述した「rule.txt」を図6に示す。(画面上ではわかりやすいようにコメントを入れている)


図6 Webサーバにおけるルール設定例


ルールを記述したらルールファイルを保存し、PktFilterサービスを起動する。PktFilterサービスの起動は、通常のサービス起動と同様に「net start」コマンド等を使用すればよい。PktFilterサービスは、サービス名「PktFilter」としてインストールされているので、「net start」コマンドを以下のように実行する。

  net start PktFilter
ルールを修正した場合は、PktFilterサービスを再起動することにより修正したルールが反映される。

なお、ルールの記述文法を誤ったり、インストール時に指定したルールファイルが存在しなかったりした場合は、PktFilterサービス起動時にエラーになり、SYSTEMイベントログにエラーメッセージが記録される。




Pktctlコマンド


pktctlコマンドは、PktFilterサービスのコマンドライン・コントロールプログラムである。通常は前述したとおり、インターフェイス名を調べるために用いることが多いが、このコマンドを使用してルールを動的に変更したり、あるいは拒否/許可されたパケットの統計情報を表示したりすることができる。図7に、pktctlコマンドを使用して「eth0」に関するパケットの統計情報を表示したところを示す。


図7 pktctlコマンドでパケット統計情報を表示


pktctlコマンドの機能は大きく以下のように分類される。

  - ルールの追加と削除
  - ルールファイルのロード
  - 設定されているルールの表示
  - 許可/拒否パケットの統計情報表示
  - ネットワークインターフェイスの一覧表示
  - インタラクティブモードでの実行
pktctlコマンドの具体的な使用方法については、PktFilterに付属しているドキュメントを参照していただきたい。




使用上の注意点


PktFilterを使用する上での注意事項を少し記しておこう。

まず第一に、ネットワークインターフェイスとインターフェイス名(「eth0」等)とのマッピングについてである。先に述べたとおり、PktFilterではインターフェイスの指定に論理的なインターフェイス名を使用するが、この名称と実際のネットワークインターフェイスとのマッピングは、ネットワークインターフェイスの追加や有効化/無効化、あるいはダイアルアップ接続の実行などにより動的に変動する場合がある。そのため、複数のネットワークインターフェイスが存在するケースでは注意が必要とされる。

もう一つ重要なことは、システム立ち上げ時にPktFilterサービスを自動的に起動するように設定していた場合、IPスタックが動作を始めてから実際にPktFilterサービスが起動するまでに2分程度のタイムラグがあることだ。サービス起動までのこの2分間は、フィルタリングが有効になっていないため、システムを再起動する際はそのことを念頭に入れて運用する必要がある。

さらにPktFilterは、実際にはRRASが使用するフィルタリングドライバと同じドライバを制御する。そのためRRASを使用したパケットフィルタリングとPktFilterとは、コンフリクトを起こす可能性があり、同時に使用することはできない。また場合によっては他のサービスが同じドライバを制御することも考えられる。このことについても気をつけた方がよいだろう。コンフリクトを起こした際はSYSTEMイベントログにエラーが記録されるので、実際に運用を開始する前によく確認していただきたい。

いずれにせよコンピュータにパケットフィルタリング機能を導入する場合は、ポリシーどおりに確実にフィルタリングが機能しているかどうかについて、実際にポートスキャナ等を使用し確認することが推奨される。



2003年3月執筆
塩月 誠人
ネットワークセキュリティコンサルタント