14.1. rc.firewall.txtスクリプトの構造

このチュートリアルのために書いたすべてのスクリプトは、ひとつの統一的な構造をもって書かれている。全てのスクリプトの骨格を共通にして、相違点を見つけやすくするためだ。そうした構造については、このチャプターで、簡略ながら、それなりに分かりやすく解説しているつもりだ。このチャプターを通じて、スクリプトがそのように書かれたわけと、こうした構造に統一している理由を、ざっと理解してもらえればと思う。

Note

僕はこの構造を用いているが、これがあなたのスクリプトにとっても最適な構造だとは限らない。ただ、僕なりに最も読みやすく理解しやすいものにしたいという要件にかなっていたため、僕はこの構造を選んだに過ぎない。

14.1.1. 構造

以下が、このチュートリアルのすべてのスクリプトが踏襲する構造だ。もし、構造に背く理由を特記することなしに何か違うやり方をしているところがあったら、それはたぶん僕のミスだ。

  1. Configuration - 一番初めには、続くスクリプト全体で使用する設定オプションが記述されている。設定オプションはどんなシェルスクリプトでもたいてい最初にあるものだ。

    1. Internet - ここはインターネット接続に関連する設定オプションのセクションだ。インターネット接続がない場合には、このセクションは飛ばされている。ここに列挙したよりもたくさんのサブセクションがある場合もあるが、少なくともインターネット接続に関わるものであることに違いはない。

      1. DHCP - そのスクリプトに特有の DHCP 要件がある場合には、ここに DHCP 特有の設定オプションが来る。

      2. PPPoE - そのスクリプトを使うユーザあるいは環境が、PPPoE 接続を使用する可能性がある場合には、ここにそのオプションが書かれる。

    2. LAN - ファイヤーウォールの背後に LAN があり、それが利用可能な場合、関連するオプションをこのセクションで追加する。たいていは LAN があるので、ほとんどの場合この設定がある。

    3. DMZ - その必要性があれば、ここで DMZ ゾーンの設定を加える。ほとんどのスクリプトにはない。通常のホームネットワークや小規模な企業ネットワークには DMZ は滅多にないからだ。

    4. Localhost - これらのオプションは我々のローカルホスト に関するものだ。ここの変数は滅多に変わることはないのだが、とりあえず、ほとんどを変数に入れることにしている。おそらくは、これらの変数を変更する必然性はまったくないだろう。

    5. iptables - このセクションは iptables に関わる設定だ。ほとんどのスクリプト、ほとんどのシチュエーションでは、 iptables バイナリの在処を示す変数ひとつだけで終わりだ。

    6. Other - その他の特異なオプションや変数があれば、まずは真っ先に妥当な項目のサブセクションに収められる (インターネット接続に関するものならインターネットのサブセクションに入るといった具合)。もしどの項目にも当てはまらなければ、それらは Configuration 自体のサブセクションとして置かれる。

  2. Module loading - スクリプトのこのセクションはモジュールのリストを管理する。最初の部分には必要なモジュールが、次に、必要でないモジュールが並んでいる。

    Note

    セキュリティを高めたり、何かのサービスや機能を追加するようなモジュールは、特に必須でなくても追加している場合がある。そうした際には、たいてい、それぞれのスクリプトに覚え書きがあるはずだ。

    Note

    iptables のバージョンが上がるにつれて、たいていのモジュールは自動的にロードされるようになってきており、敢えてロードをかけなければならないモジュールはほとんどない。しかし、コントロール性という意味では、モジュール類は明示的にロードたほうがいい。例えば conntrack ヘルパーは決して自動ではロードされない。

    1. Required modules> - このセクションには、必要なモジュールが並んでいる。セキュリティに貢献する特殊なモジュールや、管理者やクライアントに特別なサービスを与えるモジュールである場合もある。

    2. Non-required modules - このセクションには通常の動作には必要のないモジュールが並んでいる。ここのモジュールはデフォルトではすべてコメントアウトされているはずだ。いずれかのモジュールの提供する機能が必要ならば、適宜アンコメントしていただきたい。

  3. proc configuration - このセクションは、proc ファイルシステムに対して施すべき特別な設定を取り扱う。必要なものがあればしかるべくリストアップされているだろうし、必要のないものは、デフォルトではコメントアウトされた状態で Non-required proc configuration の下に並んでいるはずだ。有用な proc 設定はほとんどこの中でリストアップされているが、それとて全部というにはほど遠い。

    1. Required proc configuration - このセクションには、そのスクリプトが機能するために必要とされる proc の全設定項目が並んでいる。セキュリティを高めるためのものや、またある時は、管理者やクライアントに対して特別なサービスや機能を与えるものである場合もある。

    2. Non-required proc configuration - このセクションには、使ってみれば役に立つ、しかし特に必須ではない proc の設定項目が並んでいる。そのスクリプトが動作するのに必要というわけではないため、すべてコメントアウトされているはずだ。ここにリストされるのは、proc の設定やノードの中のほんの一握りに過ぎない。

  4. rules set up - これより上の部分で、まず間違いなく、ルールセット を挿入するための準備は整っているはずだ。ルールが見つけやすく読みやすいようにするため、僕はまずルールをテーブル毎にまとめ、その下位はチェーン名毎にまとめることにした。いつも、ユーザ定義チェーンはシステム組み込みチェーンを云々する前に作っている。また、チェーンとその中のルール定義は、iptables -L コマンドで出力されるのと同じ順番で配置することにしている。

    1. Filter table - まず最初に filter テーブルとその中身を仕上げる。最初にやるべきは、このテーブルの中のすべてのポリシーの設定だ。

      1. Set policies - システムチェーンすべてのデフォルトポリシーをセットアップする。僕が通常 filter テーブルで採るのは、各チェーンのポリシーは DROP に設定しておき、受け入れるサービスやストリームは各々のチェーンの中で具体的に ACCEPT していくというやり方だ。こうすれば、使わせたくないポートをひとつ残らず排除することができる。

      2. Create user specified chains - この段階で、当テーブル内で以後使っていくことになるユーザ定義チェーンを作成する。ユーザ定義チェーンが作られていないことには、システムチェーンからそれらを使うことは不可能なので、なるべく早い段階で着手することにしている。

      3. Create content in user specified chains - ユーザ定義チェーンを作ったら、それらのチェーンの中のルールも全部組み立ててしまう。ここで早くもこのデータを入れてしまうのは、当のユーザ定義チェーンを作成したのと近い場所にデータを並べたいからでもある。べつに後で入れることにしても構わない。まったく各自の自由だ。

      4. INPUT chain - もうここまで来たら filter テーブルでやるべきこともほぼ出尽くしたので、INPUT チェーンに乗り移る。この段階で、INPUT チェーンのルールを全部入れてしまう。

        Note

        察しはつくだろうが、ここから先で、iptables -L の出力に従ってゆく。この構造に固執してもらう必要などまったくないのだが、異なったテーブルやチェーンのデータをごちゃ混ぜにするのだけはなるべく避けよう。そのようなルールセットは非常に読みにくく、問題が起こったときに修正するのが大変だからだ。

      5. FORWARD chain - ここで FORWARD チェーンのルール作成に取りかかる。これといった理由はない。

      6. OUTPUT chain - filter テーブルの最後に、OUTPUT チェーンに関わるルールに取り組む。おそらく、ここでやるべきことはそう多くはないだろう。

    2. nat table - filter テーブルの次には、nat テーブルを処理する。filter テーブルの次に行うのには、これらのスクリプトとの兼ね合いで、いくつかの理由がある。まず第一に、あまり早い段階でフォワードメカニズムそのものと NAT 機能を有効にしたくないからだ。そうしてしまうと、好ましくないタイミング (NATオンであるにも拘わらず filter ルールが未整備という意味) で、パケットがファイヤーウォールを通り抜けてしまう可能性が高い。僕は nat テーブルを、filter テーブルのすぐ外側を取り囲む感じで存在する一種の膜のように捉えている。つまり filter テーブルが核で、nat テーブルは filter テーブルを包み込む層のように働く。そしてさらに mangle テーブルが第2 の層として nat テーブルをくるんでいるのだ。この捉え方は、見方によっては間違っているかもしれないが、当たらずとも遠からずといったところだと思う。

      1. Set policies - 一番最初に、nat テーブルの中のデフォルトポリシーをすべてセットアップする。僕は通常、最初から設定されているポリシー、具体的には ACCEPT のままでいいと考えている。そもそもこのテーブルはフィルタリングに使うべきではなく、ここでパケットを破棄させてはならない。推測するところでは、そのようなことを行うと、ある種非常に厄介な問題が発生するおそれがあるからだ。ACCEPT にしない理由は見あたらないので、僕はこのチェーンを ACCEPT に設定する。

      2. Create user specified chains - この時点で、nat テーブル内に置きたいユーザ定義チェーンを作成する。普通、僕はここにチェーンをひとつも作らないが、もしもということもあるのでこのセクションが設けてある。ユーザ定義チェーンは、それがシステムチェーンから使用される以前に作成されていなくてはならないということを忘れずに。

      3. Create content in user specified chains - ここで、ユーザ定義チェーンにルールを構築する潮時となる。filter テーブルと同様なわけだ。この項目をこの場所に設けているのは、そうしてはいけない理由が見あたらないから。

      4. PREROUTING chain - PREROUTING チェーンは、必要に応じて DNAT を行うところだ。ほとんどのスクリプトでは、使われていないか、少なくともコメントアウトされている。知らず知らずのうちにローカルネットワークに大穴を開けてしまうのは嫌だからだ。一部のスクリプトでは、この種の機能の提供こそが主眼であるため、敢えて DNAT を有効にしている場合もある。

      5. POSTROUTING chain - 僕の書いたスクリプトの大半は、ファイヤーウォールの内側にローカルネットワークがひとつ以上あってそれをファイヤーウォールでインターネットから隔てることを前提としているため、POSTROUTING チェーンは多用している。使用するのは SNAT ターゲットが主だが、特定のケースでは MASQUERADE ターゲットを使う必要性に迫られる。

      6. OUTPUT chain - OUTPUT チェーンはどのスクリプトでも、ほぼまったく使われていない。現状で見る感じでは、OUTPUT チェーンに不具合があるというわけではないにしろ、このチェーンを使うこれといった理由が今のところ見つからない。もし、このチェーンを使う必然性を見つけたら、僕にその定義行を送ってほしい。このチュートリアルに盛り込めるかもしれない。

    3. mangle table - 最後に云々するのは mangle テーブルだ。僕は通常、このテーブルをまったく使わない。このテーブルは、全マシンで TTL を統一するだとか、TOS フィールドを変えるといった特殊な要件でもない限り、滅多に使うものではない。こうした理由から、ほとんどのスクリプトでは、ほぼ何も入れないことにした。ただし、 mangle テーブルの利用法を示すこと自体を目的としたスクリプトだけは別だ。

      1. Set policies - このチェーンの中のデフォルトポリシーを設定する。ここでも nat テーブルとほぼ同じことが言える。このテーブルはフィルタリングのためのものではないので、そうしたことは一切行ってはならない。僕はどのスクリプトでも、mangle テーブルではいかなる意味でも一切ポリシーを設定していないし、あなたもしないようにすべきだ。

      2. Create user specified chains - ユーザ定義チェーンを全部作る。僕はどのスクリプトでも mangle テーブルをまったく使っていないので、チェーンもひとつも作成していない。扱うデータがないのだから、作っても意味がない。それにも拘わらずこのセクションを置いているのは、将来、使う必要性が生じた時への備えだ。

      3. Create content in user specified chains - このテーブルにユーザ定義チェーンがある時には、ここでそのルールを作るとよい。

      4. PREROUTING chain - 現在のところ、当チュートリアルのスクリプトには、この部分のルールを含む内容はほぼ皆無。パケット単位あるいはコネクション単位で、netfilter マークやルーティングマーク、 SEC マークを付けるというのが PREROUTING チェーンの基本的な活用法だ。

      5. INPUT chain - 現在のところ、当チュートリアルのスクリプトには、この部分のルールを含む内容はほぼ皆無。使うとすれば、マークのハンドリングなどに使用することができる。

      6. FORWARD chain - mangle テーブルの FORWARD チェーンは、マークのハンドリングや、このファイヤーウォールを通っていくパケットのパケットヘッダを改変する時に活用する。例えば TTLTOS の変更などだ。

      7. OUTPUT chain - OUTPUT チェーンは、ファイヤーウォール (言い換えればこのホスト) から出て行こうとしているパケットに変更を加える際に利用する。例えば、 TTLTOS を設定するなど、種々のマークを付ける場合だ。どのスクリプトでもほとんど行っていないが、セクションだけは置いてある。

      8. POSTROUTING chain - 現在のところ、当チュートリアルのスクリプトでは基本的にこのチェーンは使用していない。使うとすれば、このホスト (つまりファイヤーウォール) を離れようとする時かこのホストの中を通過中の全パケットに、某かの値を設定する時だ。例えば、パケットの MTU の再設定、 TTLTOS の設定などがこれにあたる。

この説明で、各スクリプトの構造と、そのような構造を採っている理由がよくわかってもらえたとしたらありがたい。

Caution

お断りしておくが、上記の説明は相当はしょっている。スクリプトがどんな項目から出来ていて、なぜそのように分けたかという駆け足の説明であり、それ以上の何物でもない。決して、これが唯一最良の方法だと言っているわけではない。