piyo
■CentOS サーバ構築編(3)  -- ウィルスチェック ( sendmail + ClamAV ) --

■ウィルスチェックを行う
クライアント側(WindowsPC)ではウィルス対策しているとはいえ、メーリングリストもあることだしサーバ側でもウィルスチェックをしようかと。フ リーのウィルス検索エンジンもあることだし。ということで、Clam AntiVirus(ClamAV)を試してみることにしました。
InterScanをはじめ、商用のものはいろいろ触ってますが、フリーのものは初体験。なぜに ClamAV かというと、特に根拠はなし。思い立ったときに目についたからです(をい)。「clamav」 で google先生に聞いてみたところ先頭に出た日本語のページがリンク切れだったので、探すのめんどくさくなって本 家のドキュメントだけを頼ってやってみました。本家のドキュメントに書かれているもろもろのPATH等が、ソースに含まれているドキュメント類と 異なるため若干とまどいましたが、基本的にはソースのドキュメントの方に従って設定しています。

なお、現時点(2005/3/12)での最新は0.83です。

入手元:http://www.clamav.net/
0.90のインストールメモ (2007.02.17)

■ClamAV のインストール
本家のリンクにはRedHat/Fedora用のバイナリパッケージがあるんですが、依存性の問題でインストールできませんでした。
ちなみに、rpmで突っ込もうとしたときのエラーはこれ。

# rpm -ivh clamav-0.83-1.i386.rpm
warning: clamav-0.83-1.i386.rpm: V3 DSA signature: NOKEY, key ID 6cdf2cc1
error: Failed dependencies:
        libc.so.6(GLIBC_2.3.4) is needed by clamav-0.83-1
        zlib >= 1.2.1.2 is needed by clamav-0.83-1

srpmも 試してみましたが、やはり依存性の問題で rebuild できません。glibc-2.3.4 と zlib-1.2.1.2 を要求されるためです。
うちのCentOS 3 は glibc-2.3.2-95.30/zlib-1.1.4-8.1 なので、glibc と zlib を入れ替えないと使えない模様。それ用に独自に yumの レポジトリは用意されてるみたいですが、今ひとつ信用できないのでパス。ソースからインストールすることにします。

○インストール準備
まずは環境を確認。ClamAV には sendmail と組み合わせて使うための clamav-milter が用意されているので、sendmailがこれに対応しているかチェック。

$ /usr/sbin/sendmail -d0 < /dev/null |fgrep MILTER
                MATCHGECOS MILTER MIME7TO8 MIME8TO7 NAMED_BIND NETINET NETINET6

これはOK。標準のバイナリなら問題なく使えるということですね。次に、 clamav-milter のコンパイルに sendmail-devel パッケージが要求されるので、これがインストールされているかをチェック。

$ rpm -qa | grep sendmail
sendmail-cf-8.12.11-4.RHEL3.1
sendmail-8.12.11-4.RHEL3.1

インストールされていなかったので、sendmail-devel パッケージをインストールします。

# yum -y install sendmail-devel

さらに、ClamAV 用にユーザ・グループを作成しておきます。useraddでグループも同時に作られます。

# useradd -s /bin/false clamav

○ClamAVのインストール
# tar xvzf clamav-0.83.tar.gz
# cd clamav-0.83
# ./configure --enable-milter
# make
# make isntall

clamav-milter を利用するため、 --enable-milter オプションをつけて configure しています。
./configure --help でその他のオプションを確認できます(省略)。

○clamd.conf の修正
vi /usr/local/etc/clamd.conf
[/usr/local/etc/clamd.conf]
8c8
< Example
---
> #Example
14a15,16
> LogFile /var/log/clamd.log
>
34c36
< #LogTime
---
> LogTime
43c45
< #LogSyslog
---
> LogSyslog
57a60
> PidFile /var/run/clamav/clamd.pid
72c75,76
< LocalSocket /tmp/clamd
---
> #LocalSocket /tmp/clamd
> LocalSocket /var/run/clamav/clamd.sock
144c148
< #User clamav
---
> User clamav

