Ubuntu Logo - Secure a Ubuntu Server
Ubuntu Logo

Secure a Ubuntu Server details the basic first steps necessary to secure a new Ubuntu server against the most common attacks. It is absolutely not a comprehensive list of steps, instead consider it a minimum requirement for a new server. This article is written as part of a larger guide in setting up an Opensimulator on a Ubuntu server. However, it is also a stand-alone article.

Anyone who prefers watching a video to reading should scroll straight to the bottom of the page.

Covered in Secure a Ubuntu Server

  • Making a new user
  • Giving the user sudo rights
  • Changing the SSH port
  • Creating and using SSH key pairs
  • Turning off passworth authentication and disabling root login
  • Installing and setting up fail2ban
  • UFW (uncomplicated firewall)

The Tools To Use – Secure a Ubuntu Server

Ubuntu users need to find Terminal inside the main menu, alternatively, Windows Users need to find Power Shell on the Start menu.

After loading they both look at act in very similar ways with just one minor difference in the process.

Connecting To the server – Secure a Ubuntu Server

Typically with a new server from a cloud host, they will supply an IPv4 address and a root password. If the server is a local machine connection via ssh may not be necessary. If it is still necessary use the local network address of the server.

In the command below, replace the double asterisks and everything between them with the IP address of the server.

ssh root@**IpAddress**

Assuming this is the first time the user’s computer is accessing the remote server there is a check to confirm the action. Below is an example with a local IP address.

ssh root@192.168.1.232
The authenticity of host '192.168.1.232 (192.168.1.232)' can't be established.
ECDSA key fingerprint is SHA256:7NjZjgdwbMd7XbVrXolnCALKhn4dTihSzdgNifatBKg.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

Type in “yes” then hit the enter key. Immediately after this, it will ask for the password. Type it in and hit Enter again.

Sorting out the user accounts.

One of the differences between setting up an Ubuntu server directly and the images provided by most hosting providers is the user accounts. During the install, Ubuntu Server creates a user account that account automatically has sudo privileges. Additionally, the root account has the same password. Differently, most hosting companies deliver a server with a root account and no other. Both cases need a little work to improve the situation.

Updating the Root Account Password

sudo passwd root

Create an new user and add it to the sudoers group.

In the example below the user name is “opensim”, this is only because this article is part of a larger whole. The user name can be changed to suit the user’s needs. Make sure to adjust the second line to match in this case.

sudo adduser opensim
sudo usermod -aG sudo opensim

Changing the SSH port – Secure a Ubuntu Server

By default SSH uses port 22, many attacks run scans for machines with port 22 open. Changing the port will not stop a determined attack. However, it will help to reduce the number of attacks on a server. Before changing the port it is necessary to find one which is not in use.

Find a free port

Enter the next line into the terminal and hit enter. It will output a list of ports that are currently listened to.

sudo lsof -i -P -n | grep LISTEN

It will produce output similar to the sample below.

sudo lsof -i -P -n | grep LISTEN
[sudo] password for opensim: 
systemd-r  605 systemd-resolve   13u  IPv4  20606      0t0  TCP 127.0.0.53:53 (LISTEN)
sshd       680            root    3u  IPv4  22438      0t0  TCP *:22 (LISTEN)
sshd       680            root    4u  IPv6  22449      0t0  TCP *:22 (LISTEN)

The example above it is showing SSH listening on port 22. There are some well-known ports that should be avoided. However, most port numbers from 1000 to 99999 are ok. An example of a well-known port is 3306 which MySql uses by default. Additionally, since this guide is part of a bigger one for setting up Opensimulator it’s worth noting some of them. Robust services frequently use ports 8002 to 8010 and Simulator services 9000 to 9500. These are not fixed and vary in individual configurations.

For the purpose of this guide, 2789 is randomly selected from the free ports for SSH.

Add the selected port to UFW (Uncomplicated Fire Wall)

sudo ufw allow 2789/tcp

This will give output like the example below.

