Security System

1.OSバージョンアップ対策

 FreeBSDもすでに4.xが出てくるようになったので、会社や自宅の再インストールを決意。3.5あたりが主流だったこともあってバージョンアップよりも思い切って最初から入れ直す事にした。同時にセキュリティの強化も図っていこう。

1.FreeBSD3.xからFreeBSD4.xへ
[その1]
 ちょうどProxyサーバーで動いていたホストのHDDが反応しなくなる現象に遭遇したため、急遽着手することとなる。このホストはValuestarNX/VR33で内蔵HDD増設以外は改造していない。
 FreeBSD3.51から一気に4.3まで上げる。
 すでに動作しているデーモンやサーバーの設定ファイル群、コンテンツファイル群をtarで固めて手元のPCへ転送。プライマリマスタHDDを外してスレーブにしていた17GBHDDをマスタとする。一本のHDDではちょっと不安も残るが定期的にバックアップもしているので思い切る事にする。

 以前はネットワークインストールで長時間を要したが今回はCD-ROMから入れる。主目的はProxyとネットワーク内各PCのバックアップセット保管用スペースとしてのSamba、そしてイントラネットのExchangeのメールを中継するSendmalである。
 インストールは問題なく完了する。HDDは
/  128MB
SWAP 192MB
/var  128MB
/usr  4096MB
/achi2  1GB
/achi2  残り

 一旦インストールが完了した後、パッケージを入れる。Portsは使わない。
 まずはSamba。smb.confとnmb.confをバックアップから戻し、起動スクリプトを確認。inetdを再起動するとnmbdが重複しているらしいエラーが出る。inetd.confだけ書いたつもりだったが。。。パッケージインストールだからどこかにスタートアップスクリプトがあるのかも。swatの設定(inetd.conf)を確認してしばらくは端末から監視。
 Apacheもhttpd.confを転送したが実装モジュールが異なるため手で修正。Apacheを起動してALEXシステムを転送。設定を確認して呼び出してみるものの500エラーが返ってきた。すぐにエラーログを見るとlibc.so.3が無いとかで撃沈。libc.so.4は存在しているため、リコンパイルが必要なようだがここはなまくら発揮で一時しのぎにlibc.so.4をコピーしてlibc.so.3を作成。エラーは消えた。

 続いてSendmail.cfを転送。送受信試験は成功したがイントラネットのExchangeがエラーを出す。しばらく様子を見てみる事にする。

 ではProxyへ。Squidの設定はsquid.confの書き換え部分が少ないため、ファイルを転送せず手で修正。起動後キャッシュが無いとかで怒られて慌てて作成する。-zオプションだったかな?これは最初だけ必要。

 IRCサーバーも動いていたので今回も動作させようとするが、ftp.jp.freebsd.orgのパッケージ一覧には存在しない。理由は不明だが探せば出てくると信じてソースをゲット。2.10.3-jp6だ。config,make,installと進んで設定してみるがなかなか起動しない。内部ループしているようでクラス設定が間違えていると判断。クラスを新たに追加して再起動。接続成功。しばらく様子を見る。

 Exchangeとの連携問題は残したままだが各種設定を確認しながら安定運用を目指す。
 1)ユーザーエリアのCGI動作確認
 2)wwwstat設定、monthly書き換え
 3)監視用スクリプト稼働開始(sysログ監視)
 4)バックアップスクリプト作成

