ClamAV is commonly used to scan for viruses in email, so that they can be given the proper handling by a mail delivery agent such as procmail or directly by the MTA as in the case of a sendmail message filter (milter). It is also used to scan for viruses in disk files so that infected files can be deleted or quarantined.
ClamAV is installed in the usual manner by downloading its distribution file from http://www.clamav.net/. Once you've downloaded the distribution file, unpack it like this:
tar -xvzf clamav-0.94.2.tar.gz
The install instructions are missing a part about creating the ClamAV userid and group before you run configure. Do something like this:
su /usr/sbin/groupadd clamav /usr/sbin/useradd -c "ClamAV Virus Scanner" -g clamav -M \ -s /sbin/nologin clamav
Next, we'll create a place for the daemon to store the logfiles, and an install directory:
su mkdir /var/log/clamav/ chown root:clamav /var/log/clamav/ chmod ug=rwx,o=rx /var/log/clamav/ mkdir /usr/local/clamav chown clamav:clamav /usr/local/clamav chmod ug=rwx,o=rx /usr/local/clamav
Change to the source directory, and configure and build the source:
cd clamav-0.97.4 ./configure --disable-clamuko --disable-milter --with-dbdir=/usr/local/clamav make
Then, when the build succeeds, install ClamAV:
su make install
Note that the ClamAV install appears to have omitted the step of informing the linker that it needs to rebuild the linker cache so that it can see the ClamAV dynamic libraries. You can check this by running:
su /sbin/ldconfig -p | grep libclam
If you don't see any results, you won't be able to run anything that links to these libraries (e.g. clamd).
The fix is to first make sure that the installed library directory is in "/etc/ld.so.conf" or one of the files that it includes from "/etc/ld.so.conf.d". If you used the ".configure" command shown above, you should be all set because the default is to install libclam into "/usr/local/lib" and this directory is always named in the "usr-local.conf" file in "/etc/ld.so.conf.d". If you picked some off-label library directory, you need to add another file to "/etc/ld.so.conf.d" that names the off-label directory in it. For example, if you chose "/usr/mystuff/lib" for the libclam library, you might create a file named "/etc/ld.so.conf.d/usr-mystuff.conf" that names "/usr/mystuff/lib" in it.
Once you're ready, run the following command:
su /sbin/ldconfig
This should add libclam* to the /etc/ld.so.cache file and you'll be in business. Or, you can just take the Microsoft approach and reboot your machine a half dozen times.
/etc/clam/clamav.conf
Presumably, to use ClamAV (e.g. for email scanning), one will require that the clamd daemon be run. All of the parameters that control the way clamd operates are contained in its configuration file (there are virtually no command line parameters). The standard location for the config file is /etc/clamav.conf or maybe even /usr/local/etc/clamd.conf.
We, on the other hand, prefer to create a directory for ClamAV under /etc and put the config file, along with any other clam-related files there. It makes the /etc directory neater and groups all of the logically-related files together. Not only that but we don't have to go looking in some screwy place where the product's creator thought it would be cute to put things. So, we do:
su mkdir /etc/clam chmod u=rwx,go=rx /etc/clam touch /etc/clam/clamav.conf chgrp clamav /etc/clam/clamav.conf chmod ug=rw,o= /etc/clam/clamav.conf
The options that you'll likely want to consider are those for: turning on logging; choosing how to communicate (e.g. via a socket); indicating where to store the PID file; setting where the virus signatures database is kept; adjusting scanning performance and tuning; picking what type of files to scan; limiting how far scanning goes. Here are some suggestions:
# # Turn on logging, direct where it should go, etc. # LogTime Yes LogFileMaxSize 0 LogFile /var/log/clamav/clamd.log # # Set where the PID file is kept and how we tawk, dahling. # PidFile /var/run/clamd.pid TCPSocket 2528 # # Where the virus signatures database is squirreled away. # DatabaseDirectory /usr/local/clamav # # Performance and Tooning. # MaxConnectionQueueLength 25 MaxThreads 50 ReadTimeout 30 MaxDirectoryRecursion 15 FollowFileSymlinks Yes # # Use an alter ego. # User clamav # # Wot to scan. # AlgorithmicDetection Yes HeuristicScanPrecedence No ScanPE Yes ScanELF Yes ScanOLE2 Yes ScanPDF Yes ScanHTML Yes ScanMail Yes ScanArchive Yes MailFollowURLs No ScanPartialMessages No PhishingSignatures Yes PhishingScanURLs Yes # # How far should we try to go? # MaxScanSize 100M MaxFileSize 25M StreamMaxLength 25M MaxRecursion 16 MaxFiles 10000 # # Debugging stuff. # # Debug Yes # LeaveTemporaryFiles Yes
/etc/rc.d/init.d/clamav:
This startup script will start ClamAV's clamd daemon so that requests to check for viruses may be passed to it without incurring the overhead of starting up the Perl interpreter each time a message is to be identified.
#!/bin/sh # # clamav - This script starts and stops the clamd daemon # # Revision History: # ewilde 2009Jan18 Initial coding. # # chkconfig: 2345 79 31 # description: Clamd is a daemon process which uses ClamAV to check email \ # messages for VIRUSES. # # processname: clamd # pidfile: pidfile, what pidfile? Its a Perl program, for cripes sake. # config: /etc/clam/clamav.conf # # # Define the install path for the ClamAV binaries, etc. Define the # program to run. # INSTALL_PATH="/usr/local/sbin" CONFIG_FILE="/etc/clam/clamav.conf" CLAM_DAEMON="clamd" # # Load the RedHat functions. # if [ -f /etc/redhat-release ]; then . /etc/rc.d/init.d/functions fi # # Source the networking configuration. # if [ -f /etc/sysconfig/network ]; then . /etc/sysconfig/network else NETWORKING=no fi # # Source the clamd configuration or take the defaults. # if [ -f /etc/sysconfig/clamd ] ; then . /etc/sysconfig/clamd else CLAMD_PORT=2528 fi [ -z "$CLAMD_PORT" ] && CLAMD_PORT=2528 # # Check that networking is up. We talk to our customers using TCP/IP. # [ "x$NETWORKING" != xyes ] && exit 0 # # Make sure we have something to run. # [ -f $INSTALL_PATH/$CLAM_DAEMON ] || exit 0 # # Clamd is dain bramaged. You can't pass it any command line options. So, # the port number must be set in the config file. But, we want to set it in # /etc/sysconfig/clamd. What to do? About all we can do is check that it # matches what's in the config file. # ConfSocket=`grep TCPSocket $CONFIG_FILE` if [ "x$ConfSocket" != "xTCPSocket $CLAMD_PORT" ]; then echo Clamd port $CLAMD_PORT does not match the port set in $CONFIG_FILE exit 0 fi # # Upon startup, start the daemon. # start() { echo -n "Starting $CLAM_DAEMON: " daemon $INSTALL_PATH/$CLAM_DAEMON -c $CONFIG_FILE RETVAL=$? echo # # If startup succeeded, lock the lockfile. # [ $RETVAL = 0 ] && touch /var/lock/subsys/clamd } # # Upon shutdown, stop the daemon. # stop() { echo -n "Shutting down $CLAM_DAEMON: " killproc $CLAM_DAEMON RETVAL=$? echo # # If shutdown succeeded, unlock the lockfile. # [ $RETVAL = 0 ] && rm -f /var/lock/subsys/clamd } # # See how we were called. # case "$1" in # # Start. # start) start ;; # # Stop. # stop) stop ;; # # Restart or reload (whatever). # restart|reload) stop start ;; # # Conditional restart. # condrestart) if [ -f /var/lock/subsys/clamd ]; then stop start fi ;; # # Give the status of clamd. # status) status $CLAM_DAEMON ;; # # Help text. # *) echo $"Usage: $0 {start|stop|restart|condrestart|status}" exit 1 esac exit 0
/etc/sysconfig/clamd:
If you are planning to use clamd with the sendmailfilter, you should create this file, since doing so will cause the sendmail startup script to invoke clamd for email filtering. The options for the clamav startup script (above) are also included in this file.
The permissions on this file should be:
-rw-r--r-- 1 root root
Here is a sample of the complete file:
# # Configuration for the ClamAV daemon. # CLAMD_PORT=2528
It is very important that the virus signatures database be kept up to date, since it is used to describe all of the viruses that ClamAV detects. Not to put too fine a point on it but, if the virus signature isn't in the database, the virus isn't going to be found.
ClamAV has a program, called freshclam, that can be invoked on a regular basis to contact the mother ship and download a new virus database, if there is one. It should be run at regular intervals out of crontab (or as a daemon). It is easy to set up.
However, before we proceed, consider that virus database freshness is the most important thing in an anti-virus system. Consequently, it is critical that freshclam be able to alert you when something goes wrong.
/etc/clam/notify:
Create the following script to send event notifications to root, via email, whenever ClamAV has something important to say. Note that the indentation in front of "ENDMSG" can be tabs only. If your lame-butt text editor sticks spaces in there, the shell script will get a syntax error. Here is the script:
#!/bin/sh # A shell script that can be used by freshclam to send messages to root # when a fresh copy of the virus signatures database cannot be downloaded. # Email the message to root so that they can see everything that's going on. # After all, if you're omnipotent, you need to know everything. HostName=`hostname` /bin/mail -s "Urgent message from ClamAV" root <<-ENDMSG ClamAV on $HostName failed to obtain a fresh copy of the virus signatures database. Please investigate immediately. ENDMSG
Note that, in the above script, the two sets of lines between "/bin/mail -s ... <<-ENDMSG" and up to and including the line with "ENDMSG" must either not be indented at all or only indented with actual tab characters (not blanks). If they are not, the script will fail. Also, don't forget to add execute permissions to the script after you create it:
su chmod ugo+x /etc/clam/notify
Then, it wouldn't hurt try it out after you've got it all set up. For example:
/etc/clam/notify
Check that root receives the message.
/etc/clam/freshclam.conf:
Freshclam, being almost as brain dead in the command line parameters department as clamd (actually, it has them, the docs claim they override the config file, yet it still whines about the config file being missing and gives up, so maybe it is worse), a config file for it is required. The standard location for the config file is /usr/local/etc/freshclam.conf.
However, since we earlier started the trend of creating a directory for ClamAV under /etc and putting the ClamAV config file and other clam-related files there, we'll stick with a winner:
su touch /etc/clam/freshclam.conf chgrp clamav /etc/clam/freshclam.conf chmod ug=rw,o= /etc/clam/freshclam.conf
Here is an example of a freshclam configuration file containing the options that you should consider:
# # Turn on logging and direct where it should go, etc. # LogTime Yes LogFileMaxSize 0 UpdateLogFile /var/log/clamav/freshclam.log # # Where the virus signatures database is squirreled away. # DatabaseDirectory /usr/local/clamav # # Use DNS to verify virus database version. # DNSDatabaseInfo current.cvd.clamav.net # # Where to find the database mirrors. The last one is the fallback mirror. # DatabaseMirror db.us.clamav.net DatabaseMirror db.ca.clamav.net DatabaseMirror database.clamav.net # # Performance and Tooning. # ConnectTimeout 60 ReceiveTimeout 120 MaxAttempts 3 ScriptedUpdates Yes CompressLocalDatabase No # # Use an alter ego. # DatabaseOwner clamav # # Notify root-ski if the database update process fails. # OnErrorExecute /etc/clam/notify # # Debugging stuff. # # Debug Yes
/etc/crontab:
Now we can add a line in /etc/crontab to schedule regular updates to the ClamAV virus signatures database:
# Check for an updated ClamAV virus signatures database a couple of times a # day. 40 6,18 * * * root /usr/local/bin/freshclam \ --config-file=/etc/clam/freshclam.conf >/dev/null 2>&1
/etc/logrotate.d/clamav:
Before the logfiles fill up the all the available disk space, you should add a config file to rotate them, to the logrotate config directory /etc/logrotate.d:
/var/log/clamav/*.log { missingok notifempty }
Now, before the ClamAV daemon is started, you should run freshclam once to populate the databases:
su /usr/local/bin/freshclam --config-file=/etc/clam/freshclam.conf
Also, if you're running logwatch, you may experience a problem whereby it doesn't process the clam-update logfiles properly and always generates a message that says:
The ClamAV update process (freshclam daemon) was not running! If you no longer wish to run freshclam, deleting the freshclam.log file will suppress this error message.
This problem is caused by a timestamp and arrow that were added to the beginning of all clam-update log lines under more recent versions of ClamAV. Apparently, the logwatch scanner for ClamAV hasn't kept up and it does not know about the timestamps. If you get the latest version of logwatch and the problem still isn't fixed, you can try applying this patch:
/usr/share/logwatch/scripts/services/clam-update:
--- clam-update-7.3.6 2010-09-09 08:37:51.000000000 -0400 +++ clam-update 2010-09-09 08:16:02.000000000 -0400 @@ -87,6 +87,10 @@ # Freshclam ends log messages with a newline. If using the LogSyslog option, this is # turned into a space. So we remove a space from every line, if it exists. $ThisLine =~ s/ $//; + # Later versions of Freshclam prepend each line with a timestamp (a very + # good idea) and an arrow. This messes up scanning (below). + if ($ThisLine =~ /^\s*\w{3} \w{3} [\d ]\d ..:..:.. \d{4} -> /) + { $ThisLine = substr($ThisLine, length($&)); } if ( # separator of 38 dashes ($ThisLine =~ /^\-{38}$/) or