※赤字部分は必須。ユーザclamavの権限で clamd  を起動しないと、clamav-milter が使えない模様。

○local socket用ディレクトリ作成
# mkdir -p /var/run/clamav
# chown clamav:clamav /var/run/clamav
# chmod 700 /var/run/clamav

○sendmail.cf の修正
clamav-milter を利用してウィルス検索を行うためには、sendmail側の修正も必要となります。
sendmail.cf を直接編集するのは大変なので、基本通り sendmail.mc を修正。MAILER行よりも上に、下の2行を追加。
私は直前に追加しました。

[/etc/mail/sendmail.mc(2行追加)]
INPUT_MAIL_FILTER(`clamav', `S=local:/var/run/clamav/clmilter.sock, F=, T=S:4m;R:4m')dnl
define(`confINPUT_MAIL_FILTERS', `clamav')

sendmail.mc を編集したら、sendmail.cf を再生成。

# cd /etc/mail
# cp sendmail.cf sendmail.cf.bak
# make -C /etc/mail

※万一失敗したときに備えて、sendmail.cf は必ずバックアップしておきます。



■起動・動作確認

まずは起動してみます。rootで実行。clamd、clamav-milter が無事起動したら、sendmailも再起動。
# /usr/local/sbin/clamd
# /usr/local/sbin/clamav-milter -lo /var/run/clamav/clmilter.sock --external
# service sendmail restart

動作確認のためのコマンドも用意されていますが、面倒くさいので(をい)、この状態でサーバ上のアカウントに対しメールを投げてみました。すると、配信さ れたメールのヘッダに以下の2行が挿入されていました。

X-Virus-Scanned: ClamAV version 0.83, clamav-milter version 0.83 on chibi.yomaigoto.jp
X-Virus-Status: Clean

どうやらきちんとウィルスチェックしているようです。次にテストウィルスEicar.com を添付したメールを投げてみましたら、しっかりと拒絶されました。

554 5.7.1 virus Eicar-Test-Signature detected by ClamAV - http://www.clamav.net

syslog には、以下のように記録されました。

[/var/log/mailllog](抜粋)
Mar 12 17:11:43 chibi sendmail[27332]: j2C8BhVX027332: Milter add: header: X-Virus-Status: Infected with Eicar-Test-Signature
Mar 12 17:11:43 chibi sendmail[27332]: j2C8BhVX027332: Milter: data, reject=554 5.7.1 virus Eicar-Test-Signature detected by ClamAV - http://www.clamav.net
Mar 12 17:11:43 chibi sendmail[27332]: j2C8BhVX027332: to=<***@*******.**>, delay=00:00:00, pri=30721, stat=virus Eicar-Test-Signature detected by ClamAV - http://www.clamav.net

ばっちりですね。ただ、最近のウィルスはfrom: を詐称するので、Reject したり警告メッセージを送信者に送る設定は余計なトラフィックを増やすだけになるので、本運用時にはこのあたりも考えないといけないですね。



■パターンファイルのアップデート
ウィルス検索ソフトはウィルス検索用のdbファイルパターンファイル)が随時更新されていないと使い物にならないので、アップデートができるかどうかをま ず確認。設定ファイル (/usr/local/etc/freshclam.conf) の Exapmle行をとりあえずコメントアウト。

[/usr/local/etc/freshclam.conf]
#Example

コマンドラインから freshclam を実行し、パターンファイルのアップデートが正常に行われるかを確認。

# freshclam
ClamAV update process started at Sat Mar 12 15:07:33 2005
Downloading main.cvd [*]
main.cvd updated (version: 30, sigs: 31086, f-level: 4, builder: tkojm)
Downloading daily.cvd [*]
daily.cvd updated (version: 761, sigs: 481, f-level: 4, builder: ccordes)
Database updated (31567 signatures) from database.clamav.net (IP: 61.8.0.16)

きちんとアップデートされたようです。これを自動で随時アップデートさせるには、cron に登録するか、デーモンモードで起動する必要があります。うちではデーモンモード( -d オプション) で起動することにします。また、国内のMirrorサーバを利用するように設定を変更します。

# vi /usr/local/etc/freshclam.conf
[/usr/local/etc/freshclam.conf]
9c9
< Example
---
> #Example
18c18
< #UpdateLogFile /var/log/freshclam.log
---
> UpdateLogFile /var/log/clam-update.log
26c26
< #LogSyslog
---
> LogSyslog
55c55
< #DatabaseMirror db.XY.clamav.net
---
> DatabaseMirror db.jp.clamav.net
80c80
< #NotifyClamd
---
> NotifyClamd

アップデートのログはあらかじめ touch しておかないと作成されないようなので、併せて作っておきます。

# touch /var/log/clam-update.log
# chmod 600 /var/log/clam-update.log
# chown clamav /var/log/clam-update.log



■起動スクリプトの作成・登録
自動で起動できるように、起動スクリプトを作成し、chkconfig --add しておきます。
こんな感じで作ってみました。sendmail よりも先に起動する必要があります。

○起動スクリプト [/etc/init.d/clamav]
#!/bin/bash
#
# clamav      This shell script takes care of starting and stopping
#             clamAV.
#
# chkconfig: 2345 78 30
# description: clamAV is an anti-virus daemon.

# Source function library.
. /etc/rc.d/init.d/functions

start() {
        echo -n "Starting clamd:"
        /usr/local/sbin/clamd
        RETVAL=$?
        [ $RETVAL -eq 0 ] && echo_success
        [ $RETVAL -ne 0 ] && echo_failue
        echo

        echo -n "Starting clamav-milter:"
        /usr/local/sbin/clamav-milter -eNPlo /var/run/clamav/clmilter.sock
        RETVAL=$?
        [ $RETVAL -eq 0 ] && echo_success
        [ $RETVAL -ne 0 ] && echo_failue
        echo

        echo -n "Starting freshclam:"
        /usr/local/bin/freshclam -d
        RETVAL=$?
        [ $RETVAL -eq 0 ] && echo_success
        [ $RETVAL -ne 0 ] && echo_failue
        echo
}

stop() {
        for i in clamav-milter clamd freshclam
        do
                echo -n "Stopping $i:"
                killproc $i
                echo
        done
        if [ -f /var/run/clamav/clmilter.sock ]; then
                rm /var/run/clamav/clmilter.sock
        fi
}

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        stop
        start
        ;;
  *)
        echo $"Usage: $0 {start|stop|restart}"
        exit 1
        ;;
