Setting Up ClamAV on a Linux Server for Windows remote file scanning
Overview
This week I set up ClamAV on an Ubuntu ec2 instance, with the intention of scanning files remotely from our software. This guide will walk through the setup of ClamAV to run the clamd service on port 3310, and then having a Windows host run a small .py file to scan a file using the clamd service.
Prerequisites
- You will need a Linux machine, with SSH access to it, as well as allowing inbound 3310 from the servers you are going to connect from
- A Windows machine with python installed
Configuring ClamAV
- SSH into your Linux machine and verify it is up to date
sudo apt update
sudo apt upgrade
- Install ClamAV and ClamAV Daemon (clamd) and configure the user it will run as
apt-get install -y cargo rustc
groupadd clamav
useradd -g clamav -s /bin/false -c "Clam Antivirus" clamav
sudo apt install clamav clamav-daemon
- Edit the clamd.conf file
sudo nano /etc/clamav.clamd.conf
-
You will want to make several config changes here:
LocalSocketGroup clamav
User clamav
TCPSocket 3310
TCPAddr <IP of Linux Machine>
-
To enable automatic updates, edit the FreshClam configuration file:
sudo nano /etc/clamav/freshclam.conf
- Start the clamd service and enable it to start at boot
sudo systemctl restart clamav-daemon
sudo systemctl enable clamav-daemon
Testing Windows Connection
- Now that you have your clamAV server running, you should be able to connect to it on port 3310 from your Windows machine, assuming that your network allows it. To test this, from your Windows Machine, run the following:
Test-NetConnection -ComputerName <linux_server_ip> -Port 3310
- Install the pyclam library on your windows machine
pip install pyclamd
- Create the remote_scan.py file on your computer
import argparse
import pyclamd
import os
import time
clamav_server_ip = '172.16.63.55' # Replace with your Linux server's IP address
def scan_file_remote(file_path):
# Convert Windows-style path to Linux-style path
linux_file_path = file_path.replace('\\', '/')
try:
cd = pyclamd.ClamdNetworkSocket(clamav_server_ip, 3310)
cd.ping() # Test the connection
if cd.version() == 'ClamAV/1.0':
cd.reload()
scan_results = cd.scan_stream(open(file_path, 'rb'))
attempts = 0
while scan_results is None and attempts < 5:
time.sleep(1)
scan_results = cd.scan_stream(open(file_path, 'rb'))
attempts += 1
if scan_results is not None:
if 'FOUND' in scan_results:
print('File is infected:', scan_results['FOUND'])
else:
print('File is clean.')
else:
print('No scan results received after multiple attempts.')
except pyclamd.ConnectionError as conn_ex:
print(f'Connection error: {conn_ex}')
except Exception as ex:
print(f'An unexpected error occurred: {ex}')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Remote ClamAV File Scanner')
parser.add_argument('file_path', help='Path of the file to scan')
args = parser.parse_args()
# Convert the local file path to an absolute path
args.file_path = os.path.abspath(args.file_path)
scan_file_remote(args.file_path)
- Test using a test file
python remote_scan.py "C:\temp\test.txt"