[その2]
 自宅でCGIの練習などに利用していたPC9821 Ld350AのFreeBSDもこの際4.3まで上げてみる事にした。この手のノートでは/stand/sysinstallを終了した時やX Window Systemを終了した際にブラックアウトする現象を体験しているため、Kernelの再構築が必要な事も承知。srcも入れて再構築するスケジュールとする。X Windowは入れない。
 こちらも3.xはネットワークインストールで6時間ほどかけて頑張ったが今回はLAN内のWindows2000ProをFTPサーバーに見立ててそこからインストールする事にする。
 一連の作業は/stand/sysinstallからメニューに従って進行する。一連のインストールが終了した段階で再起動後にKernel再構築。インストールに比べてKernelコンパイルにかかる時間と言ったら・・・このCPUでは無理も無いが。
 なおこのLd350はHDDが350MBしか無いため(増設などはしていない)、Kernelの再構築が終われば元の設定ファイルを残してsrc配下を削除する。こうしないと空き容量が稼げない。
 再構築後にSambaを設定する。これは自宅にプリンタが一台しか存在しないためにプリンタ・サーバーとしても活躍してもらおうと言う考えだ。子供達もプリンタをほしがっているが、無駄に資源を増やしたくない。とは言え一人で6台のPCを操っている私は一体。。。
 プリンタの設定は勤務先と同様に行うが設定はswatで行い、printcapだけは手で書いた(って見本がついてるからさほどややこしくも無いけど)。
 swatから再起動を促すとWindows98からアクセス出来るようになりプリンタが見えた。すぐにインストールしテスト印刷。うーん、満足の瞬間。
 次に今回のもう一つの予定である「セキュリティ関連」を用意する。
 自宅から勤務先のサーバーへアクセスして不要なポートが開いていないか、また分析などを行うための環境を作り上げようと考えていた。最初はポートスキャンツールである[nmap]だ。パッケージに存在するため、簡単に入ってくる。
 次に[Saint]である。これはポートスキャンと同時にデーモンやサーバープログラムのセキュリティホールなどをチェックできる優れ物でサーバーとして起動しているPCにインストールしておけばLAN内のクライアントから操作できる。早速プログラムを取りに出かけた。http://www.wwdsi.com/がそのサイトだ。
 このツールはサーバープログラムのバージョンや存在するセキュリティホールなどの定義情報も持っているようで、スキャンすることでどれほどの脆弱性があるのか評価出来る。バージョンアップの頻度も素晴らしく、CodeRedやNimdaへの対応も早かった。
 ダウンロードしたソースを展開し、./config,make,make installと進み、設定ファイルを編集。Webアクセス出来るように設定し、早速クライアントからアクセスする。見事に動いて来るでは無いか。

 すでに深夜であった事から早速事務所のサーバー二台に対してSaintによるチェックを行うことにした。するとやはり脆弱性を持ったまま動いている事がわかる。

 次は事務所のセキュリティ対策である。

