%%Title: Clam AntiVirusを試してみる
%%Created: Mon Aug 25 15:04:08 JST 2003
%%Updated: Mon Apr 18 19:43:07 JST 2005
以前から日に数十通か来ていたウイルス入りメールだけど、
感染の心配もないし無視できる量だった。
けど、2003/8/16の MS Blaster騒ぎのあと山のように降ってきて、
どれくらいかと言うと4時間で800通位、
1通100KB弱なので、4時間もほっとけば 70MBのスプールが溢れちゃう…
これはさすがに我慢ならないので何か対策を考えてみる。
o 何使ったらいいの?
やりたいことは以下の4つ
サーバ側ではねたい
ウイルス入りメールだけをはねたい
漏れたウイルスメールは次回はねるようにしたい
できればソースコードが欲しい
bogofilterを使うとウイルス入りメールじゃなくてもはねちゃうし、
そもそもbogofilterにウイルスメールを学習させると正しくspamチェックできなくなることもあるので、
ここは Anti-Virusアプリケーションの導入を考えてみた。
2003/08の時点の FreeBSDの /usr/ports/security を眺めると以下のアプリケーションがあった。
AMaViS
MTAとエンジンのパイプ。 perlなので速度が気になる。データベースが無償じゃなくなったらしい。
avcheck
MTAとエンジンのパイプ。エンジンは Dr.WEBかKasperskyを使う。
Dr.WEB
有償。お試し版があるが機能限定。
H+BEDV
有償。個人使用なら無料らしいけどバイナリ配布だし…
Clam AntiVirus
GPLライセンス。データベースは OpenAntiVirusを元にしている。
てな分けで Clam AntiVirusを試してみる。
Clam AntiVirusはファイルを検査してウイルスを見つけたり、ウイルスの入った
ファイルからシグネチャを作りユーザがデータベースを更新することができる。
圧縮してあるファイルも拡張子に対応して自動的に解凍して検査してくれる。
o どれくらい使えるか?
どういう基準を満たせば使えるのかとか、どれくらいのパフォーマンスが
必要なのかとか、はっきり言ってウイルスとは無縁の世界に住んでいたので、
まったく知識がありません。
以下のページの1章が参考になるかも。
http://clamav-jp.sourceforge.jp/
これによると相当使えなさそうだが、
今回の要求は「ウイルス入りのメールを検出したい」なので十分だと思う。
o NetBSDでのインストール
NetBSDは 2005/04/18の時点で、まだパッケージ化されていない。
libgmp4, libcurl が必要なので、これはパッケージから突っ込む。
パッケージを突っ込んだら、どっかで
setenv LDFLAGS "-L/usr/pkg/lib"
setenv CFLAGS "-I/usr/pkg/include"
しとかないとはまる。
% ./configure --with-dbdir=/usr/local/etc/clamav --disable-clamko --disable-clamav --enable-bigstack --disable-dependency-tracking
:
configure: WARNING: resolv.h: present but cannot be compiled
configure: WARNING: resolv.h: check for missing prerequisite headers?
configure: WARNING: resolv.h: see the Autoconf documentation
configure: WARNING: resolv.h: section "Present But Cannot Be Compiled"
configure: WARNING: resolv.h: proceeding with the preprocessor's result
configure: WARNING: resolv.h: in the future, the compiler will take precedence
configure: WARNING: ## ------------------------------------------ ##
configure: WARNING: ## Report this to the AC_PACKAGE_NAME lists. ##
configure: WARNING: ## ------------------------------------------ ##
:
は無視できる。
単に
# make install
すると /usr/local にインストールされるので /usr/pkgが好きな人は注意。
o FreeBSDでのインストール
FreeBSDだとパッケージ化されているので、さくっとインストールできる。
インストールされるプログラムのリスト
/usr/local/bin/clamscan
ウイルススキャンする
/usr/local/sbin/clamd
ウイルススキャンのサーバ
/usr/local/bin/clamdscan
ウイルススキャンのクライアント
/usr/local/bin/freshclam
データベースを更新する
/usr/local/bin/sigtool
シグネチャ作成ツール
clamscan(1)だけならば非ルート権限で使うことができるが、
clamd(8)を非ルート権限で動かしたいので clamav というユーザとグループを作る。
clamscanだけを使いたい場合はユーザ/グループを作る必要はない。
tarballが作られた時点のデータベースもインストールされる。
/usr/local/share/clamav/mirrors.txt
/usr/local/share/clamav/viruses.db
/usr/local/share/clamav/viruses.db2
これらは freshclam(1)を使ってすぐに更新すべきである。
o テスト
clamscan(1)でファイルを検査してみる。
ウイルスが見つかれば戻り値として0以外を返す。
35997 はウイルス入りのメールである。
% clamscan 35997
35997: OK
----------- SCAN SUMMARY -----------
Known viruses: 9340
Scanned directories: 0
Scanned files: 1
Infected files: 0
Data scanned: 0.10 Mb
I/O buffer size: 131072 bytes
Time: 0.588 sec (0 m 0 s)
おや??? base64 encodingはサポートしてない(2003/08現在)ようなので事前に
デコードしてからプログラムに渡す。
% b64decode < 35997 | clamscan -
stdin: Worm.Sobig.F FOUND
----------- SCAN SUMMARY -----------
Known viruses: 9340
Scanned directories: 0
Scanned files: 1
Infected files: 1
Data scanned: 0.07 Mb
I/O buffer size: 131072 bytes
Time: 1.426 sec (0 m 1 s)
これでいいのかな??
(少なくともclamav-0.84はサポートしています。)
o clamav.conf
o sendmail から使ってみる
少なくとも 0.75.1からは clamavに clamav-milterもパッケージされてます。
また、オプション --slient-discardが -Nに変更されています。
以下は sendmail.cfの所は使えるけど、それ以外は古い情報なので参考程度。
Milter APIを使う。FreeBSD4.7以降じゃないと libmiterが入ってないような気がする。
libmilter入りsendmailのコンパイルの方法はここを参照
http://www.sendmail.com/partner/resources/development/milter_api/api.html
- milterを使うように clamavを作り直す
configure オプションに --enable-milter を指定
少なくともFreeBSD4.8では、clamav-milterのディレクトリに以下のパッチが必要。
/usr/lib/sendmailがハードコーディングされているので適当に書き換える。
*** Makefile.in.orig Sat Jun 21 12:07:03 2003
--- Makefile.in Wed Aug 27 17:15:50 2003
***************
*** 122,124 ****
! @HAVE_MILTER_TRUE@@USE_PTHREAD_TRUE@clamav_milter_LDADD = ../clamd/cfgfile.o ../clamd/others.o
--- 122,124 ----
! @HAVE_MILTER_TRUE@@USE_PTHREAD_TRUE@clamav_milter_LDADD = ../clamd/cfgfile.o ../clamd/others.o ../clamscan/getopt.o
***************
*** 129,131 ****
LIBS = -L../libclamav -L/usr/lib/libmilter -lmilter @CLAMD_LIBS@
! INCLUDES = -I../clamd -I../libclamav
EXTRA_DIST = clamav-milter.c clamd.sh clamav-milter.sh INSTALL
--- 129,131 ----
LIBS = -L../libclamav -L/usr/lib/libmilter -lmilter @CLAMD_LIBS@
! INCLUDES = -I../clamd -I../libclamav -I../clamscan
EXTRA_DIST = clamav-milter.c clamd.sh clamav-milter.sh INSTALL
*** clamav-milter.c.orig Tue May 30 08:17:00 2000
--- clamav-milter.c Wed Aug 27 17:17:22 2003
***************
*** 952,954 ****
! sendmail = popen("/usr/lib/sendmail -t", "w");
if(sendmail) {
--- 952,954 ----
! sendmail = popen("/usr/sbin/sendmail -t", "w");
if(sendmail) {
clamav.conf を編集する
# cat /var/tmp/clamav.conf
LocalSocket /var/run/clamd.sock
ScanMail
StreamSaveToDisk ※ clamav.pdf4.1にはSaveStreamToDiskとあるがはタイポっぽい
- sendmail.cf の設定
mc に以下を追加して cf をリメイク
INPUT_MAIL_FILTER(`clmilter', `S=local:/var/run/clmilter.sock, F=, T=S:4m;R:4m')dnl
define(`confINPUT_MAIL_FILTERS', `clmilter')
- 実験
# /usr/local/sbin/clamd --config-file=/usr/local/etc/clamav.conf
# /usr/local/sbin/clamav-milter -lo --config-file=/usr/local/etc/clamav.conf /var/run/clmilter.sock
# /usr/sbin/sendmail -bd -q30m
さて、適当にウイルス入りメールを突っ込むんで /var/log/maillog を見てると
Aug 27 18:08:27 shoichi sendmail[71113]: h7R98R60071113: from=, size=103095, class=0, nrcpts=1, msgid=<20030827180827B.sakane@tanu.org>, proto=ESMTP, daemon=MTA-v4, relay=shoichi.tanu.org [127.0.0.1]
Aug 27 18:08:28 shoichi sendmail[71113]: h7R98R60071113: Milter: data, reject=550 5.7.1 Virus detected by ClamAV - http://clamav.elektrapro.com
Aug 27 18:08:28 shoichi sendmail[71113]: h7R98R60071113: to=, delay=00:00:01, pri=30377, stat=Virus detected by ClamAV - http://clamav.elektrapro.com
と検出されたようだ。あぁぁ幸せ…
ただし、コンソールに
clamfi_connect: connection from vw10.tanabe.co.jp [202.221.154.148]
clamfi_connect: connection from orange.kame.net [0.0.0.0]
と表示されるようになった。SMTPコネクションのログっぽい。
0.0.0.0 となるのは IPv6アドレスだから。
さて動かしてると core吐いて落ちました。うぬぬ。
ウイルスが見つかったことを postmasterへ通知するためにsendmailをpopen(3)する所で
落ちていた。
# gdb clamav-milter clamav-milter.core
GNU gdb 4.18 (FreeBSD)
: (snip)
Core was generated by `clamav-milter'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/lib/libmilter.so.2...done.
Reading symbols from /usr/lib/libc_r.so.4...done.
Reading symbols from /usr/lib/libc.so.4...done.
Reading symbols from /usr/libexec/ld-elf.so.1...done.
#0 0x280c40da in fileno () from /usr/lib/libc_r.so.4
(gdb) info st
#0 0x280c40da in fileno () from /usr/lib/libc_r.so.4
#1 0x280ac4fa in popen () from /usr/lib/libc_r.so.4
#2 0x804a4bc in clamfi_eom (ctx=0x805b280) at clamav-milter.c:961
#3 0x28070c0f in mi_clr_macros () from /usr/lib/libmilter.so.2
#4 0x28070100 in mi_engine () from /usr/lib/libmilter.so.2
#5 0x2806fd79 in mi_handle_session () from /usr/lib/libmilter.so.2
#6 0x2806f59e in mi_thread_handle_wrapper () from /usr/lib/libmilter.so.2
#7 0x2808f0a8 in _thread_start () from /usr/lib/libc_r.so.4
#8 0xbfa98ffc in ?? ()
どうもスレッドが絡んでそう…深そうなので追求せず。
オプションで postmasterへ通知しない(popen(3)しない)ようにして回避。
検知したことはsyslogに落ちるので必ずしも通知する必要ないはず。
*** clamav-milter.c.orig Thu Sep 4 09:35:45 2003
--- clamav-milter.c Mon Sep 1 10:58:41 2003
***************
*** 209,210 ****
--- 209,211 ----
static const char *serverIP = "127.0.0.1";
+ static int quiet = 0;
***************
*** 283,284 ****
--- 284,288 ----
{
+ "silent-discard", 0, NULL, 'Q'
+ },
+ {
"version", 0, NULL, 'V'
***************
*** 324,325 ****
--- 328,332 ----
break;
+ case 'Q': /* server running clamd */
+ quiet++;
+ break;
case 'V':
***************
*** 952,980 ****
! #if 0
! sendmail = popen("/usr/sbin/sendmail -t", "w");
! if(sendmail) {
! fputs("From: MAILER-DAEMON\n", sendmail);
! if(bflag) {
! fprintf(sendmail, "To: %s\n", privdata->from);
! fputs("Cc: postmaster\n", sendmail);
! } else
! fputs("To: postmaster\n", sendmail);
!
! for(to = privdata->to; *to; to++)
! fprintf(sendmail, "Cc: %s\n", *to);
! fputs("Subject: Virus intercepted\n\n", sendmail);
!
! if(bflag)
! fputs("A message you sent to\n\t", sendmail);
! else
! fprintf(sendmail, "A message sent from %s to\n\t", privdata->from);
!
! for(to = privdata->to; *to; to++)
! fprintf(sendmail, "%s\n", *to);
! fputs("contained a virus and has not been delivered.\n\t", sendmail);
! fputs(mess, sendmail);
! pclose(sendmail);
}
- #endif
--- 959,987 ----
! if (!quiet) {
! sendmail = popen("/usr/local/sbin/sendmail -t", "w");
! if(sendmail) {
! fputs("From: MAILER-DAEMON\n", sendmail);
! if(bflag) {
! fprintf(sendmail, "To: %s\n", privdata->from);
! fputs("Cc: postmaster\n", sendmail);
! } else
! fputs("To: postmaster\n", sendmail);
!
! for(to = privdata->to; *to; to++)
! fprintf(sendmail, "Cc: %s\n", *to);
! fputs("Subject: Virus intercepted\n\n", sendmail);
!
! if(bflag)
! fputs("A message you sent to\n\t", sendmail);
! else
! fprintf(sendmail, "A message sent from %s to\n\t", privdata->from);
!
! for(to = privdata->to; *to; to++)
! fprintf(sendmail, "%s\n", *to);
! fputs("contained a virus and has not been delivered.\n\t", sendmail);
! fputs(mess, sendmail);
! pclose(sendmail);
! }
}
しばらく使ってみたが3日に1度、同じ所で落ちるみたい。
# gdb clamav-milter /root/clamav-milter.core
GNU gdb 4.18 (FreeBSD)
: (snip)
Core was generated by `clamav-milter'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/lib/libmilter.so.2...done.
Reading symbols from /usr/lib/libc_r.so.4...done.
Reading symbols from /usr/lib/libc.so.4...done.
Reading symbols from /usr/libexec/ld-elf.so.1...done.
#0 0x804a672 in clamfi_cleanup (ctx=0x805b280) at clamav-milter.c:1040
1040 if(privdata->dataSocket >= 0) {
(gdb) info st
#0 0x804a672 in clamfi_cleanup (ctx=0x805b280) at clamav-milter.c:1040
#1 0x804a628 in clamfi_abort (ctx=0x805b280) at clamav-milter.c:1012
#2 0x280701f0 in mi_engine () from /usr/lib/libmilter.so.2
#3 0x2806fd79 in mi_handle_session () from /usr/lib/libmilter.so.2
#4 0x2806f59e in mi_thread_handle_wrapper () from /usr/lib/libmilter.so.2
#5 0x2808f0a8 in _thread_start () from /usr/lib/libc_r.so.4
#6 0xbf9bbffc in ?? ()
(gdb)
うむむ、スレッド回りに虫がいるのかも…
o ウイルスデータベース
OpenAntiVirusのデータベースは更新されていないようだが、Clam AntiVirus側で更新し続けているようである。
ここから拾ってこれる。
freshclam(1)を使うと見て自動的にデータベースが更新される。
mirror.txt に書かれている所から MD5をチェックして取ってくる。
# freshclam
Current working dir is /usr/local/share/clamav
Checking for a new database - started at Wed Aug 27 18:05:54 2003
Connected to clamav.elektrapro.com.
Reading md5 sum (viruses.md5): OK
Reading md5 sum (viruses2.md5): OK
Downloading viruses.db .........................................(snip)
Downloading viruses.db2 ....... done
Database updated (containing in total 9433 signatures).
Database updated from clamav.elektrapro.com.
cron(8)で動かすと便利かもしれない。
# cat /etc/crontab
0 5 * * * clamav /usr/local/bin/freshclam --quiet -l /var/log/freshclam.log
freshclamはユーザclamavで実行されるので /var/log/clam-update.logに書けるようにしておく必要がある。
# touch /var/log/freshclam.log
# chown clamav:clamav /var/log/freshclam.log
/etc/newsyslog.conf の編集も忘れずに
# cat /etc/newsyslog.conf
: (snip)
/var/log/freshclam.log clamav:clamav 640 2 100 * Z
sigtoolを使うと自分でデータベースのレコード(virus signature)を作れる。
ここ
からウイルスのレポートを送ることもできる。反映されるのかは不明。
o clamdscan
clamd(8)のクライアント