5. Install UFW and ClamAV

by Double Bastion - Updated September 20, 2022

5.1. Install UFW

UFW or Uncomplicated Firewall, is a tool designed to allow administrators to easily manage the native Debian firewall. Instead of using complicated commands to edit the iptables directly, you can manage the firewall rules very easily using UFW. First install UFW:

apt-get install ufw

5.1.1. Set the default firewall rules

In general, a server only needs a small number of ports open for incoming connections, while all the other ports should remain closed. The ufw default command can be used to set the default response to incoming and outgoing connections. To deny all incoming and allow all outgoing connections, run:

ufw default allow outgoing
ufw default deny incoming

The ufw default command also allows the use of the reject parameter. Please note that the deny and allow rules have no effect until you enable ufw, so, make sure that you set the proper allow rules for SSH and for other critical services as we describe below, before enabling ufw with the default allow/deny rules from above. Otherwise, you may lock yourself out of your server.

5.1.2. Adding firewall rules

Rules can be added in two ways: by specifying the port number or by specifying the service name.

For example, to allow both incoming and outgoing connections on port 80 for HTTP, you can run:

ufw allow 80

or

ufw allow http

You can add a rule to deny traffic on a certain port like this:

ufw deny 111

If you do this, when you run the ufw status command to list all the rules implemented by UFW, port 111 will be preceded by DENY, like this:

To                          Action       From
--                          ------       ----
111                         DENY         Anywhere

You can fine-tune your rules, by allowing data packets based on the TCP or UDP protocols. Both commands from below will do the same thing: allow TCP packets on port 80:

ufw allow 80/tcp
ufw allow http/tcp

The following command will allow UDP packets on port 2536:

ufw allow 2536/udp

5.1.3. Removing firewall rules

To remove a rule, use the delete command, like this:

ufw delete allow 80

The delete command also allows the use of service names (http, ssh, etc.).

5.1.4. Allow connections for the custom SSH port

Remember that in the /etc/ssh/sshd_config file, you changed the default SSH port, which is 22, to a custom port, 6283 in our example. This is very important for security reasons but it’s equally important to remember to allow SSH connections on this custom SSH port, otherwise you will lock yourself out of your sever when enabling UFW. To open port 6283 in the firewall run:

ufw allow 6283

Replace 6283 with your custom SSH port. This implies that you won’t open port 22, which is the main target of attackers.

Since it’s safer to enable SSH connections over IPv4 only, you should disable IPv6 access to the port that you have just opened in the firewall. First run:

ufw status numbered

The output will look similar to:

     To                         Action      From
     --                         ------      ----
[ 1] 6283                       ALLOW IN    Anywhere                                  
[ 2] 6283 (v6)                  ALLOW IN    Anywhere (v6)

To delete the rule allowing IPv6 access to port 6283, run:

ufw delete 2

Replace 2 with the number of the IPv6 rule in your case. This will allow SSH connections on port 6283 only over IPv4.

5.1.5. Advanced rules

Using UFW you can allow or deny connections based on ports, but also based on specific IP addresses, subnets, or a combinations of IP addresses, subnets and ports.

To allow connections from the IP 111.111.111.111, run:

ufw allow from 111.111.111.111

To allow connections from the 111.111.111.111/24 subnet run:

ufw allow from 111.111.111.111/24

To allow a specific IP address-port-protocol combination:

ufw allow from 111.111.111.111 to any port 4234 proto tcp

proto tcp can be removed or replaced with proto udp depending on your requirements, and all instances of allow can be changed to deny .

To open a range of ports run:

ufw allow 12200:12299/tcp

In the case of port ranges, the protocol part (/tcp or /udp) is mandatory.

5.1.6. Editing UFW Configuration Files

Before running the rules added using the command line, UFW runs the rules listed in the /etc/ufw/before.rules file, which can be complex rules associated with loopback, pings or DHCP. To add rules to be run before the rules entered in command line, edit the /etc/ufw/before.rules file. A before6.rules file is also located in the same directory for IPv6.

An after.rule and an after6.rule file also exist to add any rules that need to be run after running the rules that you added in command line.

Another important configuration file is the /etc/default/ufw file. In this file, you can enable or disable IPv6 support and configure different default settings.

5.1.7. Enable UFW

After you have set all your rules, if you run:

ufw status

you will see:

Status: inactive

To enable UFW and apply all the firewall rules that you have set up, run:

ufw enable

