サーバー専門のフリーランスエンジニアです。クラウドサービスを利用してWebサイト、ITシステムのサーバー構成設計とサーバー構築を行います。7のサーバーにおけるClamAVによる定期ウイルススキャンの設定方法について記載しました。今回は、定期ウイルススキャンの運用において、CPU・メモリリソース使用に関する工夫や、実際にウイルスを検知したときの対処方法について記載します。7サーバー環境に対して、引き続き設定を追加します。以下の設定作業はrootユーザー(もしくはsudoによるroot権限)で実施します。定期スキャンの運用における工夫メモリ使用量が増える問題への対策CPUを占有使用する問題への対策プライベートネットワーク内サーバーのウイルス定義更新ウイルス検知時の対応について記載します。メモリ使用量が増える問題への対策よくあるケースとして、サーバーのメモリが2GB以下で、Apache+mod_phpを使用しているWebサーバーで定期スキャンの設定を行うと、スワップ領域を常時数百MB程度使用するようになります。前回の記事でも書きましたが、clamscanコマンドは、メモリを500MB~700MBほど使用します。これはおそらく、スキャン実行時に読み込むウイルス定義ファイルのサイズが数百MBあるからだと思います。Apacheプロセスによる実メモリの使用量が大きい状態でウイルススキャンを実行すると、実メモリ上では必要なメモリを確保できないため、既存のApache子プロセスをスワップ領域に追いやるか、もしくはclamscanコマンド自体がスワップ領域を使用するのでしょう。これを日々繰り返していくと、スワップ領域の使用量がじわじわと増えていきます。スワップ領域をある程度使用することは、利用頻度の低いページをページアウトすることで実メモリを効率よく使えるようになるので、それ自体は悪いことではありません。スワップ領域も上限があるので増え続けるのは好ましくありませんし、ページアウト(実メモリ→スワップへの移動)とページイン(スワップ→実メモリへの移動)が頻発すると、サーバーのパフォーマンスが落ちます。「サーバーのスペック(つまりサーバー料金)は運用前に決められていて増やせない」とか「ウイルススキャンのためだけにメモリ(つまりサーバー料金)は増やせない」といった事情もあるでしょう。このように「メモリ使用量が増える問題」への対策としては、僕は「スキャン実行前後に、Apacheを再起動する」という方法をとっています。スキャン実行前に再起動することで、Sleep状態のApache子プロセスをクリアして、実メモリの空きを確保します。スキャン実行後に再起動することで、スキャン実行中にスワップに追いやられてしまったApache子プロセスをクリアします。具体的には、前回設置したスキャン実行スクリプトの前後に、Apacheを再起動するコマンドを挿入します。scanvirus.sh#ウイルススキャンを実行し、ウイルスを検知したときのみ、#指定した宛先にアラートメールを送信する。#誤検知もあり得るため、検知しても駆除(削除)は実施しない。##スキャンの実行前には、ClamAVプログラムおよびウイルス定義を#アップデートする。##スキャンの除外対象ディレクトリ、ファイルは、${EXCLUDE_LIST_FILE}#ファイルに1行ずつ記載すること。EOF--補足します。Apache子プロセスを再起動(graceful)」を追加しています。httpdで実行します。reloadのときの実行コマンドとして、Apacheのサービス起動オプションgracefulを使用するよう設定されているためです。${MAINPID}...--サービス起動オプションgracefulを使用すると、処理中の子プロセスはその処理を終えてから終了するため、ユーザーから接続中のセッションが切れることはありません。gracefulのように、initスクリプトもしくはserviceコマンドでgracefulを指定します。親プロセスごと再起動をかけても問題がなければ、restartで再起動をかけてもよいでしょう。Apache子プロセスを再起動(graceful)」の部分のみ、再起動後に10秒間のsleepを入れています。これは、再起動の命令から実際に子プロセスが終了するまで、少し時間がかかるためです。この「スキャン実行前後に、Apacheを再起動する」方法の効果については、これまでの運用でもっともうまくいったときは、設定前後でメモリ使用量が以下のとおり改善されました。30MBなお、Linuxにおけるメモリ使用、スワップに関する説明や調べ方は、以下の記事がとてもわかりやすいです。・どうしてメモリはスワップするのか!?https://heartbeats.jp/hbblog/2014/01/linux-page-swap.html・Linuxで、どのプロセスがページングを行っているのか調べるには?https://yakst.com/ja/posts/382CPUを占有使用する問題への対策clamscanコマンドはディスク上の全ファイルの検査を行う重い処理ですから、実行時は、1つのCPUをほぼ占有使用します。CPUが複数あるサーバーであれば、他の処理は空いているCPUを使用できますが、CPUが1つしかないサーバーでは、例えば「Webサイトの表示が遅い」など、ウイルススキャン以外の本来の機能に影響があります。仮にサーバー監視ツールで「CPU使用率が90%以上のときはアラート通知する」というような設定を行っていれば、「毎日わかっていることなのにアラートがうるさい」ということもあるでしょう。「CGroupでスキャン実行プロセスのCPU使用を制限する」という方法があります。このアイデアと設定方法は、以下の記事を参考にしました。コントロールグループ内のプロセスの開始https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Resource_Management_Guide/Starting_a_Process.htmlCGroupは、Linuxカーネルの機能で、プロセスへのCPU使用時間、システムメモリー、ネットワーク帯域幅などのリソース割り当てを制御することができます。今回は、CGroupを使用して、clamscanコマンドのCPU使用時間を70%に制限する設定を行います。libcgroupのインストールCGroupの機能が含まれる、libcgroupおよびlibcgroup-toolsパッケージをインストールします。6の場合は、libcgroupパッケージのみでOKです。clamscanコマンドのCPU使用時間を70%に制限する「clamscang」グループを定義します。「1000000マイクロsec=1秒あたり、700000マイクロsec=700msec使用する」すなわち「CPU使用時間を70%に制限する」ということになります。}}--cgconfigサービスを起動し、自動起動設定を行います。full.CGroupを使用してClamAVを実行してみる比較のため、まずCgroupを使用せずに、スキャン実行スクリプトを実行します。/root/bin/scanvirus.sh実行中のCPU使用率をtopコマンドで確認します。clamscanコマンドのCPU使用率は85%から99%ぐらいの間で推移しました。全ディスクのスキャンに2分57秒かかりました。s)続いて、CGroupを使用してclamscanコマンドを実行するようにします。定義した「clamscang」グループをCPU制御に適用して実行するには、以下のようにcgexecコマンドを使用します。<適用するコマンド>スキャン実行スクリプト内で、clamscanコマンドはcgexecコマンドと組み合わせてCPU使用時間を制限して実行するよう修正します。${LOGFILE}--CPU使用時間の制限を行ったスキャン実行スクリプトを実行します。/root/bin/scanvirus.sh先ほどと同様に、実行中のCPU使用率をtopコマンドで確認します。clamscanコマンドのCPU使用率は65%から72%ぐらいの間で推移しました。全ディスクのスキャンに3分44秒かかりました。s)想定どおり、CGroupを使用することで、clamscanコマンドのCPU使用率を70%程度に抑えることができました。CPU使用時間を70%に抑えたため、全ディスクのスキャン時間が2分57秒から3分44秒と約1.27倍に増えました。1.43ですから、こんなものですかね。いうことで、「CGroupでスキャン実行プロセスのCPU使用を制限する」ことで「ウイルススキャン処理がCPUを占有使用する問題」が改善されることが確認できました。スキャン処理に要する時間が少し増えることに注意しましょう。「WebプロキシサーバーをDMZに設置、バックエンドのアプリケーションサーバーやDBサーバーはプライベートネットワーク内に設置してインターネットにアクセスできないようにする」というネットワーク構成とすることが多いと思います。clamav-updateといったパッケージのRPMファイルを入手してサーバーにアップロードすることでインストールできますね。Webプロキシサーバーなどインターネットにアクセスできる上位のサーバーで、一時的にSquidなどのフォワードプロキシーを起動(インストール作業が終わったら停止)すれば、yumコマンドでインストールできます。HTTPProxyの設定を行うことで、freshclamコマンドによりウイルス定義が更新できます。<上位サーバーのフォワードプロキシーの使用ポート>--フォワードプロキシーが使用できない場合は、上位サーバーのClamAVが保持している最新のウイルス定義ファイルを何らかの方法で取得すればよいです。以下に保存されています。clamscanコマンドがウイルススキャン時に使用するウイルス定義ファイルですので、これらを上位のサーバーからscpコマンドやrsyncコマンドで取得します。インターネットにアクセス可能な上位サーバーを「Webプロキシーサーバー」、インターネットにアクセスできないサーバーを「アプリケーションサーバー」とすると、下図のようなイメージです。長くなってしまうので、詳しい設定手順はここでは記載しませんが、上の図の例の設定方針としては以下のような感じです。アプリケーションサーバーから、ウイルス定義ファイルの所有者clamupdateユーザーで、Webプロキシーサーバーに対してSSH鍵認証が可能とする。スクリプト内で自動実行するため、SSH鍵認証のパスフレーズは空とする。Webプロキシーサーバーでは、clamupdateユーザーのSSHに制限を加える。アプリケーションサーバーのスキャン実行スクリプト(ここまでの例では、/root/bin/scanvirus.sh)では、ウイルス定義取得処理をfreshclamコマンドからscpまたはrsyncコマンドに置き換える。Webプロキシーサーバーがウイルス定義を更新してから取得するよう、アプリケーションサーバーのcronでは、スキャン実行スクリプトの開始時刻を遅らせる(10分とか)。SSH鍵認証を使用したリモートサーバー間の自動データ転送設定については、以下の記事が参考になります。変更する必要があります。ファイルで、アクセス元IPアドレスの制限をかけると、万一秘密鍵ファイルが漏れても、外部からはSSHできません。追記して転送や端末の割り当てを禁止します。(SSH公開鍵データ)...--アプリケーションサーバーにおいて、ウイルス定義ファイルを取得するときのコマンドは、実際には、こんな感じになるでしょうscpコマンドの場合。/var/lib/clamav/rsyncコマンドの場合。/var/lib/clamav/やや泥臭い方法になりますが(笑)、プライベートネットワーク内のサーバーでも、インターネットにアクセスできる上位サーバーとのSSH通信が可能であれば、上記のように最新のウイルス定義を使用した自動定期スキャンが可能となります。(ClamAVパッケージのアップデートは手動で行う必要がありますね。)「そもそも、インターネットにアクセスできないサーバーでウイルススキャンを行う必要があるのか?」という疑問もあるかと思います。インターネットに公開しているWebサイト、Webサービスの複数台サーバー構成であれば、インターネット公開サーバー経由で、何らかのデータが何らかの形式でバックエンドのサーバーに保存されるのですから、やはりウイルス感染する可能性はゼロではない、といえるのではないでしょうか。「企業内のクローズなネットワーク内のサーバーやPCでウイルス感染した」という事例もわりとよくありますし。前回の記事で行った定期ウイルススキャンの設定では、ウイルス検知時は、スキャン実行スクリプトで指定したメールアドレスに、ウイルススキャン結果およびウイルス検知ファイル名を送信することで、通知してくれます。ClamAVのウイルス検知は、実際には誤検知で、本当はウイルスではないことがあります。いいますか、僕の経験では、検知の頻度はサーバー1台あたり1年に数回ありますが、95%以上は誤検知で、本当にウイルスのようだったことは1回だけしかありません。このため、ウイルス検知時は、運用担当者自身が、検知したファイルの内容、タイムスタンプや、インターネット上の情報等をチェックし、本当にウイルスか、あるいは誤検知か、判断する必要があり、その作業はなかなか大変です。ファイルのタイムスタンプを確認して、ずっと前から更新されていないのに、ある日突然ウイルスとみなされた場合は、誤検知の可能性が高いです。この場合は、GoogleやTwitterなど、インターネット上で通知メールに記載されたメッセージ(何のウイルスか)で、検索してみるとよいでしょう。誤検知であれば、他のユーザーも同じメッセージに遭遇し、掲示板等で質問をしているケースが多いです。誤検知の場合は、ウイルス定義の不具合ですので、数日後のウイルス定義更新で修正されます。修正後、自動的にウイルスと判定されなくなりますので、少し待ちましょう。/root/bin/scanvirus_exclude_list.txt)に該当ファイルを追記するとよいでしょう。誤検知ではなく、ウイルスの可能性が高そうなら、ファイルを削除するか、少なくともWeb公開ディレクトリ以外の箇所に退避すべきでしょう。僕が経験した、2017年7月の誤検知の例をあげます。このときは、以下のようなウイルス検知がありました。(ファイルパスは実際のものから変更しています)。ClamAV」でGoogle検索しても、とくに情報は出てきませんでしたが、lsコマンドで確認すると、ファイルのタイムスタンプは2016年3月で、ずっと前からこのサーバーに存在したのにこの日初めて検知したので、誤検知の可能性が高いと判断しました。念のため、このファイルをPCにダウンロードして、PDFファイルを開いて、中身が普通のデータで、PCのアンチウイルスソフトがウイルス検知しないことも確認しました。(本当にウイルスだったら、実は危険!)ClamAVのウイルス定義の変更内容は、以下のメーリングリストアーカイブで確認できます。307」で追加されたことがわかりました。BC.Pdf.Exploit.CVE_2017_3032-6316401-6...このときは、ウイルス定義から削除されるのを待つことにして、実際に5日後に削除され、ウイルス検知がなくなりました。308」で削除(Drop)されたことがわかります。/root/bin/scanvirus_exclude_list.txt--/sys//proc//dev//var/www/html/image/koukoku201501.pdf--なお、clamscanコマンドのスキャン除外指定であるexludeオプションでは、正規表現を使用することができます。配下の拡張子「.pdf」のファイルをすべて除外するのであれば、以下のように追記します。/var/www/html/image/(.*).pdf僕のこれまでの運用経験では、日本語ファイル名の場合はうまくマッチしない(文字コードの問題かもしれませんが)ようなので、ディレクトリやファイル名を限定したうえで、正規表現を使用するとよいでしょう。まとめ今回の記事では、ClamAVによる定期ウイルススキャンの運用において工夫するポイントや、実際に検知したときの対処方法について記載しました。ClamAVは無償で利用できますし、インターネット上に多くの導入手順がみられるとおり、サーバーへのインストール、定期スキャン設定は比較的簡単です。不特定ユーザーからファイルをアップロードさせる機能を持つようなWebサーバーの場合は、悪意を持ったユーザーがウイルスファイルをアップする可能性がゼロではありません。ウイルス感染した関係者のPCから、CMSの管理画面を経由してウイルスがサーバーにアップロードされるという可能性もあるでしょう。ClamAVを導入すると、そういったウイルス感染を未然に防ぐことはできませんが、比較的早く気づくことはできるはずです。本番環境で長期にわたって運用を続ける場合は、CPU、メモリリソースを多く消費するので、とくに低スペックのサーバーでは工夫が必要です。誤検知がときどき発生し、そのたびに調査、判断が必要となるので、運用担当者の負担も発生します。いった運用コストを踏まえたうえで、導入の可否を判断されるとよいと思います。オンアクセススキャンや、より精度の高いスキャンが必要な場合は、トレンドマイクロ社、シマンテック社等の商用アンチウイルスソフトのご利用をおすすめします。DesignInaba【お問い合わせ】お名前または法人名・団体名、メールアドレスと、簡潔な内容で構いませんので、お問い合わせ内容をご記入ください。折り返しご連絡いたします。※いただいた情報は他の目的には使用いたしません(個人情報の取り扱いについてはこちらのプライバシーポリシーをご参照ください)。(必須)↑お問い合わせ内容をご確認のうえ、チェックを入れてから「送信」してください。