opensim@robust-login:~$ sudo ufw allow 2789/tcp
Rules updated
Rules updated (v6)

Edit the SSH configuration file

sudo nano /etc/ssh/sshd_config

This will open the Nano text editor displaying the following file. In the example below the line that needs changing is lighted in yellow.

#       $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/bin:/bin:/usr/sbin:/sbin

# 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 ::

#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
PermitRootLogin yes
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#PubkeyAuthentication yes

# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile     .ssh/authorized_keys .ssh/authorized_keys2

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# 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

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no

# 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 yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#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

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

# override default of no subsystems
Subsystem       sftp    /usr/lib/openssh/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
#       X11Forwarding no
#       AllowTcpForwarding no
#       PermitTTY no
#       ForceCommand cvs server

Near the top of the file change “Port 22” to to the port number added to the firewall above. Save and exit with

CTRL+0 ENTER
CTRL+X

Restart the ssh server

Type in the following command and hit enter to restart the ssh server. IMPORTANT do not close the terminal window at this stage.

sudo systemctl restart ssh

Check the new port is working

Before exiting the SSH terminal, open a new terminal and try connecting to it. In our example the user name is “opensim”, the IP address is “192.168.1.232 and the new SSH port is 2789. Consequently, put all that together into a command in the new terminal window.

ssh -p 2789 opensim@192.168.1.232

Assuming it works this will connect to the server using the new SSH port with output that looks similar to the example below.

sara@sara-Ubuntu-Desktop:~$ ssh -p 6230 opensim@192.168.1.232
opensim@192.168.1.232's password: 
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-88-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Fri Oct 15 17:18:53 UTC 2021

  System load:  0.0                Processes:               129
  Usage of /:   3.3% of 195.86GB   Users logged in:         1
  Memory usage: 1%                 IPv4 address for enp0s3: 192.168.1.232
  Swap usage:   0%


150 updates can be installed immediately.
1 of these updates is a security update.
To see these additional updates run: apt list --upgradable


Last login: Fri Oct 15 15:28:37 2021 from 192.168.1.93

Enable UFW and remove rule for the original SSH port.

To enable the firewall use the following. IMPORTANTLY keep this terminal window open and test in a new window afterwards.

sudo ufw enable

This will return output like the example below

opensim@robust-login:~$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

Open a new terminal window and check the connection still works before closing the original.

Block Port 22 with UFW

sudo ufw delete allow 22/tcp

This will give output like the example below

opensim@robust-login:~$ sudo ufw delete allow 22/tcp
Rule deleted
Rule deleted (v6)

Use SSH Key Pairs Instead of Password Authentication – Secure a Ubuntu Server

This stage is done on the local machine rather than the server. If the connection to the remote server is still active type

exit

giving output like

opensim@robust-login:~$ exit
logout
Connection to 192.168.1.232 closed.
sara@sara-Ubuntu-Desktop:~$

Generate the key pair

Type the following into the terminal and hit enter.

ssh-keygen -b 4096

Unless there is an existing key pair just click enter to accept the default location for the key pair. When prompted hit enter without adding a passphrase. .

The key fingerprint is:
SHA256:eZH85b/egcqTP7Cpy6hbH02+HnDCmoXStLprRlXSZ7M sara@ns524967
The key's randomart image is:
+---[RSA 4096]----+
| . |
| . + = |
| .o * o . |
| o.+. E o |
| ..+S=.o. . |
| .o +.B. .. |
| .. + . +=. ..|
| oo + o=+. +|
| o=+. =+=o.oo.|
+----[SHA256]-----+

Windows output is slightly different showing the location the file is saved to. However, it is still essentially the same.

Copy the key pair to the server

Ubuntu desktop users and Windows users deviate slightly for this little bit. However, a Ubuntu user can use the same command as the Windows users but not vice versa. Before exiting the SSH terminal, open a new terminal and try connecting to it. In our example the user name is “opensim”, the IP address is “192.168.1.232 and the new SSH port is 2789. Consequently, put all that together into a command in the new terminal window. IMPORTANTLY keep the terminal window open after this.

