Scannedonly scalable samba anti-virus module

What is scannedonly?

Scannedonly is a samba VFS module and a scanning daemon that ensure that only files that have been scanned for viruses are visible and accessible to the end user.

Scannedonly was developed because of scalability problems with samba-vscan: high server loads when (the same) files were requested often, and timeouts when large zip files were requested. Scannedonly doesn't have these problems, but it does introduce some other issues. Choose the product that suits you best.

Scannedonly is available under the open source GPL licence. The source code repository is available on Sourceforge. You can contact the author by email oli4 (at) users . sourceforge . net.

How does scannedonly work?

Scannedonly comes in two parts: a samba vfs module (included in samba since samba-3.5.0) and (one or more) daemons. The daemon scans files. If a certain file is clean, a second file is created with prefix .scanned:. The samba module simply looks if such a .scanned: file exists, and is newer than the pertinent file. If this is the case, the file is shown to the user. If this is not the case, the file is not returned in any directory listing, and cannot be opened. The samba vfs module will also tell the daemon to scan this file.

So what happens for the user. The first time a directory is listed, it is empty, but after a first refresh all files are shown. There is a utility scannedonly_prescan that can help you to prescan all directories.

If a virus is found by the daemon, a file with a warning message is created in the directory of the user, a warning is sent to the logs, and the file is renamed to have prefix .virus:. Files with the .virus: prefix are never shown to the user and all access is denied.


29-10-2010 - Scannedonly 0.21 release

Scannedonly moved from mtime to ctime to use a more reliable timestamp. The clamav daemon now cleans the queue if duplicate filenames are requested. Last scannedonly handles file rename situations better.

08-06-2010 - Scannedonly 0.20 release

The VFS module in the 0.20 release handles applications that write to a temporary file and then rename to the final name better. It furthermore includes an experimental daemon for the F-prot anti-virus engine contributes by Fred Gansevles from

28-03-2010 - Scannedonly 0.19 release

The 0.19 release fixes a symlink handling issue on samba shares, fixes an issue if the filesystem supports no sub-second timestamps, and improves the quarantaine option of the scannedonld_clamav daemon. An experimental patch to compile with a different libtalloc has been added, use ./configure --with-talloc-source=

31-01-2010 - Scannedonly 0.18 release

The 0.18 release is a backport of the module that is now part of samba-3.5. The samba code was made compatible with samba 3.2 and 3.4, and upon request I've re-introduced samba 3.0 support.

25-01-2010 - Scannedonly 0.17 release

The loop that was fixed in the 0.16 release was not fixed for all cases. This release has a complete rewrite of the loop that should fix the problem in a much better way. This release furthermore fixes AIX compatibility in the VFS module.

19-01-2010 - Scannedonly 0.16 release

The 0.16 release has some bug fixes (loop in the scanning daemon for some exclude patterns) and a fix in the VFS module when there is no permission for a directory listing. Some logging messages from the scanning daemon are also slightly improved.

17-01-2010 - Scannedonly Samba VFS module now part of Samba

From Samba-3.5.0 and newer the Scannedonly VFS module is part of Samba. The scanning daemon will not be part of samba. For older versions of samba use the VFS module included in the scannedonly source.

16-10-2009 - Scannedonly 0.15 released

The 0.15 release brings compatibility with samba 3.4 (tested with 3.4.2). There are no other changes.

07-06-2009 - Scannedonly 0.14 released

The 0.14 release brings compatibility with ClamAV 0.95 and features some performance improvements when a directory with a very large number of unscanned files is opened for the first time.


Communication between the samba module and the anti-virus scanning daemon

Communication between the vfs module and the daemon is done over a socket. Either a UDP (network) socket or a unix (domain) socket can be used. Traffic is one way, only the vfs module sends filenames to the daemon, nothing is returned. Scanning can be offloaded to a separate server if UDP is used, but this server needs access to the same files.

The scanning daemon

The first daemon supplied with scannedonly uses clamav, it is called scannedonlyd_clamav. It can run multiple scanning threads to speed up scanning on multi-core multi-cpu servers. The default is 4 threads. To make sure that most normal files are scannned rapidly, only one thread will be scanning large files (default 5mb or higher), all other threads scan only small files.

