ノウハウ

ナビゲーションをスキップして本文へ

階層ナビゲーション

前後のナビゲーション

概要

この章では ClamdOmitScan をよりうまく運用するためのノウハウについて説明します。

ClamdOmitScan.pl の使い方についてはそのオンラインマニュアルやその HTML 版をご覧ください。前章の節「インストール」でそれらの生成について言及してあります。po2manpod2html が使えないなどの理由で生成できない人は次のリンクから参照してください。(man.html)

スキャン対象の限定

概要

スキャン対象を限定するのは ClamAV を利用する上で重要です。ClamAV はスキャン対象のファイルが大きくなればなるほど多くのメモリを消費しスキャン時間が長くなります。スキャン中は 1CPU あるいは 1core の利用率をかなり消費するので、そうするとシステム全体を圧迫してしまいます。

そこで効率よく定期スキャンを行うためにスキャン対象から外すファイルを検討してみましょう。このセクションの内容のほとんどは clamscan にも通じます。clamdscan には通じません。clamd の設定ファイル clamd.conf に似た設定項目はありますが、それは clamuko というのが有効でないと利用できません。それに用途が少し異なります。つまり clamdscan で一般に特定のファイルやディレクトリをスキャン対象から外すことはできません。

ここに書いたオプションを付けると時間がかかり過ぎてディスク全体の定期スキャンに使えなかった ClamAV が使える範囲に入ってきます。ClamdOmitScan.pl なら最初こそ我慢すれば実用的になります。

OS の重要なファイル

--move オプションや --remove オプションで感染ファイルを隔離したり削除したりしている場合、カーネルやスワップイメージなども対象にすると OS が停止したり、二度と起動できないようになってしまいます。ですから自動で隔離したり削除するようにしている場合は OS の重要なファイルはスキャン対象から外すべきです。

このようなファイルをスキャン対象から外すオプションは例えば次のようになります。

Mac OS X 10.4.x
'--exclude=^/+mach_kernel$'
'--exclude=^/+mach\.sym$'
'--exclude=^/+private/var/vm/sleepimage$'
'--exclude=^/+private/var/vm/swapfile\d+$'
'--exclude=^/+private/var/vm/app_profile/[0-9a-f]+_(?:data|names)$'

これら以外でそのファイルがないとシステムが立ち行かないファイルはたくさんあります。しかしそれらを全て列挙するのはほとんど無理です。システム領域をスキャンするときは隔離や削除を行わないようにしたほうがよいでしょう。それでもスワップイメージやスリープのためのメモリイメージはかなり大きいのでシステムを致命的に圧迫します。外すべきです。

ディスクイメージ

ClamAV はディスクイメージの内容を取り出すことができません。このためディスクイメージのファイルをスキャンしても無駄です。そしてそういうファイルは得てしてサイズが大きく、システムを圧迫してしまいます。

このようなファイルをスキャン対象から外すオプションは例えば次のようになります。

一般
'--exclude=[^/]+\.iso$'
'--exclude=[^/]+\.iso\.gz$'
'--exclude=[^/]+\.iso\.bz2$'
Mac OS X 10.4.x 固有
'--exclude=[^/]+\.dmg$'
'--exclude=[^/]+\.dmg\.gz$'
'--exclude=[^/]+\.dmg\.bz2$'
仮想化ソフトの仮想ハードディスク
'--exclude=[^/]+\.hds$'
'--exclude=[^/]+\.vhd$'

ディスクイメージはマウントしたときにスキャンするのがよいでしょう。マウントしなければその中のファイルがシステムに影響を与えることもありません。しかしマウントする OS の機能の脆弱性につけ込む攻撃方法もあります。ディスクイメージのファイルをスキャン対象から外すということはその種類の攻略ファイルに対して無防備になることでもあります。実際に上のようなオプションを付けるかどうかは、そのリスクに対する評価と付けないことによるシステムパフォーマンスへの影響の評価によって運用者自身が判断してください。

隔離ディレクトリ

--move オプションや --copy オプションで指定したディレクトリの中のファイルをスキャンするのは無駄です。既に感染していることがわかっているからです。もし感染していないファイルもあるディレクトリを指定しているのであれば、誤って感染しているファイルを実行したり開いたりしてしまう危険を自ら背負うことになります。ですからそれはやめましょう。どんなセキュリティシステムを導入しても人のミスや不注意がセキュリティホールとして残るものです。

隔離ディレクトリをスキャン対象から外すオプションは例えば次のようになります。

一般
'--exclude-dir=^隔離ディレクトリの絶対パス(/.*)?$'

上の「隔離ディレクトリの絶対パス」は少し細工しておくのがよいでしょう。それは先頭の「/」の直後に + を付けておく細工です。ClamdOmitScan.pl ではそんなことはありませんが、clamscan は引数に / を指定すると全てのパスを //… として扱う可能性があります。+ はそれへの対処です。

