\section{Bacula Antivirus Verify Job Plugin}
\subsection{Distinction between Antivirus Plugin and Malware}

In an Antivirus Check, Bacula will transmit the files to the ClamAV Antivirus
Socket, which will perform the scan and report to Bacula if any viruses are
discovered.  In the instance of \vref{MalwareDetection}, Bacula will retrieve
the Malware database signatures from https://abuse.ch/ and then do a file
verification with those signatures. If a Backup job finds malware in the backup
content, an error message is generated and the Job status is changed.

\subsection{Overview}

The Bacula Antivirus Plugin provides integration between the ClamAV Antivirus
daemon and Bacula verify jobs, allowing post-backup virus detection within
Bacula.

\subsection{ClamAV Installation}

ClamAV is an open source (GPLv2) anti-virus toolkit. It provides a flexible and
scalable multi-threaded daemon.  For more information on ClamAV architecture,
best practices and options, please refer to https://docs.clamav.net/


\subsubsection{Debian / Ubuntu}

\subsubsection*{Installation}

Use the existing Debian packages:

\begin{bVerbatim}
  sudo apt-get update
  sudo apt-get install clamav clamav-daemon
\end{bVerbatim}

\subsubsection*{TCP Configuration}

The ClamAV 'clamd' daemon is configured with the clamav.conf file (located in /etc/clamav/).
By default, the ClamAV daemon listens on a Unix LocalSocket:

\begin{bVerbatim}
    LocalSocket /var/run/clamav/clamd.ctl
    FixStaleSocket true
    LocalSocketGroup clamav
    LocalSocketMode 666
\end{bVerbatim}

In order for Bacula to interact correctly with ClamAV, it is essential to
reconfigure the ClamAV daemon so it allows TCP connections instead.

On Debian you can do so automatically by running:

\begin{bVerbatim}
    sudo dpkg-reconfigure clamav-daemon
\end{bVerbatim}

Answer "yes" to reconfigure automatically
Make sure to change the socket type to "TCP".
Choose the TCP port clamd will listen on (The default port 3310 will be assumed in the rest of the documentation).
Continue the reconfiguration according to your needs (press enter to keep the default settings)
At the end of the reconfiguration process, the ClamAV daemon restarts.
You can verify that the clamav.conf file now contains:

\begin{bVerbatim}
    TCPSocket 3310
\end{bVerbatim}

Alternatively, you can reconfigure manually, by editing clamav.conf.
Replace:

\begin{bVerbatim}
    LocalSocket /var/run/clamav/clamd.ctl
    FixStaleSocket true
    LocalSocketGroup clamav
    LocalSocketMode 666
\end{bVerbatim}

with:

\begin{bVerbatim}
    TCPSocket 3310
\end{bVerbatim}

and restart the ClamAV daemon:

\begin{bVerbatim}
    sudo systemctl restart clamav-daemon
\end{bVerbatim}


\subsubsection{Fedora / Redhat / Centos}
\subsubsection*{Installation}

EPEL creates ClamAV packages for Fedora.
To enable the EPEL repository for CentOS:


\begin{bVerbatim}
    sudo dnf install -y epel-release
\end{bVerbatim}

EPEL offers a selection of packages to install ClamAV:

\begin{bVerbatim}
    clamd - The ClamAV Daemon
    clamav - End-user tools for the ClamAV scanner
    clamav-data - Virus signature data for the ClamAV scanner
    clamav-devel - Header files and libraries for the ClamAV scanner
    clamav-lib - Dynamic libraries for the ClamAV scanner
    clamav-milter - Milter module for the ClamAV scanner
    clamav-update - Auto-updater for the ClamAV scanner data-files
\end{bVerbatim}

Bacula minimally requires clamav, clamd, and clamav-update to run:


\begin{bVerbatim}
  sudo dnf install -y clamav clamd clamav-update
\end{bVerbatim}

\subsubsection*{TCP Configuration}
The ClamAV daemon is configured with the clamav.conf file (located in /etc/clamav/).

