google

最近のコメント

最近のトラックバック

他のアカウント

Powered by TypePad

2008年4月26日 (土)

SYSLOG機能を利用したルータのログ管理

私の所有するルータには,SYSLOG機能があります.ログを,指定したIPアドレスに送ってくれる機能です.もしルータにこの機能があるなら,絶対に利用するべきです.

ルータの設定は説明書にお任せして,ここではサーバ側の設定を行います./etc/sysconfig/syslogを編集します.

#Options to syslogd
# -m 0 disables 'MARK' messages.
# -r enables logging from remote machines
# -x disables DNS lookups on messages recieved with -r
# See syslogd(8) for more details
SYSLOGD_OPTIONS="-m 0 -r" <-ここを変更
# Options to klogd
# -2 prints all kernel oops messages twice; once for klogd to decode, and
#    once for processing with 'ksymoops'
# -x disables all klogd processing of oops messages entirely
# See klogd(8) for more details
KLOGD_OPTIONS="-2"

SYSLOGD_OPTIONS="-m 0 -r"の"-r"オプションをつけることで外部からのSYSLOGを受け付けるようになります.最後に,SYSLOGデーモンを再起動すると,/var/log/messagesにルータのログが記録されていきます.

% /etc/init.d/syslog restart

Gentoo Linuxの強力なパッケージ管理(emerge と glsa-check)を利用したアップデート

セキュリティホールを埋めるためのアップデートはLinuxでは依存関係なんかがあってとても面倒くさいものだとされてきましたが、Gentoo LinuxにはPortageと呼ばれる仕組みで強力なパッケージ管理がされているため、依存関係をほぼ意識することなくアップデートを行えるようになり ました。ここでは、Portageを利用したアップデートを仕方を紹介します。

# emerge --sync

で更新情報のアップデートを行った後、

# glsa-check -t new
dns home # glsa-check -t new
WARNING: This tool is completely new and not very tested, so it should not be
used on production systems. It's mainly a test tool for the new GLSA release
and distribution system, it's functionality will later be merged into emerge
and equery.
Please read http://www.gentoo.org/proj/en/portage/glsa-integration.xml
before using this tool AND before reporting a bug.

This system is affected by the following GLSA:
200510-26 ←この辺から注目
200601-10
200511-14
200605-02
200605-05

というように、セキュリティ関係でアップデートが必要な情報があった場合、その日付が表示されます。さらに、

# glsa-check -l 200601-10
WARNING: This tool is completely new and not very tested, so it should not be
used on production systems. It's mainly a test tool for the new GLSA release
and distribution system, it's functionality will later be merged into emerge
and equery.
Please read http://www.gentoo.org/proj/en/portage/glsa-integration.xml
before using this tool AND before reporting a bug.

[A] means this GLSA was already applied,
[U] means the system is not affected and
[N] indicates that the system might be affected.

200601-10 [N] Sun and Blackdown Java: Applet privilege escalation
( dev-java/sun-jre-bin dev-java/blackdown-jre dev-java/blackdown-jdk ... )

glsa-check -l yyyymm-dd といった文法で、その更新情報の内容が表示されます。必要だと思われたら、

# emerge -u [更新すべきパッケージ名]

とし、パッケージの更新を行います。cronでglsa-checkを動かしておくと、毎日メールなりで更新情報が届けられます。

Gentoo Linuxに玄人志向のGbE-PCI(VT6122)をインストールした時のメモ

家庭内LANをGigabit Ethernetにした時に、Gentoo Linuxサーバに玄人志向のGbE-PCIをインストールした時でメモです。

GbE-PCIは、 VIA製VT6122を搭載した、玄人志向のギガビットのNICです。1000円で購入でき、性能も比較的高評価です。Gentoo Linuxにもインストール可能ですが、私の場合は結構苦労したので、インストール方法を紹介します。なお、カーネルは2.6.16時の記録です。

まず、ドライバをダウンロードします。
VIA Velocity Family Gigabit Ethernet Driver

解凍したら、解凍したディレクトリに移動して、

# make
# make install

で、コンパイルに成功したらラッキー。しかし、私はコンパイルでエラー発生。その場合は、以下の内容を"patch.txt"として保存します。た だし、改行コードなどは「velocity_main.c」ファイルと同じくしなければなりません。私は、Fedora Core5上のFireFoxでコピーした後、gEditでペーストし、保存しました。

--- velocity_main.orig.c        2005-07-22 10:57:16.000000000 +0200
+++ velocity_main.c     2006-05-17 22:14:14.000000000 +0200
@@ -1957,7 +1957,11 @@
#endif
             if(pci_dev_driver(pcid) == &velocity_driver) {
                 if (pci_get_drvdata(pcid))
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
+                    velocity_suspend(pcid, PMSG_SUSPEND);
+#else
                     velocity_suspend(pcid, 3);
+#endif
             }
         }
     }
@@ -2001,7 +2005,11 @@
         velocity_save_pci_context(pInfo, &pInfo->pci_context);
         velocity_shutdown(&pInfo->hw);
         pci_disable_device(pcid);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
+  power_status = pci_set_power_state(pcid, pci_choose_state(pcid, state));
+#else
         power_status = pci_set_power_state(pcid, state);
+#endif
     }
#else
     pci_disable_device(pcid);

保存後、

# patch < patch.txt

として、「velocity_main.c」にパッチを当てます。

# make
# make install

で、モジュールのコンパイルとインストールが終了。コンパイルできなければ文字コード、改行コードなどを改めてみてください。

ディレクトリ /etc/modules.autoload.d にあるkernel-2.6のファイルに、

velocityget

の一行を書き込みます。これで、起動時にvelocitygetのモジュールが読み込まれます。

# cd /etc/init.d
# cp net.eth0 net.eth1
# rc-update add net.eth1 default

で、再起動時にeth0とeth1が起動するようにし、

# vi /etc/conf.d/net

で、ネットワークの設定を行います.

# /etc/conf.d/net:
# $Header: /home/cvsroot/gentoo-src/rc-scripts/etc/conf.d/net,v 1.7
# 2002/11/18 19:39:22 azarah Exp $

# Global config file for net.* rc-scripts

# eth0とeth1のネットワークの設定
#
iface_eth0="192.168.0.10 broadcast 192.168.0.255 netmask 255.255.255.0"
iface_eth1="192.168.0.20 broadcast 192.168.0.255 netmask 255.255.255.0"

#ゲートウェイをどうするか。インタフェース/デフォルトゲートウェイ
gateway="eth1/192.168.0.1"

再起動してみて、

# /sbin/ifconfig
eth1      Link encap:Ethernet  HWaddr 00:02:2A:DD:05:45
          inet addr:192.168.0.20  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:85241 errors:0 dropped:0 overruns:0 frame:0
          TX packets:119855 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:26372969 (25.1 Mb)  TX bytes:45627488 (43.5 Mb)
          Interrupt:9 Base address:0x1800

とし、「HWaddr 00:02:2A:DD・・・」となっているほうが今回インストールしているVT6122のNICとなります。従来ついているNICと逆転するかもしれま せん(従来ついているのがeth0からeth1になったりする)。場合によっては/etc/conf.d/netを所望の設定になるようにさらに設定しな おします。

ハードウェアの選定

特に電気屋さんで今売っているようなハイスペックな物は必要ありませんが、ルータなので攻撃に備えられるような、それなりの物をそろえたほうがいい かも知れません。すぐにメモリが一杯になっちゃうようなスペックは控えられたほうが吉でしょう。私の使っているマシンのスペックを以下に示します。

  • CPU:AMD Duron(tm) processor 1.3GHz
  • MEM:256MB
  • HDD:20GB
  • NIC:VT6122(玄人志向のギガビットNIC) x 2 & M/BオンボードのNIC(100Mbps) x 1

すべて余りパーツでした。NICは計3枚です。WAN(M/BオンボードのNIC(100Mbps))、DMZ(玄人志向のギガビットNIC)、LAN(玄人志向のギガビットNIC)にそれぞれつながります。

OSのインストール

OSは、今回は手軽さを考えてFedore Core 5を利用しました。もっとも、今回参考にさせていただいたネットワークマガジン2006年5月号がFedora Core 5だったって言うのもあるのですが。

それはともかく、Gentoo Linuxと違って気をつけなくてはならない点は、「インストールが簡単=オートメーション=ブラックボックス化してしまう」ということです。サーバや ルータは「必要なものはインストールしない」「インストールされているものが自分でわかっている」というのが、セキュリティホールを作らないうえで重要だ からです。ですので、いくらインストールが簡単といっても気をつけなくてはならないいくつかの点がありますので述べていきます。

「ネットワークデバイス」では

NIC3枚挿しの場合、ちゃんと認識されていればeth0~eth2が表示されているはずです。とりあえずここでは「起動時にアクティブ」のチェックをはずし、起動時にはアクティブにしないようにします。

「Fedora Core のデフォルトのインストールは・・・」では

「必要のないものはインストールしない」という観点からはとりあえず「オフィスとプロダクティビティ」をチェックし、「即時カスタマイズ」をチェッ クすることで、必要のあるもの、ないものを自分でカスタマイズ可能です。今回必要なものは「iptables」ぐらいなものです。時間がある方はこの部分 をしっかり閲覧して、どのようなものがインストールされるかをチェックしてください。面倒くさい方はある程度お任せでもいいかもしれませんが・・・。

「ファイアウォール」では

「Enabled」になっていることを確認し、すべての「Trusted Services」からチェックをはずします。

「システムユーザー」では

「root」以外のユーザを作ったほうがいいでしょう。作業用ユーザをお好みで作成してください。

ネットワークの設定

OSのインストールに成功し、ランレベル5で起動するとXが立ち上がります。ログイン後、設定を確認していきます。図のような前提で話を進めて生きたいと思います。

ルータ構築のネットワーク図

ファイアウォールの確認

「デスクトップ」→「管理」→「セキュリティレベルとファイアウォールの設定」で、「ファイアウォールのオプション」の「信頼できるサービス」のすべてのチェックボックスが外れていればOKです。

サービスを停止する

不要なサービスが開始されている場合があります。Fedora Core 5では、デフォルトでsendmailとsshがONになっている場合があるので、これらのサービスをストップしておきます。「デスクトップ」→「管理」 →「サービスの設定」で、「Background Services」の不要なサービス、特にsshやsendmailのチェックをはずして、サーバ起動時に開始しないようにした後、「停止」を押して、 サービスを停止させます。