スキャンデータディレクトリ

ClamdOmitScan.pl のスキャンデータが収められているディレクトリには大量のファイルが生成されます。今使っているスキャンデータのディレクトリは自動的にスキャン対象から外されますが他のユーザのは外されません。大量のファイルは clamd に大量の要求を発するのでスキャン効率が落ちてしまいます。ですから他のユーザのスキャンデータのディレクトリはスキャン対象から外しておいた方が効率よくスキャンできます。

スキャンデータのディレクトリをスキャン対象から外すオプションは例えば次のようになります。

Mac OS X
'--exclude-dir=^/+Users/[^/]+/.ClamdOmitScan(/.*)?$'
'--exclude=^/+Users/[^/]+/.ClamdOmitScan\.lock$'
UNIX 系一般
'--exclude-dir=^/+home/[^/]+/.ClamdOmitScan(/.*)?$'
'--exclude=^/+home/[^/]+/.ClamdOmitScan\.lock$'

スキャンデータのディレクトリはデフォルトでは他の一般ユーザが全く読み書きできないようになっています。ですから他のユーザのスキャンデータのディレクトリの中をスキャンする心配は root によるスキャンに限られます。

外部ディレクトリ

WebDAV や FTP あるいは SFTP によるネットワーク上のフォルダをマウントしたディレクトリ、USB メモリ等遅いデバイスをマウントしたディレクトリをスキャンするのも効率を落とします。ファイルの内容や情報を取得するのに時間がかかるからです。

外部ディレクトリをスキャン対象から外すオプションは例えば次のようになります。

Mac OS X
'--exclude-dir=^/+Volumes(/.*)?$'
'--exclude-dir=^/+afs(/.*)?$'
'--exclude-dir=^/+Network(/.*)?$'
'--exclude-dir=^/+automount(/.*)?$'

ただしマウントしてあるのでこれらのディレクトリのファイルもローカルのファイルと同じ操作方法で操作できます。ということは気軽に開いたり実行したりできるということです。そこに感染ファイルがあると危険です。これも効率とリスクの評価によって運用者が決めてください。スキャン対象から外す場合は直接そこから開かずに一旦ローカルディスクに保存して ClamXavSentry などでスキャンしてから開きましょう。恒常的にマウントしたり自動マウントするフォルダはスキャン対象にしていた方がよいかもしれません。

ClamAV のソースアーカイブ

ClamAV のソースアーカイブにはテスト用の仮想感染ファイルが入っています。このためソースアーカイブをスキャンすると感染ファイルとして報告してしまいます。

ソースアーカイブをスキャン対象から外すオプションは例えば次のようになります。

ソースアーカイブ
'--exclude=/clamav-[0-9]+(\.[0-9]+)*\.tar\.gz$'
'--exclude-dir=/clamav-[0-9]+(\.[0-9]+)*/test(/.*)?$'
Perl モジュール
'--exclude=/File-Scan-ClamAV-([0-9]+)(\.[0-9]+)*\.tar\.gz$'
'--exclude-dir=/\.cpan/build/File-Scan-ClamAV-([0-9]+)(\.[0-9]+)*/testfiles(/.*)?$'

上のオプションで指定されたファイルと同名のファイル、あるいは同じような場所にあるファイルはスキャンされません。ということはそれを装った感染ファイルを見逃してしまうということです。これも効率とリスクの評価によって運用者が決めてください。

ファイルサイズの制限

概要

スキャン対象の限定」で述べたように大きなファイルのスキャンはシステム全体を圧迫するので避けたいところです。もし運用しているマシンのメモリが少ない等で重大な影響があるようでしたらファイルのサイズでスキャンする/しないを選別することができます。

clamscanclamdscan、そして ClamdOmitScan.pl にもスキャン対象のファイルの大きさを制限するオプションはありません。その代わり ClamdOmitScan.pl には --stream-max-length というオプションがあります。clamd は STREAM clamd コマンドを使ってファイルをスキャンするときに送られてくるデータ(ファイルの内容)に制限をもっていて、その制限を超えたデータがやってくるとデータ送信の接続を有無を言わさず切断するようになっています。このときクライアント側の Perl が落ちてしまいます。これを防止するために clamd の制限に合わせて、その制限以上の大きさのファイルを送信しないためのオプションが --stream-max-length なのです。

ですから ClamdOmitScan.pl が必ず STREAM clamd コマンドを使用するような状況にすれば --stream-max-lengthclamd.conf に書かれた StreamMaxLength の値より大きいファイルはスキャンされません。必ず STREAM clamd コマンドを使用するためには INET ソケットを使って clamd に接続するようにします。そして INET ソケットで clamd に接続するためには clamd がそれを受け付けるように設定されなければなりません。

しかし、大きいファイルをスキャンしないということは大きな感染ファイルを検知できないことでもあるということを心に留めておいてください。

clamd の設定