Edit the configuration file:

\begin{bVerbatim}
    sudo dnf install nano -y
    sudo nano /etc/clamd.d/scan.conf
\end{bVerbatim}

Make sure the Example line is commented out:


\begin{bVerbatim}
  #Example
\end{bVerbatim}

By default, the ClamAV daemon connects over Unix LocalSocket.
In order for Bacula to interact correctly with ClamAV, it is essential to reconfigure the ClamAV daemon so it allows TCP connections instead.
enable TCP connection instead by uncommenting the following line:

\begin{bVerbatim}
  TCPSocket 3310
\end{bVerbatim}

Optionally, you can also restrain the TCP binding (by default the ClamAV daemon binds to INADDR_ANY):

\begin{bVerbatim}
    TCPAddr 127.0.0.1
\end{bVerbatim}

Once that’s done, you can run the virus definition database update:

\begin{bVerbatim}
    sudo freshclam
\end{bVerbatim}

Lastly, start the clamd service and run it on boot:

\begin{bVerbatim}
    sudo systemctl enable clamd@scan
    sudo systemctl start clamd@scan
\end{bVerbatim}

\subsubsection{Bacula Enterprise Antivirus Plugin Installation}

Installation of the Bacula Antivirus Plugin can be installed from community binary repository, or via the ./configure command line.

\subsection{Bacula Verify Job Configuration}

\subsubsection{Parameters}

The Bacula Antivirus Plugin accepts two parameters:

\begin{itemize}
  \item \texttt{hostname} The binding address of the ClamAV daemon (specified in clamav.conf as TCPAddr). Can be any IP4 TCP address. Default is 'localhost'
  \item \texttt{port} The ClamAV daemon port number (specified in clamav.conf as TCPSocket). Default port is 3310.
\end{itemize}
    
\subsubsection{Plugin Options}
Contrary to "classical" Bacula FD plugins, these parameters are configured in the Verify Job
as PluginOptions rather than a "Plugin =" in a FileSet.

There are three possible ways to instruct a Bacula Verify Job to run the antivirus plugin:

\begin{bVerbatim}
# Add a PluginOptions directive to the Verify Job configuration (recommended):

    Job {
      Name = Verify_and_AV_Scan
      Type = Verify
      Level = Data
      Client = localhost-fd
      FileSet = LinuxHome
      Storage = File
      Pool = Default
      Messages = Standard
      PluginOptions = "antivirus: hostname=127.0.0.1 port=3310"   # <---- Add this line here
    }

# Specify the ``pluginoptions`` as a parameter to the 'run' command in bconsole:

    *run job=Verify_and_AV_Scan jobid=1 storage=File1 pluginoptions="antivirus: hostname=localhost port=3310"

# Dynamically modify the verify job within bconsole

    *run job=Verify_and_AV_Scan jobid=1 storage=File1

    JobName:        Verify_and_AV_Scan
    Level:          Data
    Client:         localhost-fd
    FileSet:        LinuxHome
    Pool:           Default (From Job resource)
    Storage:        File1 (From Command input)
    Verify Job:     LinuxHome.2021-10-12_05.31.58_03
    Verify List:
    When:           2021-10-12 05:40:12
    Priority:       10
    OK to run? (yes/mod/no): m
    Parameters to modify:
        1: Level
        2: Storage
        3: Job
        4: FileSet
        5: Client
        6: When
        7: Priority
        8: Pool
        9: Verify Job
        10: Plugin Options
    Select parameter to modify (1-10): 10
    Please Plugin Options string: antivirus: hostname=127.0.0.1 port=3310
    Run Verify Job
    JobName:        Verify_and_AV_Scan
    Level:          Data
    Client:         localhost-fd
    FileSet:        LinuxHome
    Pool:           Default (From Job resource)
    Storage:        File1 (From Command input)
    Verify Job:     LinuxHome.2021-10-12_05.31.58_03
    Verify List:
    When:           2021-10-12 05:40:12
    Priority:       10
    Plugin Options: antivirus: hostname=127.0.0.1 port=3310
    OK to run? (yes/mod/no): yes