ppp0(WAN側ポート)の作成

さて、ppp0(WAN側ポート)の作成に入ります。プロバイダとの接続をするところです。

「デスクトップ」→「管理」→「ネットワークの設定」で、「デバイス」の「新規」をクリックします。「デバイスタイプ」では「xDSL接続」を選 択、「DSL接続の設定」では、「イーサネットデバイス」にeth0、プロバイダ名、ログイン名、パスワード(プロバイダから発行されたもの)を入力しま す。設定が終了すると、「デバイス」の一覧にppp0が作成されます。

続けて、この作成された「ppp0」を選択し、「編集」をクリックします。「xDSL設定」という設定画面が出てきます。ニックネームには 「ppp0」「コンピュータの起動時にデバイスを起動」にチェック、「すべてのユーザに・・・」と「このインタフェース用にIPv6の設定・・・」の チェックははずします。また、「固定のIPアドレス設定」をクリックし、プロバイダからもらっている固定IPを入力します。私の場合は、

アドレス                      :218.45.162.38
サブネットマスク              :255.255.255.255
デフォルトゲートウェイアドレス:218.45.162.38

としました。

設定を抜け、VDSLモデム(フレッツ光マンションタイプの場合)とeth0ポートを実際にストレートケーブルで接続し、先ほどの「デスクトップ」 →「管理」→「ネットワークの設定」画面でppp0を選択、「起動」をクリックします。状態が「起動中」となればppp0の設定は完了したことになりま す。

カーネルモードPPPoE

PPPoEをカーネルの一部として起動させ、スループットをあげるための設定をします。

設定ファイルは /etc/sysconfig/networking/profiles/default/ifcfg-ppp0(ppp0の部分は、「xDSL設定」のニックネームに依存する)です。viなどのエディタで、このファイルの最終行に

LINUX_PLUGIN=/usr/lib/pppd/2.4.3/rp-pppoe.so

と入力します。この設定を有効にするため、「デスクトップ」→「管理」→「ネットワークの設定」画面でppp0を選択、「再起動」をクリックします。

アップデート

「アプリケーション」→「システムメニュー」→「Software Updater」で、「Apply updates」をクリックすると、アップデートが開始されます。

また、「デスクトップ」→「管理」→「サービスの設定」で、「yum」を起動するようにしておくと、自動でアップデート(デフォルトでは午前5時くらい)が行われるようになります。

eth1(DMZ)、eth2(LAN)ポートの設定

「デスクトップ」→「管理」→「ネットワークの設定」で、eth1またはeth2を選択し、「編集」を押します。そこで、「コンピュータの起動時にデバイスを起動」にのみチェックを入れ、さらに、「固定のIPアドレス設定」で、

eth1

アドレス        :192.168.10.1
サブネットマスク:255.255.255.0

eth2

アドレス        :192.168.20.1
サブネットマスク:255.255.255.0

とします。ここで、DMZのネットワークは192.168.10.0/24、LANのネットワークは192.168.20.0/24とします。また、デフォルトゲートウェイの設定はしません。

DNSの設定

ここでは、DMZに立てられているDNSサーバに名前解決を依頼します。ここでの「名前解決」という意味は、この「ルータ」が必要とする何らかの処 理のために必要な「名前解決」を意味します。例えば、ルータからブラウザを用いて外部にアクセスするために、ここで設定するDMZに立てられたDNSサー バに名前解決しに行くということです。外部から来る名前解決を行う、ということではありません。/etc/resolv.confに、

nameserver 192.168.10.2

と書き加えます。ここで、DMZ上のDNSサーバのアドレスを192.168.10.2とします。複数、DNSサーバを指定したいときは、

nameserver 192.168.10.2
nameserver 211.***.**.1
nameserver 211.***.**.2

というふうに、列挙していきます。例えば、プロバイダのDNSなどを設定しておくと、DMZ内に何らかの理由でアクセスできなくなったときでもルータは名前解決できるようになります。

セキュリティポリシの策定

ここでは、ルータに入るパケット、ルータから出るパケット、ルータを通過するパケットについてのルール(ポリシ)を決定します。

ルータに入るパケット

ルータに入るパケットというのは、「ルータ自体があて先で、ルータが処理すべきパケット」の事を指します。例を挙げると、現在構築中のルータについ ているFirefoxブラウザで、外部にアクセスした際の、受け取るhtmlデータなどを指します。「通過する」ために入るパケットはここではなく、 「ルータを通過するパケット」のところでのルールが適用されます。

ここでは、

・不正な(攻撃に使われるような)パケットは拒否
・すでに接続が確立されているパケットであれば許可
・あとは拒否

とします。外部から新しく何かの接続を確立させよう、というものははじき、こちらからの応答のみ許可します。

ルータから出るパケット

ルータから出るパケットというのは、「ルータ自体が送信元のパケット」の事を指します。例を挙げると、現在構築中のルータについている Firefoxブラウザで、外部にアクセスする際の、データ要求などを指します。「通過した」結果出るパケットはここではなく、「ルータを通過するパケッ ト」のところでのルールが適用されます。

