Skip to content

The Advanced Guide To Secure Your Server

Ubuntu firewall open port Ubuntu firewall open port

Disclaimer

No system is safe. This chapter ends our exploration of Ubuntu server security. Remember however that skilled hackers or well-funded organisations can breach basic and even more advanced defences.

Privileged Access

Only a specific user group should have privileged access, as described in the following.

Step-by-step guide

Create a group called sudousers, and add both users gofossroot and gofossadmin (adjust user names according to your own setup):

sudo groupadd sudousers
sudo usermod -a -G sudousers gofossroot
sudo usermod -a -G sudousers gofossadmin

Backup the sudoers configuration file. If something goes wrong, you'll be able to recover the initial settings:

sudo cp --archive /etc/sudoers /etc/sudoers-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /etc/sudoers

Add the following line, if it's not already there:

%sudousers   ALL=(ALL:ALL) ALL

Remove privileges for the existing admin and sudo groups by commenting out the following lines with a hash tag:

# Members of the admin group may gain root privileges
# %admin ALL=(ALL) ALL

# Allow members of group sudo to execute any command
# %sudo ALL=(ALL:ALL) ALL

Save and close the file (:wq!). Finally, limit access to elevated privileges to the sudousers group:

sudo dpkg-statoverride --update --add root sudousers 4750 /bin/su

Check permissions with the following command:

ls -lh /bin/su

The terminal should display something like:

-rwsr-x--- 1 root sudousers 55K Oct 21 2025 /bin/su


What is server hardening

Restricted Data Access

The /proc directory holds process-related data, potentially exposing sensitive information. By default, all users have access. Follow these steps to restrict access and safeguard sensitive data from unauthorized access.

Step-by-step guide

Back up the fstab configuration file. If something goes wrong, you'll be able to recover the initial settings:

sudo cp --preserve /etc/fstab /etc/fstab-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /etc/fstab

Hide process information by adding the following line at the end of the file:

proc    /proc   proc    defaults,hidepid=2  0   0

Save and close the file (:wq!). Finally, reload systemd and remount the /proc directory:

sudo systemctl daemon-reload
sudo mount -o remount,hidepid=2 /proc


Sudo meaning

Secure User Authentication

By default, users are free to choose any password. Impose robust password rules! Set a maximum lifespan and minimum interval before password changes; specify also a minimum length and required number of uppercase, lowercase, and numerical characters.

Step-by-step guide

Configure account parameters

Back up the login.defs configuration file. If something goes wrong, you'll be able to recover the initial settings:

sudo cp --preserve /etc/login.defs /etc/login.defs-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /etc/login.defs

Modify or add the following parameters:

PASS_MAX_DAYS   365
PASS_MIN_DAYS   1
PASS_WARN_AGE   30
SHA_CRYPT_MIN_ROUNDS 1000000
SHA_CRYPT_MAX_ROUNDS 1000000

Save and close the file (:wq!).

Let's apply the same settings to administrator users gofossroot and gofossadmin, which were created before password rules were hardened (adjust usernames according to your own setup):

sudo chage -m 1 -M 365 -W 30 gofossroot
sudo chage -m 1 -M 365 -W 30 gofossadmin

Make sure all changes were correctly applied:

sudo chage -l gofossroot
sudo chage -l gofossadmin

Some additional information on those settings:

Setting Description
PASS_MAX_DAYS Maximum number of days a password may be used.
PASS_MIN_DAYS Minimum number of days allowed between password changes.
PASS_WARN_AGE Number of days a warning is given before a password expires.
SHA_CRYPT_MIN_ROUNDS & SHA_CRYPT_MAX_ROUNDS By default, Linux stores the administrator password using a single, salted SHA-512 hash. To strengthen the password, use multiple rounds of a hash.

Configure PAM

Linux Pluggable Authentication Modules (PAM) is a powerful suite to manage user authentication. Install the following PAM module, which allows to strength-check passwords:

sudo apt install libpam-pwquality

Back up the pam.dconfiguration file. If something goes wrong, you'll be able to recover the initial settings:

sudo cp --archive /etc/pam.d/common-password /etc/pam.d/common-password-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /etc/pam.d/common-password

Modify or add the following parameters:

password requisite pam_pwquality.so retry=3 minlen=12 ucredit=-1 lcredit=-1 dcredit=-1 difok=3 gecoschec