まずは clamd 側の設定を整えます。clamd が使用する設定ファイル clamd.conf で次のようにします。

TCPSocket 接続ポート
TCPAddr 接続アドレス

接続ポート」は例えば 3310 を指定します。運用している他のサービスと重ならない 2000 より大きい値を指定してください。「接続アドレス」は他のマシンからの接続をしないのであれば 127.0.0.1 を、そうでなければ clamd を実行するマシンに割り当てられた LAN 上の IP アドレスを指定します。複数の IP アドレスを持っているマシンで、全ての IP アドレスで clamd への接続を許可したい場合は TCPAddr の行は不要です。

INET ソケットしか使わないのであれば

LocalSocket /tmp/clamd

と書いてあるところを次のようにコメントにします。

#LocalSocket /tmp/clamd

今テーマにしていることから考えるとこのコメント化はしておいたほうがよいでしょう。

他のマシンから接続する場合は、もしあればファイアーウォールの設定で「接続ポート」への接続を許可するようにしてください。

STREAM clamd コマンドが受け付けるデータの容量のデフォルトは 10M ですが、別な値を使用したいときは次を加えてください。

StreamMaxLength 容量

容量」には 10M, 10240K のようにメガとキロの単位を付けることもできます。

ClamdOmitScan.pl のオプション

clamd が実際に使用している clamd.conf またはそのコピーがあり、それが /usr/local/etc/clamd.conf のときは、そこに LocalSocket の設定があると ClamdOmitScan.pl は必ず UNIX ドメインソケットを使用しようとして INET ソケットを使用してくれません。ここでは必ず INET ソケットを使うようにすることがテーマなので、そのような /usr/local/etc/clamd.conf があるときに備えてダミーの clamd.conf を用意してください。その内容は次のようにします。

TCPSocket 接続ポート
TCPAddr 接続アドレス

本来の clamd.confStreamMaxLength を指定しているときはそれに倣って次を加えます。

StreamMaxLength 容量

接続ポート」「接続アドレス」「容量」は clamd の設定で用いた値を使用してください。

そして、ClamdOmitScan.pl を使用するときに次のようにします。

ClamdOmitScan.pl --config-file=ダミーのclamd.conf

そのときに --port, --host, --socket, --stream-max-length オプションは使用しないでください。

もちろん本来の clamd.confLocalSocket が設定されていないのであればダミーの clamd.conf を用いる必要はありません。--port, --host, --stream-max-length 場合によっては --config-file を用いて実行します。これらのどのオプションが必要なのかはケースバイケースで全てを網羅すると煩雑になるので割愛します。

スキャンデータの保守

ClamdOmitScan.pl はスキャン対象になっているファイルやディレクトリのスキャンデータを自動的に保守します。ここでいう保守とは次をすることです。

  • 既に削除されたファイルやディレクトリのスキャンデータを削除する。

    普段の使用でファイルやディレクトリを削除したときにスキャンデータが取り残されます。取り残されたスキャンデータを削除し無駄なデータをなくします。

  • 内容を正しく読み取れないスキャンデータを削除する。

    スキャン途中で ClamdOmitScan.pl を停止させたときに壊れたスキャンデータができることがあります。このような壊れたデータをなくします。

  • ファイルからディレクトリへというようにタイプが変わったパスのスキャンデータを削除する。

    以前あったファイルと同名のディレクトリを作ったり、その逆をしたときにスキャンデータが取り残されます。取り残されたスキャンデータを削除し無駄なデータをなくします。

  • パーミッションの不整合を補正する。

    異なった --perm-root--perm-dir--perm-file--perm-lock オプションの値が用いられるとスキャンデータの中のファイルやディレクトリに異なったパーミッションが混在してしまいます。これを実行時の指定またはデフォルト値に統一します。

自動で保守する場合スキャンデータのディレクトリ内の全てのデータを保守するわけではありません。このため定期スキャンの対象が変わったときやコマンドラインから実行したときに作成されたスキャンデータが残ることがあります。残っていても特に困るようなことはあまりありませんが、多少はディスクを使用するので無駄を省くためにときどきスキャンデータ全体を保守するのがよいでしょう。また既存のデータは書き換えられない限りパーミッションは変更されません。上に示したオプションの指定が変わるとパーミッションの状況も変わってしまいます。そうすると読めないデータ書けないデータが生じる可能性があります。これを解消するのもこの保守の目的です。そのためには次のようにします。

ClamdOmitScan.pl --maintain-scan-data …

保守中は他の ClamdOmitScan.pl がスキャンデータを参照するのを待たせた方が良いかもしれません。そのためには次のようにします。

ClamdOmitScan.pl --maintain-scan-data --lock …

これを定期的に(例えば毎月一回)行うようにしておくとスキャンデータの無駄が自動で取り除かれます。デフォルトではスキャンデータは実行時のユーザ毎に異なるので自分のスキャンデータだけでなく定期スキャンのときのユーザのスキャンデータもあることに注意してください。定期スキャンの対象はそうそう変えることはないと思うので、対象を変更したときにコマンドラインから明示的に行うのでもよいでしょう。