Similarly, to disable UFW’s rules, run:

ufw disable

This will still leave the UFW service running and enabled on reboots.

5.1.8. Resetting UFW Rules

If you have set up some UFW rules but you decide that you want to start again, you can use the reset command to disable UFW and delete all the rules added previously:

ufw reset

This will enable you to remove all your changes and start fresh.

5.1.9. UFW Status

You can check the status of UFW at any moment by running:

ufw status

This will show whether or not UFW is active and will list all the rules added using the command line:

Status: active

To                         Action      From
--                         ------      ----
6283                       ALLOW       Anywhere
80                         ALLOW       Anywhere
443                        ALLOW       Anywhere
6283 (v6)                  ALLOW       Anywhere (v6)
80 (v6)                    ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)

You can list all the rules as a numbered list by running:

ufw status numbered

     To                         Action      From
     --                         ------      ----
[ 1] 2581                       ALLOW IN    Anywhere
[ 2] 6258                       ALLOW IN    Anywhere
[ 3] 6814                       ALLOW IN    Anywhere
[ 4] 6815                       ALLOW IN    Anywhere
[ 5] 443                        ALLOW IN    Anywhere

The big advantage when listing the rules in a numbered list is that you can delete any rule by specifying its number, like this:

ufw delete 2

or

ufw delete 5

After you install all the applications described in this guide, your UFW rules should look like below. (Please note that the ports in red will be custom ports, so, you shouldn’t use the ones shown below. You should replace them with your own custom ports, as we’ll explain for each application when describing how to install it. Don’t open all these ports yet. We’ll explain when to open each of them further down below.)

ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 6283                       ALLOW IN    Anywhere (SSH)
[ 2] 1053                       ALLOW IN    Anywhere (FTP)
[ 3] 30856                      ALLOW IN    Anywhere (FTP passive)
[ 4] 30857                      ALLOW IN    Anywhere (FTP passive)
[ 5] 443                        ALLOW IN    Anywhere (HTTPS)
[ 6] 80                         ALLOW IN    Anywhere (HTTP)
[ 7] 1194/udp                   ALLOW IN    Anywhere (OpenVPN)
[ 8] 995                        ALLOW IN    Anywhere (POP3S)
[ 9] 993                        ALLOW IN    Anywhere (IMAPS)
[10] 587                        ALLOW IN    Anywhere (STARTTLS over SMTP)
[11] 465                        ALLOW IN    Anywhere (SMTPS)
[12] 143                        ALLOW IN    Anywhere (IMAP)
[13] 110                        ALLOW IN    Anywhere (POP3)
[14] 25                         ALLOW IN    Anywhere (SMTP)
[15] 8443                       ALLOW IN    Anywhere (STUN)
[16] 10000:20000/udp            ALLOW IN    Anywhere (Asterisk)
[17] 5827                       ALLOW IN    Anywhere (Asterisk)
[18] 8088                       ALLOW IN    Anywhere (SIP over WebSocket)
[19] 8089                       ALLOW IN    Anywhere (SIP over WebSocket)
[20] 53                         ALLOW IN    Anywhere (DNS BIND)
[21] 443 (v6)                   ALLOW IN    Anywhere (v6)
[22] 80 (v6)                    ALLOW IN    Anywhere (v6)
[23] 995 (v6)                   ALLOW IN    Anywhere (v6)
[24] 993 (v6)                   ALLOW IN    Anywhere (v6)
[25] 587 (v6)                   ALLOW IN    Anywhere (v6)
[26] 465 (v6)                   ALLOW IN    Anywhere (v6)
[27] 143 (v6)                   ALLOW IN    Anywhere (v6)
[28] 110 (v6)                   ALLOW IN    Anywhere (v6)
[29] 25 (v6)                    ALLOW IN    Anywhere (v6)
[30] 8443 (v6)                  ALLOW IN    Anywhere (v6)
[31] 10000:20000/udp (v6)       ALLOW IN    Anywhere (v6)
[32] 5827 (v6)                  ALLOW IN    Anywhere (v6)
[33] 8088 (v6)                  ALLOW IN    Anywhere (v6)
[34] 8089 (v6)                  ALLOW IN    Anywhere (v6)
[35] 53 (v6)                    ALLOW IN    Anywhere (v6)

5.1.10. Upgrading UFW