[その3]
 事務所でプリイマリ・ドメインサーバー、Webサーバー、メールサーバーとして動作しているPCはRedHat7である。セキュリティホールは何度も聞いてはいたが本格的に対応するのは初めてである。
 [Saint]から出された警告(赤い印がつく)によると、BIND、Sendmailについてまず対処せよとの事である。
 まずはhttp://www.jp.redhat.com/support/errata/rh70-errata-security.htmlから情報収集。ずいぶんたくさんあるでは無いか。これ全部は無理だわなぁ。しかし放置しておくわけには行かない。一つずつでも片づけて行くことにする。
 まずはApacheから。rpmを落として来てサーバー側で-Fvhオプションでrpmを起動するだけ。何とも簡単。念のため設定ファイルも確認し、クライアントからアクセスして動作確認。OKだ。
 次はbind。これは一時期騒がれていたから次々FIXされている様子だが、Apacheと同様に最新の物を落として入れ替え。動作確認もOKだ。
 さらにSendmailとWu-FTPも同様に行う。これで少しは良くなったはず。

 ところが数日後FTPが起動していない事に気がつく。ファイルを転送しようとクライアントのFTPツールから接続しに行って初めて気がついた。PC自体はUpdateしてから何度も再起動しているのだから、スタートアップから動作していないことになる。早速スクリプトを探す。
 以前のRedHat(6.x系)はinetd.confで設定していたと記憶しているが、7.xではxinetd.dと言うディレクトリの配下にスタートアップスクリプトが存在している事が分かった。しかもFTPはデフォルトで「起動しない」設定になっている。まあ、安全策なのだがこのままでは困るのでenableに修正して起動する。
 また最近FTPポートへの不正なスキャン行為が増えている事もあって、土日の監視できない間はFTP自体を停止する事にした。んでここで理解したスタートアップスクリプトを二種類用意(ftpstartとftpstop)し、それぞれを必要な時に入れ替えるバッチを作成。これでいちいちログインしなくても済む。クライアントのTeraTermで起動と停止のファイルを入れ替えてxinetdを再起動するマクロを書いて終わり。

 さらに今度はSI業者の担当から「メールがエラーではじかれた」と電話が入る。「あん?なんでやねん!」ともがくこと数分。実はこのPCからイントラネットのExchangeへメールを中継する為にもう一台のメールサーバーへ転送する設定を施してあった。その中継が無視されているようだ。確かに最初に起動した時に「cfが古いぞ」と警告が出ていたような気もするけど気にしていなかった。
 内部リレーはsendmail.cfのLowerHostと言う箇所で定義しているが今回入れ替えたバージョンでは使えないオプションのようだ。ではどうすれば?
 インターネットを探すこと数時間。何とか最近のSendmail.mcやcfを解説するサイトを見つけだし読みふける。現在のバージョンではオプションのほとんどがcf内部だけでなく外部ファイルで定義できるようになっている。以前も同様な部分はあったがdefに書き込んだ方が早いケースが多かったように感じていた。
 今回はsendmail.lwと言うファイルを定義してそこで設定すれば良いことが判明。同時にspmalistも使えるように修正して動作させる。試験は成功した。
 ただし現在のバージョンのSendmailはデフォルトで中継を許さない設定になっているので、厳格な管理である。もちろんそれが望ましいことは言うまでも無いが、メールサーバーを複数運用するケースなどでは注意が必要だろう。今回はaccessデータベースやlocaldomainデータベースの力も借りることとした。

 さていささか穴は塞がれたがまだ安心は出来ない。定期的に確認してプログラムを入れ替えるなり某かの対応に迫られる事になる。

2.Syslog Hostの作成

[その1]
 ポートスキャンなどが増えてきた事でそれまで定期的にルータのログを「ログダウンロードツール」で落としては確認していたのだが、うっかりダウンロード予定時刻を過ぎたり、翌朝になったりするとログがturned overしてほとんど役に立たない事が出てきた。特にCodeRed以降からひどくなってきたので何とか方法が無いか考える事になる。
 ルータのマニュアルは何度も読んでいたのだが[syslog host]と言う部分がずっと気になっていた。ロギングエリアがさほど大きく無いのは分かっていたのだが、こんな風に着手する事になるとは。
 YAMAHAのRT102iと言うルータだが、機能は豊富である。しかし多機能と言えるほど要求に応えられるものでは無いため思い切ってsyslog hostsに取りかかる事にした。
 RT102iでは、
syslog host 192.168.1.5
syslog facility local0
と言った風にログを飛ばすホストとファシリティを決める。ログを受け取ったホスト(RedHatLinux)側では、
/etc/rc.d/init.d/syslog
 での起動スクリプトに-rを加える。
 daemon syslogd -m 0 -r
/etc/syslog.conf
 local0.*  /var/log/router.log
と設定する。これでルータのログは192.168.1.5の/var/log/router.logへ落ちる事になる。
 しかしこのままではログが溜まる一方であり、最新情報を確認しようとすると膨大な履歴を吐き出して来ることになる。そこでローテーションを検討する。
 RedHatLinux7Jだとデフォルトでは/etc/logrotate.dに存在するスクリプトで定義できるが試しに独自の物を作ってみることにする。