BSD 系の UNIX を使用していて常時稼働しているわけではないコンピュータのときは、crontab@reboot 指定で起動時に保守するのもよいかもしれません。--maintain-scan-data を付けたときは clamd と接続しないので OS の起動途中でも実行できます。

シリアル実行

ウィルススキャンはコストがかかる処理です。clamd が一つ一つのファイルのデータをスキャンしている最中は 1CPU または 1core に対する使用率は 90% 以上になります。マルチプロセッサやマルチコアのマシンならともかくシングルプロセッサのマシンでは全体のパフォーマンスに大きく影響します。これは ClamAV に限ったことではありません。

そこで ClamdOmitScan.pl は同じスキャンデータを利用する、したがって同じユーザの、スキャンが同時に行われないようにする機能を持っています。これは複数のプロセスが同時に変更してスキャンデータに不整合をもたらすのを防ぐためでもあります。

同じスキャンデータを利用する他の ClamdOmitScan.pl がスキャンデータを参照し始めるのを待たせるためには次のようにします。

ClamdOmitScan.pl --lock …

この --lock オプションを付けると排他ロックという種類のロックをスキャンデータのロックファイルにかけます。このオプションがないと共有ロックという種類のロックをかけます。排他ロックと共有ロックの影響を表にしてみます。

排他ロックと共有ロックの影響
影響
排他ロック 排他ロック 待たされる
排他ロック 共有ロック 待たされる
共有ロック 排他ロック 待たされる
共有ロック 共有ロック 待たされない

このように共有ロック同士なら待たされませんがそれ以外のケースは全て後からロックするプロセスは一時停止します。したがって --lock オプションを付けて ClamdOmitScan.pl を実行すると同じスキャンデータを利用する他の ClamdOmitScan.pl が実質的な処理を開始する直前で一時停止します。逆に他のプロセスが同じスキャンデータを利用していると --lock オプションを付けた ClamdOmitScan.pl は実質的な処理を開始する直前で一時停止します。

これを利用することで ClamdOmitScan.pl の処理をシリアル化できます。つまり他の ClamdOmitScan.pl の処理が終わってから次の ClamdOmitScan.pl の処理が開始されるようにできます。ただし効力が及ぶのは同じスキャンデータを利用する範囲です。

定期処理は多くの場合幾つかの種類があります。日次処理、週次処理、月次処理などです。それぞれにスキャン対象の範囲を変えて ClamdOmitScan.pl を実行するようにしていると、ClamdOmitScan.pl が重複して実行されることもあるでしょう。そういうときに --lock オプションを付けておくことで別個に予定された ClamdOmitScan.pl の実行をシリアル化することができます。

clamd の不調への対処

常時起動されているマシンで clamd を運用していると clamd も常時起動されているので終了するまで解放しないメモリが少しずつ溜まって OS の仮想メモリを消費してしまいます。仮想メモリの出し入れはパフォーマンスに大きく影響します。このため clamd の応答が鈍ってしまいます。その他にも clamd が原因不明で応答しなくなることもあるようです。

普段はタイムアウトしないのに ClamdOmitScan.pl が「Scan timeout: ファイルのパス名」と警告を出力したり「Frequence of continual clamd timeout is over 連続タイムアウト許容回数.」と出力して終了するようになったら clamd を再起動してみてください。それで軽快になることがほとんどです。

ClamdOmitScan.pl にはスキャン時にタイムアウトが発生したときに実行するコマンドラインを指定するオプションがあります。--timeout-command オプションです。このオプションの引数に clamd を再起動するコマンドラインを指定しておくとタイムアウトが発生するたびに clamd が再起動されます。例を挙げます。

Linux 風
ClamdOmitScan.pl --timeout-command='/etc/rc.d/init.d/clamd restart' …
Mac OS X 風
ClamdOmitScan.pl --timeout-command='/Library/StartupItems/ClamAntiVirusDaemon/ClamAntiVirusDaemon restart' …

大抵の場合 clamdroot でしか再起動できないようにしていることと思います。ですからこれができるのは rootClamdOmitScan.pl を実行しているときです。また他のユーザも ClamdOmitScan.plclamdscan を実行していると clamd の再起動中にそちらでエラーが発生してしまうことに留意してください。複数 ClamdOmitScan.pl が実行される状況ではこの指定の影響が懸念されます。このため --timeout-command オプションをオンラインマニュアルには記載していません。

セキュリティへの配慮

概要

clamd はデフォルトの状態ではローカルユーザなら誰でも接続できるようになっています。またファイアーウォールによりますが TCPSocketclamd.conf で指定することで LAN 内の任意のユーザからの接続もできるようになります。

このことは SHUTDOWN clamd コマンドを clamd に送信したり、無駄に clamd へ接続したりすることでローカルユーザや LAN 内の任意のユーザが clamd のサービスを妨害することが簡単にできるということを意味します。いわゆる DoS 攻撃です。

このセクションではこの DoS 攻撃を緩和する方法について議論します。

検討すべき項目

clamd に限りませんがサービスを提供するときにセキュリティ上必ず考えなければならないことがあります。

  • どこからアクセスしてもよいか。

    そのサービスにアクセスする元のマシンの範囲について検討してください。ローカルからなのか、LAN からだけなのか、特定のマシンからだけなのか。clamd に関しては WAN の任意のマシンからアクセスできるようにしておくのは論外です。

    これを制御する技術にはアクセスリストやパケットフィルターなどがあります。

  • 誰がアクセスしてもよいか。

    そのサービスを利用することができるユーザの範囲について検討してください。誰でも利用してよいのか、特定のユーザ群なのか、特定のユーザだけなのか。

    これを制御する技術にはパーミッションや認証などがあります。

  • どのようにアクセスしてもよいか。

    アクセスの方法について検討してください。送受信される内容は途中の経路で盗み見されないように暗号化すべきか、複数のアクセス手段があるときはそのどれを使用するのか。

    これを制御する技術には SSL などがあります。

  • 何をしてもよいのか。

    一般にはこれも検討すべきことですが clamd には発行できる clamd コマンドを制限する機能はありません。ですからこの場合は検討しなくてもよいです。ですが、アクセスできたら SHUTDOWN もできてしまうということを念頭に置いてください。

    これを制御する技術にはパーミッションや認証などがあります。

要約すると「どこの誰がどのように何をしてよいことにするか」というのを検討するということです。そして clamd に限定すると「どこの誰がどのように clamd に接続してもよいか」を検討することになります。

ただし STREAM clamd コマンドでスキャンするときにデータを送信するには必ず INET ソケットが使用されます。「どのように」の制御は clamd コマンドに関してのみの制御です。

ローカルアドレスの使用

これは「どこからアクセスしてもよいか」を「ローカルからのみアクセスしてよい」に限定する方法です。

clamd.conf に次のように書いてください。

TCPAddr 127.0.0.1

こうすると INET ソケットを使用するとき、127.0.0.1 という IP アドレスに対してのみ接続できるようになります。127.0.0.1 はローカルホストの IP アドレスで lo という ethernet インターフェースでのみ接続できる IP アドレスです。lo でアクセスできるのはローカルホストのみなので結局のところ clamd を実行しているマシンからしか INET ソケットでアクセスできません。

TCPAddr を設定しても TCPSocket を設定しなければ INET ソケットで接続できるようにはなりません。これは INET ソケットで接続できるようにしてもローカルからしか受け付けないとする方法です。

INET ソケットの不使用

これは「どこからアクセスしてもよいか」と「どのようにアクセスしてもよいか」をそれぞれ「ローカルからのみアクセスしてよい」と「UNIX ドメインソケットでのみアクセスしてよい」に限定する方法です。

clamd.conf

TCPSocket ポート番号

と書いてあったら次のようにしてコメントにするかその行を削除してください。

#TCPSocket ポート番号

ローカルからのアクセスに限定するのなら UNIX ドメインソケットで大抵の場合は十分ですが、INET ソケットを有効にしておくと便利なこともあります。UNIX ドメインソケットにはプログラムを書かないと clamd コマンドを送れませんが、INET ソケットは telnet コマンドでインタラクティブに clamd コマンドを送信しその応答を受け取ることができます。次はその様子です。

$ telnet 127.0.0.1 3310
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
VERSION
ClamAV 0.90.2/3195/Wed May  2 18:34:51 2007
Connection closed by foreign host.
$ 

便利なことにセキュリティ上の弱点があるのはよくあることです。こうやって SHUTDOWN clamd コマンドを送れてしまうのです。

UNIX ドメインソケットへのアクセス制限

これは「誰がアクセスしてもよいか」を「特定のユーザまたはグループのみがアクセスしてよい」とする方法で、「どのようにアクセスしてもよいか」を「UNIX ドメインソケットでのみアクセスしてよい」に限定しているときにのみ効果があります。

clamd.confLocalSocket を指定すると clamd は UNIX ドメインソケットで接続できるようになります。ClamAV のソースからのインストールでは /tmp/clamd.socket というソケットファイルがその UNIX ドメインソケットです。

ソケットファイルも一種のファイルなので UNIX を強固にしている概念であるパーミッションによってアクセスを制限することができます。chmod コマンドや chgrp コマンドで書き込みができる(つまり clamd にコマンドを送信できる) UNIX グループを指定したり、特定のユーザ(例えば root)だけが書き込みができるようにできます。

しかしながら clamd を起動した直後は全てのユーザから書き込みができるようになっています。これを変更する clamd のオプションや clamd.conf の設定はありません。このため clamd の起動スクリプトに手を加えて、clamd の起動後に chmod コマンドや chgrp コマンドで制御することになります。スクリプトに手を加えるのは面倒です。

