Configuring ClamAV (clamd) for use with amavisd-new HOWTO

Solving the "Can't connect to UNIX socket" and "/parts: Access denied" problems.

This document has only been tested on Debian GNU/Linux but is presumed to apply (in general) to other Linux distributions.
I have also written a HOWTO for Red Hat/Fedora users.

Almost all the problems with clamd (as it relates to amavisd-new) stem from file permission issues or an incorrectly configured LocalSocket.

UPDATE: Since I wrote this HOWTO, I found there is a very simple way to fix the file permission issues without performing all the user changes and file ownership changes I have listed below in the original HOWTO. The original HOWTO may however still provide insight into other clamd.conf and freshclam.conf configuration options.

One requirement for a successful installation is 'AllowSupplementaryGroups yes' must be included in clamd.conf. Another requirement is the value after CONTSCAN in amavisd.conf must match the LocalSocket parameter in clamd.conf (change amavisd.conf if it does not). A third requirement is TCPSocket cannot be used simultaneously with LocalSocket so TCPSocket must be commented out and LocalSocket must be enabled. The group that your amavisd-new user belongs to must also have write privileges to the amavisd-new user's home directory and subdirectories. This step should have been done during the installation of amavisd-new, and would consist of doing something similar to chmod -R 750 /var/amavis or chmod -R 750 /var/lib/amavis (adjust path as needed). Once you have ClamAV installed and the clamav user and clamav group have been created and the above requirements have been met, all you may need to do is make the user "clamav" a member of the same group that the amavisd-new user belongs to. Your amavisd-new user likely belongs to the "amavis" or "vscan" group. If that is the case you would issue the command:

gpasswd -a clamav amavis
(or)
gpasswd -a clamav vscan (for example)