In the same file, add the shadow option as well as an increased number of rounds in the following line:

password        [success=1 default=ignore]      pam_unix.so obscure use_authtok try_first_pass sha512 shadow rounds=1000000

Save and close the file (:wq!).

Some additional information on those settings:

Setting Description
retry = 3 Prompt users 3 times before returning an error.
minlen = 10 Minimum password length.
ucredit = -1 Password must have at least one upper case letter.
lcredit = -1 Password must have at least one lower case letter.
dcredit = -1 Password must have at least one digit.
difok = 3 At least 3 characters from the new password cannot have been used in the old password.
gecoschec Do not allow passwords with the account's name in it.
shadow rounds=1000000 By default, the pam_unix module stores the administrator password using a single, salted SHA-512 hash. To strengthen the password, Linux PAM can use multiple rounds of a hash.


Sudo apt get update

Network Security

Sysctl, a system administration command, empowers users to adjust the kernel and improve network security.

Step-by-step guide

Back up the sysctl configuration file. If something goes wrong, you'll be able to recover the initial settings:

sudo cp --archive /etc/sysctl.conf /etc/sysctl.conf-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /etc/sysctl.conf

Delete the content by typing :%d. Then enter or copy/paste the following content:

# IP Spoofing protection
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Ignore ICMP broadcast requests
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Disable source packet routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

# Block SYN attacks
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5

# Log Martians
net.ipv4.conf.all.log_martians = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1

# Ignore ICMP redirects
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0

# Ignore Directed pings
net.ipv4.icmp_echo_ignore_all = 1

Save and close the file (:wq!), and load the new settings:

sudo sysctl -p

Some additional information on those security settings:

Measure Description
Enable IP spoofing protection Protect against IP spoofing where attackers disguise their IP, typically during Denial of Service (DoS) attacks.
Ignore ICMP broadcast requests Avoid that the server participates in a Smurf attack.
Ignore ICMP redirects Protect against forged ICMP redirect packets used by attackers to cause a Denial of Service (DoS) attack.
Disable source packet routing Protect against source routed packets used by attackers to obscure their identity and location.
Block SYN attacks Protect against SYN attacks, a form of Denial of Service (DoS) attack.
Log martians Protect against martian packets. These are spoofed packets with a source address which is obviously wrong. They can be used during Denial of Service (DoS) attacks.
Ignore directed pings The ping command can be used to check the connection status with your server. But it can also be misused to perform attacks.


Sudo apt update

Antivirus & Malware Scanner

Open source antivirus and malware scanners like Linux Malware Detect (LMD) and ClamAV offer robust protection. To safeguard your server effectively, you need to install and configure these solutions properly.

Step-by-step guide

Malware scanner (LMD)

Install LMD using the following commands:

sudo apt install wget
sudo wget http://www.rfxn.com/downloads/maldetect-current.tar.gz
sudo tar -xvf maldetect-current.tar.gz
cd maldetect-X.X.X
sudo ./install.sh

Back up the maldet configuration file. If something goes wrong, you'll be able to recover the initial settings:

sudo cp --archive /usr/local/maldetect/conf.maldet /usr/local/maldetect/conf.maldet-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /usr/local/maldetect/conf.maldet

Modify or add the following parameters (adjust the administrator user gofossadmin according to your own setup):

# send malware inspection results to local system administrator gofossadmin (adjust accordingly) in /var/mail/gofossadmin

email_alert="1"
email_addr="gofossadmin@localhost"

# move to quarantine & alert if malware is detected
quarantine_hits="1"

# don't automatically delete clean string-based malware injections (in case of false positives, avoid deleting files)
quarantine_clean="0"

# allow suspending users hit by malware
quarantine_suspend_user="1"

#use ClamAVs scanner engine (faster scans)
scan_clamscan="1"

#scan root owned files
scan_ignore_root="0"

Save and close the file (:wq!). Update LMD to the latest version and download the most recent malware definitions:

sudo maldet --update-ver
sudo maldet --update

Antivirus (ClamAV)

Install ClamAV with the following command:

sudo apt install clamav
sudo apt install bsdmainutils

Check if the software was successfully installed:

clamscan --version

Update the virus signature database:

sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam

Enable ClamAV to be automatically launched after each reboot:

sudo systemctl enable clamav-freshclam

Test LMD and ClamAV

We'll use dummy malware provided by the European Expert Group for IT Security (EICAR) to test the malware scanner and antivirus. Download the files as follows:

cd /var/www/html
sudo wget https://secure.eicar.org/eicar.com
sudo wget https://secure.eicar.org/eicar.com.txt
sudo wget https://secure.eicar.org/eicar_com.zip
sudo wget https://secure.eicar.org/eicarcom2.zip

Use ClamAV to recursively scan the directory /var/www/html and all its subdirectories for viruses:

sudo clamscan --recursive --infected /var/www/html

The terminal should prompt something similar to:

/var/www/html/eicar_com.zip: Win.Test.EICAR_HDB-1 FOUND
/var/www/html/eicar.com: Win.Test.EICAR_HDB-1 FOUND
/var/www/html/eicarcom2.zip: Win.Test.EICAR_HDB-1 FOUND
/var/www/html/eicar.com.txt: Win.Test.EICAR_HDB-1 FOUND

----------- SCAN SUMMARY -----------
Known viruses: 6880642
Engine version: 0.102.2
Scanned directories: 1
Scanned files: 5
Infected files: 4
Data scanned: 0.01 MB
Data read: 0.01 MB (ratio 1.00:1)
Time: 54.632 sec (0 m 54 s)

Next, use LMD to scan the same directory for malware:

sudo maldet --scan-all /var/www/html

The output should contain a scan ID, something similar to 240510-1954.2127 (adjust accordingly). Inspect the detailed report with:

sudo maldet --report 240510-1954.2127

A list of all scan reports can be accessed with:

sudo maldet -e list

Finally, remove all quarantined files:

sudo maldet -p
sudo ls /usr/local/maldetect/quarantine/

Schedule LMD scans

The malware scanner LMD is configured to run a daily cron job (/etc/cron.daily/maldet) which updates the malware registry and scans all home directories. That should be sufficient for most use cases. To keep the server load down, disable real time monitoring to avoid scans running every 10 minutes:

sudo rm /etc/cron.d/maldet_pub
sudo maldet -k

Schedule ClamAV scans

The virus signature database is updated by the freshclam service. By default, it fetches updates every hour, you can change the frequency in the /etc/clamav/freshclam.conf file and restart the service with sudo service clamav-freshclam restart.

To schedule antivirus scans, create an empty log file:

sudo touch /var/log/clamav/clamscan.log

Create a cron job to scan for viruses every day:

sudo vi /etc/cron.daily/clamav

Add the following content:

#!/bin/sh

MYLOG=/var/log/clamav/clamscan.log
echo "Scanning for viruses at `date`" >> $MYLOG
clamscan --recursive --infected --max-filesize=100M --max-scansize=100M --exclude-dir=/boot --exclude-dir=/proc --exclude-dir=/sys --exclude-dir=/dev / >> $MYLOG 2>&1

Save and close the file (:wq!). Now, make the script executable:

sudo chmod +x /etc/cron.daily/clamav

Note that we used the following options to run clamscan in the script, which should be adapted to your own needs:

Parameter Description
--recursive Recursively scan directories and sub-directories for viruses.
--infected Only print infected files in the scan report, instead of all scanned files.
--max-filesize=100M, --max-scansize=100M Scan files with a file size of up to 100 MB. By default, ClamAV doesn't scan files larger than 20 MB.
--exclude-dir=/boot,/proc,/sys,/dev In this example, we exclude the directories /boot,/proc,/sys,/dev from the scan. Make sure to adjust this to your own setup.
/ Directory which ClamAV is supposed to scan for viruses. In this example, we want to scan the entire root folder /. Of course, you can adapt the target directory according to your own needs.

Test the cron job. Be patient, depending on the size of the target directories the scan can take a while:

sudo bash /etc/cron.daily/clamav
sudo cat /var/log/clamav/clamscan.log

The terminal output should look something like:

----------- SCAN SUMMARY -----------
Infected files: 0
Time: 54.052 sec (0 m 54 s)
Start Date: 2024:05:22 21:05:29
End Date:   2024:05:22 21:06:23


What is sudo

File Permissions

Learn how to limit unauthorized access to system files effectively.

