Mac OSX 10.6.8 (でなくても良かった) に 無料 (Free) のClamAV Anti virus の自動化(drag&drop, folder action)を導入

Mac OSX 10.6.8 (でなくても良かった) に 無料 (Free) のClamAV Anti virus の自動化 (drag&drop, folder action)を導入
2016/12/25、12/31, 2020/8/20 改訂中

MacBook Pro 13 (late 2009) を、RAMを2x4GB、SSD storage (1TB )で、現役バリバリで使用している。OSは、OSX 10.6.8 (Snow Leopard) 止まり。使用しているCADアプリ他のアプリ(値段が張るのですよ)が、10.7以降に対応していないため。

OSもCADアプリ他も、必要最低限の機能はあり特に新版を購入する理由は無い、、、。(となるので、ソフト会社は新しいもののみに対応させて、旧版を陳腐化させたいのですよ、ね。)

さて、OSX 10.6.8 自身には問題は無いのだが、ネットワークに接続する際は Anti Virus アプリのインストールが必須と言うのが ITセクションの要請。(Macでvirusにかかったことは無いのだが、それはたまたま運が良かっただけ、、、なのか。)

OSXは 10.7 からAPIを変えたためか、殆どの Anti Virus アプリが 10.7以降対応となっており、10.6.8では フリー(無料)のアプリは皆無。その中で唯一 オープンソース/皆でサポートの ClamAV が利用可能。その昔、OSX 初期時代(古いね)に使用した事はあったが、今も生き残っていてくれた事は 嬉しいとともに驚き。

ClamAVを使用するには素人には敷居が高く(と思っていた)、ClamXAVなるユーザインターフェイスを使用して、簡単に使えていた。が、ClamXAVも(30日間の無料版はあるが)有料化されて、使えなくなっていた。(生きていくためにはお金が必要なのです。)

仕方が無いので、ClamAVの導入に挑戦、いくつもの壁を乗り越え(がこの備忘録)、更に、使用方法が解って来たので、applescriptでスキャンを自動化。スクリプトコマンドコマンドレベルのローレベルで設定・コントロールしているので、何をしている/させたいのか見通せて(ブラックボックスでない)精神的に良いし、自動化で快適に使えているので、今のところメデタシ メデタシ。(あとは、ClamAVコミュニティーが virus databaseを最新に維持してくれる事を願うのみ、、、か。)


[1. ClamAVのインストール]

https://www.clamav.net/downloads

から最新版を入手。この時点で clamav-0.99.2.tar.gz
tar.gzを展開すると、clamav-0.99.2フォルダーができる。
で、terminalを開き (以下、">"はterminalでコマンドを入れる事を意味する)、

> cd ...../clamav-0.99.2
> ./configure
> make
> make install

特にデフォールト設定から変える必要はない。コンパイルに時間がかかる。お茶でも飲んで気長に待つ。途中をみているとwarningらしきものが出ているが、何か解らないので無視。最後に、errorが表示されていないので、インストールは成功、とみて良い(だろう)。

config ファイル → /usr/local/etc/
freshclam, clamscan, clamdscan → /usr/local/bin/
clamd → /usr/local/sbin/

にインストールされている。


[2. clamd 環境の整備]

clamd.confの編集

> cd /usr/local/etc
> sudo cp clamd.conf.sample clamd.conf
> sudo vi clamd.conf

>>> 以下、次の文を無効/有効化する
#Example ← この文は#で無効化する、以下は#を消して有効化
LogFile /var/log/clamd.log
TCPSocket 3310
User clamav ← this is critical to make clamdscan can connect to clamd
LogTime yes
<<<

clamd.log ファイルの作成・属性の編集

> sudo touch /var/log/clamd.log
> sudo chown clamav:clamav /var/log/clamd.log
> sudo chmod 666 /var/log/clamd.log ← worldまで読み書きにしないと書き込みエラーがでる。

clamdの実行

> sudo /usr/local/sbin/clamd & ← "&"をつけてバックグランドで走らせる

(止めるには、例えば Activity monitor.app で停止。Terminal で > kill -9 <PID> でも出来る。走らせるには、「6. Scanの自動化」の script appを導入すれば、scan実行時、自動で走る。)

