Virus detection using ClamAV

In the previous section we added enhanced spam filtering capabilities to our content filter using the SpamAssassin package. In this section we shall continue to expand the functionality of our content filter by adding virus scanning capabilities using the ClamAV virus scanner.

Installing and configuring ClamAV

Before we can install the ClamAV package we need to ensure that the correct use-flags have been set so that all the functionality we require will be built in to the package and its dependencies. The example below shows the set of flags we have enabled. Feel free to add additional flags as required however be aware that removing flags will probably remove functionality which this guide uses. Once you are happy with the use-flags you have selected merge the package as shown below.

lisa emerge -pv clamav
 
These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild      ] app-antivirus/clamav-0.95.3  USE="bzip2 iconv -clamdtop -milter"
 
lisa emerge clamav

To enable the amavisd daemon to connect to the ClamAV virus scanner we also need to add the amavis group to the list of supplementary groups for the clamav user. This can be easily accomplished using the command shown below.

lisa gpasswd -a clamav amavis

As the default configuration file supplied with the clamav daemon provides suitable values for most options we shall not customise it further and can simply start the daemon and, assuming all goes well, add it to the default run-level so that it is started automatically.

lisa /etc/init.d/clamd start
lisa rc-update add clamd default

Reconfiguring amavisd-new

Now that the ClamAV daemon is installed, configured and running we can configure the amavisd daemon to make us of it. As you can see we again need to commenting out one of the lines we added to the configuration in a previous chapter. With this line removed the amavisd daemon will automatically use the ClamAV daemon to filter messages for viruses, assuming the filter profile requests this action. Unfortunately the default configuration uses an older version of the ClamAV scan syntax and requires some modifications, as shown below.

/etc/amavisd.conf
# Section I    - Essential daemon and MTA settings

@bypass_virus_checks_maps = (1);
# @bypass_virus_checks_maps = (1);

# Section VII - External programs, virus scanners

['ClamAV-clamd',
\&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd.sock"],
qr/\bOK$/, qr/\bFOUND$/,
qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],

['ClamAV-clamscan', 'clamscan',
"--stdout --no-summary -r --tempdir=$TEMPBASE {}",
[0], qr/:.*\sFOUND$/, qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
# ['ClamAV-clamscan', 'clamscan',
# "--stdout --no-summary -r --tempdir=$TEMPBASE {}",
# [0], qr/:.*\sFOUND$/, qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
lisa /etc/init.d/amavisd restart

Creating and selecting a test policy

With the amavisd daemon configured to use the ClamAV daemon we can finally create a filter policy which makes use of the virus scanning capabilities we have just added to our content filter. We shall use the psql application as before to add another row to our filter_policies table as shown in the example below. Once we have created the filter policy we can assign it to all mailboxes and aliases as shown below.

postgres=# INSERT INTO filter_policies(policy_name, bypass_spam_checks, bypass_banned_checks, 
postgres(#                             bypass_header_checks, virus_lover) 
postgres-#   VALUES('Virus checks only - NO QUARANTINE', TRUE, TRUE, TRUE, TRUE); 
INSERT 0 1 
 
postgres=# UPDATE mailboxes SET filter_policy_id = 3; 
UPDATE 3 
postgres=# UPDATE aliases SET filter_policy_id = 3; 
UPDATE 5 

We can now test to see if the virus scanner is functioning correctly by sending a test message containing the following text in the body of the message to one of our addresses. If the system is configured and operating correctly then the message should be tagged as containing a virus.

X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*

Assuming that the test worked and the message was detected as containing a virus signature we can now create a filter policy which combines the spam filtering we implemented in the previous chapter with the virus scanning we implemented above. An example of such a policy, as well as the SQL required to create it and set it to be used by all mailboxes and aliases, is given below.

postgres=# INSERT INTO filter_policies(policy_name, bypass_virus_checks, bypass_spam_checks,  
postgres(#                             bypass_banned_checks, bypass_header_checks, spam_lover, virus_lover) 
postgres-#        VALUES('Spam & Virus checks - NO QUARANTINE', FALSE, FALSE, TRUE, TRUE, TRUE, TRUE); 
INSERT 0 1 
 
postgres=# UPDATE mailboxes SET filter_policy_id = 4; 
UPDATE 3 
postgres=# UPDATE aliases SET filter_policy_id = 4; 
UPDATE 5