\end{bVerbatim}


\subsection{Bacula Antivirus Plugin Behavior}

Under normal conditions, the Verify Job will silently scan existing files from the specified backup and should terminate with a "Verify OK" Job status:

\begin{bVerbatim}
    run job=Verify_and_AV_Scan jobid=1 storage=File1

    JobName:        Verify_and_AV_Scan
    Level:          Data
    Client:         localhost-fd
    FileSet:        LinuxHome
    Pool:           Default (From Job resource)
    Storage:        File1 (From Command input)
    Verify Job:     LinuxHome.2021-10-12_06.04.11_03
    Verify List:
    When:           2021-10-12 06:04:17
    Priority:       10
    Plugin Options: antivirus: hostname=localhost port=3310
    OK to run? (yes/mod/no): yes

    12-Oct 06:04 localhost-dir JobId 2: Verifying against JobId=1 Job=LinuxHome.2021-10-12_06.04.11_03
    12-Oct 06:04 localhost-dir JobId 2: Start Verify JobId=2 Level=Data Job=Verify_and_AV_Scan.2021-10-12_06.04.17_05
    12-Oct 06:04 localhost-dir JobId 2: Connected to Storage "File1" at localhost:8103 with TLS
    12-Oct 06:04 localhost-dir JobId 2: Using Device "FileStorage1" to read.
    12-Oct 06:04 localhost-dir JobId 2: Connected to Client "localhost-fd" at localhost:8102 with TLS
    12-Oct 06:04 localhost-fd JobId 2: Connected to Storage at localhost:8103 with TLS
    12-Oct 06:04 localhost-sd JobId 2: Ready to read from volume "TestVolume001" on File device "FileStorage1" (/mnt/archive).
    12-Oct 06:04 localhost-fd JobId 2: Got plugin command = antivirus: hostname=localhost port=3310
    12-Oct 06:04 localhost-sd JobId 2: Forward spacing Volume "TestVolume001" to addr=228
    12-Oct 06:05 localhost-sd JobId 2: End of Volume "TestVolume001" at addr=98844823 on device "FileStorage1" (/mnt/archive).
    12-Oct 06:05 localhost-sd JobId 2: Elapsed time=00:00:51, Transfer rate=1.935 M Bytes/second
    12-Oct 06:05 localhost-dir JobId 2: Bacula localhost-dir 12.9.2 (11Oct21):
    Build OS:               x86_64-pc-linux-gnu ubuntu 9.12
    JobId:                  2
    Job:                    Verify_and_AV_Scan.2021-10-12_06.04.17_05
    FileSet:                LinuxHome
    Verify Level:           Data
    Client:                 localhost-fd
    Verify JobId:           1
    Verify Job:
    Start time:             12-Oct-2021 06:04:19
    End time:               12-Oct-2021 06:05:21
    Elapsed time:           1 min 2 secs
    Accurate:               no
    Files Expected:         2,238
    Files Examined:         2,238
    Non-fatal FD errors:    0
    SD Errors:              0
    FD termination status:  OK
    SD termination status:  OK
    Termination:            **Verify OK**

\end{bVerbatim}

When a virus is detected by ClamAV, an error is reported in the Bacula job log and the Job will continue
to verify the rest of the files, but it will terminate with a "Verify OK -- with warnings" Job status.

Within the job output, the antivirus plugin specifies the infected file(s) and the virus name(s) detected.