[3. freshclam 環境の整備]

Virus databaseの入手・自動アップデートは freshclam が行う。

> cd /usr/local/etc
> sudo cp freshclam.conf.sample freshclam.conf
> sudo vi freshclam.conf

>>> 以下の文を無効/有効化
#Example
UpdateLogFile /var/log/freshclam.log
LogTime yes
<<<

virus database 領域の編集

> sudo chown 82:82 /usr/local/share/clamav ← user, group 82は共にclamav
> sudo chmod 777 /usr/local/share/clamav ← clamd, freshclam で使用するので777
> sudo chmod 666 /usr/local/share/clamav/mirrors.dat ← freshclam が書き込む
> sudo chown 82:82 /usr/local/bin/freshclam

freshclam.log ファイルの作成・属性編集

> sudo touch /var/log/freshclam.log
> sudo chmod 666 /var/log/freshclam.log
> sudo chown clamav:clamav /var/log/freshclam.log

freshclamの(daemon モードでの)実行

> freshclam -d

これで virus database が 2時間おきにアップデートされる。


[4. scanの実行]

clamscan.log ファイルの作成・属性の編集

> sudo touch /var/log/clamscan.log
> sudo chown 82:82 /var/log/clamscan.log
> sudo chmod 666 /var/log/clamscan.log ← worldまで読み書きにしないと書き込みエラーがでる(かも)。

scanの個別手動実行は、

> clamdscan -r -i --no-summary <file/folder> > /var/log/clamscan.log &

clamdが走っていないと errorになる。clamd の実行は 2.を参照。各オプションは、

-r フォルダー内のフォルダーもrecursiveにscan
-i virusの検知されたファイルのみリスト
--no-summary 実行のsummaryを出力しない
> /var/log/clamscan.log 結果をファイルに保存。毎回、新規に書き出すため。--log=/var/...オプションだと追記されるので古いものが残ってしまう
& バックグランドで実行

clamdscan と clamscan の違い:

virus databaseをメモリーに保持している(clamdscan → clamdを使用)か、storage から読み出し (clamscan)の差。
実行速度が違う。


[5. White listの作成]

大きな外付け usb disk等を挿入した場合 (例えば、TimeMachine用disk)、scanに非常に時間がかかる。ので、Virusに罹っていないことが解っている場合、或は Virusが入っている事が解っていても Virusは隔離されている、、、ような場合、scanから外したい事が有る。scanから外すために White list の機能を実装する。

White list ファイルは、/var/log/clamWhiteList.log とする。

> sudo touch /var/log/clamWhiteList.log

たとえば、USBDISK と言う名の 外付けdisk をscan対象から外す場合、

> cd /var/log
> sudo vi clamWhiteList.log
>>>
/Volumes/USBDISK/
<<<

の全パスを書き込む。Directory/folder 名の場合、末尾に"/"が必要。


6. scanの自動化 (ドラッグ&ドロップ、フォルダーアクション)

applescriptを独自に作成。(コピーは自由ですが、著作権は私に有りますので宜しく。)

drop_clamscan.app : file/folder を drag&drop して clamdscan
clamscan.app : /Library/Scripts/Folder Action Scripts/ に入れて、フォルダーアクションでフォルダーをscan

OSXの アプリケーションフォルダー>ユーティリティーAppleScriptエディター.appを起動し、

>>> 以下 ...<<< までを書き込み
on open theDroppedItems
--display dialog "clamscan for " & theDroppedItems
set theLogFile to "/var/log/clamscan.log"
scanWithClamAV(theDroppedItems, theLogFile)
end open

on scanWithClamAV(theItems, theLogFile)

(* set theIcon to clamav.icns if exits *)
set theApp to (path to me) as text
set theIcon to appIcon(theApp)
--display dialog theIcon

(* check clamd and freshclam are running *)
set {appName, appDir, appOption} to {"clamd", "/usr/local/sbin/", ""}
isRunning(appName, appDir, appOption, theIcon)

set {appName, appDir, appOption} to {"freshclam", "/usr/local/bin/", " -d"}
isRunning(appName, appDir, appOption, theIcon)