そこでお薦めするのがソケットファイルを置くディレクトリへのアクセス制限の付与です。

  1. ソケットファイルを置くディレクトリを作成する。

    例えば /var/ClamdOmitScan というディレクトリを作ります。root で次のようにします。

    mkdir /var/ClamdOmitScan

    Mac OS X のように root でログインできないのがデフォルトの場合は次のようにします。

    sudo mkdir /var/ClamdOmitScan
  2. ソケットファイルを置くディレクトリのパーミッションを設定する。

    root でしかアクセスできないようにするには root で次のようにします。

    chown root /var/ClamdOmitScan
    chmod go-rwx /var/ClamdOmitScan

    Mac OS X のように root でログインできないのがデフォルトの場合は次のようにします。

    sudo chown root /var/ClamdOmitScan
    sudo chmod go-rwx /var/ClamdOmitScan

    wheel という UNIX グループに所属するユーザでしかアクセスできないようにするには root で次のようにします。

    chown root:wheel /var/ClamdOmitScan
    chmod 0770 /var/ClamdOmitScan

    Mac OS X のように root でログインできないのがデフォルトの場合は次のようにします。Mac OS X の場合は wheel ではなく admin がよいでしょう。

    sudo chown root:admin /var/ClamdOmitScan
    sudo chmod 0770 /var/ClamdOmitScan
  3. ソケットファイルをそこに置くように設定する。

    clamd.conf に次のように記述します。

    LocalSocket /var/ClamdOmitScan/clamd.socket

    この例では clamd.socket という名前のソケットファイルにしています。

ネットワークの限定

これは「どこからアクセスしてもよいか」を「特定のネットワークからのみアクセスしてよい」に限定する方法です。

一般に一つのマシンが所属するネットワークは複数あります。一つの LAN にだけ参加しているマシンでも lo というローカルインターフェースによるネットワークと LAN に繋がっている ethernet インターフェースによるネットワークの二つがあります。「ローカルアドレスの使用」はここで述べる方法の一つの具体例でもあります。

ここで重要なのは ethernet インターフェースです。そのマシンにある ethernet インターフェースに割り当てられた IP アドレスを指定して、そこへの接続のみを受け付けるようにします。例えば有線 LAN からに限定するとかということです。許可したいネットワーク向けの IP アドレスと許可したくないネットワーク向けの IP アドレスを区別していないときはここで述べる方法で限定することはできません。そういう場合はファイアーウォールで限定します。また、DHCP を用いていて IP アドレスが変動する可能性がある場合もここで述べる方法で限定することはできません。

  1. インターフェースに対する IP アドレスを調べる。

    引数無しで ifconfig コマンドを実行すると存在する ethernet のインターフェースに関する情報が出力されます。例えば次のような情報がインターフェース毎に出力されます。

    en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
            inet6 fe40::116:abff:fe15:5013%en1 prefixlen 64 scopeid 0x5 
            inet 192.168.8.12 netmask 0xffffff00 broadcast 192.168.8.255
            ether 00:26:db:35:57:03 
            media: autoselect status: active
            supported media: autoselect

    この中で inet の直後の 192.168.8.12 の部分が目的の IP アドレスです。

  2. 接続を受け付ける IP アドレスを指定する。

    clamd.conf に例えば次のように記述します。

    TCPSocket 3310
    TCPAddr 192.168.8.12

    3310192.168.8.12 はあなたの環境に合わせて変えてください。3310 はポート番号です。運用している他のサービスと重ならない 2000 より大きい値を指定してください。

複数の IP アドレスへの接続を許可したいときは TCPAddr の設定はしないで一旦全ての IP アドレスで接続を受け付けるようにしておいてからファイアーウォールで限定します。

PPTP などによる WAN のアドレスを使用するのは避けましょう。そうすると世界中の誰でもがあなたの clamd を使用できるようになってしまいます。あっという間に SHUTDOWN させられるならまだましです。未知の脆弱性を突かれるかもしれません。そうするときは必ず接続元をファイアーウォールで限定して、信頼できるところからしか接続できないようにしなければなりません。

ファイアーウォールによる限定

これは「どこからアクセスしてもよいか」を限定する方法です。

ファイアーウォールに用いられているソフトウェアによってその設定の仕方は様々です。ですからここで具体的な設定方法を述べることはできません。論理的なレベルで設定を示唆するに留めます。また INET ソケットによる接続を許可しない場合やローカルアドレスに限定する場合には不要です。

まずはポートを空けるかどうかしか設定できないファイアーウォールの場合です。

最も単純なファイアーウォールの設定
ポート プロトコル
TCPSocket の値 TCP
StreamMinPort の値から StreamMaxPort の値まで TCP