\begin{bVerbatim}
    run job=Verify_and_AV_Scan jobid=3 storage=File1

    JobName:        Verify_and_AV_Scan
    Level:          Data
    Client:         localhost-fd
    FileSet:        LinuxHome
    Pool:           Default (From Job resource)
    Storage:        File1 (From Command input)
    Verify Job:     LinuxHome.2021-10-12_06.05.22_07
    Verify List:
    When:           2021-10-12 06:05:27
    Priority:       10
    Plugin Options: antivirus: hostname=localhost port=3310
    OK to run? (yes/mod/no): yes

    12-Oct 06:05 localhost-dir JobId 4: Verifying against JobId=3 Job=LinuxHome.2021-10-12_06.05.22_07
    12-Oct 06:05 localhost-dir JobId 4: Start Verify JobId=4 Level=Data Job=Verify_and_AV_Scan.2021-10-12_06.05.27_09
    12-Oct 06:05 localhost-dir JobId 4: Connected to Storage "File1" at localhost:8103 with TLS
    12-Oct 06:05 localhost-dir JobId 4: Using Device "FileStorage1" to read.
    12-Oct 06:05 localhost-dir JobId 4: Connected to Client "localhost-fd" at localhost:8102 with TLS
    12-Oct 06:05 localhost-fd JobId 4: Connected to Storage at localhost:8103 with TLS
    12-Oct 06:05 localhost-sd JobId 4: Ready to read from volume "TestVolume001" on File device "FileStorage1" (/mnt/archive).
    12-Oct 06:05 localhost-fd JobId 4: Got plugin command = antivirus: hostname=localhost port=3310
    12-Oct 06:05 localhost-sd JobId 4: Forward spacing Volume "TestVolume001" to addr=98844823
    12-Oct 06:05 localhost-sd JobId 4: End of Volume "TestVolume001" at addr=98845442 on device "FileStorage1" (/mnt/archive).
    12-Oct 06:05 localhost-sd JobId 4: Elapsed time=00:00:01, Transfer rate=197  Bytes/second
    12-Oct 06:05 localhost-fd JobId 4: **Error: /home/nbizet/src/bacula-bee/regress/tmp/eicar Virus detected stream: Eicar-Signature FOUND**
    12-Oct 06:05 localhost-dir JobId 4: Bacula localhost-dir 12.9.2 (11Oct21):
    Build OS:               x86_64-pc-linux-gnu ubuntu 9.12
    JobId:                  4
    Job:                    Verify_and_AV_Scan.2021-10-12_06.05.27_09
    FileSet:                LinuxHome
    Verify Level:           Data
    Client:                 localhost-fd
    Verify JobId:           3
    Verify Job:
    Start time:             12-Oct-2021 06:05:29
    End time:               12-Oct-2021 06:05:29
    Elapsed time:           1 sec
    Accurate:               no
    Files Expected:         1
    Files Examined:         1
    Non-fatal FD errors:    1
    SD Errors:              0
    FD termination status:  OK
    SD termination status:  OK
    Termination:            **Verify OK -- with warnings**

\end{bVerbatim}

The Antivirus Plugin will record events into the catalog for each problem
that is detected. The \textbf{list fileevents} command can be used to list them.

\begin{bVerbatim}
  
    *list fileevents jobid=3
    Using Catalog "MyCatalog"
    +-------+-------------------+----------+----------+------+-------------------------------+
    | jobid | path              | filename | severity | type | description                   |
    +-------+-------------------+----------+----------+------+-------------------------------+
    |     3 | /home/johndoe/mp/ | eicar    |      100 | a    | stream: Eicar-Signature FOUND |
    +-------+-------------------+----------+----------+------+-------------------------------+

\end{bVerbatim}
    
The severity represents the level of threat, 0 behing harmless, 100 and above harmful.

The type indicates which kind of event is listed, here `a` meaning "antivirus".
   


\section{Bacula Malware Detection}
\label{MalwareDetection}

Bacula allows you to configure your jobs to detect known Malware. The detection
can be done at the end of the Backup job and/or with a Verify job.

The Job directive \texttt{Check Malware = yes/No} can control the behavior.