esac

※起動と停止でclamd と clamav-milter の順番が入れ替わってますが、この順でないときちんと停止できませんでした。

※追記・・・2005/6/26
stop 時にclmilter.sock が残ったままだと logのローテーション時の restart でこける場合があることが判明したので、stop時に強制的に clmirter.sock を削除する処理を追加。

○起動スクリプトの登録
# chmod 755 /etc/init.d/clamav
# chkconfig --add clamav
# chkconfig clamav on

【参考】clamav-milter の起動オプション(赤字は私が指定しているもの)
オプション
短縮形
概    要
--advisory
-A
Flag viruses rather than deleting them.
--bounce
-b
Send a failure message to the sender. (使用しないことを推奨)
--broadcast
-B [IFACE] Broadcast to a network manager when a virus is found.
--config-file=FILE
-c FILE
Read configuration from FILE.
--debug
-D
Print debug messages.
--detect-forged-local-address
-L
Reject mails that claim to be from us.
--dont-log-clean
-C Don't add an entry to syslog that a mail is clean.
--dont-scan-on-error
-d
Pass e-mails through unscanned if a system error occurs.
--dont-wait

Ask remote end to resend if max-children exceeded.
--external
-e
Use an external scanner (usually clamd).
--from=EMAIL
-a EMAIL
Error messages come from here.
--force-scan
-f
Force scan all messages (overrides (-o and -l).
--help
-h
This message.
--headers
-H
Include original message headers in the report.
--local
-l
Scan messages sent from machines on our LAN.
--max-childen
-m
Maximum number of concurrent scans.
--outgoing
-o
Scan outgoing messages from this machine.
--noreject
-N
Don't reject viruses, silently throw them away.
--noxheader
-n
Suppress X-Virus-Scanned/X-Virus-Status headers.
--pidfile=FILE
-i FILE
Location of pidfile.
--postmaster
-p EMAIL
Postmaster address [default=postmaster].
--postmaster-only
-P
Send warnings only to the postmaster.
--quiet
-q
Don't send e-mail notifications of interceptions.
--quarantine=USER
-Q EMAIL
Quanrantine e-mail account.
--quarantine-dir=DIR
-U DIR
Directory to store infected emails.
--server=SERVER
-s SERVER
Hostname/IP address of server(s) running clamd (when using TCPsocket).
--sendmail-cf=FILE

Location of the sendmail.cf file to verify
--sign
-S
Add a hard-coded signature to each scanned message.
--signature-file=FILE
-F FILE
Location of signature file.
--template-file=FILE
-t FILE
Location of e-mail template file.
--timeout=SECS
-T SECS
Timeout waiting to childen to die.
--whitelist-file=FILE
-W FILE
Location of the file of whitelisted addresses
--version
-V
Print the version number of this software.



■ログのローテーション
syslog が定期的にローテーションされるように、logrotate の設定ファイルを作成しておきます。

# vi /etc/logrotate.d/clamav
[/etc/logrotate.d/clamav]
/var/log/clamd.log {
    missingok
    create 0640 clamav root
}
/var/log/clam-update.log {
    missingok
    create 0600 clamav root
    postrotate
        /sbin/service clamav restart 2>/dev/null || /bin/true
    endscript
}

とりあえずこんなところで様子を見てみます。幸いにも私の個人アドレスにはほとんどウィルスは来ないので、サーバへの負荷もさほど気にしていません。ユー ザ数が多いサーバでも使えるのかどうか、という点については興味のあるところですね。

(2005/3/13)

※追記・・・2005/5/3
どうも syslog のローテーション時にfreshclam が寝るっぽいので、kill -HUP を追加しました。上記参照。
ついでに、0.84 にバージョンアップしました。

※さらに追記・・・2005/6/4
kill -HUP でもあんまりよろしくないので、最終的に service restart になりましたとさ。
現在は 0.85.1 です。LogWatchを何とかしようと調整中。。。うまくできたら公開します。



■LogWatchの修正
ということで。LogWatchに修正を加えてみました。デフォルトのままにしておくと、cronからのLogWatchではClamAVのログをこんな 風に通知してきます(余計な行は省いてます)。

 --------------------- sendmail Begin ------------------------

**Unmatched Entries**
   Milter add: header: X-Virus-Status: Clean: 199 Time(s)
   Milter add: header: X-Virus-Scanned: ClamAV version 0.85.1, clamav-milter version 0.85 on chibi.yomaigoto.jp: 199 Time(s)

 ---------------------- sendmail End -------------------------

別にこれでもいいんですけど、せっかく自分でインストールしたのに "Unmatched Entries" と毎日言われるのも癪なので、なんとかしようかと。

LogWatchの設定ファイルは /etc/log.d/ 以下にありまして、なんとなく眺めていたらちょこっと直せばいけそうな気がしてきたのでやってみました。LogWatch自体 perl スクリプトなので、perl が得意な方には造作ないことなんでしょうが、あいにくと私はほとんど perl わからない人なので、このあたりが限界っす。

sendmail 関係の処理は /etc/log.d/scripts/services/sendmail に書かれています。デフォルトでamavis のログは切り分けるようになってるみたいなので、これをそのままClamAVに変えてしまいます。ついでに X-Virus-Status も集計するようにしときましょ。

# vi /etc/log.d/scripts/services/sendmail
[/etc/log.d/scripts/services/sendmail]
52,53c52,57
<    } elsif ( $ThisLine =~ m/X-Virus-Scanned: by amavis/) {
<       $Amavis++;
---
>    } elsif ( $ThisLine =~ m/X-Virus-Scanned: ClamAV/) {
>       $ClamAV++;
>    } elsif ( $ThisLine =~ m/X-Virus-Status: Clean/) {
>       $ClamAVClean++;
>    } elsif ( $ThisLine =~ m/X-Virus-Status: Infected/) {
>       $ClamAVInfected++;
149,150c153,162
< if ($Amavis > 0) {
<    print "\n" . $Amavis . " messages scanned by Amavis";
---
> if ($ClamAV > 0) {
>    print "\n" . $ClamAV . " messages scanned by ClamAV";
> }
>
> if ($ClamAVClean > 0) {
>    print "\n" . "     Number of Clean messages:    " . $ClamAVClean;
> }
>
> if ($ClamAVInfected > 0) {
>    print "\n" . "     Number of Infected messages: " . $ClamAVInfected;


 --------------------- sendmail Begin ------------------------

217 messages scanned by ClamAV
     Number of Clean messages:    217

 ---------------------- sendmail End -------------------------

その後ウィルスが届いていないので、感染した場合もちゃんと集計されるかは目下の所不明(笑)。

さらに。ClamAVは結構頻繁にバージョンアップされていて、バージョンが上がると freshcram がログに吐いて教えてくれます。

/var/log/messages から抜粋:
Jun 25 10:10:28 chibi freshclam[28045]: --------------------------------------
Jun 25 12:10:28 chibi freshclam[28045]: Received signal: wake up
Jun 25 12:10:28 chibi freshclam[28045]: ClamAV update process started at Sat Jun 25 12:10:28 2005
Jun 25 12:10:28 chibi freshclam[28045]: WARNING: Your ClamAV installation is OUTDATED!
Jun 25 12:10:28 chibi freshclam[28045]: WARNING: Local version: 0.85.1 Recommended version: 0.86.1
Jun 25 12:10:28 chibi freshclam[28045]: DON'T PANIC! Read http://www.clamav.net/faq.html
Jun 25 12:10:28 chibi freshclam[28045]: main.cvd is up to date (version: 32, sigs: 34720, f-level: 5, builder: tkojm)
Jun 25 12:10:29 chibi freshclam[28045]: daily.cvd updated (version: 957, sigs: 1386, f-level: 5, builder: ccordes)
Jun 25 12:10:29 chibi freshclam[28045]: Database updated (36106 signatures) from db.jp.clamav.net (IP: 211.10.155.48)
Jun 25 12:10:29 chibi freshclam[28045]: Clamd successfully notified about the update.
Jun 25 12:10:29 chibi freshclam[28045]: --------------------------------------

/var/log/clam-update.log から抜粋:
--------------------------------------
Received signal: wake up
ClamAV update process started at Sat Jun 25 12:10:28 2005
WARNING: Your ClamAV installation is OUTDATED!
WARNING: Local version: 0.85.1 Recommended version: 0.86.1
DON'T PANIC! Read http://www.clamav.net/faq.html
main.cvd is up to date (version: 32, sigs: 34720, f-level: 5, builder: tkojm)
daily.cvd updated (version: 957, sigs: 1386, f-level: 5, builder: ccordes)
Database updated (36106 signatures) from db.jp.clamav.net (IP: 211.10.155.48)
Clamd successfully notified about the update.
--------------------------------------

もともとはこっちをLogWatchに拾わせたかったわけですが。。。挫折しました(をい)。
perl わかんないんだもん。。。仕方ないので、こんなスクリプト作ってごまかしました。

[/etc/cron.daily/ClamAV-VerCHK]
#!/bin/sh

DATE=`date +%b" "%d --date='1 day ago'`
LOG=/var/log/messages

grep "$DATE" $LOG | grep  "WARNING: Local version:" | sed -e 's/^.*\]://' | uniq

バージョンが上がるとこんな風にroot宛にメールで通知が来ます。

 Subject: Cron <root@chibi> run-parts /etc/cron.daily

/etc/cron.daily/ClamAV-VerCHK:

 WARNING: Local version: 0.85.1 Recommended version: 0.86.1

LogWatchが全部やってくれた方がスマートなんだけど、しゃあないか。目的は達しているのでよしとします。
(2005/6/27)
[TOP]