Step-by-step guide
sudo chmod 600 /etc/crontab
sudo chmod 600 /etc/ssh/sshd_config
sudo chmod 700 /etc/cron.d
sudo chmod 700 /etc/cron.daily
sudo chmod 700 /etc/cron.hourly
sudo chmod 700 /etc/cron.weekly
sudo chmod 700 /etc/cron.monthly
sudo chmod 750 /home/gofossroot
sudo chmod 750 /home/gofossadmin
Tell me more about Linux permissions

umask restricts user access to newly created files or directories. There are three user classes:

User Class Description
User The file's or directory's owner.
Group Users belonging to the file's or directory's group.
Others Users who are neither owner nor member of the file's or directory's group.

And there are three access restrictions:

Access restriction Description Decimal value
Read ( r ) Read or view the file or directory. 4
Write ( w ) Write to, edit or modify the file or directory. 2
Execute ( x ) Execute the file or directory. 1

umask restricts access to newly created files or directories by summing up those three decimal values:

umask Value Restrictions
--- 0 = 0 + 0 + 0 Can read, write & execute.
--x 1 = 0 + 0 + 1 Can read & write, but not execute.
-w- 2 = 0 + 2 + 0 Can read & execute, but not write.
-wx 3 = 0 + 2 + 1 Can read, but not write or execute.
r-- 4 = 4 + 0 + 0 Can write & execute, but not read.
r-x 5 = 4 + 0 + 1 Can write, but not read or execute.
rw- 6 = 4 + 2 + 0 Can execute, but not read or write.
rwx 7 = 4 + 2 + 1 Can't read, write or execute.

umask consists of three values, one for each user class. For example, changing umask from 022 to 027 prevents "others" from reading, writing or executing files and directories:

Umask User restrictions Group restrictions Others restrictions Resulting permissions
022 --- -w- -w- • The file's or directory's owner can read, write & execute.
• Members of the file's or directory's group can read and execute, but not write.
• Users who are neither owner nor member of the file's or directory's group can read and execute, but not write.
• In other words: the file's or directory's owner has full access, the group and others can only read and execute it.
027 --- -w- rwx • The file's or directory's owner can read, write & execute.
• Members of the file's or directory's group can read and execute, but not write.
• Users who are neither owner nor member of the file's or directory's group can't read, write or execute it.
• In other words: the file's or directory's owner has full access, the group can only read and execute it, and others don't have access.

Note that throughout this guide, the chmod command is often used to define permissions for files or directories. Contrary to umask, which sets the default restrictions for newly created files or directories, the chmod command sets permissions for existing files or directories. As such, the values between umask and chmod are somewhat symmetrical.


Core dumps

Core Dump

Core dump – a file capturing program memory upon a crash – helps debugging but risks data exposure. Disabling it enhances security, particularly if troubleshooting isn't required.

Step-by-step guide

Backup the configuration files:

sudo cp --archive /etc/security/limits.conf /etc/security/limits.conf-COPY-$(date +"%Y%m%d%H%M%S")

sudo cp --archive /etc/sysctl.conf /etc/sysctl.conf-COPY-$(date +"%Y%m%d%H%M%S")

Open the first configuration file:

sudo vi /etc/security/limits.conf

Add the following lines at the end:

* soft core 0
* hard core 0

Save and close the file (:wq!).

Open the second configuration file:

sudo vi /etc/sysctl.conf

Add the following lines at the end:

# Disable coredumps
fs.suid_dumpable=0

Save and close the file (:wq!). Finally, apply the changes:

sudo sysctl -p


Kernel modules

Kernel Modules

The Linux kernel serves as the operating system's backbone, managing hardware, memory, and processes. Kernel modules expand its functionality, enabling tasks like accessing new hardware components. However, malicious actors may exploit modules for unauthorised server access or to load harmful software. Prevent potential risks and disallow loading of unnecessary kernel modules.

Step-by-step guide

Backup the configuration file:

sudo cp --archive /etc/modprobe.d/blacklist.conf /etc/modprobe.d/blacklist.conf-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /etc/modprobe.d/blacklist.conf

Add the following lines at the end:

# Instruct modprobe to force inactive modules to always fail loading
install cramfs /bin/false
install freevxfs /bin/false
install hfs /bin/false
install hfsplus /bin/false
install jffs2 /bin/false
install udf /bin/false

Save and close the file (:wq!).


Ubuntu server security