Securing a Linux server is super important if you want to keep your system and data safe from any potential threats. Linux is known for being strong when it comes to security, but it’s still crucial to configure it properly and follow the best practices to create a secure environment.
In this guide, we’ll take you through all the steps you need to secure your Linux server, starting from the initial setup all the way to maintaining that high level of security.
Update and Patch Regularly
It’s crucial to keep your Linux system updated to protect it from security vulnerabilities. One way to do this is by using the package manager offered by your Linux distribution to regularly update all the installed packages.
Run the update command
In Linux, the update
command is a crucial tool for managing software packages and keeping your system up-to-date. Here are the syntaxes for running the update command on the system;
sudo apt update
Alternatively, you can use the following syntax:
sudo apt-get update
Running the update
command synchronizes your system’s local package database with the latest information from the configured software repositories. This database contains a list of available packages, their versions, dependencies, and other relevant details.
Run the upgrade command
Before you can upgrade existing packages or install new ones, you need to run update
. This ensures your system has the most current information about available packages, allowing for accurate and successful operations.
Here is the syntax for using the upgrade command
sudo apt upgrade
It’s important to note that running the update
command refreshes your software information like a library catalog, while the upgrade
command downloads and installs the newest editions, giving you the latest versions of the tools and packages on your Linux system.
More than upgrading using the dist-upgrade command
The dist-upgrade
command is used to perform comprehensive system upgrades. It goes beyond simply updating existing packages as the upgrade
does, and also handles more complex situations involving:
- Installing new dependencies: When updating a package, a new version may require additional packages to function properly.
dist-upgrade
automatically identifies and installs these dependencies.
- Removing conflicting packages: Sometimes, upgrading a package might create conflicts with other installed software.
dist-upgrade
intelligently analyzes these conflicts and, if necessary, removes the conflicting package to ensure a smooth upgrade.
- Upgrading to new distribution releases: In some cases,
dist-upgrade
can even be used to upgrade to a new version of your entire Linux distribution within the same software base (e.g., from Ubuntu 18.04 to 20.04). However, this requires special tools likedo-release-upgrade
and thorough preparation.
Limit the number of Users
Limiting user account access to your Linux system is important. This means that you need to understand the number of users you’ve given access to your system and remove some of them if necessary.
List and view all Users in Linux
Before you delete, you need to understand the type of users accessing registered on your server. This will allow you to understand who to remove. This is necessary especially if you have several users created on the Linux server.
There are several ways to list and display the registered users on Linux, but in this article, we will be using the following command:
cat /etc/passwd
Here’s an example of what the /etc/passwd
file might look like, including entries for example users; root, ugacomp, admin, and support:
root:x:0:0:root:/root:/bin/bash
ugacomp:x:1001:1001:UgaComp User:/home/ugacomp:/bin/bash
admin:x:1002:1002:Administrator:/home/admin:/bin/bash
support:x:1003:1003:Support User:/home/support:/bin/bash
In this example:
root
is the superuser with UID 0.ugacomp
is a regular user with UID 1001.admin
is another user with UID 1002.support
is yet another user with UID 1003.
The fields are separated by colons, and each line represents a user’s information. The fields are, in order: username, password (or ‘x’ if the password is in /etc/shadow
), UID, GID, user information, home directory, and login shell. The actual values may vary based on your system configuration.
Delete or remove unnecessary Users in Linux
After understanding the usernames assigned to users created on your Linux server, you can use the userdel
command to remove who you don’t want to access the system. Here is the syntax to use;
userdel username
Replace username
with the actual username you want to delete.
To also delete the user’s home directory and its contents, add the -r
flag:
userdel -r username
You can again use the cat /etc/passwd
command to check if the user has been removed from the user list.
cat /etc/passwd
Downgrade user permissions
If you don’t want to permanently remove users from your system, you can simply downgrade their permissions.
List the sudo users from the sudoers file
The sudoers
group in Linux isn’t actually a group in the traditional sense. It’s a special designation for users who are allowed to run commands with root privileges using the sudo
command.
Assuming the following Linux users have various permissions:
Username | Permission |
---|---|
root | root |
Mike | regular |
Ugacomp | sudo |
Jane | sudo |
Jessy | sudo |
patrick | regular |
John | Patrick |
If you want to filter out only sudo users in the above table, you can simply run the following command on your terminal;
sudo cat /etc/sudoers | awk '/User_Alias.*ADMINS/{flag=1; next} /[^[:space:]]/{flag=0} flag'
If you use the above command, it will output the lines containing the sudo users within the “ADMINS” alias, belonging to the sudoers group;
ugacomp,jane,Jessy
In this example:
ugacomp
is a sudo user.jane
is also a sudo user.Jessy
is a sudo user as well.
Alternatively, if you can’t use the above command, you can simply use the sudoers files and view who the sudo users are. Run the following command to view the sudoers file in Ubuntu Linux;
sudo visudo
Here is the sample output of the sudoers file containing various users like ugcomp, jane, Jessy, root, john and mary
# Sample sudoers file with dummy users and permissions
# User alias
User_Alias ADMINS = ugacomp, jane, Jessy
# Define sudo privileges
ADMINS ALL=(ALL:ALL) ALL
root ALL=(ALL:ALL) ALL
# Dummy user with limited permissions
john ALL=(root) /bin/ls
# Dummy user with permission to restart Apache
mary ALL=(ALL) /etc/init.d/apache2 restart
In the above file, the sudo users are defined by these lines below;
User_Alias ADMINS = ugacomp, jane, Jessy
# Define sudo privileges
ADMINS ALL=(ALL:ALL) ALL
root ALL=(ALL:ALL) ALL
Removing a single sudo user
Removing a user from the sudoers group, means that they will not have privileged access to the server. Here is the syntax;
sudo gpasswd -d username sudo
You will need to replace username
it with the actual username of the user you want to downgrade their permission.
Removing multiple sudo users
To remove multiple sudo users in Ubuntu using the terminal, you need to edit the sudoers file. You can use the visudo
command, which provides a safe way to edit the sudoers file with syntax checking.
Run the following command on your terminal:
sudo visudo
Navigate to the section where the sudo privileges are defined. This is typically under the User_Alias
or individual user lines. Remove the lines corresponding to the users you want to remove. For example, if you want to remove users “john” and “mary,” you might see lines like:
User_Alias ADMINS = alice, bob, john, mary
# Or individual user lines:
john ALL=(ALL:ALL) ALL
mary ALL=(ALL) /etc/init.d/apache2 restart
Now, you can remove users from the sudo group and assign them as regular users; See the configuration below:
# Comment out or remove the lines related to sudo access for the specified users
# User_Alias ADMINS = alice, bob, john, mary
# john ALL=(ALL:ALL) ALL
# mary ALL=(ALL) /etc/init.d/apache2 restart
# Add new lines to remove sudo privileges for the specified users
alice ALL=(ALL) /usr/sbin/nologin
bob ALL=(ALL) /usr/sbin/nologin
john ALL=(ALL) /usr/sbin/nologin
mary ALL=(ALL) /usr/sbin/nologin
Replace /usr/sbin/nologin
with the path to the shell you want to use for these users. Using /usr/sbin/nologin
ensures that the users cannot log in interactively.
Save the changes and exit the editor. In visudo
, you can usually save by typing :wq
and pressing Enter.
Secure SSH Access
SSH (Secure Shell) is a common method for remote server access. To enhance security, we need to configure some settings associated with SSH access to the server;
Change the default SSH port
Attackers often use automated scripts to scan for open ports, targeting commonly used defaults like port 22 for SSH. Changing the default SSH port makes it less likely for your server to be discovered in these initial scans, reducing the overall number of attacks.
To change the default SSH port on a Linux server, we need to edit the SSH configuration file located in the following path;
sudo nano /etc/ssh/sshd_config
In this article, we’re using the nano editor and the sshd_config file will look as follows:
# $OpenBSD: sshd_config,v 1.101 2017/03/14 07:19:07 djm Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/local/bin:/bin:/usr/bin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
# The default requires explicit activation of protocol 1
#Protocol 2
# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key
# Lifetime and size of ephemeral version 1 server key
#KeyRegenerationInterval 1h
#ServerKeyBits 1024
# Ciphers and keying
#RekeyLimit default none
# Logging
#SyslogFacility AUTH
#LogLevel INFO
# Authentication:
#LoginGraceTime 2m
#PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
#RSAAuthentication yes
#PubkeyAuthentication yes
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
#AuthorizedKeysFile .ssh/authorized_keys
#AuthorizedPrincipalsFile none
#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#RhostsRSAAuthentication no
# similar for protocol version 2
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# RhostsRSAAuthentication and HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
#ChallengeResponseAuthentication no
# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
#UsePAM yes
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none
# no default banner path
#Banner none
# override default of no subsystems
#Subsystem sftp /usr/libexec/sftp-server
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server
From your sshd_config file, locate the line that says Port 2
2 as shown below;
Port 22
Now, you need to change the port number to your desired value, preferably a high port number above 1024 that’s not commonly used by other services. In this article, we’re using port port 2250 as a substitute for the default SSH port 22. See below;
Port 2250
Make sure to choose a unique port that’s not used by any other service. You can learn more about ports in this guide.
RECOMMENDED READING: A Beginner’s guide to understanding Ports in Linux Systems
Make sure to save the changes after you’ve made the appropriate edits to your sshd_config file. Also, you will need to restart SSH server by running the following command;
sudo systemctl restart sshd
When you change the SSH port, you will also need to open it to the firewall. In this example, we’re using ufw firewall to open the example port 2250 as seen below;
sudo ufw allow 2250/tcp
To ensure the changes take effect, you can reload the UFW rules:
sudo ufw reload
Disable root login via SSH
Disabling root login in SSH is a good security practice as it adds an extra layer of protection to your system.
To disable root access to the server, you need to log in as a user with sudo privileges. Then we need to use a text editor to open the sshd_configuration file, which is usually located on this path;
sudo nano /etc/ssh/sshd_config
Please replace nano
with your preferred text editor, such as vim
or gedit
.
Once the sshd_config file is opened, you need to find the following line:
PermitRootLogin no
All you have to do is to change to yes and the root login capability will be disabled. See the command below;
PermitRootLogin yes
After making the necessary edits, save the changes and then restart your SSH server using the following command;
sudo systemctl restart ssh
Limit the number of SSH login attempts
Limiting the number of SSH login attempts helps to prevent brute force attacks, and this can be done by locating the following lines in the SSH configuration file, or adding them if they don’t exist:
MaxAuthTries 3
This line sets the maximum number of authentication attempts before the connection is closed. You can also set the time in seconds during which the user must complete authentication using the following line below. Adjust the value as needed.
LoginGraceTime 30
Use Key-based authentication
Key-based SSH authentication is a more secure and convenient way to log into a remote server than using password authentication.
Here’s a step-by-step guide on how to set up and use key-based SSH authentication:
- Generate SSH Key Pair
Open a terminal on your local machine and run the following command:
ssh-keygen -t rsa -b 2048
You can also specify a different algorithm (e.g., -t ed25519
) and key size if you prefer. Follow the prompts to specify the file location and set a passphrase.
- Copy the Public Key to the Remote Server
On the local machine, use the following command to copy the public key to the remote server. Replace username
and remote-server
with your actual username and server address:
ssh-copy-id username@remote-server
If ssh-copy-id
is not available on your system, you can manually copy the contents of the local ~/.ssh/id_rsa.pub
(or the specified file) and append it to the ~/.ssh/authorized_keys
file on the remote server:
cat ~/.ssh/id_rsa.pub | ssh username@remote-server 'cat >> ~/.ssh/authorized_keys'
- Turn off password authentication
If you’ve successfully set up the key-based authentication, you can turn off password authentication to further strengthen the security of your server.
This can be done by editing the sshd_config file and locating the following line;
PasswordAuthentication no
You need to change the value of the directive to yes to turn off password authentication as seen below;
PasswordAuthentication yes
Save the changes and restart the SSH server always
Close unnecessary Firewall Ports
It’s recommended not to unnecessarily have various ports open on the server. So, you can check the status of your firewall ports by running the following command;
sudo ufw status
This command will display the current status of the UFW, including information about which rules are active, whether the firewall is enabled, and the default policies for incoming and outgoing traffic.
Remove unnecessary port rules
If there is a port number that is open through the firewall, and you don’t want it to run, delete it using the following syntax;
sudo ufw delete allow <port_number>
For example, if you want to remove the RTMP port 1935, you can use the following command;
sudo ufw delete allow 1935
Block Port scanning in Ubuntu
Port knocking is a security technique used to protect a system from port scanning attacks by requiring a series of connection attempts to specific ports in a particular order before allowing access to a service.
Here’s how you can implement port knocking on Ubuntu using the knockd
daemon:
Install Knockd
First, you need to install the knockd
package. Open a terminal and run:
sudo apt-get update
sudo apt-get install knockd
Configure Knockd
Open the knockd configuration file in a text editor. You can use any text editor of your choice, such as nano
or vim
. For example:
sudo nano /etc/knockd.conf
Add the following configuration to the file:
[options]
logfile = /var/log/knockd.log
[openSSH]
sequence = 7000,8000,9000
seq_timeout = 15
tcpflags = syn
start_command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
cmd_timeout = 10
stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
This example assumes that you want to open SSH access on port 22. Adjust the sequence
and start_command
accordingly, if you want to open different ports or services.
After saving the configuration, restart the knockd
service:
sudo service knockd restart
Implement File System Security
Defining the file permissions and ownerships on your Linux system is very important in strengthing security. This can be achieved by using the following methods;
Using the chmod utility
In Ubuntu and other Linux-based systems, file permissions are managed using the chmod
command. You can use chmod
to change the permissions of a file or directory. The basic syntax is as follows:
chmod options permissions file
Let’s say you want to give read, write, and execute permissions to the owner of a file called example.txt
, read and execute permissions to the group, and read-only permissions to others. The permission settings for this would be rwxr-xr--
. You can achieve this with the following command:
chmod 754 example.txt
7
corresponds torwx
(read, write, and execute) for the owner.5
corresponds tor-x
(read and execute) for the group.4
corresponds tor--
(read only) for others.
You can also use symbolic notation to modify permissions. Here’s an example:
chmod u=rwx,g=rx,o=r example.txt
u=rwx
sets read, write, and execute for the owner.g=rx
sets read and execute for the group.o=r
sets read-only for others.
Here’s a table that represents various permissions using the numeric notation and symbolic notation in the chmod
command:
Here’s a table that represents various permissions using the numeric notation and symbolic notation in the chmod
command:
Numeric Notation | Symbolic Notation | Permission |
---|---|---|
0 | — | No permission |
1 | –x | Execute |
2 | -w- | Write |
3 | -wx | Write, execute |
4 | r– | Read |
5 | r-x | Read, execute |
6 | rw- | Read, write |
7 | rwx | Read, write, execute |
In the numeric notation, each digit represents a different user category:
- First digit: Owner
- Second digit: Group
- Third digit: Others
Using the chown utility
In Linux, ownership of files and directories is managed using the chown
command. The chown
command allows you to change the owner and/or group of a file or directory. Here’s the basic syntax:
sudo chown [options] owner:group file_or_directory
The above command is broken down as below;
- owner: The user to whom you want to assign ownership.
- group: The group to which you want to assign ownership. This is optional. If you don’t specify a group, the file or directory will be assigned to the user’s default group.
- file_or_directory: The file or directory for which you want to change ownership.
For example, you can change the owner of a file as seen below;
sudo chown username:groupname filename
If you want to change the owner of a directory, here is the command you can use;
sudo chown -R username:groupname directoryname
The -R
option is used for recursive ownership changes, applying changes to all files and subdirectories within the specified directory.
Remember to replace username
, groupname
, filename
, and directoryname
with the actual user, group, file, and directory names.
Regular Backups
Implement a robust backup strategy to protect your data in case of a security breach or hardware failure. Use tools like rsync
or tar
to create backups and store them in a secure, remote location.
# Example: Backup using rsync
rsync -avz /path/to/source/ user@remote:/path/to/backup/
Monitoring and Logging
Fail2Ban is a security tool that helps protect Linux servers from malicious activities by monitoring log files for suspicious behavior and blocking IP addresses that exhibit such behavior. Here’s a step-by-step guide on how to set up Fail2Ban on Ubuntu:
Update Package List
First, update the package list before installing FailzBan
sudo apt update
Install Fail2Ban
After running an update, you can now install Fail2Ban
sudo apt install fail2ban
Configure Fail2Ban
The main configuration file for Fail2Ban is located at /etc/fail2ban/jail.conf
. It’s recommended to create a local configuration file to avoid modifying the default one directly:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Now, edit the local configuration file:
sudo nano /etc/fail2ban/jail.local
Adjust the settings as needed. Here are some common configurations:
- Find the
[DEFAULT]
section and setignoreip
to specify trusted IP addresses.
ignoreip = 127.0.0.1/8 your_trusted_ip
- Adjust the bantime, findtime, and maxretry parameters to define how long an IP will be banned, the time window for counting retries, and the maximum number of retries allowed.
- Customize the
[sshd]
section to secure the SSH daemon.
[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
After making the necessary edits, you can restart fail2ban using this command;
sudo service fail2ban restart
Check if fail2ban is running using this command;
sudo fail2ban-client status
This should display information about the jails and their status.
To test if Fail2Ban is working, try to log in multiple times with incorrect credentials or perform other actions that might trigger the configured rules. After reaching the maximum allowed retries, the offending IP should be banned.
Monitor Fail2Ban Logs
You can monitor Fail2Ban logs to see its activity:
sudo tail -f /var/log/fail2ban.log
Adjust paths and settings according to your specific use case and services.
Keep Services to a Minimum
Disable unnecessary services to minimize the attack surface. Identify and stop services that are not essential for your server’s functionality.
List all running Services
You can start by listing all running services using this command.
sudo service --status-all
The sample output after running the above command would be as follows;
$ sudo service --status-all
[ + ] apache2
[ + ] vsftpd
[ + ] ssh
[ ? ] rdp
In this example:
- “[ + ]” indicates that the service is running.
- “[ ? ]” indicates that the service status is unknown.
Stop a Service
If you want to stop unwanted service, you can run the following command
sudo service servicename stop
For example, if you want to stop the apache service, here is the command you can use
sudo service apache2 stop
Conclusion
Securing a Linux server is an ongoing process that requires vigilance and regular updates. By following these steps and staying informed about the latest security practices, you can significantly reduce the risk of security breaches and ensure the integrity of your Linux server.
It’s important to note that the key to a secure server is a combination of strong configuration, regular maintenance, and a proactive approach to security.