--set theLogFile to "/var/log/clamscan.log"
set isUsedFlag to isUsed(theLogFile, "clamdscan")
if isUsedFlag is true then return 1

set theFile to POSIX path of theLogFile
--set fh to open for access file theFile with write permission
-- make sure theFile exists, otherwise the next line generates an error
set eof of theFile to 0

(* get white list *)
set whiteList to paragraphs of (do shell script "/bin/cat /var/log/clamWhiteList.log")

(* scan dropped items *)
repeat with aFile in theItems

(* check white list *)
set aFilePath to quoted form of POSIX path of aFile as text
set aFileToScan to true
repeat with aWhite in whiteList
--display dialog aFilePath & " " & quoted form of aWhite
if aFilePath is equal to quoted form of aWhite then
set aFileToScan to false
--display dialog "White list ---- " & aFilePath giving up after 5 with icon theIcon as alias
end if
end repeat
--display dialog aFileToScan

(* do scan *)
if aFileToScan then
set theShellScript to ("/usr/local/bin/clamdscan --quiet -i -m --log=" & theLogFile & " --no-summary " & aFilePath)
--display dialog theShellScript
tell me to activate
display dialog "Scanning --- " & aFilePath buttons {"Cancel", "OK"} default button 2 with title "Clamscan" giving up after 3 with icon theIcon as alias
try
do shell script theShellScript
end try
end if

end repeat
--close aFilePath with saving
--display dialog "... scan finished." giving up after 1 with icon theIcon as alias
--close access fh

(* notify virus *)
if aFileToScan then
set volumeSetting to output muted of (get volume settings)
set volume without output muted

set Shows to (do shell script "/bin/cat " & theLogFile)
--set Shows to paragraphs of (read theLogFile)
--display dialog "here"

if Shows contains "FOUND" then
beep 3
--display dialog "Virus: "
--display dialog "Virus: " & Shows buttons {"OK"} default button "OK" with icon theIcon as alias giving up after 30 with title theLogFile
-- keep displayed untill "OK" is clicked
display dialog "Virus: " & Shows buttons {"OK"} default button "OK" with icon theIcon as alias with title theLogFile
else
display dialog "Virus not found --- " & theItems buttons {"OK"} default button "OK" with icon theIcon as alias giving up after 10
end if

if volumeSetting then set volume with output muted
end if

end scanWithClamAV

on isRunning(appName, appDir, appOption, theIcon)
set appNameIsRunning to (do shell script "/bin/ps -arxo state,comm | /usr/bin/grep " & appName & " | /usr/bin/cut -c 1")
if appNameIsRunning is "" then
--display dialog "Start " & appName & " ? " giving up after 2 with icon theIcon as alias
do shell script appDir & appName & appOption & " &"
else
--display dialog appName & " --- running."
end if
end isRunning

on isUsed(fileName, byAppName)
--display dialog (do shell script "/bin/ps -arx | /usr/bin/grep " & fileName)
set fileNameIsUsed to (do shell script "/bin/ps -arx | /usr/bin/grep " & fileName)
-- & appName)
set isUsedFlag to false
repeat with theLine in paragraphs of fileNameIsUsed
--display dialog theLine
if theLine contains byAppName then
display dialog fileName & " --- is being used by other " & byAppName & ". Kill " & byAppName & " by yourself or wait till it finishes."
set isUsedFlag to true
else
--display dialog fileName & " --- not used."
end if
end repeat
return isUsedFlag
end isUsed

on appIcon(theApp)
--display dialog theApp
set clamIcon to theApp & "Contents:Resources:clamav.icns" as text
try
clamIcon as alias
set theIcon to clamIcon
on error
--display dialog clamIcon & " --- not exit."
set thePlist to theApp & "Contents:info.plist"
--display dialog thePlist
tell application "System Events"
set pList to property list file (thePlist)
set theIcon to (value of property list item "CFBundleIconFile" of pList) as text
end tell
set theIcon to theApp & "Contents:Resources:" & theIcon & ".icns"
--display dialog theIcon
end try
--display dialog theIcon with icon theIcon as alias
return theIcon
end appIcon

