The most common way how to connect to your server is using SSH.
We will open RPi to world and in that case we need to secure it a bit. Service, which takes care about SSH is called
sshd. Where is it? It is run by
systemctl status sshd will show you more info. To reduce the brutal force attacks on root account (if was thousands of attempts every day on my little unimportant server), we will disable root login through SSH.
Getting a proper randomness
A lot of security algorithms relies on having a good source of (pseudo)randomness. Why? Take for example the password file from previous chapter. If you would generate the salt in some predictable way, an attacker would have much easier work to guess the passwords.
There are two special Linux devices which you can use for getting random data. Those random data are mostly generated from user interaction with e.g. mouse, keyboard or screen.
That is the problem on headless Linux server as we can have, since they do not have such interfaces. Because of that, relaying on the basic
source of randomness is insufficient. These devices are in
/dev/urandom. The latter differs from the former in that manner that it will generate
random data even though there is not enough entropy for ensuring sufficient randomness. Hence, use
If you don't want to invest to additional hardware which provide very high and true randomness by buying e.g. OneRNG, there is another solution
which will definitely be enough for 99% of users. That solution is
havege (respective it's daemon
haveged). This is a clever algorithm which generates randomness
based on time which processor spends during computing some instructions.
Installing and activating
haveged cannot be easier. Go for:
$ pacman -S haveged $ systemctl enable haveged $ systemctl start haveged
/dev/random will be fed by
haveged data since now.
If you haven't installed SSH yet, do it by
pacman -S ssh.
Open the file
/etc/ssh/sshd_config and edit/uncomment or add these lines as follows (left the rest untouched):
Port 1234 PermitRootLogin no PubkeyAuthentication yes
ssh service by
systemctl restart sshd. Since now, you cannot login as a root by ssh and that's good. Also - we changed the port of ssh to
1234 (you are advised to change this number to something different of course). Think about port as a tunnel, which is used by some application. There are about 60 thousands of them and you can choose whichever you want. Default port for SSH is 22 and that is the port which is most widely abused by brutal force attacks. Changing it to something from this range just makes it several tenth thousands harder to guess the access...
Since now, using only
ssh bob@ipadress to connect to server is not enough. You will have to add port which should be used.
ssh -p 1234 firstname.lastname@example.org will do that for you.
Improving the security of SSH can be done basically by two approaches depending on your needs.
sshguard is going to block recurring attempts of login and in case they are failing, it denies the access entirely for some specific time. Install it by
pacman -S sshguard. For proper usage, we need to tweak Linux firewall app called
iptables are really just another layer of security often called as a firewall. It just specified what connections can come in and out. We need only simple configuration which can be done quite easily.
$ iptables -F $ iptables -X $ iptables -P INPUT ACCEPT $ iptables -P FORWARD ACCEPT $ iptables -P OUTPUT ACCEPT $ iptables -N sshguard $ iptables -A INPUT -j sshguard $ iptables-save > /etc/iptables/iptables.rules
Personally I stopped to use
sshguard, since just changing port what SSH use was enough to reduce uninvited connections. Furthermore, there is actually a safer method using only SSH keys.
This is the best you can do from the point of security. Open
/etc/ssh/sshd_config and edit these lines as follows:
ChallengeResponseAuthentication no PasswordAuthentication no UsePAM no
and again restart
ssh. We just disabled the ability to connect to your server with password. But how else to login in? Using keys!
Creating a key pair
We now need to create a key pair. Two files will with public and private key will be created. Let's do it by this command:
ssh-keygen -t ed25519 -f ~/.ssh/bobs_key (left passphrase empty).
One of created files is
~/.ssh/bobs_key.pub and that is the one (public key) you want to transfer to client - the computer from you are going to connect to the server.
The second one is private key and you should never ever show any of the keys to anyone under any circumstances. It would basically imply your vulnerability, since anyone who possess public key and the username can connect to your server.
Copy the content of the public key to the clients ssh folder. Now you need to specify this file to connect by
-i switch following the filename, e.g.
ssh -p 1234 -i ~/.ssh/bobs_key.pub bob@yourrpiaddress.
It is annoying still typing same username, port and filepath to the key when we want to connect to our server. On PC from which we are connecting (no RPi), edit
~/.ssh/config to this:
Host my_superpc HostName ipaddressofRPi IdentityFile /home/yourusername/.ssh/name_of_identityfile User bob port 1234
since now, when you want to connect to RPi, you can just type
ssh my_superpc and it will take care about rest. Quite clever, isn't it?
Opening the server to the world
Because we now already know what port is and we have an application which uses them, we can take leverage of using them for security purposes. You have already seen that when we changed the default port from SSH. In the classic scenario when you have your server plugged into your router you wouldn't have to worry anyway, because the router wouldn't allow anyone to get to your server. So how to achieve this?
You must first get your public IP address. That can be found e.g. here. There is another caveat - you might not have your own public IP, but rather some local from your provider and your provider has the one which is public. There is nothing you can do in to make your server visible from outer world unfortunately, except trying to negotiate with your provider.
In case you are not so unlucky, you have your own public IP which you can use to connect to your server. You will make a request to your IP on specific port, e.g. using
ssh to connect on port
1234. This will get into the router first and router will decide where should be the request sent next. If the port isn't explicitly mentioned in the router lookup table, the request is thrown away. That is good - we don't want let the attacker give opportunity to do anything with our inner network. So enable only those ports which are necessary.
How to do a port forwarding differs based on the router and it's firmware. But you need to get into your router and change the settings. How to do that you might find e.g. here or use google for your router type.
To get into your router you need to set up port forwarding from some chosen port to the port you have chosen before for your SSH daemon (
1234 in my case). You can choose the same even for the outer port, but you can choose different for that (let's say
8765), so your setting should be something like
8765 -> server.local.ip.address on port 1234. This will tell router to redirect requests on port
1234 to your server and specific port on that server.
Now you should be able to connect to your server using the port
bob and your public IP address. The syntax is exactly the same:
ssh -p 8765 -i ~/.ssh/bobs_key.pub bob@YOURPUBLICIPADDRESS.