補足:上記はRedHatLinuxでの実施内容。FreeBSDはデフォルトでSyslogHostが有効な設計だが、最近のパッケージはインストール直後は停止オプションがついている。従ってFreeBSDでは/etc/defaultsあたりに存在するrc.confの中でsyslogd_flags="-s"をsyslogd_flags=""に書き換える。もちろん、/etc/rc.confでsyslogd_flags=""を追加しても良い。

 DailyやWeekly,Monthlyでも各ログのローテーションを行っている。しかしそのスクリプトに手を加えるのはちょいと不安がある。さらにログを閲覧する為にわざわざログインするのも面倒だ。Webから参照できるように出来ないのか?っと考えるとどうしてもそうしたくなる(爆)
 まずポリシーとして日々ローテーションさせる前提で、何日間のログを保管するかを設定する。10日間もあれば良いかとの判断。
#*----*----*----*----*----*----*
SHELL=/bin/sh
MAILTO=root
HOME=/

cp -f /var/log/mr/mrouter-log.9 /var/log/mr/mrouter-log.10
cp -f /var/log/mr/mrouter-log.8 /var/log/mr/mrouter-log.9
cp -f /var/log/mr/mrouter-log.7 /var/log/mr/mrouter-log.8
cp -f /var/log/mr/mrouter-log.6 /var/log/mr/mrouter-log.7
cp -f /var/log/mr/mrouter-log.5 /var/log/mr/mrouter-log.6
cp -f /var/log/mr/mrouter-log.4 /var/log/mr/mrouter-log.5
cp -f /var/log/mr/mrouter-log.3 /var/log/mr/mrouter-log.4
cp -f /var/log/mr/mrouter-log.2 /var/log/mr/mrouter-log.3
cp -f /var/log/mr/mrouter-log.1 /var/log/mr/mrouter-log.2
cp -f /var/log/mr/mrouter-log.0 /var/log/mr/mrouter-log.1
cp -f /var/log/mrouter-log /var/log/mr/mrouter-log.0
rm -f /var/log/mrouter-log
touch /var/log/mrouter-log
/etc/rc.d/init.d/syslog restart
#*----*----*----*----*----*----*
 と言うスクリプトを作って毎日午前10時に実行するようcronへ設定した。
 次にユーザーのエリアへ各ログをコピーして読みとり権限を変更。このファイルを認証付きで参照できるようにするというスクリプトも追加した。

 この作業によりルータのログは漏らさず確実に把握できる事となり、ポートスキャンや不審なICMPまでも確認できる事となる。
 それ以後監視作業として定例化しているが、特に111番や515番また53番をスキャンしてくるマシンはワームに感染していたりする可能性もあるので対象のホストへメールを送るなどの処置も施している。

 さらに深刻な不正アクセスなどが増加して来た事もあって、[swatch]に頼る事になる。これは以前侵入を受けた頃から動作させていたが、今回このルータログにも施す事とした。特に開いているポートに対して総当たりで検索に来た際に即座に反応したいためである。対象は21番、25番、53番、110番として連続してスキャンがあれば携帯電話へメールを送るように設定。swatchrcの中では、
watchfor   /default(.*)81:21$|default(.*)85:21$/
(上の通り正規表現が使えるがたったこれだけ理解するのに数日を要した・・・)
などと設定。上はデフォルトフィルターに引っかかったIPで当方の.81のポート21、同様に.85の21をスキャンした際に発生する。
 これは功を奏したが夜中に多いのが困ったものだ。。。

[その2]
 監視作業はNimdaが多少落ち着いてきた頃から厳しくなってきた。これはワームの感染行動に便乗するように不正な行動を起こす人物が増加した結果だと考えているがとにかくやたらとポートスキャンを行い、忘れた頃に特定のホストへ侵入しようとするケースが目立つ。このままではまずいと判断し、ルータのReject設定を強めたりサーバーのポートを限定するなどを処置を施す。しかしこういう作業は終わりもなければ改善も難しい。そこで一旦会社へFirewallの導入に関しての伺いを立ててみる事にした。しかし反応は鈍い。それはもちろんセキュリティ面の認識の違いであり、見えない物に簡単には投資できないと言う習慣も邪魔している。ある程度納得は出来るものの監視作業は困難を極めていた。
 そんな時に17カ所点在する拠点からWeb経由で商品発注すると言う仕組みが急浮上。今のままではさらにややこしくなると考え、発注用の回線増設を申請。これは何とか許可が出た。
 しかしセキュリティはまだ未完成。そこで自力でFirewallを構築すると言う暴挙に出たのが2002年1月11日の夜の事である。

