In this tutorial series of 3 parts, our aim is to have few remote located RPis to automagically establish VPN connection to a cloud hosted Linux server based VPN server. We will also be connecting a windows based home machine to VPN into the same server and that way, we can get to any of those remote RPis from our Windows PC as these all devices will then be on same VPN subnet, we can accordingly ping them, remote desktop into those etc. We will also set the windows PC to auto connect to VPN on power up. This way, we can also setup some kind of monitoring tool to periodically ping these remote devices and alert us if any of these were to go down.
And behind these RPi could be a device that once in a while we need to http into for some maintenance or monitoring purposes.
You can imagine these remote RPis to be device at your friends and families that are not tech-savvy and you need to assist them for technology needs from your home machine. For me, I am just helping a friend for his small business needs (basically a Pi-hole DNS and IP phones to talk across few locations).
Okay back to our tech details:
- Purchased AWS lightsail small instance (virtual machine) that costs about 6 to 7 CAD or 5 USD a month. I have Ubuntu Linux on it with 1CPU, 1GB of RAM and 40GB of disk space. Note the process should be exact same for debian also. Virtual Private Server and Web Hosting–Amazon Lightsail—Amazon Web Services . As you choose the Linux distro (OS) for AWS to set up for you, you also set up the key-pair for SSH into it and you download it at your computer and safeguard it. (Note this keypair is generated for our client to login and yes multiple clients belonging to use can use the same key but not recommended just in case our one machine gets compromised, then we need to remove it from all. And we can also generate this key locally on client devices, windows or RPi). You are also allowed to use a public static IP on your instance. During install, it asks you for it and you create one, name it, and then assign it to your instance. We will discuss about certificates and encryption keys etc in some other tutorial.You may want to watch a YouTube video on this and it is very straightforward. lightsail is a simpler way to get started into AWS cloud hosting.
- By default password authentication is disabled and there is no password set for root or default username, so we cannot login with username/password. Default username is ubuntu. I enabled password authentication for it as we may need it in a pinch (while we are still learning), while for our most day to day work, we will use public key (certificate based) authentication for SSH access into server. To do that, you simply go to the lightsail portal and click on your instance, there is an option to SSH into the session from there, wherein it will log you directly with saved ssh key. On the terminal,
sudo passwd ubuntu
type in password and then again on prompt.
Now, we need to enable password use for our rare use or unless we are logging in over VPN session.
sudo nano /etc/ssh/sshd_config
change the following lines as below by uncommenting.
PasswordAuthentication yes
and if you are responsible in using root account, but we should never need it.
PermitRootLogin yes
Save the changes.
service sshd restart
or
systemctl sshd restart
If you want to login as root,
sudo password root
type in twice the password for root
Note, you can also login using Windows Terminal (install it on windows 10 using Microsoft Store, is in by default in windows 11)
ssh -i path/to/AWSkeypair.pem ubuntu@public_ip_address_of_your_instance
and after you have set password authentication, from windows terminal,
ssh ubuntu@public_ip_address_of_your_instance
and it will ask for password.
Note, if we generate the key-pair locally and accept all defaults by clicking next, next, then we will simply skip -i path/to/AWSkeypair.pem. More on how to generate and use keys for authentication and file exchange little later in this tutorial.
You can also add some more security against SSH login attempts, by changing the port from default 22 to something like 55222. Here is how to do it.
First of all, to make sure we are not locked out from our instance,
- You should do a quick backup of instance by creating a snapshot. On the portal, when you click your instance, there appears a tab for snapshot. This way if something breaks down, you can quickly restore your instance to working as before the changes in couple of minutes.Just go to snapshots, right click and restore.
- On the portal, on the left side of snapshots tab is networking tab. Click on that and it shows your instance private IP, its public IP (dynamic or if you created and assigned static, then that one) and underneath is Firewall section. By default it should have opened port 22. Add a rule in there, with application as custom, protocol as TCP and port as 55222 (or whatever you have chosen to be a high port in range of 1024 to 65535) and restricted to Any IP address. While you are it, also add a rule for application as ALL Protocols, Protocol as ALL, Port o to 65535, restricted to 10.8.0.0 to 10.8.0.255 as we will use this for openvpn IP pool and is default range used by openvpn. Similarly also add another rule for our Nomachine client / server communication for custom / TCP / 4000 / Any IP address. Note, I am only using AWS provided firewall and have not added any UFW / IPTables.
Now we can change the SSH port from default 22 to whatever, say 55222.
sudo nano /etc/ssh/sshd_config
uncomment port 22 and change port to 55222
save
Now come back to Windows Terminal (or Putty or SecureCRT, whatever you use for SSH client)
ssh -p 55222 ubuntu@public_ip_address_of_your_instance
and you will be prompted for password to log in.
you may want to make sure timezone is setup correctly on your instance.
check with or change it with following set of commands
timedatectl
timedatectl list-timezones
sudo timedatectl set-timezone America/Toronto
Public / Private key-pair use to login to server
Let us discuss some more details on this important security aspect.
ssh-keygen
generates the key-pair in RPi or for that matter on any linux machine. So issue this command and then just accept all defaults by pressing enter every time it poses you a question. Note the same command will work on windows 10 or windows 11 when issued from Windows Terminal.
It is important to not change location of the keys, especially as a beginner, else we will need to specify the path for the key in our SSH (and SCP and SFTP) sessions.
Now we copy our RPi public key into server so that we can login to server without password and SCP/ SFTPalso for file transfer if needed. This is going to append to already existing keys from other clients. With this public key in authorized clients list, client uses its private key to provide its identity for server to validate it (using the public key in store in server, it can kind of hash the two to come to a unique code to authenticate a client uniquely).
ssh-copy-id -p 55222 ubuntu@ourServerPublicIP
(if you did not change server SSH port from default 22, then remove -p 55222 from above)
This command is not available on Windows Terminal, so we need to copy it using
cat ~/.ssh/id_rsa.pub | ssh -p 55222 ubuntu@ourServerPublicIP "cat >> ~/.ssh/authorized_keys"
What above command does is to first read contents of local file containing our public key, then feeds that into a SSH session to our AWS server and asks it to write to the existing authorized keys file. Note double redirect sign, which tells cat to write to the end of the file (append) and not overwrite the file. cat>> basically here opens the file and waits for bash terminal to supply the text to be written to the file. And if you did not already know, cat is from concatenate, which essentially means append or join, but if we don’t specify >>, it lists the contents on terminal. If we specify cat > filename, then that creates a file. And if we do something like cat file1 > file2, then that will list the contents of file1 and copy into a new file named file2.
Above command will present a warning that server’s authenticity cannot be validated, since we don’t have its public key yet in our local cert store to validate presented key against. Since we know this is our trusted server, we type in yes. It will ask us to now type in password of the ubuntu account on our AWS server.
Our client key (the public key) will be scanned into the default storage location and then uploaded to server in file below
/home/ubuntu/.ssh/authorized_keys
This command above can also be written as (~ tildah represent the home directory of the user account, so it abbreviates /home/username )
~/.ssh/authorized_keys
Now we can ssh into our server from our client RPi without typing in a password.
from console(monitor) or terminal (SSH) session on RPi, we can jump to our server:
ssh -p 55222 ubuntu@ourServerPublicIP
From now onward, this client device is accepted by server as trusted host to dial into . We will use this feature to login and download something from our server in next section. And just in case, we did not know what does SSH stand for, it is secure (S) shell (SH), with shell being the name given to a command interpreter to decipher the commands for computer to understand them, to accordingly do what we want it to do in our plain English. Similarly SCP is secure copy protocol, SFTP is secure file transfer protocol. And original remote login protocol developed before advent of Internet was Telnet (which means teletype network, a way of remotely typing our commands to a network device) and this is still being used, but recommended only for either initial set up of devices on the desk in our staging lab, or at least in trusted private networks, and also with management access restricted by private IP ranges. We also typically use telnet to test a port being open, like
telnet 10.8.0.1 40000
if we see in output connected to 10.8.0.1, well that means port is open, though connected does not really mean it is connected to our server, it is just an initial; handshake that is awaiting for additional information.
Next steps are for us to install openvpn server in AWS instance. We will use pivpn for that purpose. Then we will install pivpn (only client) on our RPis and also openvpn community edition on the windows machine. We will use certs (Certificates are random ultra long set of 0s and 1s in the form of a public and private key pair, with one part being kept secret and other sent or made available publically, and public portion is also vouched for by some sort of hashing it with a Certification Authority (CA)'s Root or root authorized Intermediate cert authority’s cert, that is trusted by all common browser and OSs), created at server for use with each client for authentication. We will further venture into Nomachine setup so that we as beginners have a GUI based access to RPis as well as our server. All this and more in Part 2.