โšก Onwuachi Control Plane

Filescanner: ClamAV Malware Scanning Architecture

Filescanner: ClamAV Malware Scanning Architecture

How uploaded files are scanned for malware in a multi-tenant SaaS platform.

1. Malware Scanning Solution

System: ClamAV in TCP mode, performing signature-based scans to detect known threats.

What it scans for: malware, viruses, and suspicious file types using regularly updated virus definitions.

Documentation: ClamAV official docs

2. Scan Type & Configuration

3. Origins & Security Measures

4. Edge Routing (HAProxy)

The reverse proxy routes upload/download traffic to the scanner service based on path and query parameters, then forwards clean traffic on to the underlying application:

frontend ft_app_tcp
  acl is_ftp_download url_param urlp(cmd) file-download
  acl is_ftp_upload   url_param urlp(cmd) file-upload

  use_backend bk_file_scanner       if HTTP { path_beg /uc/ftp }
  use_backend bk_uc_direct_http     if HTTP { path_beg /ftp } is_ftp_download
  use_backend bk_upload_filescanner if HTTP { path_beg /ftp } is_ftp_upload

backend bk_file_scanner
  mode http
  # strip the app path prefix now that we're behind HAProxy
  http-request replace-path /uc/(.*) /\1
  http-request set-query %[query]&cmd=fwd&fwd_loc=http%%3A%%2F%%2Fapp%%3A80
  server FILESCANNERUPLOAD filescanner:80
  # cookies back to the app with the full path
  http-response replace-value Set-Cookie (.*)Path=(.*) \1Path=/uc\2

backend bk_upload_filescanner
  mode http
  timeout server 300s
  http-request set-query %[query]&cmd=fwd&fwd_loc=http%%3A%%2F%%2Fapp%%3A80
  server FILESCANNERUPLOAD filescanner:80

5. Filescanner Container Config

<config>
  <servers>
    <server addr='all' port='80'>
      <http/>
      <rxml/>
    </server>
  </servers>
  <resources>
    <wwwLocal>www</wwwLocal>
    <type>clamav_tcp</type>
    <host><!-- internal ClamAV service host --></host>
    <port>3310</port>
    <system>SCAN {file}</system>
  </resources>
  <tmpPath>/scandir/</tmpPath>
  <origins>
    <origin>https://*.example-app.com</origin>
    <origin>linklive://*.example-app.com</origin>
  </origins>
</config>

6. Container Lifecycle

Start:

#!/bin/sh
service=filescanner
source ../.service

SCANDIR="$(realpath /mnt/efs/share/clamav/scandir)"
[ ! -d ${SCANDIR} ] && sudo mkdir -p ${SCANDIR}

docker run \
  --platform linux/amd64 \
  --name ${service}-${INSTANCE_NAME} -dt --restart unless-stopped \
  --network ${INSTANCE_NAME} --hostname ${hostname} -it --ulimit core=-1 \
  --mount type=bind,source="$(realpath ../../$inst/app/${service})",target=/etc/app \
  --mount type=bind,source="${SCANDIR}",target=/scandir \
  <registry>/${service}:${VERSION} /config_path="/etc/app/"

Stop:

#!/bin/sh
service=filescanner
source ../.service
docker container rm -f ${service}-${INSTANCE_NAME}

7. DB Definitions & Update Tracking

FilePurpose
main.cvdCore virus definitions
daily.cldDaily updates to virus signatures
bytecode.cldBytecode signatures for advanced detection
freshclam.datMetadata for update tracking (last update time)

freshclam runs on a schedule, tests each new database before activating it, and notifies clamd on successful update. Watch for version-lag warnings (ClamAV installation is OUTDATED) โ€” these indicate the running engine version has fallen behind the recommended version even though signature databases are current; engine and signature versions are tracked and reported separately.

clamd performs a periodic self-check (SelfCheck: Database status OK) independent of freshclam’s update cycle โ€” useful for confirming the running daemon, not just the on-disk database files, is healthy.

8. References

System Context

โ† Back to Kb