--portnum -pThe UDP port to listen on2020 (but by default a domain socket is used)
--socket -sThe unix domain socket name to listen on. The directory needs to exist!/var/lib/scannedonly/scan
--maxthreads -tThe total number of scanning threads. Maximum one thread (see option maxlargethreads) will be scanning large files. Maximum one thread might be updating the clam database. So use at least 3 threads if you want to guarantee that there is always a thread for small files available.4 threads
--maxlargethreads -gSince 0.13 The maximum number of scanning threads that may scan large files.1 thread
--loglevel -lThe log level from 0 (little logging) to 3 (verbose logging)1
--big -bWhich size files are treated as big5 Mb (and higher)
--time -mThe interval for status messages in the logs10 minutes
--scanroot -rThe base directory for which requests for scanning are accepted. Requests to scan files outside this directory are ignored. Using this option is very much advised!/ (all files are accepted by default)
--quarantainedir -dSince 0.13 By default a file is renamed into .virus:file. If you want all viruses in a central location specify a quarantainedir. If a virus is found it will be moved to this directory.none
--queuelen -qThe maximum request queue length. If the maximum number of requests are on the queue, new requests are ignored.5000 requests
--pidfile -iThe location for a PID filenone
--exclude -eExclude scanning of files that match this (regular expression) pattern. For example '/home/[^/]+/Maildir/.*'. You might want to use the option veto files in your Samba configuration to exclude these files in samba as well, otherwise samba will keep telling that these files need scanning.none

The scannedonly samba-vfs module

The samba vfs module can be configured per share. The following options are possible:

scannedonly:domain_socketWhether to use a unix domain socket or not (False reverts to use udp)True
scannedonly:socketnameThe location of the unix domain socket to connect to/var/lib/scannedonly/scan
scannedonly:portnumThe udp port number to connect to2020
scannedonly:scanhostThe host to connect to (this host needs access to the files!)localhost
scannedonly:show_special_filesWhether sockets, devices and fifo's (all not scanned for viruses) should be visible to the userTrue
scannedonly:rm_hidden_files_on_rmdirWhether files that are not visible (special files, failed files and viruses) should be deleted if the user tries to remove the directory. If False, the user will get the "directory is not empty" error.True
scannedonly:hide_nonscanned_filesIf false, all non-scanned files are visible in directory listings. If such files are found in a directory listing the scanning daemon is notified that scanning is required. Download of non-scanned files is still denied. Since 0.11True
scannedonly:scanning_messageIf non-scanned files are hidden, a message is shown as a 0 byte file. This message is the original filename with a message as suffix. Since 0.13is being scanned for viruses
scannedonly:recheck_time_openIf a non-scanned file is opened, the vfs module will wait recheck_tries_open times for recheck_time_open milliseconds for the scanning daemon to create a .scanned: file. For small files that are scanned within the time (tries * time) the behavior will be just like on-access scanning. Since 0.11 50
scannedonly:recheck_tries_openSee recheck_time_open. Since 0.11100
scannedonly:recheck_time_readdirIf a non-scanned file is in a directory listing, the vfs module will wait recheck_tries_readdir times for recheck_time_readdir milliseconds for the scanning daemon to create a .scanned: file. For directory listings with many non-scanned files this will cause a significant slowdown. Only used when hide_nonscanned_files is False. Since 0.11. In 0.13 the behavior of this option has changed. Since 0.13 the vfs module now notifies the daemon once for all files that need scanning, and waits recheck_tries_readdir times for recheck_time_readdir milliseconds per directory listing (and not anymore per file).50
scannedonly:recheck_tries_readdirSee recheck_time_readdir. Since 0.112 (0.11) or 20 (0.13)
scannedonly:allow_nonscanned_filesAllow access to non-scanned files. The daemon is notified, however, and .scanned: files are not listed. If the daemon can keep up with the requests all files will be scanned within a couple of seconds, so a virus is still found quickly. Many programs that Open and close files in a high frequency in a short timespan need this in order to function. Most notably and Microsoft Office open and close the same files very frequently. Since 0.13False

A common entry in smb.conf might look like:

[myshare] path = /srv/data/myshare/ vfs object = scannedonly scannedonly: domain_socket = False scannedonly: portnum = 2020 scannedonly: scanhost = localhost scannedonly: hide_nonscanned_files = False

Tips and tricks

Force re-scanning of all files that have been scanned more than 2 weeks ago

find /data/path -name '.scanned:*' ! -mtime 14 | exec rm '{}' \; scannedonly_prescan /data/path

Move all found viruses to one quarantaine directory

find /data/path -name '.virus:*' | exec mv '{}' /quarantaine/path \;
Created with the Bluefish programmers editor