Gentoo Linux セキュリティ・ガイド
1. はじめに
このガイドはGentoo Linuxをサーバ環境で利用している人や、もうちょっとセキュアにしておきたいんだけどな、という人のために書かれています。
Note:
このガイドを読み終わってGentooのセキュリティ関連のことをもっと知りたくなったら、 Hardened Gentoo Projectのページも見てみてください。
|
2. インストールの前に考慮すべきこと
物理的なセキュリティ
いくら堅牢な設定を施しても、アタッカーがあなたのマシンに物理的に触れることができるようなら、
そんなものはいとも簡単に回避されてしまいます。ハードウエアが気軽にアクセスできるような場所に設置されていませんか?
鍵がかかるサーバ・クローゼットに置かれているようなら安心でしょう。
鍵がかかるケースに入れておくのも良いアイデアですね。
最高のセキュリティを確保しようと思うなら、ハードディスクからしか起動できないようにBIOSを設定しておくべきです。
フロッピーやCD-ROMからは起動できないようにしてしまいましょう。
もっとしつこいくらいちゃんとしたいなら、BIOSパスワードを設定するのも良いと思います。
BIOSパスワードは、ラップトップPCを使っているユーザーにも試してもらいたいですね。
起動するデーモンやサービスを決定
どんなサービスが起動していなければいけないのか、どんなサービスが起動していると良いと思うのか、
それぞれ文書化しましょう。こうしておくと、あなたのシステムのパーティション案を考えるときに参考になります。
また、侵入検知にどういう方法を取るか考えるときにもラクになります。
もちろん、使っているコンピュータが1台または数台でそれを使うのが自分だけなら、
わざわざ文書化する必要はありません。例)いまからファイアーウォール用のコンピュータをセットアップする予定で、
そのマシンで動かすつもりのサービスは何もない(でもひょっとしたらsshdぐらいは動かすかもしれない)ような場合。
起動するサービスやsshdの現在のバージョンを文書化しておきましょう。
そうすれば、sshdにセキュリティホールが見つかったときにどのシステムをアップグレードすべきなのかすぐにわかります。
また、誰がこのシステムにアクセスできるようにするのか決定するときにも役に立ちます。
パーティション計画
必勝法:
-
ユーザーが書き込める全てのディレクトリ(/homeや/tmpや/var)は、
それぞれ別のパーティションにした上で、quotaを有効にすべきです。
Portageはソースをコンパイルする際に/var/tmpを使うので、
このディレクトリが含まれるパーティションは大きめにしておく必要があります。
こうしておけば、ユーザーが/パーティションをいっぱいにしてしまう心配を減らすことができます。
-
ディストリビューション標準以外のソフトをインストールするディレクトリは、別のパーティションにするべきです。
FHS(File Hierarchy Standard)に従えば、
このディレクトリは/optか/usr/localになります。
これらのディレクトリを別パーティションにしておけば、システムを再インストールすることになっても、
別途インストールしたソフトウエアは消されずにすみます。
-
変更されることのないデータはそれ用のパーティションに移動しておき、
そのパーティションはリードオンリーでマウントしましょう。
もっと厳密にやりたいなら、これらの変更されることのないデータはCD-ROMのような書き込みのできないメディアに保存することを検討しても良いでしょう。
rootアカウント
'root'というアカウントはシステムの中で最も強いユーザーで、必要なとき以外はこのアカウントを使ってはいけません。
アタッカーにroot権限を奪取された場合、そのシステムはもう信用できません。
そうなった場合は再インストールしてください。
'root'に関する必勝法
-
日々使用するアカウントを必ず作りましょう。
そのユーザーがrootになれる必要があるなら、そのアカウントをwheelグループに追加しましょう。
wheelグループに追加しておけば、その一般ユーザーはsuコマンドでrootになれます。
-
Xなどのユーザーアプリケーションをrootで起動するのは禁止です。
-
rootとしてログインした後は毎回絶対パスを使いましょう。
rootユーザーが使っていると思っているアプリケーションが、実は別の場所に置かれた別のアプリケーションだということはありえます。
たとえば誰かが勝手にPATHの設定を変えておいたとします。
このときrootがsu -を使わずにsuした場合、rootユーザーはそのユーザーのPATHの設定を引き継ぐことになります。
-
あるユーザーが使わなくてはいけないroot権限を必要とするコマンドがそれほど多くないようなら、sudoを利用することも検討してください。
ただし、sudoの利用は慎重に!
-
rootとしてログインしているときは端末をそのままにして席を離れてはいけません。
Gentooではsuしようとする一般ユーザーに対して、
よく用いられる方法で制限をかけています。
デフォルトのPAMの設定では、wheelグループに属していないユーザーはsuできません。
セキュリティポリシー
何故セキュリティポリシーが必要なのか。それにはいくつか理由があります。
-
あなたが何をもってセキュアだと定義しているかわからなければ、
あるネットワークについてそれがセキュアだと主張することはできません。
-
潜在的なアタッカーを見つけたり、ネットワーク障害を解決したり、監査を行うためには、
ネットワークトラフィックの盗聴やプライベートなホームディレクトリを見ることは不可欠です。
そしてほとんどの国で、ユーザーの同意なしにこれらのことを行うのは違法です。
現在約60%のアタックが内部犯行であることから考えると、
あなたが目を光らせておくことは重要です。
-
セキュリティがなぜ大事かということや、
どうやってあなたのユーザーが自分自身や同僚を守るのか説明することもなしに、
ユーザーがセキュリティのことを考えてくれるなどと期待することは不可能です。
-
良いガイドラインやネットワークに関する文書はいつだって役に立ちます。たとえどんなものであるにせよ。
-
あなたのネットワークの設定やあなたが提供しているサービスがわからない限り、
警察や連邦法執行機関はあなたのためにアタッカーを捕まえることはできません。
-
アタックがあったら何をしますか? その場合に何をするのか、誰にそのことを伝えるのか、
あらかじめ決めておかないといけません。毎回毎回警察やCERTに連絡するだけですか?
たぶん相手にしてもらえないでしょうね!
というわけで、複数のユーザーが使うシステムのポリシーを決めておくことがなぜ大事なのか、
ユーザー教育がなぜ大事なのか、よくわかってもらえたと思います。
ポリシーというのは、「誰が」、「どこで」、「なぜ」、「何を」ということをQ&A形式で書いた文書のことです。
あなたのシステムやネットワークを使うユーザーに、読んでもらい、理解してもらい、サインしてもらう必要があります。
なぜポリシーにサインが必要なのか、ポリシーに直接反するような行動を取ったらどういうことになるのか、
ユーザーにポリシーを理解してもらう手助けをすることはとても重要です
(ポリシーに違反したらどうなるかは、ポリシー自体に明記しておくべきです)。
ユーザーへの説明は繰り返し行いましょう。少なくとも1年に1回は。
それはユーザーに思い出してもらうためと言うより、ポリシーは変更できるものだからです。
Note:
ポリシーは読みやすいものを作ること。また、各話題ごとに正確なものにしておくこと。
|
ポリシーの大部分は直接OS上で、もしくはファイアーウォール越しに強制することができます。
しかし、一部はそうではありません。
セキュリティポリシーには、少なくとも以下の項目がなくてはいけません:
- 利用方針
-
- スクリーンセーバー
- パスワードの取り扱い
- ソフトウエアのダウンロードとインストール
- ユーザーを監視する場合、その情報
- アンチウイルスソフトの使用
- 機密情報の取り扱い(紙であれデジタルであれ、書類すべて)
-
- デスクを綺麗にすることと、機密情報を鍵をかけて保存すること
- 席を立つ前はPCの電源を落とすこと
- 暗号の使用
- 信頼できる同僚との鍵の取り扱い
- 旅行時の機密情報の取り扱い
- 旅行時のコンピュータ機器の取り扱い
-
IT関連スタッフ向けのポリシーは、一般ユーザーとは少し違うものになります。
セキュリティポリシーは膨大なものになりがちで、新しい情報を追加してもすぐに忘れられてしまうものです。
IT関連スタッフ向けのポリシーは、一般向けユーザー用に作られたポリシーを含むことになるでしょう。
そのため、セキュリティポリシーを小さく分割して作っておくのはうまいやり方だと思います。
たとえば、「利用方針に関するポリシー」、「パスワードに関するポリシー」、「メールに関するポリシー」、「リモートアクセスに関するポリシー」などなど。
セキュリティポリシーの例はThe SANS Security Policy
Projectにあります。あなたのネットワークがそれほど大きくなく、
これらのポリシーではやりすぎだと思われるようならSite Security
Handbook(訳注:日本語訳がサイトセキュリティハンドブックにあります)を見てください。
3. インストール中、そしてインストール後にセキュリティを高める方法
USEフラグ
make.confにはユーザーが定義したUSEフラグが、
/etc/make.profile/make.defaultsにはGentoo Linux用のデフォルトのUSEフラグが、
それぞれ定義されています。このガイドにとって重要なフラグは、
pam(Pluggable Authentication Modules)、tcpd(TCP wrappers)、それからssl(Secure
Socket Layer)です。これらのフラグはすべてデフォルトで有効になっています。
GRUBパスワード
GRUBがパスワードを使うように設定ファイル(/boot/grub/grub.conf)を編集する場合、
平文でパスワードを設定する方法と、ソルト(salt)付きのMD5でパスワードを設定する方法の、
ふたつのやり方があります。
Code Listing 3.1: /boot/grub/grub.conf |
timeout 5
password changeme
|
こうしておくとchangemeというパスワードが追加され、
パスワードが入力されないと単にデフォルトの設定で起動するようになります。
MD5形式のパスワードを追加したい場合は、
/etc/shadowと同様のフォーマットであるcryptフォーマット(man crypt)にパスワードをコンバートする必要があります。
詳しくはman cryptを参照してください。
changemeを暗号化すると、$1$T7/dgdIJ$dJM.n2wZ8RG.oEiIOwJUs.となるでしょう。
直接GRUBのシェルを使ってこういう風にコンバートすることもできます:
Code Listing 3.2: GRUBのシェルでmd5crypt |
#/sbin/grub
GRUB version 0.92 (640K lower / 3072K upper memory)
[ Minimal BASH-like line editing is supported. For the first word, TAB
lists possible command completions. Anywhere else TAB lists the possible
completions of a device/filename. ]
grub> md5crypt
Password: ********
Encrypted: $1$T7/dgdIJ$dJM.n2wZ8RG.oEiIOwJUs.
grub> quit
|
次にパスワードを/boot/grub/grub.confにコピー&ペーストします。
Code Listing 3.3: /boot/grub/grub.conf |
timeout 5
password --md5 $1$T7/dgdIJ$dJM.n2wZ8RG.oEiIOwJUs.
|
マシンが遠方にあってキーボードからの入力なしで再起動しなくてはいけない場合、
timeoutを5秒に設定しておくととても便利です。
info grubと実行してGRUBのパスワードについてもっと学んでみてください。
LILOパスワード
LILOにもパスワードを設定する方法がふたつあります。
ただしこちらの場合は、イメージごとに設定する方法と、全イメージ共通で設定する方法のふたつで、どちらも平文でパスワードを設定することになります。
全イメージ共通の設定は、設定ファイルの先頭に記述します:
Code Listing 3.4: /etc/lilo.conf |
password=changeme
restricted
delay=3
|
もしくは、イメージごとに設定します。
Code Listing 3.5: /etc/lilo.conf |
image=/boot/bzImage
read-only
password=changeme
restricted
|
restrictedオプションが指定されていないと、
毎回パスワード入力のプロンプトが表示されてしまいます。
lilo.confに設定した新しい情報を反映させるには、
/sbin/liloを実行する必要があります。
コンソールのセキュリティを高める
/etc/securettyを編集することで、
どのTTY(ターミナル)デバイスからrootがログインできるようにするか指定することができます。
vc/1以外の行を全てコメントアウトしてしまうのがオススメです。
こうしておけば、一度に1回、ひとつの端末でしかrootでログインできなくなります。
Note:
この場合でも、wheelグループに所属しているユーザーはsu -とすれば別のTTYでrootになることができます。
|
Code Listing 3.6: /etc/securetty |
vc/1
|
4. いつもより多めにログを取る
詳細なログを取るようにすれば、いままさに行われようとしているアタックやすでに成功した侵入に関して、
警告やエラーを見つけることができます。アタッカーたちは、
実際にアタックする前にネットワークをスキャンしたり調査したりするものです。
ログファイルが読みやすくて扱いやすいということも、同様に不可欠なことです。
Gentoo Linuxでは、インストール時に3種類のログ記録ソフトから選べるようになっています。
ロギング:syslogd
syslogdは一般的に最も有名なLinux/UNIXのログ記録ソフトです。
syslogdはログのローテーションを行いません。
/etc/logrotate.confを設定してcronに/usr/sbin/logrotateを追加すれば、
ログのローテートができるようになります(訳注:そのためにはemerge logrotateとしてlogrotateをインストールしておく必要があります)。
どの程度の頻度でログをローテートすべきかは、そのシステムの負荷によります。
以下は標準のsyslog.confにいくつか機能を追加したものです。
cronやttyの行のコメントアウトを外して、リモートのログサーバを追加しました。
今後もっとセキュリティを高めようと思うなら、ログを2個所で記録するようにしても良いでしょう。
Code Listing 4.1: /etc/syslog.conf |
# /etc/syslog.conf Configuration file for syslogd.
#
# For more information see syslog.conf(5)
# manpage.
# This is from Debian, we are using it for now
# Daniel Robbins, 5/15/99
#
# まずは標準のログファイルをいくつか。ファシリティによるログ。
#
auth,authpriv.* /var/log/auth.log
*.*;auth,authpriv.none -/var/log/syslog
cron.* /var/log/cron.log
daemon.* -/var/log/daemon.log
kern.* -/var/log/kern.log
lpr.* -/var/log/lpr.log
mail.* /var/log/mail.log
user.* -/var/log/user.log
uucp.* -/var/log/uucp.log
local6.debug /var/log/imapd.log
#
# メールシステム用のログ。
# 解析スクリプトを書きやすくするため別ファイルに。
#
mail.info -/var/log/mail.info
mail.warn -/var/log/mail.warn
mail.err /var/log/mail.err
# ニュースシステムINN用のログ
#
news.crit /var/log/news/news.crit
news.err /var/log/news/news.err
news.notice -/var/log/news/news.notice
#
# 「全部盛り」なログファイル
#
*.=debug;\
auth,authpriv.none;\
news.none;mail.none -/var/log/debug
*.=info;*.=notice;*.=warn;\
auth,authpriv.none;\
cron,daemon.none;\
mail,news.none -/var/log/messages
#
# emergとalertはログインしているユーザー全員に。
#
*.emerg *
*.=alert *
#
# ログがコンソールに表示されているのが好きなのですが、
# いつもは触らない仮想コンソールにのみ表示するようにします。
#
daemon,mail.*;\
news.=crit;news.=err;news.=notice;\
*.=debug;*.=info;\
*.=notice;*.=warn /dev/tty8
#リモートのログサーバをセットアップ
*.* @logserver
# "xconsole"ユーティリティ用の名前付きパイプ。
# 利用する際は"xconsole"を"-file"オプション付きで起動する必要あり:
#
# $ xconsole -file /dev/xconsole [...]
#
# NOTE: 以下はうまく調節してください。そうしないと、ある程度忙しいサイトの場合
# 気がヘンになってしまうかもしれません・・・
#
#daemon.*,mail.*;\
# news.crit;news.err;news.notice;\
# *.=debug;*.=info;\
# *.=notice;*.=warn |/dev/xconsole
local2.* -/var/log/ppp.log
|
アタッカーはログファイルを編集したり削除することで、自分の痕跡を消そうとします。
別のマシン(ひとつでも複数でも)でもログを取るようにすることで、
アタッカーに対する敷居を高くすることができます。
syslogdに関する詳細な情報はマニュアルページを見てください(man syslog)(訳注:man syslogdの方が適切だと思います)。
Metalog
Frank Denis氏作のMetalogはログをリモートサーバに送ることはできませんが、
そのパフォーマンスとログを記録する際の柔軟性において他を上回っています。
Metalogでは、プログラム名や緊急度、ファシリティ(syslogdと同様)でログの指定をできる他、
正規表現を書いたり特定のパターンにマッチした場合に外部スクリプトを呼び出したりすることもできます。
そういう処理が必要な場合は大変重宝します。
標準の設定でも基本的には十分です。
もしパスワード入力ミスがあった場合に毎回メールが送られてくるようにしたければ、以下のスクリプトを使ってみてください。
Postfix用:
Code Listing 4.2: Postfix用/usr/local/sbin/mail_pwd_failures.sh |
#! /bin/sh
echo "$3" | mail -s "Warning (program : $2)" root
|
qmail用:
Code Listing 4.3: qmail用/usr/local/sbin/mail_pwd_failures.sh |
#!/bin/sh
echo "To: root
Subject:Failure (Warning: $2)
$3
" | /var/qmail/bin/qmail-inject -f root
|
/bin/chmod +x /usr/local/sbin/mail_pwd_failures.shとして、
このスクリプトを実行可能にすることを忘れずに。
次に以下のように、
"Password failures"の下にあるcommandの行のコメントアウトを外します:
Code Listing 4.4: /etc/metalog.conf |
command = "/usr/local/sbin/mail_pwd_failures.sh"
|
syslog-ng
syslog-ngは、多少の違いはあるものの、syslogとMetalogの両方が提供する機能を備えています。
レベルとcontentによってフィルタしたあとにログに落せます(Metalogのように)し、syslogのようにリモートへログを送れます。
syslogdからのログ(Solarisからのログでさえ)を記録できますし、TTYへログを書き込めます。
プログラムの実行ができ、ログサーバとして動作させることもできます。
syslog-ngは基本的には、柔軟な設定が行え、ふたつのログ記録ソフトがミックスされた、最高のものだと思います。
基本的な設定ファイルに少しだけ変更を加えてみました。
Code Listing 4.5: /etc/syslog-ng/syslog-ng.conf |
options { long_hostnames(off); sync(0); };
#どこからログを読むのか決める
source src { unix-stream("/dev/log"); internal(); };
source kernsrc { file("/proc/kmsg"); };
#記録先を設定する
destination authlog { file("/var/log/auth.log"); };
destination syslog { file("/var/log/syslog"); };
destination cron { file("/var/log/cron.log"); };
destination daemon { file("/var/log/daemon.log"); };
destination kern { file("/var/log/kern.log"); };
destination lpr { file("/var/log/lpr.log"); };
destination user { file("/var/log/user.log"); };
destination mail { file("/var/log/mail.log"); };
destination mailinfo { file("/var/log/mail.info"); };
destination mailwarn { file("/var/log/mail.warn"); };
destination mailerr { file("/var/log/mail.err"); };
destination newscrit { file("/var/log/news/news.crit"); };
destination newserr { file("/var/log/news/news.err"); };
destination newsnotice { file("/var/log/news/news.notice"); };
destination debug { file("/var/log/debug"); };
destination messages { file("/var/log/messages"); };
destination console { usertty("root"); };
destination console_all { file("/dev/tty12"); };
destination xconsole { pipe("/dev/xconsole"); };
#フィルタを作る
filter f_auth { facility(auth); };
filter f_authpriv { facility(auth, authpriv); };
filter f_syslog { not facility(authpriv, mail); };
filter f_cron { facility(cron); };
filter f_daemon { facility(daemon); };
filter f_kern { facility(kern); };
filter f_lpr { facility(lpr); };
filter f_mail { facility(mail); };
filter f_user { facility(user); };
filter f_debug { not facility(auth, authpriv, news, mail); };
filter f_messages { level(info..warn)
and not facility(auth, authpriv, mail, news); };
filter f_emergency { level(emerg); };
filter f_info { level(info); };
filter f_notice { level(notice); };
filter f_warn { level(warn); };
filter f_crit { level(crit); };
filter f_err { level(err); };
filter f_failed { match("failed"); };
filter f_denied { match("denied"); };
#フィルタと記録先を関連付ける
log { source(src); filter(f_authpriv); destination(authlog); };
log { source(src); filter(f_syslog); destination(syslog); };
log { source(src); filter(f_cron); destination(cron); };
log { source(src); filter(f_daemon); destination(daemon); };
log { source(kernsrc); filter(f_kern); destination(kern); };
log { source(src); filter(f_lpr); destination(lpr); };
log { source(src); filter(f_mail); destination(mail); };
log { source(src); filter(f_user); destination(user); };
log { source(src); filter(f_mail); filter(f_info); destination(mailinfo); };
log { source(src); filter(f_mail); filter(f_warn); destination(mailwarn); };
log { source(src); filter(f_mail); filter(f_err); destination(mailerr); };
log { source(src); filter(f_debug); destination(debug); };
log { source(src); filter(f_messages); destination(messages); };
log { source(src); filter(f_emergency); destination(console); };
#デフォルトのログ
log { source(src); destination(console_all); };
|
とても設定をしやすいものの、設定ファイルが膨大なため設定忘れもしやすいです。
作者によれば、暗号化、認証、圧縮、
MAC(Mandatory Access Control)を将来実装するとのことです。
これらの機能があれば、ネットワーク用のログ記録ソフトとしては最高のものになります。
なぜなら、アタッカーがログを盗み見ることができなくなるからです。
さらにsyslog-ngにはもうひとつ利点があります。なんと、rootとして走らせなくても良いのです!
5. パーティションのマウント
ext2やext3、ReiserFSを使用しているなら、
/etc/fstabでいくつか設定できることがあります。
以下がそのオプションです:
-
nosuid - SUIDビットを無視して、通常のファイルと同様に扱う
-
noexec - そのパーティションにあるファイルの実行を禁止する
-
nodev - デバイスの作成をできないようにする
残念ながら、パスを直接指定せずに実行すればこれらの設定を回避することができます。
とはいえ、/tmpをnoexecでマウントしておけば、
スクリプト・キディーたちの攻撃の99%は回避できるでしょう。
彼等が使う攻撃用コードは、直接/tmpから実行するように作られているからです。
Code Listing 5.1: /etc/fstab |
/dev/sda1 /boot ext2 noauto,noatime 1 1
/dev/sda2 none swap sw 0 0
/dev/sda3 / reiserfs notail,noatime 0 0
/dev/sda4 /tmp reiserfs notail,noatime,nodev,nosuid,noexec 0 0
/dev/sda5 /var reiserfs notail,noatime,nodev 0 0
/dev/sda6 /home reiserfs notail,noatime,nodev,nosuid 0 0
/dev/sda7 /usr reiserfs notail,noatime,nodev,ro 0 0
/dev/cdroms /cdrom0 /mnt/cdrom iso9660 noauto,ro 0 0
proc /proc proc defaults 0 0
|
Warning:
/tmpをnoexecモードでマウントしておくことで、
ある種のスクリプトが実行されることをちゃんと防ぐことができます。
|
Note:
quotaについてはquotaの節をご覧ください。
|
Note:
私は/varを、通常ファイルが実行されることがないにもかかわらずnoexecやnosuid付きでマウントしていません。
qmailは/var/qmailにインストールされますが、ここからファイルが実行される必要があり、
また、SUIDされたファイルがひとつあります。
それから私は/usrをリードオンリーでマウントしています。
というのも、私はGentooをアップデートするとき以外、ここに何も書き込まないからです。
そういう場合は一度読み書きモードでシステムをマウントしたあと、Gentooをアップデートし、再度リードオンリーでマウントします。
|
Note:
qmailをインストールしない場合でも、Gentooでは/var/tmpにebuildを作成するため、
ここに実行ファイルを置けるようにしなくてはいけません。
ただ、どうしても/varをnoexecモードでマウントしたければ、別のパスを使うように設定することもできます。
|
6. ユーザーやグループに対する制限
/etc/security/limits.conf
リソースの制限をすることは、ローカルユーザーのDoS攻撃を防ぎたい場合や、
グループやユーザーに最大同時ログイン数の制限を加えたい場合にとても有効です。
Code Listing 6.1: /etc/security/limits.conf |
* soft core 0
* hard core 0
* hard nproc 15
* hard rss 10000
* - maxlogins 2
@dev hard core 100000
@dev soft nproc 20
@dev hard nproc 35
@dev - maxlogins 10
|
nprocやmaxloginsを0に設定するぐらいなら、その代わりにユーザーを削除すべきでしょう。
上に載せたサンプルはdevグループの設定ですが、ここではプロセス数、コアファイルの大きさ、maxloginsの制限をしています。
これ以外の項目については、デフォルトのままです。
Note:
/etc/security/limits.confはPAMパッケージの一部なので、
PAMを使うパッケージにしか適用されません。
|
/etc/limits
/etc/limitsは、制限を行うための/etc/security/limits.confとよく似ています。
唯一の違いはフォーマットですが、制限できる対象がユーザー、もしくはワイルドカードでの指定だけになっています。
グループを制限対象にすることはできません。
以下のちょっと緩めの設定を見てみてください:
Code Listing 6.2: /etc/limits |
* L2 C0 U15 R10000
kn L10 C100000 U35
|
ここではデフォルトの設定と、knというユーザーの設定をしています。
limitsはsys-apps/shadowパッケージの一部です。
make.confでpamを無効にしていたり、
PAMを適切に設定していないなら、
このファイルでリミットの設定をする必要はありません。
quota
Warning:
使用するファイルシステムでquotaのサポートが有効になっているか確認してくさだい。
ReiserFSでは使用できません!
|
ファイルシステムにquotaを設定しておけばユーザーがディスクをあふれさせることを防げますし、
また、一切書き込めないようにすることもできます。
quotaはカーネルで有効に設定され、マウントポイントに対して付与されます。
設定するカーネルオプションは、File systems→Quota supportにあります。
以下の設定を行ったあとカーネルを再構築して、新しいカーネルが使われるように再起動してください。
まずemerge quotaでquotaをインストールします。
次に以下のように/etc/fstabを編集して、
ディスクの使用を制限したいパーティションにusrquotaとgrpquotaを設定します。
Code Listing 6.3: /etc/fstab |
/dev/sda1 /boot ext2 noauto,noatime 1 1
/dev/sda2 none swap sw 0 0
/dev/sda3 / reiserfs notail,noatime 0 0
/dev/sda4 /tmp ext3 notail,noatime,nodev,nosuid,noexec,usrquota,grpquota 0 0
/dev/sda5 /var ext3 notail,noatime,nodev,usrquota,grpquota 0 0
/dev/sda6 /home ext3 notail,noatime,nodev,nosuid,usrquota,grpquota 0 0
/dev/sda7 /usr reiserfs notail,noatime,nodev,ro 0 0
/dev/cdroms/cdrom0 /mnt/cdrom iso9660 noauto,ro 0 0
proc /proc proc defaults 0 0
|
quotaを有効にしたい全てのパーティションのルートディレクトリに、
quota用のファイル(quota.userやquota.group)を置いてください。
Code Listing 6.4: quota用ファイルを作成 |
# touch /tmp/quota.user
# touch /tmp/quota.group
# chmod 600 /tmp/quota.user
# chmod 600 /tmp/quota.group
|
この作業はquotaを有効にした全てのパーティションで行う必要があります。
quota用のファイルを追加して設定を行ったら、
quotaの起動スクリプトをデフォルトのランレベルに追加しないといけません。
Code Listing 6.5: quotaをデフォルトのランレベルに追加 |
# rc-update add quota default
|
それから、以下の行を/etc/crontabに追加して、
週に一度quotaのチェックが実行されるようにします。
Code Listing 6.6: crontabにquotaのチェックを追加 |
0 3 * * 0 /sbin/quotacheck -avug.
|
マシンを再起動したら、今度はユーザーとグループに対してquotaの設定をしなくてはいけません。
edquota -u knとすれば$EDITORで設定されたエディタ(デフォルトではnano)が起動し、
knというユーザーに対してquotaの設定をできます。
edquota -gとすれば同じことをグループに対して行えます。
Code Listing 6.7: ユーザーkn用のquotaを設定 |
Quotas for user kn:
/dev/sda4: blocks in use: 2594, limits (soft = 5000, hard = 6500)
inodes in use: 356, limits (soft = 1000, hard = 1500)
|
詳細な情報はman edquotaかQuota mini howtoで見てください(訳注:日本語訳がhttp://www.linux.or.jp/JF/JFdocs/Quota/にあります)。
/etc/login.defs
たとえば2週間ごとにユーザーにパスワードを変更させたいなら、PASS_MAX_DAYSを14に、
PASS_WARN_AGEを7に設定すると良いでしょう。
パスワードを総当たり攻撃されてしまえば、どんなパスワードでも破られるのは時間の問題なので、
あなた自身も有効期限付きのパスワードを使うべきです。
LOG_OK_LOGINSもyesに設定しておくべきでしょう。
/etc/login.access
login.accessファイルもsys-apps/shadowパッケージの一部で、
ログインアクセスをコントロールするテーブルを提供します。
このテーブルは誰がログインできて誰がログインできないかを、ユーザー名、グループ名、ホスト名で指定するのに使います。
デフォルトの状態では、そのシステムのユーザーは全員ログインできるように設定されていて、
このファイルにはコメントとサンプルしか入っていません。
あなたがサーバやワークステーションのセキュリティを強化しようとしているかどうかに関わらず、
あなた(つまり、管理者)以外の人がコンソールにアクセスできないようにこのファイルを設定してください。
Note:
このファイルでの設定はrootには適用されません。
|
Code Listing 6.8: /etc/login.access |
-:ALL EXCEPT wheel sync:console
-:wheel:ALL EXCEPT LOCAL .gentoo.org
|
Important:
これらのオプションを設定するときには注意してください。
誤って設定してしまうと、rootでのアクセス権を持たない限りマシンにアクセスできなくなってしまいます。
|
Note:
SSHのデフォルトの設定では/bin/loginを実行しないようになっているため、
login.accessを設定してもSSHでのアクセスには適用されません。
/etc/ssh/sshd_configでUseLogin yesと設定すれば/bin/loginが実行されるようになるため、
login.accessでの設定が有効になります。
|
上の設定では、wheelグループのメンバーはローカルから、もしくはgentoo.orgドメイン経由でしかログインできないように設定しています。
多少神経質な設定になっていますが、後で後悔するより良いと思います。
7. ファイルのパーミッション
「誰でも読める」ということ
設定ファイルやパスワードに一般ユーザーがアクセスできるようにすべきではあません。
アタッカーはデータベースやWebサイトからパスワードを盗み、そのパスワードを使ってデータを読めないような状態にしたり、最悪の場合削除してしまったりできます。
だから、パーミッションを適切に設定することは大事なのです。
もし、あるファイルを使うのがrootだけならそのファイルのパーミッションを0600に設定し、
chownを使って適切なユーザーがそのファイルを所有するようにしてください。
「誰でも書き込める」、「同じグループのユーザーなら書き込める」ということ
Code Listing 7.1: 誰でも読み書きできてしまうファイルやディレクトリを探す |
# /usr/bin/find / -type f \( -perm -2 -o -perm -20 \) \
-exec ls -lg {} \; 2>/dev/null >writable.txt
# /usr/bin/find / -type d \( -perm -2 -o -perm -20 \) \
-exec ls -ldg {} \; 2>/dev/null >>writable.txt
|
上のコマンドを実行すると、同じグループのユーザーが書き込めたり誰でも書き込めたりするファイルのリストが、
パーミッション付きで膨大なリストになります。
リストされたパーミッションをチェックし、
/bin/chmod o-wを実行して誰でも書けるという状態を取り除いてください。
SUIDもしくはSGIDされたファイル
ファイルにSUIDビットやSGIDビットをセットすると、実際にそのファイルを実行するユーザーの権限ではなく、
そのファイルを所有しているユーザーやグループの権限で実行することができるようになります。
通常、これらのビットはrootではないとできない作業を行うために使用されます。
このようなファイルは(もしそのファイルにセキュリティホールがあれば)ローカル環境でroot権限を乗っ取られることにもなりかねません。
こういうSUIDビットやSGIDビットが立ったファイルは危険なため、
極力無効にしなくてはいけません。
そのファイルを使うことがないならchmod 0とするか、
そのファイルが含まれるパッケージをunmergeしてしまってください(qpkg -fとするとどのパッケージにファイルが含まれるのか調べられます。
qpkgコマンドがインストールされていないならemerge gentoolkitとしてインストールしてください)。
もしくは、単純にchmod -sとやってSUIDビットを落としても良いでしょう。
Code Listing 7.2: SUIDされたファイルの検索 |
# /usr/bin/find / -type f \( -perm -004000 -o -perm -002000 \) \
-exec ls -lg {} \; 2>/dev/null >suidfiles.txt
|
上のコマンドを実行すると、SUIDもしくはSGIDされたファイルがすべて表示されます。
Code Listing 7.3: SUIDされたバイナリの一覧 |
/bin/su
/bin/ping
/bin/mount
/bin/umount
/var/qmail/bin/qmail-queue
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/crontab
/usr/bin/chage
/usr/bin/expiry
/usr/bin/sperl5.6.1
/usr/bin/newgrp
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/procmail
/usr/bin/suidperl
/usr/lib/misc/pt_chown
/usr/sbin/unix_chkpwd
/usr/sbin/traceroute
/usr/sbin/pwdb_chkpwd
|
デフォルトの状態では、Gentoo Linuxにはそれほど多くのSUIDされたファイルは存在しませんが(何をインストールしたかによります)、
上のような感じでリスト化しておくと良いでしょう。
ほとんどのコマンドは一般ユーザーが使うようなものではなく、rootだけが使うべきものです。
ping、mount、umount、chfn、chsh、newgrp、
suidperl、pt_chown、tracerouteの各ファイルについては、
chmod -sを実行してSUIDビットをオフにしてください。
su、qmail-queue、unix_chkpwdについてはSUIDビットを落としてはいけません。
これらのファイルのSUIDビットを落としてしまうとsuできなくなったりメールが受けとれなくなったりします。
SUIDビットを落とすことで、一般ユーザーが(もちろんアタッカーも)これらのファイルを通じてroot権限を奪うことを防げます。
私のシステムに存在するSUIDビットの立ったファイルは、su、passwd、
gpasswd、qmail-queue、unix_chkpwd、そしてpwdb_chkpwdと、たったこれだけです。
もしあなたがXを使っているなら、XはSUIDビットが立ったファイルへのアクセスが必要なのでもう少しこういうファイルがあるかもしれません。
8. PAM (Pluggable Authentication Modules)
PAMはいろいろなプログラムの認証部分の機能を肩代わりしてくれる、共有ライブラリのセットです。
pamのUSEフラグはデフォルトで有効になっています。
Gentoo Linuxで用意されているPAMの設定はとてもよく出来たものですが、もちろん、いつだってこういうことは改善の余地があります。
まずはcracklibをインストールしてください(訳注:/usr/portage/profiles/default-x86-1.4/packagesによれば、
少くともx86用Gentoo Linux 1.4では、systemパッケージとしてデフォルトでインストールされるようです)。
Code Listing 8.1: cracklibをインストール |
# emerge cracklib
|
Code Listing 8.2: /etc/pam.d/passwd |
auth required pam_pwdb.so shadow nullok
account required pam_pwdb.so
password required pam_cracklib.so difok=3 retry=3 minlen=8 dcredit=2 ocredit=2
password required pam_pwdb.so md5 use_authtok
session required pam_pwdb.so
|
cracklibをインストールして上のように設定しておくと、
ユーザーは「最低8文字」「2文字以上の数字を含む」「2文字以上の記号を含む」「以前のパスワードと3文字以上違う文字を含む」というパスワードを設定しないといけなくなります。
こうしておけばユーザーは良いパスワードを利用することを迫られます(パスワードポリシー)。
詳細なオプションはPAMにあるドキュメントを参考にしてください。
Code Listing 8.3: /etc/pam.d/sshd |
auth required pam_pwdb.so nullok
auth required pam_shells.so
auth required pam_nologin.so
auth required pam_env.so
account required pam_pwdb.so
password required pam_cracklib.so difok=3 retry=3 minlen=8 dcredit=2 ocredit=2 use_authtok
password required pam_pwdb.so shadow md5
session required pam_pwdb.so
session required pam_limits.so
|
/etc/pam.dで個々に設定されていないサービスに対しては、
/etc/pam.d/otherのルールが適用されます。
デフォルトの設定では当然すべて拒否されるようになっています。
ただ、私はログをたくさん溜めるのが好きなので、
pam_warn.soを追加することにしています。
PAMに関する最後の設定は/etc/security/limits.confで制御されるpam_limitsです。
これに関しては/etc/security/limits.confの節を参考にしてください。
Code Listing 8.4: /etc/pam.d/other |
auth required pam_deny.so
auth required pam_warn.so
account required pam_deny.so
account required pam_warn.so
password required pam_deny.so
password required pam_warn.so
session required pam_deny.so
session required pam_warn.so
|
9. TCP Wrappers
通常、各サービスへのアクセスをコントロールするにはinetd(Gentooには含まれていません)を使用しますが、
xinetdなどを使うことで同様のことができます。
Note:
各サービスは(xinetdの設定内で)tcpdから起動されている必要があります。
詳しくはxinetdの章を見てください。
|
Code Listing 9.1: /etc/hosts.deny |
ALL:PARANOID
|
Code Listing 9.2: /etc/hosts.allow |
ALL: LOCAL @wheel
time: LOCAL, .gentoo.org
|
見てわかるとおり/etc/login.accessのフォーマットと良く似ています。
tcpdはすべてのサービスに対して使えるというわけではなく、
またそれら個々のサービスはそれぞれ、セキュリティ的には別次元で動作しています(訳注:たとえばechoサービスとtelnetサービスでは、考慮すべきセキュリティが違うということだと思います)。
これらの設定はTCP Wrappersを使用するサービスでのみ有効になります。
サービスにアクセスがあったときに特定のコマンドを起動させることも可能です(ダイアルアップユーザーの中継を有効にした場合に使えるでしょう)。
ただし人間は問題を解決しようとしてそれ以上の問題を作ってしまいがちなので、そういうことはしない方が良いでしょう。
たとえば。denyに設定したルールに誰かが引っかかった場合、そのたびにメールを送るスクリプトを起動するように設定したとします。
この場合アタッカーはあなたのマシンのdenyルールに引っかかり続けることで、
簡単にDoS攻撃をすることができます。
こうなってしまうとI/O負荷は大きくなってしまうやらメールは溜まってしまうやらでもう大変です。
そういう設定はしないようにしましょうね! 詳しくはman 5 hosts_accessを参照してください。
10. カーネルのセキュリティ
使わない機能は削る
カーネル構築の基本原則は、必要としないものは全て削除することです。そ
うすれば小さなカーネルを構築できますし、
ドライバや他の機能の中に眠っている脆弱性も削ることができます。
それから、できればローダブルモジュールのサポートもオフにしてください。
ローダブルモジュールをサポートしないようにしていてもモジュールを追加することは可能ですが(rootkitなど)、
カーネルモジュールを経由してrootkitを仕込もうとする普通のアタッカーににとっては少々荷が重いでしょう。
/proc (カーネル用のフラグ)
/procファイルシステムやsysctlを使用することで、
多くのカーネルパラメータを変更することができます。
オン・ザ・フライで動的にカーネルのパラメータや設定を変更するためには、
カーネルでCONFIG_SYSCTLが定義されている必要があります。
2.4系のカーネルではデフォルトで定義されています。
Code Listing 10.1: pingパケットを無視 |
# /bin/echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_all
|
こうしておくと、すべてのタイプ0のICMPパケット、つまりすべてのpingを無視するようにカーネルを設定できます。
なぜこういう設定をするかというと、ICMPメッセージを載せたIPのパケットには、
あなたが思っているよりずっと多くの情報が含まれているからです。
管理者はpingを診断ツールとして使うのでpingが通らないと文句を言ってくると思います。
でも外の人がpingを打てるようにしておく理由はないですよね? ただ、内部の人がpingを使えると有用な場合があるのも事実です。
そういう場合はファイアーウォールでタイプ0のICMPパケットを無効にすれば良いです。
Code Listing 10.2: ブロードキャストpingを無視 |
# /bin/echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
|
ブロードキャスト・メッセージに応答しないようにして、Smurf攻撃から身を守ります。
Smurf攻撃はタイプ0のICMPメッセージ(ping)を、あるネットワークのブロードキャストアドレス宛てに送ることで実現します。
通常、アタッカーは偽造した送信元アドレスになりすましてこの攻撃を行います。
対象ネットワーク上のすべてのコンピュータがpingのメッセージに応答することになり、
その結果なりすましに使用されたホストのネットワーク負荷が膨大なものになってしまうわけです。
Code Listing 10.3: ソースルーティングされたパケットを使えないように |
# /bin/echo "0" > /proc/sys/net/ipv4/conf/all/accept_source_route
|
ソースルーティングされたパケットは受け付けないようにしましょう。
ソースルーティングされたパケットを使うことで、本当は全然別のところからのトラフィックを、
あたかもあなたの内部ネットワークからやってきたかのように偽装することができます。
アタッカーはあなたのネットワークを乗っ取れるのです。
ソースルーティングが本来あるべき形で使われることは稀です。使えないようにしておきましょう。
Code Listing 10.4: リダイレクトに応えないように |
# /bin/echo "0" > /proc/sys/net/ipv4/conf/all/accept_redirects
|
ICMPのリダイレクト要求を拒否します。ICMPリダイレクトでルーテイングテーブルを変更することもできます。
きっとイヤなところにルーティング先を変更されるんでしょう。
Code Listing 10.5: 不正なエラーメッセージに対する防御 |
# /bin/echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
|
嘘っぱちのエラーメッセージ応答に対する防御を有効にします。
Code Listing 10.6: リバースパスをフィルタできるように |
# for i in /proc/sys/net/ipv4/conf/*; do
/bin/echo "1" > $i/rp_filter
done
|
Note:
IPフォーワーディングをオンにしていれば、ここでやることと同じ結果になります。
|
リバースパスをフィルタできるようにします。
こうしておくと、送信元アドレスのルーティングテーブルエントリがそのパケットの到着したNICと合致しないようなパケットを自動的に弾くことができるので、
入ってくるパケットが正当な送信元アドレスを持つパケットだと保証することができます。
この設定をしておくとIPの偽造を防ぐことができるので、セキュリティ的なアドバンテージになります。
Warning:
ただしこの設定は、非対称なルーティング(あなたがあるホストに送るパケットが通る経路と、
そのホストからあなた宛てに来るパケットの通る経路が違う)を使用しているネットワークで問題を起こす可能性があります。
また、複数のNICを差して複数のIPアドレスを持っているルータではないホストでも、
同様に問題が起こる可能性があります。
|
Code Listing 10.7: 偽造/ソースルーティング/リダイレクト、といったパケットをすべて記録 |
# /bin/echo "1" > /proc/sys/net/ipv4/conf/all/log_martians
|
偽造されたパケット、ソースルーティングされたパケット、そしてリダイレクトされたパケットを記録します。
Code Listing 10.8: IPフォーワーディングを無効に |
# /bin/echo "0" > /proc/sys/net/ipv4/ip_forward
|
IPフォーワーディングをちゃんと無効にしておきます。
マルチホームホストでないならこの機能は不要です。
これら全ての設定はマシンの再起動時にリセットされてしまいます。
ですから、下記のスクリプトをrc-update add procparam defaultで必要なランレベルに追加して、
chmod +x /etc/init.d/procparamで実行できるようにしておくことを勧めます。
Code Listing 10.9: /etc/init.d/procparam |
#!/sbin/runscript
depend() {
use checkroot
}
start() {
ebegin "Setting /proc options."
/bin/echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_all
/bin/echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
/bin/echo "0" > /proc/sys/net/ipv4/conf/all/accept_source_route
/bin/echo "0" > /proc/sys/net/ipv4/conf/all/accept_redirects
/bin/echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
for i in /proc/sys/net/ipv4/conf/*; do
/bin/echo "1" > $i/rp_filter
done
/bin/echo "1" > /proc/sys/net/ipv4/conf/all/log_martians
/bin/echo "0" > /proc/sys/net/ipv4/ip_forward
eend 0
}
|
Grsecurity
Grsecurityが提供しているパッチはGentooの各カーネルソースに標準で適用されていますが、
デフォルトではオフになっています。
以下のようにすれば使用可能です:
まず普通にカーネルの構築をします。次にGrsecurityオプションを選んでCustomizedを選択し、以下のオプションを有効にしてください:
- Buffer Overflow Protection
-
- Openwall non-executable stack
- GCC trampoline support
- Filesystem Protections
-
- Proc restrictions
- Linking restrictions
- Secure file descriptors
- Chroot jail restrictions (このオプション以下にあるオプションも全て有効に)
- Kernel Auditing
-
- Log execs within chroot
- (Un)Mount logging
- Signal logging
- Fork failure logging
- Log set*ids to root
- Time change logging
- Executable Protections
-
- Dmesg restriction
- Randomized PIDs
-
Altered default IPC permissions
(正常に動いているプログラムが問題を起こす可能性もあります)
- Restricted ptrace
- Network Protections
-
- Randomized IP IDs
- Randomized TCP source ports
- Altered Ping IDs.
- Randomized TTL
- Miscellaneous Features
-
-
BSD-style coredumps (core.namedのような名前のコアファイルを作ります)
以上の設定が終わったらコンパイルして、セキュリティが高められたカーネルをインストールしてください。
Kerneli
Kerneliは、
既存のカーネルに暗号化機能を追加するパッチです。
このパッチを適用することで、「cryptographic ciphers」、「digest algorithms」、
「cryptographic loop filters」といった新しいオプションが現れます。
Warning:
Kerneliのパッチはまだ最新のカーネルに対応した安定版がありません。
利用する際は注意してください。
|
その他のカーネルパッチ
ま、きっともっとあると思うんですけどね。
11. 各サービスをセキュアに
xinetdを使う
xinetdはinetd(Gentooには入ってません)に取ってかわるもので、インターネットサービスのデーモンです。
xinetdには接続元ホストのアドレスやアクセス時間に基づいてアクセス制限する機能があります。
またxinetdは、「サーバがスタートした時間」、「接続元ホストのアドレス」、
「接続したユーザー名」、「サーバが起動していた時間」、「要求されたアクション」など、
さまざまなログを取ることができます。
他の全てのサービスと同様、デフォルトで良い設定になっていることが重要です。
しかしxinetdはroot権限で動作し、
あなたがあまり動作について詳しくないであろうプロトコルをサポートしているので、使わない方が良いと思います。
ただ、とにかく使ってみたいという場合は以下のようにすることでセキュアにできると思います:
Code Listing 11.1: xinetdのインストール |
# emerge xinetd tcp-wrappers
|
で、設定ファイルを編集します:
Code Listing 11.2: /etc/xinetd.conf |
defaults
{
only_from = localhost
instances = 10
log_type = SYSLOG authpriv info
log_on_success = HOST PID
log_on_failure = HOST
cps = 25 30
}
# 以下はpserver(cvs)をxinetd経由で起動する設定です:
# 最高10インスタンス(1度に接続できるのは10接続だけ)
# pserverはTCPでのみ応答する
# cvsというユーザーでこのサービスが動作するようにする
# インターフェースをひとつのIPに固定
# 10.0.0.*というアドレスからのみ接続できる
# 開発者がcvsを使えるのは午前8時から午後5時の間だけ
# TCP Wrappersを使う(/etc/hosts.allowと
# /etc/hosts.denyでアクセス制限をします)
# マシンのmax_load(訳注:1分間のロードアベレージ)を1.0に設定
# disableフラグはすでにデフォルトでnoになっていますが、
# 実際にdisableにしたいときのためにオプションを付けておくのが好ましいです
service cvspserver
{
socket_type = stream
protocol = tcp
instances = 10
protocol = tcp
wait = no
user = cvs
bind = 10.0.0.2
only_from = 10.0.0.0
access_times = 8:00-17:00
server = /usr/sbin/tcpd
server_args = /usr/bin/cvs --allow-root=/mnt/cvsdisk/cvsroot pserver
max_load = 1.0
log_on_failure += RECORD
disable = no
}
|
詳しくはman 5 xinetd.confを参照してください。
SSH
OpenSSHをセキュアにするために必要な設定は、公開鍵認証を使った、
より強い認証方法を使用するようにするだけです。
あまりにも多くのサイト(http://www.sourceforge.netやhttp://www.php.net、)が、
パスワードの漏洩や貧弱なパスワードのために侵入を経験しています。
Code Listing 11.3: /etc/ssh/sshd_config |
#バージョン2のプロトコルのみ有効に
Protocol 2
#直接rootでアクセスするのは禁止
PermitRootLogin no
#RSA公開鍵認証を有効に
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
#.rhostファイルや通常のパスワード認証を無効に
RhostsAuthentication no
PasswordAuthentication no
PermitEmptyPasswords no
AllowHosts *.gentoo.org
#wheelグループかadminグループに所属しているユーザーにのみアクセス権を与える
AllowGroups wheel admin
#上記グループに所属している人のうち、knとbsのみ実際にアクセス可能
AllowUsers kn bs
#ログのレベルを指定
SyslogFacility AUTH
LogLevel INFO
#IPアドレスを割り当てる
ListenAddress 127.0.0.1
|
あとはあなたのユーザー全員に、
以下のコマンドを使って(そのユーザーがサーバにログインしたいマシンで)鍵を作ってもらうだけです。
Code Listing 11.4: RSA形式の鍵ペアを作成 |
# /usr/bin/ssh-keygen -t rsa
|
パスフレーズを入力します。
Code Listing 11.5: ssh-keygenの出力 |
Generating public/private rsa key pair.
Enter file in which to save the key (/home/kn/.ssh/id_rsa):[enterを押してください]
Created directory '/home/kn/.ssh'.
Enter passphrase (empty for no passphrase): [パスフレーズを入力します]
Enter same passphrase again: [再度パスフレーズを入力します]
Your identification has been saved in /home/kn/.ssh/id_rsa.
Your public key has been saved in /home/kn/.ssh/id_rsa.pub.
The key fingerprint is:
07:24:a9:12:7f:83:7e:af:b8:1f:89:a3:48:29:e2:a4 kn@knielsen
|
こうするとあなたの~/.ssh/ディレクトリ内に、
id_rsaとid_rsa.pubというふたつのファイルが追加されます。
id_rsaというファイルはあなたの秘密鍵なので他の人にアクセスされないようにしてください。
もうひとつのid_rsa.pubはアクセスしたい各サーバに置いておきます。
鍵(訳注:公開鍵(id_rsa.pub)の方です)をサーバにあるホームディレクトリの~/.ssh/authorized_keysに追加すれば、
そのサーバにログインすることができるでしょう。
今後、あなたのユーザーはこの秘密鍵をちゃんと保管しなくてはいけません。
いつも持ち歩くメディアに入れておくか自分たちのワークステーョンのみに保存しておきます(ということをパスワードのポリシーに追加しておきましょう)。
詳細な情報はOpenSSHのサイト(訳注:日本語版はhttp://www.openssh.org/ja/)にあります。
X
XFreeは、デフォルトではXサーバとして動作するように設定されています。
Xは暗号化されていないTCP接続を使用してXクライアントの接続を待っているので危険です。
Important:
Xサーバの機能を必要としないなら無効にしておきましょう!
|
ただし、もしあなたのワークステーションをXサーバにしておく必要があるのなら、
/usr/X11R6/bin/xhostコマンドは注意して使ってください。
このコマンドを使うと、他のホスト上のXクライアントがあなたのディスプレイに接続できるようになります。
他のマシンからXアプリケーションを使う必要があってネットワーク越しでしか使用できない場合、このコマンドは便利だと思います。
このコマンドは/usr/X11R6/bin/xhost +ホスト名という風に使います。
Warning:
xhost +という機能(訳注:ホスト名なしで+のみ)は絶対に使わないようにしてください!
こうすると誰でもあなたのXをコントロールすことができるようになります。
アタッカーがあなたのXへアクセスできれば、キーストロークを記録してあなたのデスクトップを操作できます。
このコマンドを使うときは必ずホストを指定するようにしてください。
|
もっとセキュアにする方法は、startx -- -nolisten tcpとすることでTCPでの接続を無効にするか、
もしくは設定を変更して最初からこの機能を無効にしてしまうことです。
Code Listing 11.6: /usr/X11R6/bin/startx |
defaultserverargs="-nolisten tcp"
|
新しいバージョンのXFreeをemergeするときにstartxが上書きされないようにするには、
このファイルを保護しなくてはいけません。
以下の行を/etc/make.confに追加してください:
Code Listing 11.7: /etc/make.conf |
CONFIG_PROTECT_MASK="/usr/X11R6/bin/startx"
|
グラフィカル・ログインを利用しているなら、ちょっと違うことをしないといけません。
gdm(Gnome Display Manager)の場合
Code Listing 11.8: /etc/X11/gdm/gdm.conf |
[server-Standard]
command=/usr/X11R6/bin/X -nolisten tcp
|
xdm(X Display Manager)とkdm(KDE Display Manager)の場合
Code Listing 11.9: /etc/X11/xdm/Xservers |
:0 local /usr/bin/X11/X -nolisten tcp
|
FTP
基本的に、FTP(ファイル転送プロトコル)を使うというのはいただけません。
データを暗号化しないし、待ち受けポートをふたつも使うし(通常は20番と21番)、
アタッカーが(Warez交換のために)探してる匿名ログインをサポートしてるし。
FTPのプロトコルにはいくつかセキュリティ上の問題があるので、
できれば代わりにsftpかHTTPを使うべきです。
それが無理なら、できるだけセキュアにしておいて備えをしておきましょう。
Pure-FTPd
Pure-FTPdはTrollFTPDから枝分かれしたソフトです。
Frank Denis氏により、セキュリティ上の理由で変更や機能が追加されています。
AUTHオプションを有効にしてバーチャルユーザー(システムアカウントは使わないこと)を使用しましょう。
-lpuredb:/etc/pureftpd.pdbオプションを設定し、
/usr/bin/pure-pwにユーザーを指定しておきます。
Code Listing 11.10: /etc/conf.d/pure-ftpd |
AUTH="-lpuredb:/etc/pureftpd.pdb"
## その他もろもろ ##
MISC_OTHER="-A -E -X -U 177:077 -d -4 -L100:5 -I 15"
|
MISC_OTHERを設定して、匿名ユーザーを禁止したり(-E)、
全員がchrootするようにしたり(-A)「.(ドット)」で始まるファイルの読み書きを禁止したり(-X)、
アイドルタイムの上限を設定したり(-I)、再帰処理を制限したり(-L)、
ちゃんとしたumaskを使用したりするようにしましょう。
Warning:
-wオプションと-Wオプションは絶対に使っちゃダメです!
Warezなサイトを作りたいなら、ここでこのガイド読むの止めちゃてください!
|
http://www.pureftpd.orgに行けばドキュメントが見つかります。
ProFTPD
ProFTPDにはいくつかセキュリティ上の問題がありましたが、そのほとんどは解決された模様です。
いくつかセキュリティを高める設定をしておきます:
Code Listing 11.11: /etc/proftpd/proftpd.conf |
ServerName "My ftp daemon"
#サーバを特定できる情報は見せない
ServerIdent on "Go away"
#バーチャルユーザーの作成をやりやすく
RequireValidShell off
#システムとは別のユーザー/グループのファイルを使用する(passwdファイルはcryptフォーマットです)
AuthUserFile "/etc/proftpd/passwd"
AuthGroupFile "/etc/proftpd/group"
# パーミッション関連
Umask 077
# タイムアウトとリソースの制限
MaxInstances 30
MaxClients 10 "Only 10 connections allowed"
MaxClientsPerHost 1 "You have already logged on once"
MaxClientsPerUser 1 "You have already logged on once"
TimeoutStalled 10
TimeoutNoTransfer 20
TimeoutLogin 20
#全員chrootする
DefaultRoot ~
#rootとして起動しない
User nobody
Group nogroup
#全転送を記録する
TransferLog /var/log/transferlog
#グロブの問題(訳注:DoS攻撃が可能な問題のことだと思います)に対処
DenyFilter \*.*/
|
http://www.proftpd.orgに行けばドキュメントが見つかります(訳注:少し古いですがhttp://www.infoscience.co.jp/technical/proftpd/に設定内容に関する日本語訳があります)。
vsftpd
vsftpd(とてもセキュアなftpという意味)は小さなFTPデーモンで、
デフォルトの設定も良い感じです。
vsftpdはシンプルで、Pure-FTPdやProFTPDが持っているような多くの機能(バーチャルユーザーなど)はありません。
Code Listing 11.12: /etc/vsftpd |
anonymous_enable=NO
local_enable=YES
#リードオンリー
write_enable=NO
#転送ログを取れるようにする
xferlog_std_format=YES
idle_session_timeout=20
data_connection_timeout=20
nopriv_user=nobody
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chrootlist
ls_recurse_enable=NO
|
見てのとおり個々にパーミッションを設定したりchrootしたりといったことはできません。
が、匿名ユーザー用の設定となると、とても良い感じになります。
時にはアノニマス(匿名)FTPサーバを用意するのはとても良いことですが(オープンソースなものを共有したり)、
vsftpdはこういったとき、本当にいい仕事をします。
Apache
Apache(1.3.26)はかなり親切な設定ファイルを持つようになりました。
ただし多少の作業を行うともっと良くなります。
ひとつのアドレスでだけ待ち受けるようにしたり、余分な情報を漏らさないようにしたり。
設定ファイルに追加するべきものは・・・:
/etc/make.confでsslを無効にしていないようであれば、
Apacheをインストールする前にSSLを有効にしたサーバを作れるようにしておきましょう。
以下の行を追加しておけば大丈夫です。
Code Listing 11.13: /etc/conf.d/apache |
HTTPD_OPTS="-D SSL"
|
(訳注:実は大丈夫ではありません。まず、Apacheをインストールした後、emerge
mod_sslでmod_sslをインストールする必要があります。その後、
/etc/conf.d/apacheを編集してAPACHE_OPTS="-D SSL"を追加してください。
また2002.11.07時点でのApacheのebuildは1.3.27-r1ですが、
そもそもUSEにsslが含まれているか見ていないようです)
(訳注その2:2003.11.02現在ではApacheのバージョンは2.0.48が最新です。
このため別途mod_ssslをインストールする必要はなくなりました。
ただしここに書かれている設定内容は微妙に実際の設定内容と違うので、
設定ファイルのコメント等を参考に適切な設定を行ってください)
Code Listing 11.14: /etc/apache/conf/apache.conf |
#特定のIPアドレスでのみ待ち受けるようにする
Listen 127.0.0.1
BindAddress 127.0.0.1
#nobodyとnogroupを使うのはよろしくありません
#他の全てのサービスはrootでは走っていませんし
#(apacheというグループに所属したapacheというユーザーを追加しましょう)
User apache
Group apache
#Apacheのバージョンがバレないようにする
ServerSignature Off
ServerTokens min
|
Apacheは--enable-shared=maxと--enable-module=allが指定された状態でコンパイルされます。
デフォルトでは全てのモジュールが使えるようになっているので、
使わないモジュールは全て、
LoadModuleセクション(LoadModuleとAddModule)でコメントアウトしておきましょう。
/etc/init.d/apache restartを実行してサービスを再起動してください。
に行けばドキュメントが見つかります(訳注:http://www.apache.jp/に日本語の情報があります)。
qmail
qmailは最もセキュアなメールサーバだと見なされています。
qmailはセキュリティを念頭に(ま、ちょっとやり過ぎなぐらい)書かれています。
デフォルトではメールを転送しませんし、1996年以降セキュリティホールは見つかっていません。
さ、emerge qmailで設定しましょう!
BIND
Important:
BINDは、軽々しく扱うにはちょっと困るようなひどいセキュリティの歴史で知られています。
他の全てのサービスと同様、絶対にrootとして動作させてはダメです。
ですから、このサービスのデフォルト設定を変更しないでください。
|
Internet Software Consortiumに行けばドキュメントが見つかりますし、
doc/armにBIND 9の管理者リファレンスマニュアルがあります(訳注:
日本語で読める情報としてはhttp://www.linux.or.jp/JF/JFdocs/DNS-HOWTO.htmlが参考になると思います)。
djbdns
djbdnsについては、実際のところあまり言うことがありません。
あえて言うなら、作者がdjbdnsがセキュアであることに関して、喜んでお金をかけてるという点でしょうか。
というわけなのでhttp://www.djbdns.org/に行って試してみてください(訳注:日本語で読める情報がhttp://djbdns.qmail.jp/にあります)。
BIND 9とは随分やり方が違いますが、そのうちコツが分かると思います。
Samba
SambaはマイクロソフトやNovellのネットワークとファイル共有をできるプロトコルです。
ですから、インターネット上で使ってはいけません。
とはいえ、それでも、セキュアにすることは必要です。
Code Listing 11.15: /etc/samba/smb.conf |
[global]
#待ち受けるインターフェースを指定
interfaces = eth0 10.0.0.1/32
#ちゃんと暗号化パスワードを使う
encrypt passwords = yes
directory security mask = 0700
#10.0.0.*からの通信のみ許可
hosts allow = 10.0.0.
#ユーザー認証を有効に
#(shareモードで使ってはダメです)
security = user
#特権アカウントは接続禁止
invalid users = root @wheel
#smbが共有の際に表示する最大サイズ(サイズを制限するわけではない)
max disk size = 102400
#パスワードポリシーをちゃんとする
min password length = 8
null passwords = no
#PAMを使う(PAMのサポートが追加されてるなら)
obey pam restrictions = yes
pam password change = yes
|
共有ごとにパーミッションがきちんと設定されていることを確認してください。
また、ドキュメントも読んでください(訳注:http://www.samba.gr.jp/でドキュメントの翻訳が行われています)。
では、Sambaサーバを再起動して、
このサービスにアクセスするユーザーを追加してください。
/usr/bin/smbpasswdを-aオプション付きで実行すれば大丈夫です。
chroot環境、もしくはバーチャルサーバ
サービスをchrootした状態で提供すれば、アクセスされても良い情報にだけアクセスできるように、
そしてrootアクセスにつながるようなアクセス権(や情報)の取得をできないように、
サービス(やユーザー)の環境を制限することができます。
サービスをroot以外のユーザー(nobody、apache、namedなど)の権限で動作させておけば、
アタッカーはそのユーザーに権限があるファイルにしかアクセスできません。
ということは、たとえそのサービスにセキュリティ上の問題があっても、アタッカーはroot権限を得ることはできないということです。
Pure-FTPdやBINDなどのいくつかのサービスはchrootの機能を持っていますが、
そうではないサービスもあります。
使おうとしているサービスがchroot機能を持っているなら使いましょう。
しかし、そうではない場合は、自分でなんとかしないといけません。
では、とりあえずのchrootの理解のために、どうやってchroot環境を作るのかご覧に入れましょう。
BASHでやってみます(わかりやすいように)。
/chrootという名前のディレクトリを作ります(mkdir chroot)。
そして、BASHがどんな共有ライブラリとダイナミックリンクしてコンパイルされているか調べます(-static付きでコンパイルされているならこのステップは不要です)。
以下のコマンドでBASHが使っているライブラリのリストが得られます。
Code Listing 11.16: 使っているライブラリのリストを得る |
# ldd /bin/bash
libncurses.so.5 => /lib/libncurses.so.5 (0x4001b000)
libdl.so.2 => /lib/libdl.so.2 (0x40060000)
libc.so.6 => /lib/libc.so.6 (0x40063000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
|
では、BASHのための環境を作りましょう。
Code Listing 11.17: BASHのためのchroot環境を作成 |
# mkdir /chroot/bash
# mkdir /chroot/bash/bin
# mkdir /chroot/bash/lib
|
次にBASHが使用しているファイル(/libの中のもの)をchrootしたlibにコピーし、
BASH自身を同じくchrootしたbinディレクトリにコピーします。
こうすると、多少使えない機能はありますが、バッチリ同じ環境ができあがります。
コピーが終わったら次のようにしてください──chroot /chroot/bash。
/ディレクトリにいるというプロンプトが返ってきたら成功です!
うまくいかないときは、どのファイルが足りないか教えてくれるハズです。
共有ライブラリの中にはお互いに依存しあっているものもあります。
chroot環境の中ではecho以外は何も動作しないことに気がつくと思います(訳注:echo以外でも、BASHの組み込みコマンドなら動作します)。
これはchroot環境の外にあるコマンドを何も使えないので、
BASHとechoしか機能として組み込まれていないからです。
基本的には、こういう風にすれば他のサービスでもchroot環境を作ることができます。
BASHとの違いは、デバイスファイルや/etc内にある設定ファイルを必要とすることがままあることです。
とりあえずそれらをchroot環境内にコピー(デバイスファイルはcp -aでコピーできます)して、
起動スクリプトを編集してサービスが実行される前にchrootを使うように変更してください。
あるサービスに関して、どのデバイスファイルや設定ファイルが必要なのか見極めるのはとても難しいことです。
こういうときはstraceコマンドが便利です。
使いたいサービスを/usr/bin/strace bashという風に起動して、openやreadやstat、はたまたconnectしてる様子を観察してください。
どんなファイルをコピーすれば良いかの糸口を示してくれるでしょう。
とはいいつつも、だいたいの場合は、passwdファイル(そのサービスで使わないユーザーは削除してください。
もちろん編集するのはコピーです)と/dev/zero、/dev/log、
そして/dev/randomがあれば大丈夫でしょう。
セキュアな環境を作るもうひとつの方法は、バーチャルサーバ環境を使うことです。
これは既存のLinuxをコピーし、バーチャルモードで起動します。
つまり、もしサーバが乗っ取られてもそれは単にバーチャルサーバが乗っ取られたということに過ぎず、
実環境が乗っ取られることにはなりません。
バーチャルサーバの例:
12. ファイアーウォール
ファイアーウォールというもの
よく、ファイアーウォールがあればセキュリティは完璧だと思っている人がいますが、
それは間違っています。ファイアーウォールの設定を間違っていると、
ファイアーウォールがない場合よりもセキュリティ上の問題が大きくなる場合がほとんどです。
ファイアーウォールもソフトウエアのひとつなので、他のいろいろなソフトウエアと同様の扱い方をする必要があります。
ファイアーウォールにもバグ(要するにセキュリティホール)はありえるのですから。
なので、実際に導入する前に考えましょう! 本当にファイアーウォールが必要ですか?
必要だと思うのなら、どういう風に動作すべきか、それはどんなファイアーウォールか、
誰が操作をするのか、ポリシーに書き加えることを考えなくてはいけません。でも、とりあえずまず、このガイドを読んでください。
ファイアーウォールにはふたつの用途があります:
- ユーザー(ワームやアタッカー)が入って来ないようにする
- ユーザー(従業員や子供)が出て行かないようにする
基本的に、ファイアーウォールは3種類に分けられます:
- パケットフィルタ
- サーキットリレー
- アプリケーションゲートウェイ
ファイアーウォールを動かすマシンでは他のサービスを動かしてはいけません(動かすとしてもsshdだけです)。
マシンはこのガイドが推奨するやり方でセキュアにしてください。
パケットフィルタ
すべてのネットワークトラフィックはパケットの形を取ります。
大きなトラフィックは扱いやすいように小さなパケットに分けられ、
目的の場所に届いてから再度組み立てられます。
全てのパケットには、どのように、そしてどこにパケットが届けられるべきかの情報が含まれています。
これらの情報こそ、まさにファイアーウォールが利用するものです。フィルタリングは以下に基づいて行われます:
- 送信元/送信先IPアドレスに基づいた許可または禁止
- 送信元/送信先ポートに基づいた許可または禁止
- 使用されているプロトコルに基づいた許可または禁止
- 特定のプロトコルに含まれるフラグに基づいた許可または禁止
基本的にフィルタリングはパケットのヘッダ情報にのみ基づき行われ、
パケットの中身には一切関知しません。
短所:
-
パケット中のアドレスの情報は虚偽のものだったり、送信元により、
いわゆる偽造されたものだったりする
-
許可されたパケットの中には、
アタッカーがサービスやファイアーウォールにある既知のバグを利用するための、
データやリクエストが含まれている可能性がある
- 一般的にSingle Point of Failureである(訳注:つまり「蟻の穴から堤も崩れる」ということが往々にしてある、ということ)
長所:
- 簡単なので実装が容易
-
実際にアタックされる前にその徴候に対して警告を出すことが可能
(例:ポートスキャンの検知)
- SYNアタックをうまく防げる
Linuxで利用されているパケットフィルタの例:
サーキットリレー
サーキットレベルゲートウェイとも呼ばれますが、
データが実際にやり取りされる前にコネクションの妥当性をチェックすることができるファイアーウォールです。
これはつまり、パケットの許可/禁止の決定は単純にパットのヘッダに基づいて行うものの、
そのコネクションが妥当なものかどうかは、セッションが確立されデータが交換される前の段階で、
事前に設定されたルールに基づいて決定されるということです。フィルタリングは以下に基づいて行われます:
- 送信元/送信先アドレス
- 送信元/送信先ポート
- 時刻
- プロトコル
- ユーザー
- パスワード
全てのトラフィックは認可され、点検されていて、不要なトラフィックは破棄することができます。
短所:
-
トランスポート層で動作し、実際に通信処理を提供するためには、
事実上プログラムを修正する必要がある場合もある
アプリケーションゲートウェイ
アプリケーションレベルゲートウェイはアプリケーションのプロクシであり、
クライアントに代わってリモートのシステムとデータをやり取りします。
アプリケーションゲートウェイを利用することで、DMZ(De-Militarized Zone、非武装地帯:ファイアーウォール越しに到達することのできる、
プライベートネットワークの一角)やファイアーウォールの背後から、
実際には外側と接続することなしに外部とアクセスすることができます。フィルタリングは以下に基づいて行われます:
- 送信元/送信先IPアドレスに基づく許可/禁止
- パケットの内容
- ファイルの種類や拡張子によるアクセス制限
長所:
- ファイルをキャッシュできるのでネットワークのパフォーマンスを向上できる
- 全てのコネクションに対して詳細なログを取ることが可能
- 完全に拡張可能(プロクシサーバの中にはキャッシュされたデータを「共有」することが可能なものもある)
- 外側と直接には通信しない
- その場でパケットの中身を変更することも可能
短所:
アプリケーションゲートウェイはrootとして動作させる必要もなければ、
ゲートウェイの背後にあるホストはインターネットから直接到達不可能なので、
最もセキュアな解決法だと見なされています。
フリーなアプリケーションゲートウェイの例:
iptables
iptablesを動作させるためには、カーネルでiptablesが使えるようになっていないといけません。
私はiptablesをモジュールとして追加し(iptablesのコマンドは必要なときに呼び出されます)、
カーネルを再コンパイルしました。
iptables用にどうカーネルを設定すれば良いかについてもっと知りたい場合は、
Iptables
Tutorial Chapter 2: Preparationsをどうぞ。カーネルをコンパイルしたあとは(もしくはコンパイルしている最中に)、
iptablesのコマンドを追加してください。
単にemerge iptablesとすれば動くでしょう。
では、iptables -Lとしてiptablesが動作しているか確認してください。
失敗するようなら何かが間違っているわけで、再度設定をチェックする必要があります。
iptablesはLinux 2.4系カーネルの、新しくて非常に進化したパケットフィルタです。
Linux 2.2系カーネルで利用されていた、以前のipchainsパケットフィルタの後継にあたります。
大きな改良点としては、iptablesではステートフルなパケットフィルタリングが可能だという点が挙げられます。
ステートフルなパケットフィルタリングを使えば、
確立状態になったそれぞれのTCPコネクションを追跡し続けることができます。
TCPコネクションはパケットの集合によって成り立っています。
それぞれのパケットには、送信元アドレス、送信先アドレス、そしてシーケンス番号が含まれており、
このおかげでそれぞれのパケットは再構築することが可能で、データを忘れてしまったりしません。
UDPがコネクションレスなプロトコルであるのと対照的に、TCPはコネクション型のプロトコルです。
TCPパケットのヘッダを解析することで、ステートフル・パケットフィルタは、
受信したTCPパケットがすでに確立したコネクションの一部なのかどうか判断することが可能で、
また、そのパケットを許可するか拒否するか決定することができます。
ステートレスなパケットフィルタを相手にする場合、
TCPのパケットヘッダに細工をして本来拒否されるべきパケットを許可されるよう、パケットフィルタを騙すことができます。
TCPヘッダのSYNフラグ等を細工するとこのようなことが可能なのです。
ステートフルなパケットフィルタの場合は、
こういう、既に確立しているコネクションの一部ではないパケットを拒否することが可能です。
このため「ステルススキャン」に遭ってしまう可能性もなくなります。
なぜなら、この手のスキャンのパケットは、確立したコネクションの一部ではないからです。
iptablesには他にもNAT(Network Address Translation)やレートリミットのような機能もあります。
レートリミット機能は、
SYNアタックのような特定のDoS攻撃(サービス拒否攻撃)を防ぐにはもってこいです。
TCPの接続は、いわゆる3ウェイハンドシェイクによって確立されます。
TCPの接続を確立しようとする場合、クライアントからサーバへ、
SYNフラグがセットされたパケットが送られます。
SYNパケットを受信すると、サーバはクライアントへSYN+ACKパケットを返します。
SYN+ACKパケットを受け取ったクライアントは、3番目のパケットになるACKパケットを送り、
このパケットが事実上接続の証明書のような役割を果たすわけです。
SYNフラッド攻撃とは、SYNパケットは送るもののSYN+ACKパケットに応えない、
とう方法で実行されます。クライアント側はそもそも返答を必要としませんから、
嘘の送信元IPアドレスを使ったパケットを偽造することができます。
サーバ側のシステムはSYNパケットを受け取ると、
そのエントリーをハーフオープンなコネクションのキュー(待ち行列)に加え、
キューからエントリーが削除されるまでは、最終パケットであるACKパケットを待ちます。
キューには一定個数のスロットが存在しますが、すべてのスロットが埋まってしまうと、
もうそれ以上新しいコネクションをオープンできなくなります。
指定されたタイムアウトの時間を経過してもACKパケットが到着しなかった場合、エントリーは自動的にキューから削除されます。
タイムアウトの設定は様々ですが、一般的には30秒から60秒、あるいはもう少し大きい値に設定されます。
クライアント側がそれぞれ送信元IPアドレスが異なる大量のSYNパケットを偽造し、
そのパケットを攻撃対象のIPアドレス宛てへ可能な限りのスピードで送信して攻撃を始めれば、
その攻撃によりキューはハーフオープン状態のコネクションで一杯になってしまい、
その結果本来そのサーバへと接続を確立するはずだった他のクライアントが接続できなくなってしまいます。
こういうときはレートリミットを使えば簡単です。-m limit --limit 1/sとすることで、
どんな割合でSYNパケットを受け付けるか、制限することができます。
この例では1秒間にひとつのSYNパケットしか受け付けないように制限するので、
こちらのリソースをSYNフラッドから守れるわけです。
では、実践編に入りましょうか!
カーネルにiptablesがロードされると、5つの場所にルールを設置するフックが用意されます。
それぞれ、INPUT、OUTPUT、FORWARD、PREROUTING、
そしてPOSTROUTINGという名前です。これらはチェインと呼ばれ、一連のルールを作ります。
それぞれのルールでは、あるパケットのヘッダがそのルールに見合うかどうか調べられ、
見合うパケットであった場合はそこで処理されます。
あるルールがパケットにマッチしなかった場合、そのチェインの次のルールが調査さます。
ルールは上記の5つのチェインに直接追加することもできますし、
新しくチェインを作成してそれを既存のチェインにルールとして追加することも可能です。
iptablesは以下のオプションをサポートしています。
オプション: |
その説明: |
-A |
追加 |
-D |
削除 |
-I |
挿入 |
-R |
置き換え |
-L |
一覧表示 |
-F |
チェインの中にあるルール、もしくは全てのルールの削除 |
-Z |
あるチェイン、もしくは全てのチェインのカウンタをゼロに |
-C |
パケットをチェインでチェック |
-N |
ユーザー定義チェインを作成 |
-X |
ユーザー定義チェインを削除 |
-P |
ターゲットのチェインのポリシーを変更 |
-E |
チェイン名を変更 |
-p |
プロトコル |
-s |
送信元アドレス/ネットマスク |
-d |
送信先アドレス/ネットマスク |
-i |
入力の名前(インターフェース名) |
-o |
出力の名前(インターフェース名) |
-j |
処理の内容(ルールのターゲット) |
-m |
拡張されたマッチ(拡張モジュールと共に使用) |
-n |
アドレスやポートを数字で表示 |
-t |
適用するテーブル |
-v |
冗長モード |
-x |
数字を拡張(厳密な数字で表示) |
-f |
フラグメントされた2番目以降にのみマッチ |
-V |
バージョンを表示 |
--line-numbers |
一覧表示の際に行番号を表示 |
まずはiptablesに慣れるために、
こちらにやってくるICMPパケットをブロックしてみましょう。
Code Listing 12.1: すべてのICMPパケットをブロック |
# iptables -A INPUT -p icmp -j DROP
|
最初にどのチェインに追加するか指定します。次にプロトコルを指定し、
それからターゲットを指定します。タゲットにはユーザー定義のチェイン、
もしくはACCEPT、 DROP、 REJECT、 LOG、 QUEUE、
MASQUERADEという特別なターゲットのうちひとつを指定できます。
ここでは、クライアントに応答を返さずにパケットを破棄するDROPを使います。
では、ping localhostとしてみてください。iptablesがマシンに入ってくる全てのICMPパケットをブロックしているので、
何も応答を得られないはずです。他のマシンにpingを打つこともできません。
返答用のICMPパケットも拒否されるからです。
ではチェインを初期化して、またICMPを使えるようにしましょう。
Code Listing 12.2: 全ルールをフラッシュ |
# iptables -F
|
今度はiptablesのステートフルなパケットフィルタリングの部分に注目してみましょう。
eth0に入ってくるパケットに対してステートフルな検査をしたいなら、
以下のようにしましょう:
Code Listing 12.3: すでに確立されたパケットに起因するパケットを許可 |
# iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
|
こうすると既に確立された接続のパケットとINPUTチェインに関係するパケットを許可することができます。
またつい先程説明したようにiptables -A INPUT -i eth0 -m state --state INVALID -j
DROPとするとパケットの状態リストにないパケットをすべて破棄することができます。
iptablesでステートフルなパケットフィルタリングが可能なのは、
state拡張モジュールをロードしているからです。
他のマシンからの接続をあなたのマシンへ受け付けたいなら、--state NEWとすれば良いでしょう。
iptablesにはさまざまな用途に使えるモジュールが揃っています。いくつか例を挙げると:
マッチングを拡張するモジュール |
説明 |
拡張オプション |
mac |
入力パケットのMACアドレスに対するマッチング拡張 |
--mac-source |
state |
ステートフルな検査を有効に |
--state (stateに使用できるのはESTABLISHED、RELATED、INVALID、NEWです) |
limit |
レートのリミット |
--limit、--limit-burst |
owner |
作成されたパケットのさまざまな特性とのマッチングを試行する |
--uid-owner ユーザーID --gid-owner グループID --pid-owner プロセスID
--sid-owner セッションID
|
unclean |
パケットに対して様々な正当性チェックを行う |
|
ユーザー定義チェインを作成し、
既存のチェインに適用してみてください:
Code Listing 12.4: ユーザー定義チェインを作成 |
# iptables -X mychain
# iptables -N mychain
# iptables -A mychain -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -P OUTPUT ACCEPT
# iptables -P INPUT DROP
# iptables -A INPUT -j mychain
|
INPUTチェインにルールを追加すると、次のようなポリシーになります──出力は全て許可し、
入力は全て拒否する。
Netfilter/iptables documentationに行けばドキュメントが見つかります(訳注:リンク先の文書のうちいくつかは、
JFで日本語訳が見つかると思います)。
では、ここまでの全てが入った例を見てみましょう。ここでの私のファイアーウォール/ゲートウェイのポリシーはというと:
- ファイアーウォールへの通信はSSH(22番ポート)のみ許可
-
ローカルネットワークはHTTP、HTTPS、
それからSSHでの通信を許可する必要がある(ので、DNSも必要)
-
特定のペイロードを持ったICMPの通信は禁止。もちろん、
いくつかのICMP通信は許可する必要がある
- ポートスキャンを検知し、検知したらログを取る
- SYNアタックから身を守る
- これ以外の通信は破棄し、ログを取る
Code Listing 12.5: /etc/init.d/firewall |
#!/sbin/runscript
IPTABLES=/sbin/iptables
IPTABLESSAVE=/sbin/iptables-save
IPTABLESRESTORE=/sbin/iptables-restore
FIREWALL=/etc/firewall.rules
DNS1=212.242.40.3
DNS2=212.242.40.51
#内部ネットワーク
IIP=10.0.0.2
IINTERFACE=eth0
LOCAL_NETWORK=10.0.0.0/24
#外部ネットワーク
OIP=217.157.156.144
OINTERFACE=eth1
opts="${opts} showstatus panic save restore showoptions rules"
depend() {
need net procparam
}
rules() {
stop
ebegin "Setting internal rules"
einfo "Setting default rule to drop"
$IPTABLES -P FORWARD DROP
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
#デフォルトルール
einfo "Creating states chain"
$IPTABLES -N allowed-connection
$IPTABLES -F allowed-connection
$IPTABLES -A allowed-connection -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A allowed-connection -i $IINTERFACE -m limit -j LOG --log-prefix \
"Bad packet from ${IINTERFACE}:"
$IPTABLES -A allowed-connection -j DROP
#ICMPでの通信
einfo "Creating icmp chain"
$IPTABLES -N icmp_allowed
$IPTABLES -F icmp_allowed
$IPTABLES -A icmp_allowed -m state --state NEW -p icmp --icmp-type \
time-exceeded -j ACCEPT
$IPTABLES -A icmp_allowed -m state --state NEW -p icmp --icmp-type \
destination-unreachable -j ACCEPT
$IPTABLES -A icmp_allowed -p icmp -j LOG --log-prefix "Bad ICMP traffic:"
$IPTABLES -A icmp_allowed -p icmp -j DROP
#入力トラフィック
einfo "Creating incoming ssh traffic chain"
$IPTABLES -N allow-ssh-traffic-in
$IPTABLES -F allow-ssh-traffic-in
#FLOOD攻撃を防ぐ
$IPTABLES -A allow-ssh-traffic-in -m limit --limit 1/second -p tcp --tcp-flags \
ALL RST --dport ssh -j ACCEPT
$IPTABLES -A allow-ssh-traffic-in -m limit --limit 1/second -p tcp --tcp-flags \
ALL FIN --dport ssh -j ACCEPT
$IPTABLES -A allow-ssh-traffic-in -m limit --limit 1/second -p tcp --tcp-flags \
ALL SYN --dport ssh -j ACCEPT
$IPTABLES -A allow-ssh-traffic-in -m state --state RELATED,ESTABLISHED -p tcp --dport ssh -j ACCEPT
#出力トラフィック
einfo "Creating outgoing ssh traffic chain"
$IPTABLES -N allow-ssh-traffic-out
$IPTABLES -F allow-ssh-traffic-out
$IPTABLES -A allow-ssh-traffic-out -p tcp --dport ssh -j ACCEPT
einfo "Creating outgoing dns traffic chain"
$IPTABLES -N allow-dns-traffic-out
$IPTABLES -F allow-dns-traffic-out
$IPTABLES -A allow-dns-traffic-out -p udp -d $DNS1 --dport domain \
-j ACCEPT
$IPTABLES -A allow-dns-traffic-out -p udp -d $DNS2 --dport domain \
-j ACCEPT
einfo "Creating outgoing http/https traffic chain"
$IPTABLES -N allow-www-traffic-out
$IPTABLES -F allow-www-traffic-out
$IPTABLES -A allow-www-traffic-out -p tcp --dport www -j ACCEPT
$IPTABLES -A allow-www-traffic-out -p tcp --dport https -j ACCEPT
#ポートスキャンを検知
einfo "Creating portscan detection chain"
$IPTABLES -N check-flags
$IPTABLES -F check-flags
$IPTABLES -A check-flags -p tcp --tcp-flags ALL FIN,URG,PSH -m limit \
--limit 5/minute -j LOG --log-level alert --log-prefix "NMAP-XMAS:"
$IPTABLES -A check-flags -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
$IPTABLES -A check-flags -p tcp --tcp-flags ALL ALL -m limit --limit \
5/minute -j LOG --log-level 1 --log-prefix "XMAS:"
$IPTABLES -A check-flags -p tcp --tcp-flags ALL ALL -j DROP
$IPTABLES -A check-flags -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG \
-m limit --limit 5/minute -j LOG --log-level 1 --log-prefix "XMAS-PSH:"
$IPTABLES -A check-flags -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
$IPTABLES -A check-flags -p tcp --tcp-flags ALL NONE -m limit \
--limit 5/minute -j LOG --log-level 1 --log-prefix "NULL_SCAN:"
$IPTABLES -A check-flags -p tcp --tcp-flags ALL NONE -j DROP
$IPTABLES -A check-flags -p tcp --tcp-flags SYN,RST SYN,RST -m limit \
--limit 5/minute -j LOG --log-level 5 --log-prefix "SYN/RST:"
$IPTABLES -A check-flags -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
$IPTABLES -A check-flags -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit \
--limit 5/minute -j LOG --log-level 5 --log-prefix "SYN/FIN:"
$IPTABLES -A check-flags -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
#INVALIDステートをINPUTチェインに追加して適用
einfo "Applying chains to INPUT"
$IPTABLES -A INPUT -m state --state INVALID -j DROP
$IPTABLES -A INPUT -j icmp_allowed
$IPTABLES -A INPUT -j check-flags
$IPTABLES -A INPUT -i lo -j ACCEPT
$IPTABLES -A INPUT -j allow-ssh-traffic-in
$IPTABLES -A INPUT -j allowed-connection
einfo "Applying chains to FORWARD"
$IPTABLES -A FORWARD -m state --state INVALID -j DROP
$IPTABLES -A FORWARD -j icmp_allowed
$IPTABLES -A FORWARD -j check-flags
$IPTABLES -A FORWARD -o lo -j ACCEPT
$IPTABLES -A FORWARD -j allow-ssh-traffic-in
$IPTABLES -A FORWARD -j allow-www-traffic-out
$IPTABLES -A FORWARD -j allowed-connection
einfo "Applying chains to OUTPUT"
$IPTABLES -A OUTPUT -m state --state INVALID -j DROP
$IPTABLES -A OUTPUT -j icmp_allowed
$IPTABLES -A OUTPUT -j check-flags
$IPTABLES -A OUTPUT -o lo -j ACCEPT
$IPTABLES -A OUTPUT -j allow-ssh-traffic-out
$IPTABLES -A OUTPUT -j allow-dns-traffic-out
$IPTABLES -A OUTPUT -j allow-www-traffic-out
$IPTABLES -A OUTPUT -j allowed-connection
#クライアントがNAT(Network Address Translation)を通して通信できるようにする
$IPTABLES -t nat -A POSTROUTING -o $IINTERFACE -j MASQUERADE
eend $?
}
start() {
ebegin "Starting firewall"
if [ -e "${FIREWALL}" ]; then
restore
else
einfo "${FIREWALL} does not exists. Using default rules."
rules
fi
eend $?
}
stop() {
ebegin "Stopping firewall"
$IPTABLES -F
$IPTABLES -t nat -F
$IPTABLES -X
$IPTABLES -P FORWARD ACCEPT
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P OUTPUT ACCEPT
eend $?
}
showstatus() {
ebegin "Status"
$IPTABLES -L -n -v --line-numbers
einfo "NAT status"
$IPTABLES -L -n -v --line-numbers -t nat
eend $?
}
panic() {
ebegin "Setting panic rules"
$IPTABLES -F
$IPTABLES -X
$IPTABLES -t nat -F
$IPTABLES -P FORWARD DROP
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -A INPUT -i lo -j ACCEPT
$IPTABLES -A OUTPUT -o lo -j ACCEPT
eend $?
}
save() {
ebegin "Saving Firewall rules"
$IPTABLESSAVE > $FIREWALL
eend $?
}
restore() {
ebegin "Restoring Firewall rules"
$IPTABLESRESTORE < $FIREWALL
eend $?
}
restart() {
svc_stop; svc_start
}
showoptions() {
echo "Usage: $0 {start|save|restore|panic|stop|restart|showstatus}"
echo "start) will restore setting if exists else force rules"
echo "stop) delete all rules and set all to accept"
echo "rules) force settings of new rules"
echo "save) will store settings in ${FIREWALL}"
echo "restore) will restore settings from ${FIREWALL}"
echo "showstatus) Shows the status"
}
|
ファイアーウォール構築に関する大まかなアドバイス:
- 実装する前にファイアーウォールのポリシーを作りましょう
- シンプルに!
-
各プロトコルがどういう風に動作するか知りましょう(RFC(Request For Comments)を読んでください)
- ファイアーウォールはrootで動いているソフトのうちのひとつだということを忘れないでください
- 作ったファイアーウォールはテストしましょう
iptablesは理解するのが難しいとか設定に時間がかかりすぎると思ったら、Shorewallという親切なファイアーウォールを使っても良いでしょう。
ファイアーウォールのルールの作成には基本的にiptablesが使われていますが、
ルールの作成に特化し、特にプロトコルを問いません。
Squid
Squidはとても強力なプロクシサーバで、以下のようなことに基づいて通信をフィルタすることができます──時間、
パスやURIの正規表現、送信元/送信先IPアドレス、ドメイン、ブラウザ、認証されたユーザー名、
MIMEタイプ、そしてポート番号(プロトコル)。
いくつかの機能を忘れてしまってるような気もしますが、
全機能のリストを作るのは至難の技です。
以下の例では、ポルノサイトのフィルタの代わりにバナーのフィルタを扱います。
というのも、Gentoo.orgがポルノサイトとしてリストされるのはナシだからです。
それに、あなたのために良いサイトをいくつか見つける時間もないわけで。
ここでは、以下のようなポリシーに従います:
-
就業時間(月金の8時から17時と土曜の8時から13時)のネットサーフィン(HTTP/HTTPS)は許可、
残業中ならサーフィンしてる場合じゃないので仕事しましょう
-
ダウンロードは禁止(.exe、.com、.arj、.zip、.asf、.avi、.mpg、.mpegなど)
-
バナーはキライなので、
フィルタして透明なGIFファイルに変換(ここが腕の見せどころですね!)
- これ以外の通信やインターネットからの通信は禁止
これはカンタンな4つのステップで実現します。
Code Listing 12.6: /etc/squid/squid.conf |
# IPアドレスとポートを割り当てる
http_port 10.0.2.1:3128
# 基本設定
hierarchy_stoplist cgi-bin ?
acl QUERY urlpath_regex cgi-bin \?
no_cache deny QUERY
# 基本的なアクセス制限用リスト
acl all src 0.0.0.0/0.0.0.0
acl manager proto cache_object
acl localhost src 127.0.0.1/255.255.255.255
# 誰がこのプロクシサーバにアクセスできるのか追加
acl localnet src 10.0.0.0/255.255.0.0
# それからポートについても
acl SSL_ports port 443
acl Safe_ports port 80
acl Safe_ports port 443
acl purge method PURGE
# URLを正規表現に基づいてアクセス制限
acl archives urlpath_regex "/etc/squid/files.acl"
acl url_ads url_regex "/etc/squid/banner-ads.acl"
# 時間や曜日に基づいてアクセス制限
acl restricted_weekdays time MTWHF 8:00-17:00
acl restricted_weekends time A 8:00-13:00
acl CONNECT method CONNECT
# manager権限でのアクセスはローカルホストからのみ許可
http_access allow manager localhost
http_access deny manager
# PURGE(訳注:キャッシュ内のオブジェクトの削除)要求はローカルホストからのみ許可
http_access allow purge localhost
http_access deny purge
# 不明なポートへのリクエストは禁止
http_access deny !Safe_ports
# SSLとして設定したポート以外のCONNECT要求は禁止
http_access deny CONNECT !SSL_ports
# ここから、私独自の設定です
# バナーを除去した後に表示されるページを追加
deny_info NOTE_ADS_FILTERED url_ads
# で、それらを拒否
http_access deny url_ads
# すべてのアーカイブへのアクセスを禁止
http_access deny archives
# 就業時間のみしかアクセスできなくする
http_access allow localnet restricted_weekdays
http_access allow localnet restricted_weekends
# 残りは全て禁止
http_access deny all
|
次にユーザーにダウンロードさせたくないファイルのリストを埋めます。
私は、zip、viv、exe、mp3、rar、ace、avi、mov、mpg、mpe、au、ra、arj、tar、gz、それからzという拡張子を持つファイルをリストに入れました。
Code Listing 12.7: /etc/squid/files.acl |
\.[Zz][Ii][pP]$
\.[Vv][Ii][Vv].*
\.[Ee][Xx][Ee]$
\.[Mm][Pp]3$
\.[Rr][Aa][Rr]$
\.[Aa][Cc][Ee]$
\.[Aa][Ss][Ff]$
\.[Aa][Vv][Ii]$
\.[Mm][Oo][Vv]$
\.[Mm][Pp][Gg]$
\.[Mm][Pp][Ee][Gg]$
\.[Aa][Uu]$
\.[Rr][Aa]$
\.[Aa][Rr][Jj]$
\.[Tt][Aa][Rr]$
\.[GgZz]$
\.[Zz]$
|
Note:
[]の中に各文字の大文字と小文字が入っていますよね?
これはaviファイルを要求する代わりにAvIファイルを要求されてスリ抜けられてしまう、ということを防ぐためです。
|
次にバナーを検知するための正規表現を追加します。
あなたは私よりもっとうまくやれると思います:
Code Listing 12.8: /etc/squid/banner-ads.acl |
/adv/.*\.gif$
/[Aa]ds/.*\.gif$
/[Aa]d[Pp]ix/
/[Aa]d[Ss]erver
/[Aa][Dd]/.*\.[GgJj][IiPp][FfGg]$
/[Bb]annerads/
/adbanner.*\.[GgJj][IiPp][FfGg]$
/images/ad/
/reklame/
/RealMedia/ads/.*
^http://www\.submit-it.*
^http://www\.eads.*
^http://ads\.
^http://ad\.
^http://ads02\.
^http://adaver.*\.
^http://adforce\.
adbot\.com
/ads/.*\.gif.*
_ad\..*cgi
/Banners/
/SmartBanner/
/Ads/Media/Images/
^http://static\.wired\.com/advertising/
^http://*\.dejanews\.com/ads/
^http://adfu\.blockstackers\.com/
^http://ads2\.zdnet\.com/adverts
^http://www2\.burstnet\.com/gifs/
^http://www.\.valueclick\.com/cgi-bin/cycle
^http://www\.altavista\.com/av/gifs/ie_horiz\.gif
|
で、仕上げとして。バナーを除去したあとに表示したいファイルがこれです。
基本的には、4x4の透明なGIF画像が入った途中までのHTMLファイルです。
Code Listing 12.9: /etc/squid/errors/NOTE_ADS_FILTERED |
<HTML>
<HEAD>
<META HTTP-EQUIV="REFRESH" CONTENT="0; URL=http://localhost/images/4x4.gif">
<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
</HEAD>
<BODY>
<H1>Add filtered!</H1>
|
Note:
<HTML>と<BODY>タグを閉じないでください。それはSquidがやってくれます。
|
以上のようにSquidには沢山の可能性があり、
フィルタとプロクシに関して非常に有効です。
他に複数のSquidプロクシを用意して大規模ネットワークに対応させることも可能です。
ここで私が挙げた設定は、1から20ユーザーぐらいの小規模ネットワーク向けです。
しかし、Squidがどこか安全な場所に置かれていて、外部から誰もアクセスできないようになっているなら、
パケットフィルタ(iptables)とアプリケーションゲートウェイ(Squid)の組み合わせは、
恐らく一番良い解決策でしょう。
もちろん内部からのアタックには気を付ける必要はありますが。
では、クライアントのブラウザでプロクシサーバを使うように設定してください。
ここで設定したゲートウェイは、
プロクシ経由でない接続を一切禁止します。
Note:
Mozillaを使っている場合は、Edit→Preferences→Advanced→Proxiesから設定できます。
|
iptablesを使ってすべての外向きトラフィックを透過的にSquidに向けることも可能です。
ゲートウェイのFORWARD、
もしくはPREROUTINGルールに以下を追加してください:
Code Listing 12.10: プロクシサーバへのポートフォワーディングを有効に |
# iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to proxyhost:3128
# iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to proxyhost:3128
|
さて、ここまでで私たちは何を学んだんでしょうか?
私たちが学んだことは:
-
ファイアーウォールはそれ自体が脅威になりうる。
不適切な設定をされたファイアーウォールなら無い方がマシ
- 基本的なゲートウェイの構築方法と、透過的なプロクシの構築方法
- 許可したいプロトコルについて知ることが良いファイアーウォールのカギ
-
IPのトラフィックはいつも正当なデータばかりが含まれているわけではない。
例) ICMPパケットはペイロードを持つ場合もある
- SYNアタックの防ぎ方
-
イヤな画像やウイルスのダウンロードからHTTPトラフィックをフィルタする方法
-
パケットフィルタとアプリケーションゲートウェイを組み合わせると制御がしやすい
さあ、もし本当に必要なら、自分のニーズに合ったファイアーウォールを作りましょう。
13. 侵入検知
AIDE (Advanced Intrusion Detection Environment)
AIDEは(Tripwireの代わりとして使えるフリーの)ホストベース侵入検知システムです。
あなたが既にTripwireのことを知っているなら、
AIDEの設定ファイルは全然難しくありません。
設定ファイルは、正規表現、マクロ、それからファイルやディレクトリに対するルールで出来ています。
マクロには以下のようなものがあります:
マクロ |
意味 |
書き方 |
ifdef |
定義されていれば |
@@ifdef "name" |
ifndef |
定義されていなければ |
@@ifndef "name" |
define |
変数を定義 |
@@define "name" "value" |
undef |
変数を未定義に |
@@undef "name" |
ifhost |
指定されたホストで動作しているなら |
@@ifhost "hostname" |
ifnhost |
指定されたホストで動作していないなら |
@@ifnhost "hostname" |
endif |
endifは上に挙げたdefineとundef以外のいずれかのマクロの後で使う必要があります
|
@@endif |
Gentooが動いているマシンが複数あってすべてのマシンにAIDEをインストールしようと思っているなら、
これらのマクロはとても便利です。しかしすべてのマシンで同じサービスを動作させることはないでしょうし、
もっと言えば、すべてのユーザーが同じサービスを動作させてるわけではないでしょう。
次にファイルやディレクトリのチェックに使用するフラグを見てみましょう。
フラグは、パーミッション、ファイルの属性、暗号化ハッシュやチェックサムといったものがあります。
フラグ |
意味 |
p |
パーミッション |
i |
iノード |
n |
リンク数 |
u |
ユーザー |
g |
グループ |
s |
サイズ |
b |
ブロック数 |
m |
mtime |
a |
atime |
c |
ctime |
S |
サイズの増加をチェック |
md5 |
MD5形式のチェックサム |
sha1 |
SHA1形式のチェックサム |
rmd160 |
RMD160形式のチェックサム |
tiger |
Tiger形式のチェックサム |
R |
p+i+n+u+g+s+m+c+md5と同じ |
L |
p+i+n+u+gと同じ |
E |
何も指定しないのと同じ(訳注:原文はEmpty Groupです。
ファイルの属性等についてはチェックされませんが、
ファイルの存在自体のチェックはできるようです)
|
> |
ログファイルのようにどんどん大きくなるもの用。p+u+g+i+n+Sと同じ |
AIDEがmhashサポート付きでコンパイルされているなら、他にもいくか使えるフラグがあります(訳注:2003.11.04時点の最新版であるaide-0.9.ebuildでは、デフォルトでmhashサポートが有効になります)。
フラグ |
意味 |
haval |
HAVAL形式のチェックサム |
gost |
GOST形式のチェックサム |
crc32 |
CRC32形式のチェックサム |
上記フラグを組み合わせることで、独自のルールを作ることも可能です:
Code Listing 13.1: AIDE用のルールを作成 |
All=R+a+sha1+rmd160
Norm=s+n+b+md5+sha1+rmd160
|
設定ファイルを作成するために必要な最後の項目は、
どうやってファイルやディレクトリにルールを適用するかということです。
基本的には、単にファイル名やディレクトリ名と、それに対応するルールを書けば大丈夫です。
あなたが何か特別な設定をしない限り、AIDEは再帰的にすべてのファイルをチェック対象に追加してくれます。
フラグ |
意味 |
! |
このファイルやディレクトリを無視 |
= |
このディレクトリを追加。ただしサブディレクトリは無視 |
では、出来上がった例を見てみましょう。
Code Listing 13.2: /etc/aide/aide.conf |
@@ifndef TOPDIR
@@define TOPDIR /
@@endif
@@ifndef AIDEDIR
@@define AIDEDIR /etc/aide
@@endif
@@ifhost smbserv
@@define smbactive
@@endif
# 読み込まれるデータベースの場所
database=file:@@{AIDEDIR}/aide.db
# 書き込まれるデータベースの場所
database_out=file:aide.db.new
verbose=20
report_url=stdout
# ルールを定義
All=R+a+sha1+rmd160
Norm=s+n+b+md5+sha1+rmd160
@@{TOPDIR} Norm
!@@{TOPDIR}etc/aide
!@@{TOPDIR}dev
!@@{TOPDIR}proc
!@@{TOPDIR}root
!@@{TOPDIR}tmp
!@@{TOPDIR}var/log
!@@{TOPDIR}var/run
!@@{TOPDIR}usr/portage
@@ifdef smbactive
!@@{TOPDIR}etc/smb/private/secrets.tdb
@@endif
=@@{TOPDIR}home Norm
|
上記の例では、どこをトップディレクトリにするか、
AIDEのディレクトリがどこにあるかなどのマクロを設定しています。
AIDEはファイルの改竄チェックをする際/etc/aide/aide.dbを使いますが、
データベースの更新や新規作成時には/etc/aide/aide.db.newに情報を記録します。
つまり、古いデータベースファイルを自動的には上書きしないということです。
report_urlオプションはまだ実装されていません。ただし作者によると、
メールで通知したり、スクリプトを実行したりといったことが出来るようになるようです。
設定が終わったら、aide -iを実行してデータベースファイルを作成しなくてはいけません。
データベースファイルが出来たら/etc/aide/aide.db.newを/etc/aide/aide.dbにコピーして、
チェック用のコマンドをcronに追加しましょう。
rootでcrontab -eとしてください。
Note:
マシンのCPUやディスクの速度や指定したフラグによっては、
多少の時間がかかる場合があります。
|
Code Listing 13.3: AIDEをcronに登録 |
0 3 * * * /usr/bin/aide -u
|
Note:
root宛てのメールを読めるようにするのを忘れないでください。
そうしないと、AIDEが何をレポートしても気が付かない、なんてことになります。
|
今回の設定では毎日午前3時にチェックされます。こうしたのは仕事してるユーザーの邪魔をしたくなかったからです。
-C(チェック)オプションではなく-u(更新)オプションを使っていることに注意してください。
なぜなら-uオプションでもチェックは行われ、オリジナルのデータベースファイルが上書きされることもないので、
変更が検出された場合は単にファイルをコピーすれば良く時間の節約になるからです。
実際にコピーする前には、あなた自身がその変更を行ったのか、それともアタッカーが行ったのか、
ちゃんとチェックしてくださいね!
さて、実はデータベースファイルをローカルに保存することには少し問題があります。
なぜならアタッカーは(AIDEがインストールされていることがわかれば)、
ほぼ確実にデータベースファイルを変更、更新するか、/usr/bin/aide自体を修正してしまうからです。
なので、CDなどのメディアに.dbファイルとAIDEのバイナリのコピーを保存しておきましょう。
AIDEのページを見れば情報が見つかります。
Snort
Snortはネットワーク侵入検知システム(NIDS)です。
Snortをインストールして設定したい場合は以下の例を参考にしてください。
Code Listing 13.4: snortというユーザーをシステムに追加 |
# useradd snort -d /var/log/snort -s /dev/null
# chown -R snort /var/log/snort
|
Code Listing 13.5: /etc/conf.d/snort |
PIDFILE=/var/run/snort_eth0.pid
MODE="full"
NETWORK="10.0.0.0/24"
LOGDIR="/var/log/snort"
CONF=/etc/snort/snort.conf
SNORT_OPTS="-D -s -u snort -dev -l $LOGDIR -h $NETWORK -c $CONF"
|
Code Listing 13.6: /etc/snort/snort.conf |
var HOME_NET 10.0.0.0/24
var EXTERNAL_NET any
var SMTP $HOME_NET
var HTTP_SERVERS $HOME_NET
var SQL_SERVERS $HOME_NET
var DNS_SERVERS [10.0.0.2/32,212.242.40.51/32]
var RULE_PATH ./
preprocessor frag2
preprocessor stream4: detect_scans detect_state_problems detect_scans disable_evasion_alerts
preprocessor stream4_reassemble: ports all
preprocessor http_decode: 80 8080 unicode iis_alt_unicode double_encode iis_flip_slash full_whitespace
preprocessor rpc_decode: 111 32771
preprocessor bo: -nobrute
preprocessor telnet_decode
include classification.config
include $RULE_PATH/bad-traffic.rules
include $RULE_PATH/exploit.rules
include $RULE_PATH/scan.rules
include $RULE_PATH/finger.rules
include $RULE_PATH/ftp.rules
include $RULE_PATH/telnet.rules
include $RULE_PATH/smtp.rules
include $RULE_PATH/rpc.rules
include $RULE_PATH/rservices.rules
include $RULE_PATH/dos.rules
include $RULE_PATH/ddos.rules
include $RULE_PATH/dns.rules
include $RULE_PATH/tftp.rules
include $RULE_PATH/web-cgi.rules
include $RULE_PATH/web-coldfusion.rules
include $RULE_PATH/web-iis.rules
include $RULE_PATH/web-frontpage.rules
include $RULE_PATH/web-misc.rules
include $RULE_PATH/web-attacks.rules
include $RULE_PATH/sql.rules
include $RULE_PATH/x11.rules
include $RULE_PATH/icmp.rules
include $RULE_PATH/netbios.rules
include $RULE_PATH/misc.rules
include $RULE_PATH/attack-responses.rules
include $RULE_PATH/backdoor.rules
include $RULE_PATH/shellcode.rules
include $RULE_PATH/policy.rules
include $RULE_PATH/porn.rules
include $RULE_PATH/info.rules
include $RULE_PATH/icmp-info.rules
include $RULE_PATH/virus.rules
# include $RULE_PATH/experimental.rules
include $RULE_PATH/local.rules
|
Code Listing 13.7: /etc/snort/classification.config |
config classification: not-suspicious,Not Suspicious Traffic,3
config classification: unknown,Unknown Traffic,3
config classification: bad-unknown,Potentially Bad Traffic, 2
config classification: attempted-recon,Attempted Information Leak,2
config classification: successful-recon-limited,Information Leak,2
config classification: successful-recon-largescale,Large Scale Information Leak,2
config classification: attempted-dos,Attempted Denial of Service,2
config classification: successful-dos,Denial of Service,2
config classification: attempted-user,Attempted User Privilege Gain,1
config classification: unsuccessful-user,Unsuccessful User Privilege Gain,1
config classification: successful-user,Successful User Privilege Gain,1
config classification: attempted-admin,Attempted Administrator Privilege Gain,1
config classification: successful-admin,Successful Administrator Privilege Gain,1
# 新規classification
config classification: rpc-portmap-decode,Decode of an RPC Query,2
config classification: shellcode-detect,Executable code was detected,1
config classification: string-detect,A suspicious string was detected,3
config classification: suspicious-filename-detect,A suspicious filename was detected,2
config classification: suspicious-login,An attempted login using a suspicious username was detected,2
config classification: system-call-detect,A system call was detected,2
config classification: tcp-connection,A TCP connection was detected,4
config classification: trojan-activity,A Network Trojan was detected, 1
config classification: unusual-client-port-connection,A client was using an unusual port,2
config classification: network-scan,Detection of a Network Scan,3
config classification: denial-of-service,Detection of a Denial of Service Attack,2
config classification: non-standard-protocol,Detection of a non-standard protocol or event,2
config classification: protocol-command-decode,Generic Protocol Command Decode,3
config classification: web-application-activity,access to a potentially vulnerable web application,2
config classification: web-application-attack,Web Application Attack,1
config classification: misc-activity,Misc activity,3
config classification: misc-attack,Misc Attack,2
config classification: icmp-event,Generic ICMP event,3
config classification: kickass-porn,SCORE! Get the lotion!,1
|
詳しくはSnortのWebサイトを参照してください。
The contents of this document are licensed under the Creative Commons - Attribution / Share Alike license.
|