You can test that clamav now belongs to both groups by issuing the command "groups clamav". The command above may not bring the desired result on some systems, so as an alternative you can directly edit /etc/group (use vigr if it's installed and you are familiar with vi commands) and manually add the user "clamav" to the "amavis" or "vscan" group:

amavis:x:104:clamav
(or)
vscan:x:999:clamav (for example)


As a third alternate, you could (for example) possibly use   usermod -G amavis clamav  but if you do, be very careful that you use an upper case "G" or you will have a mess to fix. Then, of course, stop and restart clamd and amavisd (amavisd-new), or simply reboot (if appropriate). Send a test virus through and read the log files. I suggest downloading eicar.com.txt, renaming it to eicar.txt and then attaching it to the email. Give it a try. If it doesn't work, try the other "change owner and ownership" method outlined in the original HOWTO below. Also consider that SELinux or AppArmor may interfere with the way clamd and amavisd-new work together. If you use SELinux or AppArmor I leave it up to you to solve that problem. This document assumes the reader knows to comment out "@bypass_virus_checks_*" to enable virus scanning (and to also uncomment the "ClamAV-clamd" code in the @av_scanners section). One last note: in at least one version of the 0.90 release, it can take several minutes for clamd to create the Unix socket. If you are using a 0.90 version, please allow several minutes for creation of the clamd socket once clamd is started. Better yet, upgrade to the latest version. If using Debian etch stable 0.90.1, read this.

And now the original HOWTO:

It seems many people get frustrated when trying to configure ClamAV to work with amavisd-new. They get the ClamAV daemon (clamd) installed via their distro's package maintainer or they download the source and install it from there. Part of the frustration comes from the inconsistent placement of files between different versions of ClamAV and different versions of binary packages available, but this can be said of nearly any program that consists of more than a few files. Partly because of these inconsistencies it becomes difficult for anyone to instruct a person on how to configure ClamAV for use with amavisd-new.

If you have the opportunity, you should install the binary package available for your distribution. Binary packages are available for Debian, RedHat Fedora, PLD Linux Distribution, Mandrake, Slackware, FreeBSD, OpenBSD, NetBSD and AIX. Installing and configuring ClamAV from source code is somewhat more daunting and you will have to come up with way to start clamd automatically and automate the virus definition database updates. I suggest you read through this document, then read the ClamAV documentation.

I suggest running   updatedb   and then   locate clam | more   and   locate .cvd   to find where the files are located. If you would like to move some of the data files that ClamAV uses (the ones that are referred to in the configuration files) you can create new directories and move the files there provided you also make the changes in the configuration files and change the ownership of the new directories (and the files contained therein).

Almost all the problems with clamd (as it relates to amavisd-new) stem from file permission issues or an incorrectly configured LocalSocket. From what I see, when clamd is installed, the "clamav" user that is created (either manually or by the installation process) is the only "normal" user that can write to the files that the program uses during it's operation. Thus, when you install the clamd daemon the first time, and you try to use it with amavisd-new, you may get "Can't connect to UNIX socket". This is because you are running amavisd-new as a different user (probably "amavis" or "vscan" or something) and that user does not have permission to write to a file that the two programs use to communicate with each other (the LocalSocket file).

I imagine you could break all the security that ClamAV has set up and allow anyone to write it's files, but I don't want to break stuff. One alternative is to set ClamAV up to run under the same user that amavisd-new runs under and then hand the ownership of the ClamAV files over to that user. Let's call that user "amavis" from now on. Fortunately, the ClamAV developers expected there might be instances where doing this might be necessary so they built the capability into the program. So our somewhat simple task is to change the owner the program runs under, then change the ownership of the files that it writes to.

The examples below are from a Debian machine on which I installed clamav-daemon version 0.90.1-1 using "apt-get -t unstable install clamav clamav-daemon". Use the following directory names and file names and user names only as examples. They are provided to illustrate the concepts and your system may use different directories, file names and user names.

Open up your   /etc/clamav/clamd.conf   with your favorite editor.
This is the clamav main configuration file. Look for a line similar to this:
LocalSocket /var/run/clamav/clamd.ctl
Make a note of this.

Now open up your amavisd.conf, mine is   /etc/amavis/amavisd.conf
and look for the section:
 ['Clam Antivirus-clamd',
  \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd.ctl"],
  qr/\bOK$/, qr/\bFOUND$/,
  qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
 
The text illustrated above must match the LocalSocket parameter you found in clamd.conf.
Edit amavisd.conf to match what you found in clamd.conf if it is different.
This "clamd.ctl" is the file that is shared between the two programs and the reason we have problems.
Now open up the clamd.conf file again (mine is   /etc/clamav/clamd.conf)
Below is illustrated the items in the file we are interested in:
LocalSocket /var/run/clamav/clamd.ctl
User clamav
LogFile /var/log/clamav/clamav.log
PidFile /var/run/clamav/clamd.pid
DatabaseDirectory /var/lib/clamav/
We need to edit this file and change:
User clamav
to
User amavis

Remember, you may be using a different name for your amavisd-new user.
Notice, that in my system, there are 3 directories listed above:
/var/run/clamav
/var/log/clamav
/var/lib/clamav
Now let's change the ownership of the 3 directories shown above (and the files contained therein) so "amavis" can write to them.
Before you do this, be aware, not all installations use a   /var/log/clamav   directory.
If your   LogFile   parameter reads something like   LogFile /var/log/clamav.log
Then you do not want to change permissions on the entire   /var/log   directory!!!!!
In this case you would only change ownership of the FILE, like so:
chown amavis:amavis /var/log/clamav.log
This applies any time the ClamAV file(s) we want to change ownership of are not in a directory specifically created to hold ClamAV files.

chown -R amavis:amavis /var/run/clamav
chown -R amavis:amavis /var/lib/clamav
and provided you have a separate directory for your log files:
chown -R amavis:amavis /var/log/clamav

The virus definition database update program "freshclam" has a configuration file that also needs to be modified.
Mine is called   /etc/clamav/freshclam.conf
Open this file in your editor. The items we are interested in are:
DatabaseOwner clamav
UpdateLogFile /var/log/clamav/freshclam.log
Change the DatabaseOwner to amavis (or whatever your amavis user is named) and make a note of the location of the log file.
As mentioned above, if   freshclam.log   is not in its own   clamav   directory then only change ownership of the   freshclam.log   file, not the entire directory. In our case, we already changed the ownership of the   /var/log/clamav   directory and all it's contents, so we don't have any more to do here. Your system may differ, so you may need to change ownership.

On my Debian system there are two more files that have to be modified. They are the files that control the maintenance of our log files. You will not necessarily have these files on your system. Our log files get "rotated" by the "logrotate" program each week and these files, if left unchanged, will assign "clamav" as the owner of any new log files it creates. If it does this, we will not be able to write to them. Not a good thing.

These files, on my Debian system are:
/etc/logrotate.d/clamav-daemon (controls the clamav.log)
and
/etc/logrotate.d/clamav-freshclam (controls the freshclam.log)

The interesting parts of   /etc/logrotate.d/clamav-daemon   on my system are:
 create 640  clamav adm
     /etc/init.d/clamav-daemon reload > /dev/null
Edit this file and change:
create 640 clamav adm
to
create 640 amavis adm

Also shown above is how the clamav-daemon is shutdown and restarted. (/etc/init.d/clamav-daemon reload)
Handy to know.

We need to do the same thing with   /etc/logrotate.d/clamav-freshclam
create 640 clamav adm
     /etc/init.d/clamav-freshclam reload > /dev/null
 
Edit this file and change:
create 640 clamav adm
to
create 640 amavis adm

We should reload clamd with the command we found above (/etc/init.d/clamav-daemon reload) in order for the daemon to read it's new configuration. Your system will probably differ here. At any rate, you need to stop and restart the clamd process.

Also do the same for freshclam: (/etc/init.d/clamav-freshclam reload)
If there are errors in the configuration, it should tell you.
You will also need to stop and restart (or reload) amavisd-new.
If this is a new computer you are building (not in production yet), I suggest you simply reboot.


FYI: These are my configuration files in their entirety (version 0.90.1):

/etc/clamav/clamd.conf:
LocalSocket /var/run/clamav/clamd.ctl
FixStaleSocket true
User amavis # user can be clamav if clamav is a member of amavis group
AllowSupplementaryGroups true
ScanMail true
ScanArchive true
ArchiveMaxRecursion 5
ArchiveMaxFiles 1000
ArchiveMaxFileSize 21M
ArchiveMaxCompressionRatio 250
ArchiveLimitMemoryUsage false
ArchiveBlockEncrypted false
MaxDirectoryRecursion 15
FollowDirectorySymlinks false
FollowFileSymlinks false
ReadTimeout 180
MaxThreads 12
MaxConnectionQueueLength 15
StreamMaxLength 10M
LogSyslog false
LogFacility LOG_LOCAL6
LogClean false
LogVerbose false
PidFile /var/run/clamav/clamd.pid
DatabaseDirectory /var/lib/clamav
TemporaryDirectory /tmp
SelfCheck 3600
Foreground false
Debug false
ScanPE true
ScanOLE2 true
ScanHTML true
DetectBrokenExecutables false
MailFollowURLs false
ArchiveBlockMax false
ExitOnOOM false
LeaveTemporaryFiles false
AlgorithmicDetection true
ScanELF true
NodalCoreAcceleration false
IdleTimeout 30
MailMaxRecursion 64
PhishingSignatures true
LogFile /var/log/clamav/clamav.log
LogTime true
LogFileUnlock false
LogFileMaxSize 0 # only appropriate because I use logrotate

/etc/clamav/freshclam.conf:
DatabaseOwner amavis # owner can be clamav if clamav is a member of amavis group
UpdateLogFile /var/log/clamav/freshclam.log
LogVerbose false
LogSyslog false
LogFacility LOG_LOCAL6
LogFileMaxSize 0 # only appropriate because I use logrotate
Foreground false
Debug false
MaxAttempts 5
DatabaseDirectory /var/lib/clamav/
DNSDatabaseInfo current.cvd.clamav.net
AllowSupplementaryGroups true
PidFile /var/run/clamav/freshclam.pid
ConnectTimeout 30
ReceiveTimeout 30
ScriptedUpdates yes
NotifyClamd /etc/clamav/clamd.conf
DatabaseMirror db.local.clamav.net
DatabaseMirror database.clamav.net
DatabaseMirror db.us.clamav.net

/etc/logrotate.d/clamav-daemon:
/var/log/clamav/clamav.log {
     rotate 12
     weekly
     compress
     delaycompress
     create 640  amavis adm
     postrotate
     /etc/init.d/clamav-daemon reload-log > /dev/null
     endscript
     }

/etc/logrotate.d/clamav-freshclam:
/var/log/clamav/freshclam.log {
     rotate 12
     weekly
     compress
     delaycompress
     create 640 amavis adm
     postrotate
     /etc/init.d/clamav-freshclam reload-log > /dev/null
     endscript
     }
The /etc/init.d/clamav-daemon and /etc/init.d/clamav-freshclam startup scripts are specific to Debian.


To further illustrate, here is another example with the program installed from source code:
Note that I personally don't like this setup. It's only an example. Remember that YOU can define were ClamAV files reside.

We will uncomment a few of the default parameters in the configuration files and change the user to "amavis". You must comment out TCPSocket if the system is configured such that the interface between amavis and clamav is through the LocalSocket file. These settings cannot be used simultaneously.
The parameters of interest in /etc/clamd.conf will look something like:
LogFile /tmp/clamd.log
PidFile /var/run/clamd.pid
LocalSocket /tmp/clamd
DatabaseDirectory /var/lib/clamav
User amavis
We will set parameters in /etc/freshclam.conf to:
UpdateLogFile /var/log/freshclam.log
DatabaseOwner amavis
We will edit amavisd.conf to match the LocalSocket parameter above:
 ['Clam Antivirus-clamd',
  \&ask_daemon, ["CONTSCAN {}\n", "/tmp/clamd"],
  qr/\bOK$/, qr/\bFOUND$/,
  qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
 
Now we will change ownership of the files: Note that if this is a new installation, we may need to "touch" the log files and the /var/lib/clamav directory may have to be created.

Oddly enough, the configuration files show "DatabaseDirectory /var/log/clamav" but the installer has put the database files (main.cvd and daily.cvd) in the /usr/local/share/clamav directory (apparently this is the default location).
   
touch /tmp/clamd.log
touch /var/log/freshclam.log
chown amavis:amavis /tmp/clamd.log
chown amavis:amavis /var/log/freshclam.log
chown amavis:amavis /tmp/clamd
mkdir /var/lib/clamav
chown -R amavis:amavis /var/lib/clamav
 
I started up clamd and looked in the clamd.log and got:
"ERROR: Can't save PID in file /var/run/clamd.pid"
So I did the following to solve the problem:
mkdir /var/run/clamav
chown amavis:amavis /var/run/clamav
Then I changed the PidFile parameter to:   PidFile /var/run/clamav/clamd.pid

You will need an init script to start and stop clamd during reboots. There are some supplied with the source code; look in the /usr/local/src/clamav-X.XX/contrib/init directory (or similar location) for those. If you don't find one there that serves your purpose, Google around for others. For example:
http://clamav.skc.com.pl/howtos/files/rc.clamd
http://enki.cthuugle.com/downloads/clamav.txt
http://verchick.com/mecham/public_html/spam/redhat-clamd-init.txt
http://mingo.ath.cx/files/clamd

You can simply run freshclam as a cron job:
Create a file ("freshclam" for example) in the /etc/cron.d directory which reads something like this for example:
MM * * * * amavis /usr/local/bin/freshclam --quiet
(pick a random number between 1 and 59 for the "MM" time - don't use the digit zero).
This will run every hour.

Run 'freshclam'.
Stop and restart clamd.
Stop and restart amavisd-new.
If you have freshclam running as a daemon, stop and restart that too.
Test your installation by sending the eicar test virus through the system.
Read the log files.
Read the ClamAV documentation.
To make things a little easier right from the beginning, use the following options before you compile the program (obviously you may need to substitute 'amavis' for your current amavisd-new user and group):
./configure --with-user=amavis --with-group=amavis --sysconfdir=/etc/clamav --with-dbdir=/var/lib/clamav
I think the /directory/file setup examples given in the beginning are more logical.

Document by Gary V, mr88talent at yahoo dot com

I hope this has been of some help to you. Please contact me only if you find stupid errors or find that this simply does not work or you have a useful addition.

I leave it up to you for any other issues. Absolutely no warranty of any kind. Use entirely at your own risk. The author accepts no responsibility for any loss or damage caused by the use, lack of use, or misuse, of information contained in this document. 20 MAR 2007

Special thanks to Debian package maintainer Stephen Gran and co-maintainers Thomas Lamy and Magnus Ekdahl.

Home