Since UFW has been installed from the official Debian repository, to upgrade it, all you need to do is to run apt-get update && apt-get dist-upgrade with a specific frequency, as described in the Maintenance steps chapter. This command will upgrade UFW if there is a new version available. Also, during these upgrades, the configuration changes implemented as described above, will be preserved.

5.2. Install ClamAV

For the setup described in this guide you will need an antivirus. ClamAV is the best choice because it’s a mature, feature-rich, free and open source antivirus. It can be used to scan files and directories periodically or on demand and for email scanning. To install ClamAV, run:

apt-get install clamav clamav-daemon clamav-freshclam clamdscan

Make a copy of the /etc/clamav/clamd.conf file:

cp /etc/clamav/clamd.conf /etc/clamav/clamd.conf_orig

Open the /etc/clamav/clamd.conf file:

nano /etc/clamav/clamd.conf

Change the following directives, to make them look like this:

LocalSocket /var/run/clamav/clamd.ctl
LocalSocketMode 664
MaxScanSize 600M
MaxFileSize 600M

Stop and disable the clamav-freshclam daemon, because you will use a cron job to update ClamAV with a specific frequency, so, you won’t need the clamav-freshclam daemon for updating purposes:

systemctl stop clamav-freshclam
systemctl disable clamav-freshclam

Now add a cron job to update ClamAV once a day, at a moment when the server is not busy:

crontab -e

Add the following lines inside the file:

# Update the ClamAV antivirus definitions every day at 3:40 AM
40 3 * * * /usr/bin/freshclam --quiet

This cron job will run the freshclam command and update ClamAV once a day, at 3:40 a.m.

Restart clamav-daemon and update the virus signatures:

systemctl restart clamav-daemon
freshclam

Add the webserver user, www-data, to the clamav group, to allow applications like Roundpin to invoke clamdscan to scan uploaded files:

adduser www-data clamav

If you use the top command to see the memory used by all the running processes on the server (run top, then press f, then use the arrow keys to select %MEM, to order all the processes by the RAM percentage which they use, then press s, then press Esc), you will see that clamd uses a big portion of the server’s RAM (more than 700MB). This is because it has to load into memory, for quick access, all the virus and malware signatures, which take a lot of space. Although this substantial memory consumption is an important disadvantage, it is inevitable. Stopping the clamav-daemon and configuring ClamAV to load all the signatures in memory only when emails arrive, is not feasible, because from time to time a large number of emails can arrive simultaneously and the antivirus won’t be able to load the virus signatures and scan the emails properly, causing errors or overloading issues.

Please note that even if you keep all your installed packages up-to-date, from time to time, you may see the follwoing warning in the /var/log/clamav/freshclam.log file:

WARNING: Your ClamAV installation is OUTDATED!

This happens because in general there is a delay between the moment a new version of ClamAV is released and the moment the new version is included in the Debian repository. If your version of ClamAV is the newest version that exists in the Debian repository, you should ignore this warning, because the freshclam utility will still work and you will get the newest virus signatures in your version of ClamAV. Installing the latest ClamAV version from source or from the official website is not recommended since this can create problems when upgrading the antivirus or other packages. Therefore, the best method to run ClamAV is to install the version included in the Debian repository, as explained above, and keep that version up to date.

5.2.1. Scan directories and files manually with ClamAV

You can scan manually any directory or file with ClamAV by running:

clamscan -ir /path/to/directory/or/file

5.2.2. Scan directories and files automatically with ClamAV

You can also scan automatically any directories or files with ClamAV by setting a cron job like this:

crontab -e

Add a line like the following:

30 2 * * * /usr/bin/clamscan -r /folder/to/scan/ | grep FOUND >> /path/to/saved/report/scanreport.txt > /dev/null 2>&1

This will set ClamAV to scan the specified directory every day at 2:30 a.m., and save a report with the infected files in the specified file.

Please note that when scanning folders and files as shown above, by default, ClamAV will only identify the infected files but will not remove them, so, once you know which are the infected files, you’ll have to delete them manually. The situation will be different with the infected files uploaded to Nextcloud, as we’ll describe further down below. All the infected files uploaded to Nextcloud will be removed the very moment they will be detected.

5.2.3. Upgrading ClamAV

Since ClamAV has been installed from the official Debian repository, to upgrade it, all you need to do is to run apt-get update && apt-get dist-upgrade with a specific frequency, as described in the Maintenance steps chapter. This command will upgrade ClamAV if there is a new version available. Also, during these upgrades, the configuration changes implemented as described above, will be preserved.

You can send your questions and comments to: