Important Information
If you have little or no experience on how to run a server / virtual private server (VPS) which has a global external IPv4 and/or IPv6 address with several open ports it is advised by the Safing team to not run a SPN node.
This tutorial is meant to be supplemental to server administrators who are aware of the dangers of running software exposed to the global internet. This guide does however consider the fact that some individuals might wish to run a node without linux server management experience. It is highly advised that you at least get comfortable with the bash scripting language and how to navigate the linux file system through a terminal before you try to follow this tutorial.
This tutorial will use Debian 12. If you have experience with another distribution you would like to use, do so at your own risk. This guide will use UFW as the firewall to harden the security of the system.
This guide also assumes that you are using a terminal with OpenSSH installed. If you're on Linux you most likely already have OpenSSH installed, but for MacOS you might have to enable or download it. On Windows you can install the Windows Subsystem for Linux (WSL) and install OpenSSH.
MAKE SURE YOU READ THE ENTIRETY OF THIS PAGE, DO NOT THINK YOU CAN SKIP ANY PART OF THE PROCESS IF YOU'RE NOT EXPERIENCED OR HAVE SUFFICIENT KNOWLEDGE WITH LINUX
Location: Use a well connected datacenter to host your node with good speeds (~ 300Mbit/s).
Hardware: 4GB of RAM and 2 cores should be enough, but this is subject to change.
Bandwidth: A month of uptime of your node can easily result in over 1TB of bandwidth, choose a provider that provides unthrottled bandwidth which can cover at least 3TB. (Read through the terms of service for the provider, they usually list their terms for bandwidth there.)
Remember that the node installer wants to automatically configure itself to use your global externally accessed IP addresses. Not all providers will provide a IPv6 address, but you need at least 1 globally accessable IPv4.
This section of the tutorial is mainly server side. Pay attention to the warning and info labels throughout the tutorial and make sure you are doing client processes when asked, and server process on the server.
Any system that is exposed to the global internet needs to be hardened to prevent bad actors from gaining root access to your server. Your VPS / server provider will usually issue the root password to your root user on their web interface or send you an e-mail with the password.
Any system that's globally accessible through the internet will get hacked if given enough time. The only unhackable server is one that's turned off and not connected to anything. Keep in mind that patching and making sure you are aware of the commands and tools you are using will be your greatest defense against bad actors.
To access your server, edit the command below and input the correct IPv4 address into your terminal. If the connection is successful you'll be prompted to input the password which should have been given to you through your providers web interface, or through e-mail. When you type your password nothing will show up visually for you, but it's registering your keystrokes.
ssh root@your-ipv4-address
replace your-ipv4-address with your assigned ip-address for the server
If you're greeted to a welcome or message of the day you have successfully logged into the root account on your server.
Now we're going to update all the packages that are currently installed on the system. For Debian run:
apt update && apt upgrade -y
The -y after upgrade commands the program to respond yes to the: are you sure you want to upgrade prompt. At this stage you might be asked if you want to change or edit a file that your VPS provider has already edited or changed to work with their systems. Just leave them unchanged for now.
At this point you should already be logged into your server as root.
We'll use the adduser command to create a new user on your system.
adduser your_username
your_username should be a username you remember
Now you'll be prompted to enter a new UNIX password. Again you can't see what you type with asterisks. Make sure to use a password you'll remember.
Afterwards you'll be prompted to enter some user information, you can skip this by just hitting enter, or you can fill out the details if you want.
Now we're going to add your new user to the sudo group which will give the user administrator privileges, or sudo access.
usermod -aG sudo your_username
To verify that you added your user to the sudo group run:
getent group sudo
This should output the username you've chosen.
Eg.
sudo:x:27:your_username
You also need to run:
su - your_username
this will change the current user (which is root) to your new sudo user. Run any command to make sure you have sudo access:sudo apt update -y
. The sudo password is the password you chose for your sudo user.
While you are logged in as your sudo user you can can check if your system has the required .ssh folders
This assumes that you are in the home directory of your system. If you are unsure you can type
cd ~
and hit enter. You can also use thels -a
command to see hidden directories. A directory with a period in front of it, is considered hidden. {.is-info}
ls .ssh
If the output states that this directory does not exist you can not move anything into it. So you should create it:
mkdir .ssh
This section is for the client, so if you're connected to your server and you don't have another tab or window on your client. Type
exit
, until you're at localhost, or the hostname of your client.
If you're tired of typing out IPv4 addresses you can easily create a config file which will make connecting to your VPS easier. I only know how to do this on Linux and MacOS, so if you're using WSL it should be similar, or exactly the same.
touch ~/.ssh/config
vim ~/.ssh/config
or nano ~/.ssh/config
.Host *spn-node
User *your_username
Port 22
IdentityFile ~/.ssh/id_rsa
HostName *your_ipv4_address
ssh spn-node
and it will automatically use the config file to establish the connection.This section is client side. If you are still connected to your VPS you can create a new tab with CTRL + SHIFT + T to create a new tab. Read the entire section and the information and warning labels.
This section will deal with generating the SSH key-pair, uploading the public key to your server, disabling password authentication and the ability to log in as root. You can still swap your sudo user into the root user if you know what you are doing. Only connecting through SSH as root is disabled.
If you already have a SSH key-pair on you client, you can skip to: Upload the public key to your server
Firstly you need to generate a key-pair in your clients' .ssh folder, this is where OpenSSH will pull the key which authenticates your user. Below are the different paths for most operating systems.
Keypair location on Linux: ~/.ssh/
Keypair location on Windows: C:\Users\your_username.ssh
Keypair location on MacOS: ~/.ssh/
We'll use the ssh-keygen program to create a public and a private key on our client.
ssh-keygen -t rsa
You'll be prompted with: Enter file in which to save the key. ~/.ssh/id_rsa
You can just hit enter if you're going to use this as your primary or only key. You can also change the name to whatever you want. After this you'll be prompted to enter a passphrase.
It's important to use a passphrase as this will make your key more secure. Ideally choose a password that you haven't used online yet, and something that you can remember with symbols, numbers and letters. The complexity of the passphrase is up to you, but be smart when choosing your passphrase.
After this you'll be met with some randomart, and your .ssh folder will now contain.
You'll have to enter your key's passphrase every time you connect to your server.
This is easy on MacOS and Linux clients. We'll use the ssh-copy-id command to upload the public key to the server.
ssh-copy-id your_username@your_ipv4_address
your_username must be the sudo user you created earlier in this tutorial.
If you're on Windows you'll need to exit out of WSL and use the normal Windows command prompt. When you're in the normal Windows command prompt copy and paste this the code below.
If you changed the name of the id_rsa.pub file you should use the name you chose for it instead
scp .ssh/id_rsa.pub your_username@your_ipv4_address:~/.ssh/authorized_keys
Now test the connection with your server by typing in:
ssh your_username@your_ipv4_address
If everything worked you should be prompted to enter your passphrase and then you'll connect to the server without using the password of your user.
Be certain that you have a surefire way to access your server. After this point you'll not be able to SSH to the server as root, or use a password to authenticate your sudo user. Successful key authentication will be the only way to access your server.
This subsection is server-side. You need to use Vim or nano to edit the file. We're looking at the sshd_config file. On Debian 12 it's located in the /etc/ssh/
directory. This directory has some sshd_config files which have a .d filetype after it's name. We are ONLY looking for the sshd_config file.
To view the contents of the file:
cat /etc/ssh/sshd_config
This should output the contents of the file to your terminal. We are specifically looking for:
Change all of these entries to the following using either Vim (only use Vim if you know the differences between the different modes) or Nano. If there are hashtags in front of these entries remove them:
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
PermitRootLogin no
Write and quit your editor.
If you can't find ChallengeResponseAuthentication, you can simply add it to the line below PasswordAuthentication.
When you are done, you have to restart the SSH daemon.
sudo systemctl restart sshd
Now you should try exiting your connection with exit
, and try to connect as the root user. ssh root@your_ipv4_address
. You should see that you are automatically denied access. Also try reconnecting to your server with your sudo user, you should now only have to enter the passphrase to connect.
Uncomplicated Firewall is a firewall config tool that runs on top of the iptables program. To make sure our SPN node runs correctly we'll have to open some ports to make sure packets are transported. Some of these ports will be configured slightly to enable a bit more of a secure environment.
This section assumes you are connected to your server. Make sure you are connected to your server before executing these commands. If you open these ports on your client device you might expose yourself to attacks from bad actors. (If you have UFW installed and are using Linux)
Firstly make sure you have UFW installed:
sudo apt install ufw
If you get prompted to install it, type y and hit enter. After it's finished installing run:
sudo ufw status
Depending on your output you'll see if it's active or inactive. We do not want to enable the service just yet. If it's active skip to Port management and disable it.
Network Mapper is a tool that can scan the ports of globally or locally accessible computers. Nmap is used to scan open or closed ports on a system and can be used to gain information about a system, which a bad faith actor can use to further exploit your system.
This small subsection will just deal with how you can scan your server and confirm which ports are open and closed. This subsection will also assume that you are on Linux, as I have no experience with port scanning on any other operating system.
This should be run on your client, not on your server.
First install Nmap through your distros package manager:
sudo apt install nmap
Then run:
sudo nmap -sW <your-server-ip-address>
The terminal will hang for a moment, but just wait it might take a while for any output to show up on your terminal.
Starting Nmap 7.94 ( https://nmap.org ) at 2024-03-31 17:29 CEST
Nmap scan report for vps-my-server-address.stwvps.net (my-server-address)
Host is up (0.043s latency).
Not shown: 994 filtered tcp ports (no-response)
PORT STATE SERVICE
17/tcp open qotd
22/tcp open ssh
80/tcp closed http
443/tcp closed https
8080/tcp closed http-proxy
8888/tcp closed sun-answerbook
This is called a Window scan. As you can see I have some closed and some open ports. SPN will still connect through these ports but the Nmap will display them as closed.
On your server you should now have UFW installed. For now we'll disable (if it for some reason is active) and reset UFW, and we'll enable it once we have added some of the rules to our firewall.
Run:
sudo ufw disable
then
sudo ufw reset
Now sudo ufw status verbose
or sudo ufw status
will not display the ruleset. If you think you have added a rule by mistake you can review them through: sudo ufw show added
First we want to add the SSH port to allow connections.
Read the next section carefully
sudo ufw limit 22/tcp
Do not use the below metod if you do not understand how it works, or have opted for solution 1.
If you opt to use this method to secure your server make sure you actually have a static IP. When this rule is added and UFW is enabled it will be impossible to access the server from any other IP. (Your VPS provider might have a web console where you can recover the server.)
sudo ufw allow from your-static-ip-address proto tcp to any port 22
Now we're gonna add some ports to our firewall, and allow connections from them.
For now though we'll just allow these ports so SPN can establish a connection when we finally install it to our system.
Run every line seperately
sudo ufw allow 17/tcp
sudo ufw allow 80/tcp
sudo ufw allow 8080/tcp
sudo ufw allow 443/tcp
sudo ufw allow 17017/tcp
Our firewall is still not enabled, but we'll get to that very soon, first we need to further harden our network a little bit before we turn on the firewall and install the node software.
If you mistyped and added a wrong port number you can do eg.
sudo ufw delete allow 80/tcp
replace the number with whatever number you mistyped.
We're going to change some of the core rules of UFW for this section, make sure to read carefully and if you are unsure of what to do, you can skip this section. Skipping this section will make your system more vulnerable as attackers can see what sort of ports and services you are currently running.
TCP handshakes consist of a three way handshake: SYN, SYN-ACK, and ACK. Abnormal connections don't start with the first SYN flag, and don't follow the TCP three-way handshake. Bad actors will therefore try to send TCP packets with unusual and weird flag combinations which we are gonna block with UFW.
We'll be looking at two files located at /etc/ufw/
the two files we are working with are:
Grab your favorite editor and open the file. Note that if you are on your sudo user you should run sudo before opening the file, otherwise you can't edit / write to it.
Eg. sudo nano /etc/ufw/before.rules
In this file you are looking for this section:
# drop INVALID packets (logs these in loglevel medium and higher)
-A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack --ctstate INVALID -j DROP
Under the last line you should add.
-A ufw-before-input -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j ufw-logging-deny
-A ufw-before-input -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j DROP
For before6.rules add these lines:
-A ufw6-before-input -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j ufw6-logging-deny
-A ufw6-before-input -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j DROP
Write and exit the file. Now INVALID packets can not be used to identify which ports are open on your system when you are running UFW.
Now we can finally enable UFW, because we never enabled the service we didn't have to reload the service for the changes to take effect, now run:
sudo ufw enable
You might be prompted that any SSH connection might be disconnected, but you shouldn't be disconnected because you have a valid key which we set up earlier.
If all goes well and UFW reports that it's active. Go ahead and do sudo ufw reload
for good measure to make sure our rules have been added. You can also do cat /etc/ufw/before.rules
and if it spits out the 2 additional lines you added to the file, they should be working as expected. You can also do sudo ufw status verbose
to get an output of your current port rules.
Here is a before and after Nmap Window scan where UFW is configured correctly:
Before:
Starting Nmap 7.94 ( https://nmap.org ) at 2024-03-31 17:29 CEST
Nmap scan report for vps-my-server-ip.stwvps.net (my-server-ip)
Host is up (0.043s latency).
Not shown: 994 filtered tcp ports (no-response)
PORT STATE SERVICE
17/tcp open qotd
22/tcp open ssh
80/tcp closed http
443/tcp closed https
8080/tcp closed http-proxy
8888/tcp closed sun-answerbook
(Note: Just because a service is displayed as closed, doesn't mean it's not actively used by another program. UFW shows if a port is being used based on it's own list of applications.)
After:
Starting Nmap 7.94 ( https://nmap.org ) at 2024-04-01 23:46 CEST
Nmap scan report for vps-my-server-ip.stwvps.net (my-server-ip)
Host is up (0.0097s latency).
All 1000 scanned ports on vps-my-server.stwvps.net (my-server-ip) are in ignored states.
Not shown: 1000 filtered tcp ports (no-response)
With this server hardening there is a reduced chance that a bad actor might gain access to your server. The passwordless SSH setup ensures that you can only have 6 connections from any given IP trying to connect to your 22 port. They also automatically get refused because they lack the correct id_rsa.pub key. Root is also disabled so it will again be impossible for anyone to login with root. One way they can gain access is if you have a weak password with your VPS provider and they somehow get access to the web console there. I recommend setting up 2FA with the provider you are using to prevent these kinds of attacks.
We've also removed the ability of anyone who tries to scan your box from seeing what ports are open. This leaves them in the dark and makes it very difficult for them to decide how they are going to attack your box. There are further enchancements you could do to improve the performance of UFW but that's outside of the scope of this tutorial. I recommend looking into UFW performance optimisation.
We've also left out any malware or rootkit scanning. Maldet and ClamAV can be quite resource intensive when they scan. We don't want the SPN users to experience worse performance because we are running a malware or rootkit scan. Malware can come from many sources, but it is usually downloaded and executed by a user or administrator, or injected by an attacker. If you don't download, or use random scripts from untrusted sources it is very unlikely that you'll ever get malware. It should also be noted that rootkits must be placed by someone who has administrator access, so if you have a rootkit on your box you have already been compromised, or you ran a script or software with sudo access and unintentionally placed it yourself.