OXY NOTES

メールサーバが「451 Local Error」を返した際の対処法

先日メールのチェックをしているとサーバが「451 Local Error」というエラーを返すようになりました。
具体的には以下のようなエラーメッセージです。

This is the mail system at host mail.sukegra.com.

I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below.

For further assistance, please send mail to postmaster.

If you do so, please include this problem report. You can delete your own text from the attached returned message.

                   The mail system

<hogehoge@example.com>: host 127.0.0.1[127.0.0.1] said: 451 Local Error (in
    reply to end of DATA command)

エラーコードを元に原因を特定するべく検索すると、どうやらウイルス対策で利用しているClam AntiVirusが原因のようです。
当サイトではメールのリアルタイムチェックにclamdClamSMTPを組み合わせて利用していたのですが、何らかの理由でclamdが停止することで「451 Local Error」が発生していました。

まずはclamdが生きているか調べます。

# ps aux | grep clamd
clamsmtp  1253  0.0  0.0 844088  1212 ?        Ss    2018   1:31 /usr/sbin/clamsmtpd -f /etc/clamsmtpd.conf -p /var/run/clamd.clamsmtp/clamsmtpd.pid

clamsmtpは動いていますが、あるはずのclamdがありません。

clamdは何らかの原因で突然落ちることがあります。(主にメモリ不足。設定にOOMKiller時に自動で停止する設定もあります)
とりあえず再起動をかけてみます。

# /etc/init.d/clamd restart

Stopping Clam AntiVirus Daemon:                            [FAILED]
Starting Clam AntiVirus Daemon:                            [  OK  ]

やはり落ちていたようです。
これで終わってはまた自動で停止する可能性があるので原因を探ってみます。

まずは困ったときの更新作業。とりあえずウイルスのデータベースを更新します。

[root@sukegra ~]# freshclam
ClamAV update process started at Sat Mar  2 10:37:46 2019
WARNING: Your ClamAV installation is OUTDATED!
WARNING: Local version: 0.99 Recommended version: 0.101.1
DON'T PANIC! Read http://www.clamav.net/support/faq
main.cld is up to date (version: 58, sigs: 4566249, f-level: 60, builder: sigmgr)
daily.cvd is up to date (version: 25374, sigs: 2264251, f-level: 63, builder: raynman)
bytecode.cld is up to date (version: 328, sigs: 94, f-level: 63, builder: neo)

Your ClamAV installation is OUTDATED!」と出ています。バージョンが古いのでアップデートしろとのこと。
EPELリポジトリを有効にしてアップデートします。

# yum --enablerepo=epel update clamav

Dependencies Resolved

=================================================================================================================
 Package                    Arch                    Version                          Repository             Size
=================================================================================================================
Updating:
 clamav                     x86_64                  0.100.2-1.el6                    epel                  1.3 M
Installing for dependencies:
 json-c                     x86_64                  0.11-13.el6                      base                   27 k
Updating for dependencies:
 clamav-db                  x86_64                  0.100.2-1.el6                    epel                  161 M
 clamd                      x86_64                  0.100.2-1.el6                    epel                  243 k

Transaction Summary
=================================================================================================================
Install       1 Package(s)
Upgrade       3 Package(s)

Total download size: 163 M
Is this ok [y/N]: y ←yキーを入力してエンター

0.100.2-1.el6」というのが最新のものらしいです。インストール後に再起動します。

# /etc/init.d/clamd restart

Stopping Clam AntiVirus Daemon:                            [FAILED]
Starting Clam AntiVirus Daemon: WARNING: Ignoring deprecated option AllowSupplementaryGroups at line 204
LibClamAV Warning: Detected duplicate databases /var/lib/clamav/main.cvd and /var/lib/clamav/main.cld, please manually remove one of them
LibClamAV Warning: Detected duplicate databases /var/lib/clamav/bytecode.cvd and /var/lib/clamav/bytecode.cld. The /var/lib/clamav/bytecode.cvd database is older and will not be loaded, you should manually remove it from the database directory.
                                                           [  OK  ]

なにやら警告がわさわさと出ています。
バージョンが変わったので設定も変わったのだと思います。とりあえず上から順番に直します。

1行目の警告の対処

1行目は設定ファイルの204行目にあるAllowSupplementaryGroupsをコメントアウトしろとのこと。
ちなみに設定ファイルは「/etc/clamd.conf」です。公式サイトのチュートリアルに「/etc/clamd.d/clamsmtp.conf」とあったのでそちらを編集しましたが、反映されませんでした。「/etc/clamd.d/clamsmtp.conf」を使うのはLinux 7からで、Linux 6では「/etc/clamd.conf」のようです。

# vi /etc/clamd.conf

# Initialize supplementary group access (clamd must be started by root).
# Default: no
AllowSupplementaryGroups yes

以下のように変更

# Initialize supplementary group access (clamd must be started by root).
# Default: no
# AllowSupplementaryGroups yes

2行目の警告の対処

次は「/var/lib/clamav/main.cvd」と「/var/lib/clamav/main.cld」というデータベースが重複しているとのこと。データベースの形式も変わったようです。どちらかを削除するべきか…。

# cd /var/lib/clamav/
# ls -al

drwxr-xr-x  2 clam   clam        4096 Oct 24 03:19 .
drwxr-xr-x 29 root   root        4096 Mar  2 03:43 ..
-rw-r--r--  1 clamav clamav   1013248 Jan  3 03:40 bytecode.cld
-rw-r--r--  1 clam   clam      187426 Oct  4 14:57 bytecode.cvd
-rw-r--r--  1 clamav clamav 168627200 Mar  1 03:27 daily.cld
-rw-r--r--  1 clam   clam    51005708 Oct  4 14:57 daily.cvd
-rw-r--r--  1 clamav clamav 307499008 Jun  9  2017 main.cld
-rw-r--r--  1 clam   clam   117892267 Jan  9  2018 main.cvd

