The goal of this guide is to walk you through steps you can take to secure your node against malicious actors. Whether you're running a local server at home or a VPS server / virtual machine on the cloud, the tips here will help you harden your node against outside attack and help protect it during its lifespan.
This section will describe both essential actions, which you must take, and nice-to-have actions, which are helpful but not required.
This guide is meant to be an introduction to some of the things you can do to harden your node machine. If you are comfortable with the command-line terminal and want to go even further in protecting your node, take a look at the popular imthenachoman/How-To-Secure-A-Linux-Server guide.
This guide assumes your node runs Ubuntu 20.04 LTS
.
The concepts will carry over to other systems but the example commands may not.
As with all of the commands in this guide, we assume that you are connecting remotely to your node's command terminal using ssh
.
If you need a refresher on how to use ssh
, take a look at the Intro to Secure Shell guide first.
If you use your Smartnode locally (by physically logging into it with a keyboard and monitor directly attached to it), then this section is not relevant to you - you can skip it.
Most Smartnode operators interact with their node remotely by connecting to its terminal from another computer using ssh
:
One of the most important things you can do to secure your Smartnode is to keep your client machine secure. If your client machine is compromised and you use it to log into your node, then most of the security settings you apply to the node can be bypassed.
For example: if you use a laptop as an SSH client, and it has a keylogger installed, then any secret things you type on the node (such as your password or recovery mnemonic) when connected via SSH will be stolen.
There is no definitive guide to keeping your client machine secure, but being aware that it is a factor in your security is a good first step. Make sure that your client machine is as secure as it can be.
Here are a few tips:
For maximum security, you may want to use a dedicated machine as your SSH client, though this may not be practical for you.
If you use your Smartnode locally (by physically logging into it with a keyboard and monitor directly attached to it), then this section is not relevant to you - you can skip it.
Whether you run your Smartnode at home or you use a VPS in a remote datacenter, it is likely that either you access it through SSH, or that SSH is enabled even if you do not use it.
SSH connections are based on secure cryptography, but as with any secure system, the real security comes from using it correctly. There are two main things to do for your SSH settings:
As you are probably familiar with now, the default way to log into your node via SSH is with a username and password. The downside of this is that your password is typically something rather "short" and susceptible to brute-force attacks.
Luckily, there is an alternative way to log in via SSH: an SSH key pair.
SSH key pairs work similarly to blockchain wallets; they come with a public part (such as your wallet address) and a private part (the private key for your wallet address):
If you'd like to learn more about SSH key pairs before creating your own, take a look at these links:
Let's start by creating a new SSH key pair on your client machine. There are many varieties of key out there, but we're going to use a key type called ed25519 which provides excellent security.
Run the following command on your client machine (i.e., you should not run this while already SSH'd into your node machine - if you are, exit out of SSH first):
You will see the following:
This asks you where you would like to save your private key file. SSH is compatible with the provided default and will automatically use it for you if you select it. However, you have the option of changing it to something else if you wish.
::: tip NOTE
The path /home/username/.ssh/id_ed25519
is just an example, assuming your username is username
.
You likely have a different username.
Whenever you see a path like the above in this guide, replace it with whatever path your system actually prints with your actual username.
If you are comfortable with the default setting, simply press Enter
.
Otherwise, type your desired location for the key.
It must be an absolute path (e.g. /home/username/.ssh/rocketpool_key
on Linux, or /Users/username/.ssh/rocketpool_key
on OSX).
Press Enter
when you're done.
After pressing Enter
, you will see:
This will become the password for the private key itself. Whenever you use the key to connect to your node, you will need to enter this password first.
You should not leave this blank - otherwise, anyone with the SSH key file will be able to use it! Pick a good password that you (and only you) will know.
Also, don't forget your password - there is no way to recover this password if you lose it.
Once you finish typing the password, press Enter
.
It will ask you to retype it for confirmation.
After that, you will see something like the following output:
The first line states the location of the private key, which is called id_ed25519
by default (notice that it does not have a file extension).
Ubuntu will load this key for you automatically when you use ssh
if this private key file is in the default location.
The second line states the location of the public key, which is called id_ed25519.pub
by default.
We'll need the public key for the next step.
Ubuntu should load this new key automatically. However, some systems (such as macOS machines) will not load it automatically - you will have to tell it to do this with the following command on your client machine:
Note that this is the path of the private key that we generated in the previous step, not the public key. Replace the path with whatever your system printed in that previous step.
If you get an error saying that the ssh-agent
is not running, start it by running the following command on your client machine:
If you don't want to type these two commands every time you open the terminal, you can create a shortcut for adding your key by adding an alias
to your ~/.bashrc
file.
Open the file using the text editor:
Add this line to the end (assuming you used the default path for the private key - update as necessary):
Save and exit with Ctrl+O
and Enter
, then Ctrl+X
.
Next, close and open your terminal for the changes to take effect.
You can now type loadkey
on your client machine to load the key.
Once you have your SSH key pair, you can now add the public key to your node.
This will let you connect to it over ssh
using the private key you just generated, instead of your username and password.
There are two ways to do this - if one doesn't work, try the other way:
Note: if your client machine is running Windows, ssh-copy-id
is not yet available.
Please follow the instructions in the "Manually Adding the Key" tab.
Run the following command on your client machine:
For example, if my username on the node was staker
and my node's IP address was 192.168.1.10
, I would run the following command:
You will see some messages like the following:
This tells you that it's trying to log in with your key first to make sure it isn't already there. Once it fails logging in, it knows that it's OK to add the new public key to the node machine.
It will then prompt you for the password of the user on your node machine. (Note that this is not the password of the SSH key!)
Enter your user's password, and you will see the following output:
That means it worked!
You should now be able to ssh
into the node like you normally would, but now you won't have to type the password of the user account.
Instead, you will have to type the password of your SSH private key. Depending on your system settings, you may only have to do this once per restart, or you may have to do it every time you use the key to connect to your node.
Even though you have an SSH key pair set up, your node will still allow other machines to try to log in using the username and password method. This defeats the entire purpose of using SSH keys in the first place, so the next step is to disable those.
You are about to modify the SSH server's configuration.existing SSH sessions will be preserved. However, if you make a mistake, then it's possible that you will not be able to create new SSH sessions anymore and effectively lock yourself out of the machine.
All of your
To prevent this, we strongly recommend that you create 2 SSH sessions for the next steps - one for editing things and testing, and one as a backup so you can revert any breaking changes.
Start by logging into your machine using ssh
as usual:
As a reminder, you should do this twice on two separate terminals so you have a backup session just in case. You can ignore the backup session for now - we'll tell you when you need it. Run the following commands only in the first session.
Open the configuration file for the SSH server:
As with all commands that start with sudo
, this will prompt you for your user account's password.
This is a large file, so you'll have to navigate through it using the arrow keys on your keyboard or Page Up
/ Page Down
.
Make the following changes:
#AuthorizedKeysFile
if it is commented (by removing the #
in front of it)KbdInteractiveAuthentication yes
to KbdInteractiveAuthentication no
and uncomment (by removing the #
in front of it) - note that older versions of SSH call this option ChallengeResponseAuthentication
instead of KbdInteractiveAuthentication
PasswordAuthentication yes
to PasswordAuthentication no
and uncomment (by removing the #
in front of it)PermitRootLogin yes
to PermitRootLogin prohibit-password
unless it's already set to that and has a #
in front of itOnce you're done, save with Ctrl+O
and Enter
, then exit with Ctrl+X
.
Finally, run sudo sshd -T | grep -i passwordauthentication
and make sure that it prints passwordauthentication no
.
If it does not, you may need to run sudo nano /etc/ssh/sshd_config.d/50-cloud-init.conf
and set PasswordAuthentication yes
to PasswordAuthentication no
in that file as well.
Save and exit as before, with Ctrl+O
and Enter
, then Ctrl+X
Next, restart the SSH server so it picks up the new settings:
After this, logging into SSH via a username and password should be disabled.
At this point, you should exit the SSH session and try to SSH back in.
If you are able to do so successfully, then your SSH configuration is still valid!
If you are not able to get back in, then something has gone wrong with your configuration.
Use the backup SSH session you created at the start of this section to modify the /etc/ssh/sshd_config
file.
Try to find the mistake or undo your changes, then restart the SSH server using sudo systemctl restart sshd
.
Once it's been restarted, try connecting with SSH again on your "other" terminal. Keep doing this until you have it working again and are able to successfully connect.
Two-factor authentication involves requiring a second security measure in addition to your password or SSH key, usually on a separate device from your primary one.
For example, you may be familiar with logging into a website such as a crypto exchange using both a password and a Google Authenticator code (or an SMS code). This two-step process is an example of two-factor authentication.
SSH can also be configured to require a Google Authenticator code, which means that an attacker that somehow compromised your SSH key and its passphrase would still need the device with the authenticator app on it (presumably your phone). This adds an extra layer of security to your system.
We strongly recommend that you open a second terminal with an SSH connection to your node, just in case you misconfigure something. This way, you will have a backup that is still connected in case you lock yourself out, so you can easily undo your mistakes.
If you do manage to lock yourself out, you will need to physically access your node via its local monitor and keyboard to log in and repair the misconfiguration.
Start by installing Google Authenticator (or a compatible equivalent) on your phone if you don't already have it. For Android users, consider andOTP which is an open-source alternative that supports password locking and convenient backups.
Next, install the Google Authenticator module on your node with this command:
Now tell the PAM
(pluggable authentication modules) to use this module.
First, open the config file:
Find @include common-auth
(it should be at the top) and comment it out by adding a #
in front of it, so it looks like this:
Next, add these lines to the top of the file:
Then save and exit the file with Ctrl+O
, Enter
, and Ctrl+X
.
Now that PAM
knows to use Google Authenticator, the next step is to tell sshd
to use PAM
.
Open the sshd
config file:
Now change the line KbdInteractiveAuthentication no
to KbdInteractiveAuthentication yes
so it looks like this:
(Older versions of SSH call this option ChallengeResponseAuthentication
instead of KbdInteractiveAuthentication
.)
Add the following line to the bottom of the file, which indicates to sshd
that it needs both an SSH key and the Google Authenticator code:
Then save and exit the file with Ctrl+O
, Enter
, and Ctrl+X
.
Now that sshd
is set up, we need to create our 2FA codes.
In your terminal, run:
First, it will ask you about time-based tokens.
Say y
to this question:
You will now see a big QR code on your screen; scan it with your Google Authenticator app to add it. You will also see your secret and a few backup codes looking like this:
Record the emergency scratch codes somewhere safe in case you need to log into the machine but don't have your 2FA app handy.
Without the app, you will no longer be able to SSH into the machine!
Finally, it will ask you for some more parameters; the recommended defaults are as follows:
Once you're done, restart sshd
so it grabs the new settings:
When you try to SSH into your server with your SSH keys, you should now also be asked for a 2FA verification code, but not for a password.
Operating System vendors routinely publish updates and security fixes, so it is important that you keep your system up to date with the latest patches. The easiest way to do this is to enable automatic updates.
Run the following commands on your node machine:
You can change the auto-update settings by editing /etc/apt/apt.conf.d/20auto-upgrades
:
This is an example of reasonable auto-update settings:
When you are done adding your changes, save with Ctrl+O
and Enter
, then exit with Ctrl+X
.
After, make sure to load the new settings:
In general, your machine should only accept network traffic on ports that your Execution client, Consensus client, and Smartnode stack use. To enforce that and prevent any unexpected or undesirable traffic, we can install a firewall on the node.
If you selected a different execution/consensus client port during the Rocketpool setup, you need to edit the ports below to reflect your settings.
Ubuntu comes with ufw
installed by default (the uncomplicated fire wall), which is a convenient utility for managing your node's firewall settings.
The following commands will set ufw
up with a good default configuration for your Smartnode.
Run these on your node machine.
Disable connections unless they're explicitly allowed by later rules:
Allow SSH:
Allow execution client (formerly referred to as ETH1):
Allow consensus client (formerly referred to as ETH2):
If you run lighthouse client v4.5.0+, you can use quic protocol to reduce latency / increase bandwitdh, quic protocol uses lighthouse's --port + 1 to listen for quic messages by default: https://lighthouse-blog.sigmaprime.io/Quic,%20Networking.html
Finally, enable ufw
:
iptables
experts might note that Docker bypasses ufw
settings.
Strictly speaking, that means unless you are running in Hybrid mode, you do not need the Execution and Consensus client rules.
Adding them, however, has no downside and will make sure that if you ever switch to Hybrid mode you will not run into firewall issues.
To protect your server from DDoS attacks and brute-force connection attempts, you can install fail2ban
.
This program will monitor incoming connections and block IP addresses that try to log in with faulty credentials repeatedly.
See this guide for more information on intrusion prevention.
Run the following commands on your node machine:
Install the service:
Next, open /etc/fail2ban/jail.d/ssh.local
:
Add the following contents to it:
You can change the maxretry
setting, which is the number of attempts it will allow before locking the offending address out.
Once you're done, save and exit with Ctrl+O
and Enter
, then Ctrl+X
.
Finally, restart the service:
And with that, you've just greatly improved the security posture of your node. Congratulations!