3.Firewallの構築[FreeBSD4.2R]

 勤務先ではイントラネットで3台、インターネットとの同時使用で3台のホストがある。イントラネットはまだ不安が少ないが問題は外へ出しているホストである。この入口にFirewallを構築しようと考えた。まずはイントラネット側のホストで構築してみようと考えるが、何故か二枚目のNICを差し込んで起動するとSCSIが見えなくなる。原因は不明だがこのPCでは無理をしないことにして、外向けの3台のうちの一台を利用する事にする。
 このホストはFreeBSD4.2で構築されている。主として将来にわたってナレッジ・マネジメントを支援しようとドキュメントの保管と検索を行う目的を持っていたが当面利用する予定は無かった。Firewallとして機能しても内側から参照できるように構成すれば問題も少ないだろうと判断し着手。
 二枚目のNICはすんなり認識出来てKernelの再構築へ進む。しかしFirewallのポリシーはどうするか。もちろん基本は[Deny]であるが、内側に公開するホストがある場合はポリシーに逆行した定義も必要となる。ここでかなりの時間悩むことになる。丸一日悩んだ結果「NIC三枚差しでDMZを作ろう」と判断を下す。
 翌日三枚目のNICを装着してみるが、Kernelを再構築したあたりから妙なエラーに出くわす。
watchdog time out
である。
 これはKernelレベルの警告であり、本来常時アクセスや更新が行われるべきデバイスなどに対して一定時間の間に何の行動も起きなかった事から発せられる。しかも数分後にはPANIC寸前と判断されてRebootする。このRebootがくせ者で実はプロセス終了を正常に行わない。恐らくPANICが先行してkill allが間に合わないのでは無いかと感じる。
 再起動後はまずfsckのお世話になる可能性が大きい。unmountせずにいきなり電源を落としたのとほぼ同じと言えるためだ。
 どうやらこれは三枚目のNICの影響だと判断できた。
 ここでDMZはあきらめる事になる。

 しかし挫折は出来ない。
 インターネットをうろつくこと半日。[BRIDGE]を見つけた。
 これは二枚のNICで通過するパケットを制御する仕組みで基本はFirewallだがルータ機能とも取れる。
 再度Kernelの構築から開始する事になる。

options ICMP_BANDLIM
options BRIDGE
options IPFIREWALL
options IPFIREWALL_VERBOSE
options IPFIREWALL_VERBOSE_LIMIT=500
options IPFIREWALL_DEFAULT_TO_ACCEPT
options IPDIVERT
options TCP_DROP_SYNFIN
options TCP_RESTRICT_RST

設定ファイルに上記を書き加えてさらに
pseudo-device bpf
が有効になっている事を確認。
# config NEWKERNEL
# make depend ; make
# make install
と進む。
/etc/rc.conf
firewall_enable="YES"
firewall_type="OPEN"
tcp_restrict_rst="YES"
tcp_drop_synfin="YES"
と編集し、再起動して新しいカーネルで起動されるとデフォルトではACCEPTになっているため全て通ると思ったが、Bidgeとして動作していないため何も通らない。
# sysctl -w net.link.ether.bridge=1
# sysctl -w net.link.ether.bridge_ipfw=1
これで素通しになる。次回起動時から自動設定されるように/etc/sysctl.confを作成して上記のように書く。このファイルは存在すれば起動時に読み込まれるので次回からは自動。