ここでは、

・不正な(攻撃に使われるような)パケットは拒否。
・あとは許可。

とします。

ルータを通過するパケット

ルータに、ルータ以外への、ほかへのあて先のパケットがきたときどう処理するかを決めます。ルータなので、ここが一番重要です。言わずもがな、ここではすべて

・不正な(攻撃に使われるような)パケットは拒否。

とします。

WAN→DMZ

・あて先ポートがDMZ内サーバのサービスに使用されているポートならば、
 送信先IPアドレスをDMZ内サーバ(192.168.10.2)に変換して通過させる。
・それ以外は拒否。

WAN→LAN

・すでに接続が確立されているパケットであれば、IPマスカレードのIP変換
 テーブルに基づいて、送信先IPアドレスをLAN内端末のIPアドレスに変換
 して通過させる。
・それ以外は拒否。

DMZ→WAN

・すべてIPマスカレードを実行して通過。

DMZ→LAN

・すでに接続が確立されているパケットであれば通過させる。
・それ以外は拒否。

LAN→WAN

・すべてIPマスカレードを実行して通過。

LAN→DMZ

・基本的にすべて通過。

iptablesについて

ptablesのパケットパス

iptablesのパケットパス

下記では、それぞれの意味について説明します。左からそれぞれ転送される時のパス、入力されるときのパス、出力されるときのパスを示します。

テーブルとチェイン

iptablesには、

  • filter
  • nat
  • mangle

という3つのテーブルが用意されています。そして、それぞれのテーブルに、下記のようにチェインが備わっています。

  • filter
    • FORWARD
    • INPUT
    • OUTPUT
  • nat
    • PREROUTING
    • POSTROUTING
  • mangle
    • PREROUTING
    • OUTPUT

filterテーブル

パケットの内容をチェックして、パケットを受け入れたりブロックしたりします。FORWARDチェインはポートからポートへ転送されるときにパケッ トをチェックします。INPUTチェインははローカルプロセスに入力されるとき、OUTPUTチェインはローカルプロセスからアウトプットされたときにパ ケットをチェックします。

natテーブル

NAT(Network Address Translation)を実行します。WAN→DMZのあて先NATはPREROUTINGチェイン、IPマスカレードはPOSTROUTINGチェインで行われます。

mangleテーブル

ヘッダの変更や処理の最適化を行うテーブルです。あまり必要としませんので、説明を割愛します。

ユーザチェイン

iptablesはその処理の構造化を可能にするため、ユーザが特別なチェインを作成することができます。ユーザチェインは3つのテーブルのいずれかに関連付けられます。プログラムで言うところの、関数を作るようなイメージです。

これらiptablesの基本的な機能をうまく利用して、次のページでは実際にiptablesを用いたファイアウォールのルールを構築していきます。

ファイアウォールの作成

iptablesスクリプト作成

習うより慣れろ・・・ということで、実際のiptablesの設定を見ていただきたいと思います。iptablesの設定は、特に設定ファイル書く というよりは、shellスクリプトを書いて、実行させ、それをiptablesに記憶させるという方法をとります。以下は、そのshellスクリプトで す。途中、for文などですっきりさせたつもりですが、不都合などございましたらご連絡ください。

#!/bin/bash

##########################################################################
# 変数の設定
##########################################################################
LAN_PORT=eth2
LAN_NET="192.168.20.0/24"
LAN_BASE="192.168.20.0"
LAN_BCAST="192.168.20.255"
LAN_IP="192.168.20.1"

DMZ_PORT=eth1
DMZ_NET="192.168.10.0/24"
DMZ_BASE="192.168.10.0"
DMZ_BCAST="192.168.10.255"
DMZ_SVR="192.168.10.2"
DMZ_IP="192.168.0.1"

WAN_PORT=ppp0
WAN_IP="218.45.162.31"

IPTABLES="/sbin/iptables"
MODPROBE="/sbin/modprobe"

# 通信すべきでないホストとネットワークのIPアドレス
SHUN=""

# ありえなさそうなIPアドレス
BADIP="$DMZ_BCAST $DMZ_BASE $LAN_BASE $LAN_BCAST 0.0.0.0/8 \
10.0.0.0/8 127.0.0.0/8 169.254.0.0/16 172.16.0.0/12 224.0.0.0/4 \
240.0.0.0/5 255.255.255.255"

