Enabling a firewall and securing SSH are two essential first steps when setting up a new server. In this tutorial I'll take you through the process I go through for every server I spin-up regardless of its use. I'll be using Ubuntu 18.04LTS on Linode, but this should apply to almost any recent Debian based distribution. If you're using a different VPS host or are on your own hardware there may be differences regarding root access and packages installed by default, I'll try to make note of this when needed. So, let's get to it.
On your local machine, move into the
~/.ssh directory and generate an SSH key
pair for the new server. If you haven't used SSH on this machine, it may be
necessary to create the directory.
mkdir ~/.ssh # if directory not present cd ~/.ssh ssh-keygen -t ed2559
Having filled in the form you should see something like below. You can name
your key anything you like but I've found the format of
id_ed25519_example.com to work best for me as it makes keeping track of
multiple keys very easy. A password is not required but I highly recommend
creating a strong, unique password for each key pair you generate.
Generating public/private ed25519 key pair. Enter file in which to save the key (/home/user/.ssh/id_ed25519): id_ed25519_<domain-name-or-ip> Enter passphrase (empty for no passphrase): <highly recommended> Enter same passphrase again: <highly recommended> Your identification has been saved in id_ed25519_<domain-name-or-ip>. Your public key has been saved in id_ed25519_<domain-name-or-ip>.pub. The key fingerprint is: SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx user@hostname The key's randomart image is: +--[ED25519 256]--+ | | | | | | | | | | | | | | | | | | +----[SHA256]-----+
Now you can add the newly created key to
ssh-agent, this should work on most
popular distributions as the agent should already be running. If you created a
password in the previous step you will be prompted for it now.
You should get confirmation that the key was added, if not try the below and then re-run the command above.
Now from your local machine, SSH into your server using either the IP address assigned to you by your host or domain name if you've already set one up. Depending on your host you should have had to provide a root password or been asked to create a non-root user during the VPS setup. If the latter, substitute root with that user and use sudo as necessary from here on out.
Now that we're on the server let's go through the initial firewall configuration and enable it. We're going to be using Uncomplicated Firewall or UFW as it's easy to use and installed by default on Ubuntu.
First, lets make sure UFW has the default application profile for OpenSSH available.
ufw app list
You should at least see OpenSSH listed under available applications.
Available applications: OpenSSH
Now, add OpenSSH to the allowed applications with the below command.
ufw allow OpenSSH
This will, once UFW is enabled, allow traffic on the default port of 22 for SSH, but we don't want to stop here because later we will be changing the default port used for SSH for more security. Now is the time to choose which port you want to use, anything between say 5000 and 65535 is typical but it's a good idea to check here and pick a port not used by other services. So, let's create a new rule and add it to the allowed applications list. We'll also limit the attempted connections allowed to this port with the default limit of 6 tries in 30 seconds, again for a bit more security.
ufw allow <chosen-port>/tcp ufw limit <chosen-port>/tcp ufw reload
The only thing left to do now is enable the firewall.
Let's check our work now and make sure all is as it should be.
You should get output similar to this:
Status: active To Action From -- ------ ---- OpenSSH ALLOW IN Anywhere <chosen-port>/tcp LIMIT IN Anywhere OpenSSH (v6) ALLOW IN Anywhere (v6) <chosen-port>/tcp (v6) LIMIT IN Anywhere (v6)
That's it for the firewall for now, later we'll come back and remove the default OpenSSH rule once we've changed the port in the SSH configuration file.
Add a New User
If you've been required to create a regular user by your host already then you can skip this step. If your only access right now is via root, you'll want to create a regular user for yourself now.
Run the following command with a user name of your choosing. A good password is strongly recommended but the default/blank options for all other questions are fine, it's up to you.
Now we need to make sure this new user has the
sudo command available to
them. We can do this by adding them to the sudo group.
usermod -aG sudo <new-user-name>
You can confirm that this worked using the
id command. You should see ‘sudo’
listed in the groups section.
Next, in a separate terminal without logging out of the first terminal, SSH into your server using the new user to make sure all is well. We'll be removing root access through SSH next so it is very important to make sure you have full access with sudo working for the new account before moving forward. We're keeping the first terminal with root login open for safety so we can correct any problems if they arise.
# On your local machine, in a second terminal ssh <new-user-name>@<domain-name-or-ip>
You should now have two terminals open, one logged in with root and another
with your new user account. Check that you can successfully run sudo commands
with your new user account. A simple
sudo ls -al should be all you need to
confirm. If you get an error, check back through the sections above and make
sure nothing was skipped. If all is good, it's time to move on to editing the
Disable Root Access & Change SSH Port
Now we need to edit a few options in the SSH configuration. Remember, keep that original terminal open with root access as a backup if something goes wonky but do all of this as the new user in the second terminal.
sudo nano /etc/ssh/sshd_config
We need to edit two lines and add a new one. Near the top of the file you should see the port entry, it should be commented out and set to the default 22. Uncomment this line and change 22 to your choice of port from earlier. Create a new line just below it and add the ‘AllowUsers’ entry. Set this to your new user. Last, move down in the file and look for the ‘PermitRootLogin’ entry. Uncomment it if necessary and make sure it is set to ‘no’. The three entries should look like below.
Port <chosen-port> AllowUsers <new-user-name> PermitRootLogin no
To activate the new configuration we need to restart the SSH service. A nice feature of SSH is that even though we are restarting the service with new configuration, it won't close our open connections.
sudo systemctl restart ssh
Now, in the second terminal using the new user, exit out of the SSH session
and try out the new settings. Note the
-p <chosen-port> being added to the
ssh command, you will need to use this from here on and keep this in mind for
other commands you might need in the future such as
exit ssh -p <chosen-port> <new-user-name>@<domain-name-or-ip>
If all went well you should be back on the server using your new user. You will no longer be able to SSH into the server using the root account and only be able to connect through the new port you chose. The last thing we need to do is remove the old UFW rules for the default port 22.
First, get the status of UFW again but this time add
numbered to the end of
the command to make things easier.
sudo ufw status numbered
Should get output similar to this:
Status: active To Action From -- ------ ---- [ 1] OpenSSH ALLOW IN Anywhere [ 2] <chosen-port>/tcp LIMIT IN Anywhere [ 3] OpenSSH (v6) ALLOW IN Anywhere (v6) [ 4] <chosen-port>/tcp (v6) LIMIT IN Anywhere (v6)
You need to delete both entries for OpenSSH, just issue the ‘delete’ command with the corresponding number for each entry.
sudo ufw delete 1 sudo ufw delete 3
Now, reload UFW and check its status one more time.
sudo ufw reload sudo ufw status
Should get output similar to this:
Status: active To Action From -- ------ ---- <chosen-port>/tcp LIMIT IN Anywhere <chosen-port>/tcp (v6) LIMIT IN Anywhere (v6)
Disable Password Authentication
Our last step is to copy the public key we generated earlier on our local machine over to the server, check that it works, then disable password authentication for SSH.
On your local machine, terminate the SSH session of your new user in the second terminal and issue the command to copy over your public key. You will be asked for the password of your new user once more and should get confirmation that the key was successfully copied over.
exit cd ~/.ssh ssh-copy-id -i id_ed25519_<domain-name-or-ip>.pub -p <chosen-port> <new-user-name>@<domain-name-or-ip>
Now, start a new SSH session. You should be able to log in now without needing a password.
ssh -p <newport> <newuser>@<server>
Once back on the server we need to edit the SSH configuration file one more time. This time to disable password authentication.
sudo nano /etc/ssh/sshd_config
Find the following line, uncomment it if necessary, and make sure it's set to ‘no’.
Finally, restart the SSH service and check that you can still connect one final
time. If everything works you can now update the server and close the original
root terminal. I generally like to reboot the system and run a quick
apt autoremove and
apt autoclean after it's initial update.
sudo systemctl restart ssh sudo apt update && sudo apt dist-upgrade sudo reboot # SSH back into the server once it's up and running again then: sudo apt autoremove && sudo apt autoclean
Hopefully I haven't missed anything and this was helpful.