\begin{bVerbatim}
  Job {
    Name = MyBackup
    Check Malware = yes
    FileSet = FullSet
    JobDefs = Default
  }

  FileSet {
    Name = FullSet
    Include {
       Options {
          Signature = md5
       }
       File = /home
    }
  }
\end{bVerbatim}

The FileSet of the Backup Job must use the \texttt{Signature = MD5} or
\texttt{Signature = SHA256} option to use the \textt{Check Malware} directive.

By default, the Malware database is fetched from \texttt{abuse.ch}. If needed, it
can be adapted with the Director \texttt{MalwareDatabaseCommand} directive.

If a Backup job detects a malware in the backup content, an error is reported
and the Job status is adapted.

\begin{bVerbatim}

  20-Sep 12:26 zog8-dir JobId 9: Start Backup JobId 9, Job=backup.2022-09-20_12.26.30_13
  ...
  20-Sep 12:26 zog8-dir JobId 9: [DI0002] Checking file metadata for Malwares
  20-Sep 12:26 zog8-dir JobId 9: Error: [DE0007] Found Malware(s) on JobIds 9
     Build OS:               x86_64-pc-linux-gnu archlinux
     JobId:                  9
     Job:                    backup.2022-09-20_12.26.30_13
     Backup Level:           Full
     ...
     Last Volume Bytes:      659,912,644 (659.9 MB)
     Non-fatal FD errors:    1
     SD Errors:              0
     FD termination status:  OK
     SD termination status:  OK
     Termination:            Backup OK -- with warnings
\end{bVerbatim}
     
 The list of the Malware detected in a given Job can be displayed with the \texttt{list files type=malware}
 command.

\begin{bVerbatim}

    *list files type=malware jobid=1
    +-------+-----------------------------+---------------+----------+
    | jobid | filename                    | description   | source   |
    +-------+-----------------------------+---------------+----------+
    |     1 | /tmp/regress/build/po/fr.po | Malware found | abuse.ch |
    +-------+-----------------------------+---------------+----------+

\end{bVerbatim}

A Verify Job with the level \texttt{VolumeToCatalog} or \texttt{Data} can be configured
with the \texttt{Check Malware=yes} directive to report malware in addition to
standard errors detected by the Verify Job feature.


\begin{bVerbatim}
     *run job=VerifyVolCat jobid=1 yes
     Job queued. JobId=7
     *wait
     You have messages.
     *messages
     20-Sep 12:26 zog8-dir JobId 7: Verifying against JobId=1 Job=backup.2022-09-20_12.25.48_03
     20-Sep 12:26 zog8-dir JobId 7: [DI0002] Checking file metadata for Malwares
     20-Sep 12:26 zog8-dir JobId 7: Error: [DE0007] Found Malware(s) on JobIds 1
     20-Sep 12:26 zog8-sd JobId 7: Ready to read from volume "TestVolume001" on File device "FileChgr1-Dev1" (/tmp/regress/tmp).
     20-Sep 12:26 zog8-sd JobId 7: Forward spacing Volume "TestVolume001" to addr=216
     20-Sep 12:26 zog8-sd JobId 7: Elapsed time=00:00:01, Transfer rate=94.08 M Bytes/second
     20-Sep 12:26 zog8-dir JobId 7: Bacula zog8-dir 14.1.1 (12Aug22):
       Build OS:               x86_64-pc-linux-gnu archlinux
       JobId:                  7
       Job:                    VerifyVolCat.2022-09-20_12.26.14_09
       FileSet:                Full Set
       Verify Level:           VolumeToCatalog
       Client:                 zog8-fd
       Verify JobId:           1
       Verify Job:
       Start time:             20-Sep-2022 12:26:16
       End time:               20-Sep-2022 12:26:25
       Elapsed time:           9 secs
       Accurate:               yes
       Files Expected:         3,640
       Files Examined:         3,640
       Non-fatal FD errors:    1
       SD Errors:              0
       FD termination status:  OK
       SD termination status:  OK
       Termination:            Verify OK -- with warnings
\end{bVerbatim}