#ログの出力のタイミング
LOGOPT="--log-level=3 -m limit --limit 3/minute --limit-burst 3"
#SYNFLOODと扱うしきい値
SYNOPT="-m limit --limit 10/second --limit-burst 20"
#pingを許可するネットワーク
PING="192.168.10.0/24 192.168.20.0/24"
##########################################################################
# モジュールの読み込み、カーネル動作の設定
##########################################################################
$MODPROBE ip_tables
$MODPROBE iptable_filter
$MODPROBE ip_conntrack
$MODPROBE iptable_nat
$MODPROBE ip_nat_ftp
$MODPROBE ip_conntrack_ftp
$MODPROBE ipt_state
$MODPROBE ipt_MASQUERADE
$MODPROBE ipt_LOG
$MODPROBE ipt_REJECT
$MODPROBE ipt_limit
# IPマスカレード許可
echo 1 > /proc/sys/net/ipv4/ip_forward
# pingのブロード/マルチキャストを無視
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
# ソースアドレスの妥当性検査
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f; done
# ありえないアドレスをログに記録
for f in /proc/sys/net/ipv4/conf/*/log_martians; do echo "1" > $f; done
# ICMP redirect messageを無視
for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do echo 1 > $f; done
# SYN FLOOD攻撃対策
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
# Smurf攻撃対策
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

##########################################################################
# DMZで公開するポート
##########################################################################

DMZ_SVC_TCP="ssh smtp domain http pop3"

DMZ_SVC_UDP="domain"

##########################################################################
# 既存のファイアウォールルールをクリアする
##########################################################################

if [ ! -x $IPTABLES ]
then
echo "firewall: can't execute $IPTABLES"
fi

$IPTABLES -P INPUT   DROP # デフォルトポリシーはDROP
$IPTABLES -P OUTPUT  DROP # デフォルトポリシーはDROP
$IPTABLES -P FORWARD DROP # デフォルトポリシーはDROP
$IPTABLES -F   # すべてのチェインをフラッシュ
$IPTABLES -X   # すべてのチェインをフラッシュ

#すべてのテーブルでルール、チェイン、カウンタをクリアする
for table in filter nat mangle
do
$IPTABLES -t $table -F  # ルールの削除
$IPTABLES -t $table -X  # チェインの削除
$IPTABLES -t $table -Z  # カウンタのクリア
done


##########################################################################
#ユーザ定義のチェイン。プログラムで言うところの自作した関数。
##########################################################################

#-------------------------------------------------------------------------
# BAD_IPチェイン。望ましくないIPのものはログを残して破棄。
#-------------------------------------------------------------------------

$IPTABLES -N BAD_IP
$IPTABLES -A BAD_IP -j LOG --log-prefix "IPTABLES BAD_IP: " $LOGOPT
$IPTABLES -A BAD_IP -j DROP

#-------------------------------------------------------------------------
# SHUNチェイン。敵対ホストのIPアドレスならBAD_IPチェインに渡す。
#-------------------------------------------------------------------------

$IPTABLES -N SHUN
for ip in $SHUN
do
$IPTABLES -A SHUN -s $ip -j BAD_IP
$IPTABLES -A SHUN -d $ip -j BAD_IP
done
#-------------------------------------------------------------------------
# IN_IP_CHECKチェイン。送信元IPアドレスがありえないものなら
# BAD_IPチェインに渡す
#-------------------------------------------------------------------------

$IPTABLES -N IN_IP_CHECK

#送信元IPアドレスが変数 BADIP にあるものならBAD_IPチエインに渡す
for sip in $BADIP
do
$IPTABLES -A IN_IP_CHECK -s $sip -j BAD_IP
done

#それぞれのポートから入るパケットで、ありえない送信元IPアドレスなら、
#BAD_IPチエインへ
$IPTABLES -A IN_IP_CHECK -i $WAN_PORT -s $DMZ_NET -j BAD_IP
$IPTABLES -A IN_IP_CHECK -i $WAN_PORT -s $LAN_NET -j BAD_IP
$IPTABLES -A IN_IP_CHECK -i $DMZ_PORT -s $WAN_IP  -j BAD_IP
$IPTABLES -A IN_IP_CHECK -i $DMZ_PORT -s $LAN_IP  -j BAD_IP
$IPTABLES -A IN_IP_CHECK -i $LAN_PORT -s $WAN_IP  -j BAD_IP
$IPTABLES -A IN_IP_CHECK -i $LAN_PORT -s $DMZ_NET -j BAD_IP

#------------------------------------------------------------------------
# OUT_IP_CHECKチェイン。送信先、送信元IPアドレスが正しくなければ
# BAD_IPチエインに渡す
#------------------------------------------------------------------------

$IPTABLES -N OUT_IP_CHECK

#送信先IPアドレスが変数 BADIP にあるものならBAD_IPチェインに渡す
for dip in $BADIP
do
$IPTABLES -A OUT_IP_CHECK -d $dip -j BAD_IP
done

#それぞれのポートから出るパケットで、送信元IPが正しければこのチェインは通過。
#正しくなければBAD_IPチェインに渡す
$IPTABLES -A OUT_IP_CHECK -o $WAN_PORT -s $WAN_IP  -j RETURN
$IPTABLES -A OUT_IP_CHECK -o $LAN_PORT -s $LAN_NET  -j RETURN
$IPTABLES -A OUT_IP_CHECK -o $DMZ_PORT -s $DMZ_NET  -j RETURN
$IPTABLES -A OUT_IP_CHECK -j BAD_IP


#------------------------------------------------------------------------
# CHKMSNETチェイン。Microsoftネットワーク関連のFORWARD拒否。
#------------------------------------------------------------------------

$IPTABLES -N CHKMSNET
$IPTABLES -A CHKMSNET -p tcp --dport 42 -j DROP # wins dup
$IPTABLES -A CHKMSNET -p tcp --dport 135 -j DROP # MS-RPC
$IPTABLES -A CHKMSNET -p udp --dport 135 -j DROP # MS-RPC
$IPTABLES -A CHKMSNET -p udp --dport 137:138 -j DROP # MS browse
$IPTABLES -A CHKMSNET -p udp --dport 137:138 -j DROP # MS browse
$IPTABLES -A CHKMSNET -p tcp --dport 139 -j DROP # SMB
$IPTABLES -A CHKMSNET -p tcp --dport 445 -j DROP # DHSMB

#------------------------------------------------------------------------
# BADFLAGSチェイン。望ましくないTCPフラグならばログに残して破棄。
#------------------------------------------------------------------------

$IPTABLES -N BADFLAGS
$IPTABLES -A BADFLAGS -j LOG --log-prefix "IPTABLES BADFLAGS: " $LOGOPT
$IPTABLES -A BADFLAGS -j DROP

#------------------------------------------------------------------------
# TCPフラグの検査。望ましくないTCPフラグならBADFLAGSチェインに渡す。
#------------------------------------------------------------------------
echo "tcp flag"
$IPTABLES -N TCP_FLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ACK,FIN FIN -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ACK,PSH PSH -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ACK,URG URG -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags FIN,RST FIN,RST -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags SYN,FIN SYN,FIN -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags SYN,RST SYN,RST -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ALL ALL -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ALL NONE -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ALL FIN,PSH,URG -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j BADFLAGS
$IPTABLES -A TCP_FLAGS -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j BADFLAGS

#------------------------------------------------------------------------
# SYN_FLOODチェイン。しきい値以上のタイミングでパケットがきたら
# SYNフラッド攻撃としてログに残した上で拒否する。
#------------------------------------------------------------------------
echo "syn flood"
$IPTABLES -N SYN_FLOOD
$IPTABLES -A SYN_FLOOD -p   tcp   --syn $SYNOPT -j RETURN
$IPTABLES -A SYN_FLOOD -p ! tcp                 -j RETURN
$IPTABLES -A SYN_FLOOD -p   tcp ! --syn         -j RETURN
$IPTABLES -A SYN_FLOOD -j LOG --log-prefix "IPTABLES SYN_FLOOD: " $LOGOPT
$IPTABLES -A SYN_FLOOD -j DROP

#------------------------------------------------------------------------
# IN_ICMPチェイン。入ってくるICMPが害のあるものならログに残して拒否
#------------------------------------------------------------------------
echo "inbound icmp"
$IPTABLES -N IN_ICMP

#変数 PING に指定されるネットワークからのpingには応答する。
for sip in $PING
do
$IPTABLES -A IN_ICMP  -p icmp --icmp-type echo-request -s $sip   -j ACCEPT
$IPTABLES -A FORWARD_FROM_WAN -o $DMZ_PORT -p tcp --dport $i -j ACCEPT
$IPTABLES -A IN_ICMP  -p icmp --icmp-type echo-reply   -s $sip   -j ACCEPT
done

#ネットワーク管理上必要なicmpパケットは許可する。ないものは拒否。
$IPTABLES -A IN_ICMP  -p icmp --icmp-type destination-unreachable  -j ACCEPT
$IPTABLES -A IN_ICMP  -p icmp --icmp-type source-quench            -j ACCEPT
$IPTABLES -A IN_ICMP  -p icmp --icmp-type time-exceeded            -j ACCEPT
$IPTABLES -A IN_ICMP  -p icmp --icmp-type parameter-problem        -j ACCEPT
$IPTABLES -A IN_ICMP -j LOG --log-prefix "IPTABLES In ICMP: " $LOGOPT
$IPTABLES -A IN_ICMP -j DROP

#------------------------------------------------------------------------------
# OUT_ICMPチェイン。出て行くICMPが害のあるものならログに残して拒否
#------------------------------------------------------------------------------
echo "outbound icmp"
$IPTABLES -N OUT_ICMP

#送信先が変数 PING に登録されていれば許可
for dip in $PING
do
$IPTABLES -A OUT_ICMP -p icmp --icmp-type echo-request -d $dip     -j ACCEPT
$IPTABLES -A OUT_ICMP -p icmp --icmp-type echo-reply   -d $dip     -j ACCEPT
done

#ネットワーク管理上必要なicmpパケットは許可する。ないものはログに残して拒否。
$IPTABLES -A OUT_ICMP -p icmp --icmp-type fragmentation-needed -j ACCEPT
$IPTABLES -A OUT_ICMP -p icmp --icmp-type source-quench            -j ACCEPT
$IPTABLES -A OUT_ICMP -p icmp --icmp-type parameter-problem        -j ACCEPT
$IPTABLES -A OUT_ICMP -j LOG --log-prefix "IPTABLES Out ICMP: " $LOGOPT
$IPTABLES -A OUT_ICMP -j DROP

#------------------------------------------------------------------------------
# DROPPACKETチェイン。不正なパケットをログに記録して破棄
#------------------------------------------------------------------------------
echo "droppacket"
$IPTABLES -N DROPPACKET # DROPPACKTチェインの作成
$IPTABLES -A DROPPACKET -j LOG --log-prefix "INVALID_PACKET: " $LOGOPT
$IPTABLES -A DROPPACKET -j DROP

#------------------------------------------------------------------------------
# FORWARD_BEFORE_CHECKチェイン。FORWARD前の不正なパケットでないかをチェック
#------------------------------------------------------------------------------
echo "checking before forward"
$IPTABLES -N FORWARD_BEFORE_CHECK

# LANから外部へフォワードされるMicrosoftネットワークのチェック
$IPTABLES -A FORWARD_BEFORE_CHECK -o $WAN_PORT -j CHKMSNET

# ブラックホールルータ対策
$IPTABLES -A FORWARD_BEFORE_CHECK -o $WAN_PORT -p tcp --tcp-flags SYN,RST \
SYN -j TCPMSS --clamp-mss-to-pmtu

# PINGについてのチェック
$IPTABLES -A FORWARD_BEFORE_CHECK -p icmp -j IN_ICMP
$IPTABLES -A FORWARD_BEFORE_CHECK -p icmp -j OUT_ICMP
# TCPのフラグが正しいかをチェック
$IPTABLES -A FORWARD_BEFORE_CHECK -p tcp -j TCP_FLAGS
# SYN_FLOOD攻撃でないかをチェック
$IPTABLES -A FORWARD_BEFORE_CHECK -p tcp --syn -j SYN_FLOOD

#------------------------------------------------------------------------------
# FORWARD_FROM_WANチェイン。WANポートから来たパケットのFORWARDについての設定
#------------------------------------------------------------------------------
echo "from wan port"
$IPTABLES -N FORWARD_FROM_WAN

# 外部からDMZへの接続で、接続済みのもののFORWARDを許可
$IPTABLES -A FORWARD_FROM_WAN -o $DMZ_PORT -m state --state \
ESTABLISHED,RELATED -j ACCEPT

for i in $DMZ_SVC_TCP
do
# 外部からDMZへの新規接続で、サービスをしているもののFORWARDを許可(tcp)
$IPTABLES -A FORWARD_FROM_WAN -o $DMZ_PORT -p tcp --dport $i -j ACCEPT
done

for i in $DMZ_SVC_UDP
do
# 外部からDMZへの新規接続で、サービスをしているもののFORWARDを許可(udp)
$IPTABLES -A FORWARD_FROM_WAN -o $DMZ_PORT -p udp --dport $i -j ACCEPT
done

# 外部からLANへの接続で、接続済みのもののFORWARDを許可 図5
$IPTABLES -A FORWARD_FROM_WAN -o $LAN_PORT -d $LAN_NET -m state --state \
ESTABLISHED,RELATED -j ACCEPT

#------------------------------------------------------------------------------
# FORWARD_FROM_DMZチェイン。DMZポートから来たパケットのFORWARDについての設定。
#------------------------------------------------------------------------------
echo "from dmz port"
$IPTABLES -N FORWARD_FROM_DMZ

#DMZから外部への接続を許可
$IPTABLES -A FORWARD_FROM_DMZ -o $WAN_PORT -s $DMZ_NET -m state --state \
NEW,ESTABLISHED,RELATED -j ACCEPT

#DMZからLANへの、接続済みのもののみ許可
$IPTABLES -A FORWARD_FROM_DMZ -o $LAN_PORT -s $DMZ_NET -m state --state \
ESTABLISHED,RELATED -j ACCEPT

#------------------------------------------------------------------------------
# FORWARD_FROM_LANチェイン。LANポートから来たパケットのFORWARDについての設定
#------------------------------------------------------------------------------
echo "from lan port"
$IPTABLES -N FORWARD_FROM_LAN

# LAN内からDMZへの接続を許可
$IPTABLES -A FORWARD_FROM_LAN -o $DMZ_PORT -s $LAN_NET -m state --state \
NEW,ESTABLISHED,RELATED -j ACCEPT
# LAN内から外部への接続を許可
$IPTABLES -A FORWARD_FROM_LAN -o $WAN_PORT -s $LAN_NET -m state --state \
NEW,ESTABLISHED,RELATED -j ACCEPT

#------------------------------------------------------------------------------
# INPUT_FIREWALLチェイン。INPUTチェインの基本的なルール。
#------------------------------------------------------------------------------
echo "input chain"
$IPTABLES -N INPUT_FIREWALL

#icmpのチェック
$IPTABLES -A INPUT_FIREWALL -p icmp -j IN_ICMP
#TCPフラグのチェック
$IPTABLES -A INPUT_FIREWALL -p tcp -j TCP_FLAGS
#SYNフラッド攻撃かをチェック
$IPTABLES -A INPUT_FIREWALL -p tcp --syn -j SYN_FLOOD
#IPアドレスが正当化をチェック
$IPTABLES -A INPUT_FIREWALL -j IN_IP_CHECK
# パケットの正当性チェック
$IPTABLES -A INPUT_FIREWALL -m state --state INVALID -j DROPPACKET
# 接続済みの入力を許可
$IPTABLES -A INPUT_FIREWALL -m state --state ESTABLISHED,RELATED -j ACCEPT
# AUTHリクエストを拒否
$IPTABLES -A INPUT_FIREWALL -p tcp --dport 113 -j REJECT --reject-with tcp-reset
#ログに残す
$IPTABLES -A INPUT_FIREWALL -j LOG --log-prefix "UNDEFIND_INPUT: " $LOGOPT

#------------------------------------------------------------------------------
# OUTPUT_FIREWALLチェイン。OUTPUTチェインの基本的なルール。
#------------------------------------------------------------------------------
echo "output chain"
$IPTABLES -N OUTPUT_FIREWALL
#icmpパケットのチェック
$IPTABLES -A OUTPUT_FIREWALL -p icmp -j OUT_ICMP
# TCPフラグのチェック
$IPTABLES -A OUTPUT_FIREWALL -p tcp -j TCP_FLAGS
#ipアドレスのチェック
$IPTABLES -A OUTPUT_FIREWALL -j OUT_IP_CHECK

# 出力を許可
$IPTABLES -A OUTPUT_FIREWALL -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

# 上記以外のパケットはログに記録(デフォルトポリシーで破棄)
$IPTABLES -A OUTPUT_FIREWALL -j LOG --log-prefix "UNDEFIND_OUTPUT: " $LOGOPT

##########################################################################
# IPマスカレード
##########################################################################
echo "masquerade"
# DMZからの外部へのIPマスカレード(SNAT)の許可
$IPTABLES -t nat -A POSTROUTING -s $DMZ_NET -o $WAN_PORT -j MASQUERADE
# LANからの外部へのIPマスカレード(SNAT)の許可
$IPTABLES -t nat -A POSTROUTING -s $LAN_NET -o $WAN_PORT -j MASQUERADE

##########################################################################
# DMZへの転送~DNAT(静的NAT)
##########################################################################
echo "dnat"

for i in $DMZ_SVC_TCP # DMZで公開するポートの設定(tcp)
do
# WANからの接続要求をDMZに転送する(tcp)
$IPTABLES -t nat -A PREROUTING -i $WAN_PORT -p tcp --dport $i \
-j DNAT --to-destination $DMZ_SVR
done

for i in $DMZ_SVC_UDP # DMZで公開するポートの設定(tcp)
do
# WANからの接続要求をDMZに転送する(tcp)
$IPTABLES -t nat -A PREROUTING -i $WAN_PORT -p udp --dport $i \
-j DNAT --to-destination $DMZ_SVR
done

########################################################################
#メインのファイアウォールルール。プログラムで言うmain関数。
########################################################################
echo "main firewall -- forward"
$IPTABLES -A FORWARD                    -j FORWARD_BEFORE_CHECK
$IPTABLES -A FORWARD                    -j SHUN
$IPTABLES -A FORWARD -i $WAN_PORT -j FORWARD_FROM_WAN
$IPTABLES -A FORWARD -i $DMZ_PORT -j FORWARD_FROM_DMZ
$IPTABLES -A FORWARD -i $LAN_PORT -j FORWARD_FROM_LAN
$IPTABLES -A FORWARD -j LOG --log-prefix "IPTABLES DROP FORWARD: " $LOGOPT
$IPTABLES -A FORWARD -j DROP
echo "main firewall -- input"
$IPTABLES -A INPUT -i lo -j ACCEPT
$IPTABLES -A INPUT              -j SHUN
$IPTABLES -A INPUT -j INPUT_FIREWALL
$IPTABLES -A INPUT -j LOG --log-prefix "IPTABLES DROP INPUT: " $LOGOPT
$IPTABLES -A INPUT -j DROP
echo "main firewall -- output"
$IPTABLES -A OUTPUT -o lo -j ACCEPT
$IPTABLES -A OUTPUT         -j SHUN
$IPTABLES -A OUTPUT -j OUTPUT_FIREWALL
$IPTABLES -A OUTPUT -j LOG --log-prefix "IPTABLES DROP OUTPUT: " $LOGOPT
$IPTABLES -A OUTPUT -j DROP

ポートスキャンによるチェック

sygate online serviceから、「Quick Scan」を行って、サービスを提供しているものは「OPEN」、していないものは「BLOCKED」「CLOSED」になっているはずです。なっていなければ、早急にスクリプトを見直してみましょう。

設定を保存する

現在のiptablesの設定を保存することで、次回サーバ起動時に自動的に現在の設定を読まれます。

# /etc/init.d/iptables save

で、現在の設定(スクリプトの内容)が保存されます。また、「デスクトップ」→「管理」→「サービスの設定」で、iptablesを起動時にスタートするようにしましょう。

最後に

最後に,私が自宅サーバを立ち上げてよかったなって思うことをいくつか.

まず,知識レベルがものすごく高くなりました.インターネットって,どんな仕組みなんだろうってことがだいぶわかるようになってきました.これは, 資格などに非常に有利だと思います.資格は実務経験がものをいうことが多いです.学生のうちはそんなものは得ることができないので,この自宅サーバを通じ て得る経験は大変に意義深いものだと思います.

リアクションがあるのも非常に嬉しいです.「DNSのセカンダリになって」とか,「設定わからないので教えて」というメールが多くなってきています.やりがいがあります.

最近は,就職活動の面接のネタとして非常に役に立ちました.私はネットワークスペシャリストを持っていますが,資格ではなく,経験を重視する企業も多いはずです.僕は面接で自宅サーバについて,たとえば苦労話など,熱く語ったらそこから話が弾むことも多かったです.

どうでしょう,皆さん.今すぐ始めてみたらいかがですか?少々費用がかさむかもしれませんが,自分の将来への投資と考えて・・・.