Linux users

ssh-copy-id -p 2789 opensim@192.168.1.232

This will give an output similar to the following after entring the password.

sara@sara-Ubuntu-Desktop:~$ ssh-copy-id -p 2789 opensim@192.168.1.232
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
opensim@192.168.1.232's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh -p '2789' 'opensim@192.168.1.232'"
and check to make sure that only the key(s) you wanted were added.

Windows Users

cat ~/.ssh/id_rsa.pub | ssh -p port userName@remoteHose "cat >> ~/.ssh/authorized_keys"

This will give output similar to the example below.

PS C:\Users\sarap> cat ~/.ssh/id_rsa.pub | ssh -p 2789 opensim@192.168.1.232 "cat >>~/.ssh/authorized_keys"
The authenticity of host '[192.168.1.232]:2789 ([192.168.1.232]:6230)' can't be established.
ECDSA key fingerprint is SHA256:7NjZjgdwbMd7XbVrXolnCALKhn4dTihSzdgNifatBKg.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[192.168.1.232]:2789' (ECDSA) to the list of known hosts.
PS C:\Users\sarap>

Test the new authentication

Open a new terminal window and use the ssh command again. This time it should connect without asking for a password.

ssh -p 2789 opensim@192.168.1.232

Sample output below

sara@sara-Ubuntu-Desktop:~$ ssh -p 2789 opensim@192.168.1.232                                           Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-88-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Fri Oct 15 18:04:33 UTC 2021

  System load:  0.0                Processes:               128
  Usage of /:   3.3% of 195.86GB   Users logged in:         1
  Memory usage: 1%                 IPv4 address for enp0s3: 192.168.1.232
  Swap usage:   0%

 * Super-optimized for small spaces - read how we shrank the memory
   footprint of MicroK8s to make it the smallest full K8s around.

   https://ubuntu.com/blog/microk8s-memory-optimisation

150 updates can be installed immediately.
1 of these updates is a security update.
To see these additional updates run: apt list --upgradable


Last login: Fri Oct 15 17:40:04 2021 from 192.168.1.93

Assuming everything is working, its time to turn off password authentication and disable root logins.

Turn off password authentication

Edit the SSH config file again

sudo nano /etc/ssh/sshd_config
#       $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/bin:/bin:/usr/sbin:/sbin

# 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 2789
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
PermitRootLogin yes
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#PubkeyAuthentication yes

# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile     .ssh/authorized_keys .ssh/authorized_keys2

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# 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

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no

# 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 yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#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

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

# override default of no subsystems
Subsystem       sftp    /usr/lib/openssh/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
#       X11Forwarding no
#       AllowTcpForwarding no
#       PermitTTY no
#       ForceCommand cvs server

Scroll down until PermitRootLogin yes” and change it to “no”.

Continue scrolling down until “PasswordAuthentication yes” and change it to “yes” then save, exit and restart SSH.

Save, exit and then restart ssh with the following commands.

CTRL+O ENTER
CTRL+X
sudo systemctl restart ssh

Add a second layer of security with Fail2Ban

Fail to ban monitors login attempts and updates firewall rules to block addresses which repeatedly fail authentication. Install fail2ban with:

sudo apt-get install fail2ban
sudo systemctl start fail2ban
sudo systemctl enable fail2ban

This will generate lots of output while fails to ban is installed and end with

opensim@robust-login:~$ sudo systemctl start fail2ban
opensim@robust-login:~$ sudo systemctl enable fail2ban
Synchronizing state of fail2ban.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable fail2ban
opensim@robust-login:~$

Next set up a new local jail configuration file by creating it with a text editor such as nano.

sudo nano /etc/fail2ban/jail.local

Add the content listed below changing the port number to match the port number used for SSH.

[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
maxretry = 3

Now save, close and restart fail2ban

CTRL+O
CTRL+X
sudo systemctl restart fail2ban

Secure a Ubuntu Server is now complete, however, remember this is a realistic minim standard, there is more that could be done.

Video Version