解放するかしないかの二者択一です。これはファイアーウォールと呼べるかどうか疑問ですが、Mac OS X の環境設定から設定できるファイアーウォールはこの程度の設定しかできません。「どこからアクセスしてもよいか」を全く限定できないのでこれだけの設定で満足しないでください。Mac OS X には ipfw という優れたファイアーウォール用の仕組みが入っているのでわざわざセキュリティ製品を買ってこなくても高度なファイアーウォールが設置できます。

比較的低機能なファイアーウォールの設定
種類 方向 ソース デスティネーション プロトコル
アドレス ポート アドレス ポート
1 許可 入力 許可する IP アドレス
またはその範囲
任意 clamd を運用するマシンの IP アドレス TCPSocket の値 TCP
2 許可 出力 clamd を運用するマシンの IP アドレス TCPSocket の値 許可する IP アドレス
またはその範囲
任意 TCP
3 不許可 入力 任意 任意 clamd を運用するマシンの IP アドレス TCPSocket の値 TCP
4 許可 入力 任意 任意 clamd を運用するマシンの IP アドレス StreamMinPort の値から StreamMaxPort の値まで TCP
5 不許可 入力 任意 任意 任意 StreamMinPort の値から StreamMaxPort の値まで TCP

上のは一昔前のルータ等で設置できるファイアーウォールの設定はこの程度です。2 番目の設定が弱点です。

高機能なファイアーウォールの設定
種類 方向 ソース デスティネーション プロトコル 条件
アドレス ポート アドレス ポート
1 許可 入力 任意 任意 任意 任意 TCP 接続済み
またはそれに関連する
2 許可 入力 許可する IP アドレス
またはその範囲
任意 clamd を運用するマシンの IP アドレス TCPSocket の値 TCP 接続要求
3 不許可 入力 任意 任意 clamd を運用するマシンの IP アドレス TCPSocket の値 TCP

1 のルールは clamd に限らず何にでも通用する基本の設定です。2 のルールで clamd への接続を許可し、1 のルールでその後のやり取りと STREAM clamd コマンドのデータ送信に使用される接続を許可します。3 のルールで許可されていないマシンからの clamd への接続を拒否します。問題は STREAM clamd コマンドのデータ送信のためのポートが、clamd コマンドのための接続と関連したものであると認識されるかどうかです。もし認識されないようならば次のようにしなければなりません。

高機能なファイアーウォールの設定 その2
種類 方向 ソース デスティネーション プロトコル 条件
アドレス ポート アドレス ポート
1 許可 入力 任意 任意 任意 任意 TCP 接続済み
またはそれに関連する
2 許可 入力 許可する IP アドレス
またはその範囲
任意 clamd を運用するマシンの IP アドレス TCPSocket の値 TCP 接続要求
3 不許可 入力 任意 任意 clamd を運用するマシンの IP アドレス TCPSocket の値 TCP
4 許可 入力 許可する IP アドレス
またはその範囲
任意 clamd を運用するマシンの IP アドレス StreamMinPort の値から StreamMaxPort の値まで TCP 接続要求
5 不許可 入力 任意 任意 clamd を運用するマシンの IP アドレス StreamMinPort の値から StreamMaxPort の値まで TCP

どれも同じですがデフォルト不許可です。そういうルールを入れておいてください。ファイアーウォールはデフォルト不許可にして許可するものを追加するのが基本です。

設定の振り分け

root で行うユーザをまたぐ定期スキャンと各ユーザが独自に行うスキャンとで clamd のインスタンスを分けることもできます。これは複数のポリシーの clamd を用意するということです。

まず、それぞれのポリシーに従って、次のものが重ならないように clamd.conf を複数用意します。

  • LocalSocket の値
  • TCPSocket の値
  • StreamMinPort の値から StreamMaxPort の値までの範囲

INET ソケットによる接続を許可しないのであれば TCPSocket を設定しないでください。UNIX ドメインソケットを使用しないのであれば同様に LocalSocket を設定しないでください。そしてこのセクションのこれまでのサブセクションで述べた事柄で必要なものをそれぞれの clamd.conf に対して行います。もはや clamd.conf という名前にする必要はありませんがファイルの種類としてここでは clamd.conf という名前を使い続けます。

更にそれぞれの clamd.conf の用途に従って clamd が起動した後のプロセスのオーナとなるユーザを検討してください。root で行わなくてよいことは root で行ってはいけません。root 以外のユーザで行うようにするには次の設定を clamd.conf に加えます。

User 起動後のプロセスのオーナ

そしてそれぞれの clamd.conf を用いて clamd を起動するようにします。これは次のようにします。

/usr/local/sbin/clamd --config-file=使用するclamd.conf

このコマンドラインを実行するサービスの起動/終了を管理するスクリプトをプラットフォームのポリシーに従って作成しておくとよいでしょう。