設定ファイルはrc.firewallを参考に記述すると楽である。と言うか私の場合はそもそもIPFWとNATで解決しようと考えていたためrc.firewallの定義がすでに完了していた。そこでこのファイルをコピーして新たなファイルを作成した。
名付けてipfw.bridge(そのまんま)。
#
fwcmd="/sbin/ipfw -q"
ip="192.168.1.5"
net="192.168.1.0/24"
wserver="192.168.1.6"
mserver="192.168.1.7"

# Disable all rules
${fwcmd} -f flush
# Allow all in our network
${fwcmd} add pass all from ${net} to ${net}
# Allow Netbios packet
${fwcmd} add pass udp from ${net} to 255.255.255.255 via rl0
${fwcmd} add pass tcp from 255.255.255.255 to ${net} via rl0
# Allow DHCP
${fwcmd} add pass udp from any to ${ip} 67 via rl0
${fwcmd} add pass udp from any to ${ip} 68 via rl0
${fwcmd} add pass udp from ${ip} to any via rl0
${fwcmd} add pass udp from 0.0.0.0/8 68 to 255.255.255.255 67 in via rl0
${fwcmd} add pass udp from ${net} 67 to 255.255.255.255 68 in via vr0
${fwcmd} add pass icmp from ${net} to 224.0.0.0/24 in via vr0
${fwcmd} add pass icmp from ${net} to 224.0.0.0/24 in via rl0
# Stop spoofing
${fwcmd} add dyny all from any to ${net} in via rl0
# Stop RFC1918 nets on the outside interface
${fwcmd} add deny all from 10.0.0.0/8 to any
${fwcmd} add deny all from 172.16.0.0/12 to any
# Stop draft-manning-dsua-03.txt (1 May 2000) nets (includes RESERVED-1,
# DHCP auto-configuration, NET-TEST, MULTICAST (class D), and class E)
# on the outside interface
${fwcmd} add deny all from 169.254.0.0/16 to any
${fwcmd} add deny all from 192.0.2.0/24 to any
${fwcmd} add deny all from 224.0.0.0/4 to any

 以下ずらずらと書いていく。rc.firewallとは若干記述方法がルなる。これは片方のNICにのみIPを振って無差別受信モードで動作する為だと理解している。
 もちろん「素通り」が前提なのでポリシーをしっかり検討した上でこのホストではサービスを一切解放しないのが望ましい。
 感覚的には利用しているルータRT102iのフィルタ定義に似ていて理解しやすい。
 RT102iでは100個がフィルタ定義の制限だが、これでいくつでも利用できる事になる。

 なお、deny log を指定した際に/var/log/securityへ落ちるようにしているが、各チェーンエントリのログが指定(Kernel構築の際の[IPFIREWALL_VERBOSE_LIMIT=500])した制限数に達すると、そのエントリに関するログ取りが停止される。 ログ取りを再開するには、ipfw(8)ユーティリティを使用して関連するカウンタをリセットする必要がある。
ipfw zero 4500
4500 とは、ログ取りを続行したいチェーンエントリの番号。

各エントリの状況を確認するには
ipfw -a list | more
でも叩いて見るか、Dailyのメッセージをメールで受け取れば把握できる。

 /var/log/securityのローテーションは/etc/newsyslog.confで設定する。


[付録]
 セキュリティと言う意味では過去に不正侵入を受けた影響で十分に理解していなくても神経質になるが、Linux上で施した内容を記録しておく。

(1)passwdなど所有者権限で動作するコマンド類はSetUIDを外す事が望ましい。
(2)suコマンドを実行できるユーザーを制限し、不用意にユーザーにroot権限を与えない。
(3)SendmailやBINDのバナー表示を停止する。
(4)SMTPのEXPNやVRFYコマンドを制限する。
 各設定方法などはしっかりしたマニュアル(man)や参考書籍、サイトを参照して頂きたい。


トップへ戻る

21/January/2002