<<<

ファイル>別名で保存>「名前」は drop_clamscan、「場所」は自分の判断で、ファイルフォーマット「アプリケーション」で「保存」。(ファイルをドロップで起動するには、アプリケーションである必要があるため。)

drop_clamscan.appのやっている事は、
on open ... ← drag&drop対応
scanWithClamAVの前半は、clamd 、freshscan が走っているかどうかをチェック。走っていなければ起動。
また、clamscan.log が別clamdsan に使用されていないかチェック。
ドロップされたファイル/フォルダー毎に、white listをチェックし、入っていなければ clamdscan を実行、結果をログファイルに書き出し
その後、volumeをONし、
virusが検知されていれば、ビープ音を鳴らしlogファイルを表示、無いときは not foundを表示
最後の、volumeをもとに戻す。
display dialogは最少限になっているので、debugしたい場合は "--"を消して有効化する。

drop_clamscan.app をDockにドロップしておけば、scanしたいファイルをDock内のdrop_clamscan.appにドロップする事でscanできる。


つぎに、フォルダーアクションで On-Access Scan を実現する。

上記の applescript appで、

on open theDroppedItems
--display dialog "clamscan for " & theDroppedItems
set theLogFile to "/var/log/clamscan.log"
scanWithClamAV(theDroppedItems, theLogFile)
end open

の代わりに、

on adding folder items to this_folder after receiving added_items
--display dialog "clamscan for " & this_folder
set theLogFile to "/var/log/clamscan1.log"
scanWithClamAV(added_items, theLogFile)
end adding folder items to

を書き込む。「別名で保存」で、

名前: clamscan1
場所: ライブラリー>Scripts>Folder Action Scripts
ファイルフォーマット:スクリプトバンドル

で保存。(ファイルフォーマットはアプリケーションでも良いが、スクリプトバンドルならダブルクリックでスクリプトエディターが起動する。)

対応するログファイルを作成しておく:

> sudo touch /var/log/clamscan1.log
> sudo chown 82:82 /var/log/clamscan.log
> sudo chmod 666 /var/log/clamscan.log ← worldまで読み書きにしないと書き込みエラーがでる(かも)。


監視したいフォルダーをFinderで選択し、フォルダーアクション設定で clamscan.app を関連づける。例えば、

デスクトップ、ダウンロード、Volumes (外付けdiskがマウントされるdirectory)等のフォルダー。

監視を終わらせたいときは、フォルダーアクション設定で関連付けを外す。
また、Scanを途中でも終わらせたいときには、Activityモニター.appで clamd を停止する。

大きなdiskをscan中にdiskを切り離すと、clamdscan は実行中のままになる。このまま、次のclamdscan が自動的に走ろうとすると、clamscan.log ファイルが実行中の clamdscan に占有されているので フォルダーアクション実行がキャンセルされる(しかも、無言で)。script appに、clamdscanが実行中かのチェックを入れ、警告を出すようにした。

注意:フォルダーアクション/clamdscanは、1時に1つしか実行出来ない。大きなフォルダーをスキャンしているときは、新しいスキャンは、実行中のスキャンが終了してから、手動でdrop_clamscan.appにドロップする。


[7. ClamAV が実行されているかの確認]

clamav-0.99.2/test/ フォルダーを drop_clamscan.appにドロップしてみる。testフォルダーには、virusファイルが例題として入っているので、...Found になればOK。


[8. logファイルの確認]

コンソール.appを起動し、/var/log/clamd.log、/var/log/freshscan.log を表示し、ERRORが出ていないか確認。ERRORが出ていたら、適宜、解決するよう対処する。

以上。

(感想:いやー、全てのステップが壁だった。ところで、10.6.8で作業をしたが、ClamAVコンパイル出来、またapplescriptが動作するなら、どのOSXバージョンでも動作するはず。)


おまけ:
drop_clamscan.app、clamscan1.scptd の /Contents/Resources/に適当な iconファイルをclamav.icns 名で放り込んでおくと、virus検知のdialogにそのiconが表示されるようになるようscrip appは書いてある。例えば、ClamAVの画像を icns化して貼付けると、こんな風になる、、、