どうやら拡張子がcldのものが古く、cvdのものが新しいようです。
ウイルス定義ファイルなら新しい方が良かろうということで「main.cld」を削除します。

# rm main.cld

3行目の警告の対処

/var/lib/clamav/bytecode.cvd」が古いのでロードできない。手動で削除しろとのこと。

# rm bytecode.cvd

さて、これで警告の修正が終わったので早速起動してみます。

# /etc/init.d/clamd start
Starting Clam AntiVirus Daemon:                            [FAILED]

あれ、起動しなくなりました。悪化しとるがなw
ひとまず、ログでも見てみます。

# vi /var/log/clamav/clamd.log

Sat Mar  2 14:34:21 2019 -> +++ Started at Sat Mar  2 14:34:21 2019
Sat Mar  2 14:34:21 2019 -> Received 0 file descriptor(s) from systemd.
Sat Mar  2 14:34:21 2019 -> clamd daemon 0.100.2 (OS: linux-gnu, ARCH: x86_64, CPU: x86_64)
Sat Mar  2 14:34:21 2019 -> Log file size limited to 4294967295 bytes.
Sat Mar  2 14:34:21 2019 -> Reading databases from /var/lib/clamav
Sat Mar  2 14:34:21 2019 -> Not loading PUA signatures.
Sat Mar  2 14:34:21 2019 -> Bytecode: Security mode set to "TrustSigned".
Sat Mar  2 14:34:41 2019 -> Loaded 6823116 signatures.
Sat Mar  2 14:34:43 2019 -> LOCAL: Unix socket file /var/run/clamav/clamd.sock
Sat Mar  2 14:34:43 2019 -> LOCAL: Setting connection queue length to 30
Sat Mar  2 14:34:43 2019 -> ERROR: daemonize() failed: Cannot allocate memory
Sat Mar  2 14:34:43 2019 -> Socket file removed.

気になるのはPUA signaturesが読み込めないという部分。PUAとはPotentially Unwanted Applicationのことで一般的に言えば「悪意あるソフトを検出するための定義ファイル」といったところでしょうか。
そして具体的なエラーの内容は「ERROR: daemonize() failed: Cannot allocate memory」つまりメモリが足りないよとのこと。

ClamAVのリアルタイムチェックにclamdを走らせるとメモリ食いなことで知られていますが、それでも使用メモリは300MB程度です。当サーバではGMO VPSの2GBプランで、メモリに余裕を持たせているため、たかが300MBでメモリ不足になることは考えられません。
どうしたものかと調べていると有益な情報がstack overflowに。
どうやら起動時に限りPUA signaturesを読み込んだあとコピーするという作業が発生するとのこと。(個人的に検証はしていません)その際に最大で500MB×2つまり1GB程度のメモリを消費するとのこと。これならメモリ不足になったことも理解できます。

通常こういった一時的に多くのメモリを消費する作業には仮想メモリを利用します。Linuxでいうスワップですね。
ということでClamAVが起動するに十分な量のスワップ領域を作成します。

ひとまず構成を確認

# vi /etc/fstab

/dev/vda1               /                       ext3    defaults        1 1
/dev/vdb                swap                    swap    defaults        0 0
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0

/dev/vdb」にswapがあります。どうやらこれでは足りなかったようです。「/swapfile」というスワップファイルを追加するべく最後の行に以下を追加。

/swapfile               swap                    swap    defaults        0 0

ddコマンドでスワップファイル「/swapfile」を作成

# dd if=/dev/zero of=/swapfile bs=1024K count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 62.7715 s, 17.1 MB/s

ざっくり解説するとifの内容をofに書き込んでいます。ちなみに/dev/zero0でファイルを埋めています。サイズはbsかけるcountで、1024Kのファイル1024カウント分、つまり合計1073741824 bytesです。

権限変更

$ chmod 600 /swapfile

スワップ領域を作成

$ mkswap -f /swapfile

スワップ領域を有効にする

$ swapon /swapfile

スワップが正しく設定できたか確認

$ swapon -s
Filename                                Type            Size    Used    Priority
/dev/vdb                                partition       1048572 490288  -1
/swapfile                               file            1048572 0       -2

無事「/swapfile」が作成されています。priorityとあるので、「/dev/vdb」がいっぱいになったら「/swapfile」を使う感じですね。

メモリサイズを確認

$ free
             total       used       free     shared    buffers     cached
Mem:       1920268    1794016     126252     139928      61836     525804
-/+ buffers/cache:    1206376     713892
Swap:      2097144     490288    1606856

無事Swapの項目が合計の2GBになってます。
clamdが起動できるかテストします。

# /etc/init.d/clamd start
Starting Clam AntiVirus Daemon:                            [  OK  ]

これで無事にclamdが起動しました。


アップデート後にfreshclamを実行するとエラー

万事解決と思いきやfreshclam時にもエラーが出るようです。

ERROR: Can't create temporary directory /var/lib/clamav/clamav-ad7315d02d042720ae5290a4c7a2f8a6.tmp

これは以前も直した経験のあるテンポラリーディレクトリの所有権の問題です。

# chown 495:493 /var/lib/clamav

所有権がclamavとなっているところをclamにするという設定です。(所有権は実行者や設定に合わせて適宜変更してください。)
clamAVのややこしいところは、このへんの所有権をバージョンアップごとに変更することです。作者にも思惑があるのかもしれませんが、定義ファイルの更新は普通cron等で自動実行しているため、書き換えが面倒ですね。

以上、ClamAVがメモリ不足で自動停止する問題と、バージョンアップ時の諸問題の解決方法でした。