特に root によるユーザをまたぐ定期スキャンは重要で、他のユーザに邪魔されるのは問題です。「INET ソケットの不使用」と「UNIX ドメインソケットへのアクセス制限」を行い一般ユーザや外部に対する clamd サービスとは区別しておくことをお薦めします。

スキャンデータの共有

ClamdOmitScan.pl のメリットは偏にスキャンデータにあります。いつどのバージョンの ClamAV とそのウィルスデータベースを使用してスキャンしたかを一度スキャンしたファイルに対して記録しているデータです。これを参照することで再びスキャンする必要があるかどうかを判断し、スキャンする必要がないファイルのスキャンを省略するのが ClamdOmitScan.pl のコアのアイデアです。

デフォルトでは ClamdOmitScan.pl を実行するユーザ毎に別なスキャンデータを使用するようになっていて、他のユーザからは全く参照できないようなパーミッションが付与されます。それはスキャンデータの中身を見ればどこになんという名前のディレクトリやファイルがあるかが全てわかってしまうからです。他のユーザがそういう情報を知ることができるとしたらセキュリティ上の弱点に繋がる可能性があります。

しかし同じディレクトリやファイルをスキャンするのに別々のスキャンデータを使用するとしたら、本当はもうスキャンする必要がないのにまたスキャンしてしまうという無駄が発生することになります。セキュリティ上の弱点に繋がる可能性なしにこの無駄を抑えたいものです。

次のケースでは同じスキャンデータを使用してもよいでしょう。

  • rootsu コマンドで切り替われる、あるいは sudo コマンドで root として任意のコマンドを実行できるユーザが ClamdOmitScan.pl を実行する。
  • 同じ UNIX グループに所属するユーザが、そのグループ内では自由に読み書きできるディレクトリに対して ClamdOmitScan.pl を実行する。

特別なセキュリティの仕組みがなければ root はパーミッションに関係なく全てのディレクトリとファイルを参照できます。したがって root として何かを実行できるユーザに対してファイルやディレクトリを隠し切ることはできません。できないのでスキャンデータを共有しても問題ありません。というより共有しても発生する問題は同じです。同じ UNIX グループが共有するディレクトリについても同様です。

これを実現するためには次のようにします。

  1. UNIX グループの選定または作成。

    まずスキャンデータを共有させたいユーザが一つの UNIX グループに所属している必要があります。su コマンドや sudo コマンドで root に切り替わることができるユーザを一つの UNIX グループにまとめます。そういうグループは例えば wheeladmin というグループがプラットフォームの中で決まっているでしょう。既にそういうグループがあればそれを用います。

  2. スキャンデータを置くディレクトリの作成。

    次にその UNIX グループが共有するスキャンデータを置くディレクトリを作成します。1 で選定または作成した UNIX グループに所属するユーザか root で次を行います。

    mkdir スキャンデータを置くディレクトリ
  3. スキャンデータを置くディレクトリのオーナーとパーミッションの設定。

    そしてそのディレクトリに次のようにオーナーとパーミッションを付与します。これも 1 で選定または作成した UNIX グループに所属するユーザか root で行います。

    chgrp 共有するユーザが所属するグループ スキャンデータを置くディレクトリ
    chmod 02770 スキャンデータを置くディレクトリ

    ディレクトリに setgid ビットを付与しています。これはそのディレクトリの下に作られるファイルやディレクトリのオーナグループは、そのディレクトリのオーナグループと同じになるようにするためです。

  4. ClamdOmitScan.pl を実行するときのオプション。

    そしてその UNIX グループに所属するユーザが共有するスキャンデータを使用したいときに次のようにして ClamdOmitScan.pl を実行します。

    ClamdOmitScan.pl --perm-root=02770 --perm-dir=02770 --perm-file=0660 --perm-lock=0660 …

    ここでもディレクトリに setgid ビットを付与しています。これによって再帰的にスキャンデータ全体が同じオーナグループになります。

    これらのオプションを付け忘れると共有スキャンデータの中に共有されないデータが混じってしまいます。徹底するためにシェルスクリプトや alias を用意するとよいでしょう。例えば次のようなものを用意します。

    シェルスクリプト
    #!/bin/sh
    /usr/local/bin/ClamdOmitScan.pl --perm-root=02770 --perm-dir=02770 --perm-file=0660 --perm-lock=0660 --include-dir='共有しているディレクトリの指定' $*
    alias
    alias groupScan="/usr/local/bin/ClamdOmitScan.pl --perm-root=02770 --perm-dir=02770 --perm-file=0660 --perm-lock=0660 --include-dir='共有しているディレクトリの指定'"

    ここで「共有しているディレクトリの指定」はそのグループが共有しているディレクトリを表す正規表現です。例えば“/home/project”ならば“^/+home/project(/.*)?$”とします。--include-dir オプションを付けるとそのディレクトリ配下のファイルのみがスキャン対象になります。複数の --include-dir オプションがあるときはそれらで指定されたどれかのディレクトリ配下であればスキャン対象になります。つまり OR 条件です。