On my FreedomBox I want SSH access from the internet for the following reasons:
- My FreedomBox is designed to be shared with family and friends, any user can get his/her own private virtual machine(s). To remotely manage a virtual machine SSH access is needed.
- SSH can be used as a secure inter - FreedomBox communication channel.
Using virtual machines complicates the use of SSH. Each virtual machine has its own IP address, and the FreedomBox only has one external IP address. There must be a way to connect this external address to one of the many internal addresses. Fortunately SSH is very flexible and it is possible to do this very elegantly.
Read this first.
This article is one in a series that describes the building of my FreedomBox. Not all information from the previous articles is repeated.
On my FreedomBox the external IP address is connected to a special virtual machine which I call the internet module. This internet module acts as a gateway to the host system and all the other virtual machines.
[client (A)] --> Internet --> [internet module (IM)] --> n*[virtual machine (B)]
If you want a SSH connection from client A to a virtual machine B then you need two SSH connections. First you have to make a connection from A to an account on the internet module (IM). From this connection you can make a second connection from IM to B. Making connections this way is not transparent. Machine A does not know it's connected to machine B, machine B does not know it's connected to machine A. Because the machines are not connected directly some SSH commands do not behave normally, or may not work at all.
Fortunately there is an elegant way to let both machines think they have a direct connection. For this you have to use the ProxyCommand statement in the ~/.ssh/config configuration file. With this statement you can specify a shell command that makes the connection to the remote system. The SSH client then uses the resulting stdin/stdout of the command as a channel to the remote SSH server.
For a transparent connection the returned stdin/stdout must be connected to the SSH port of the target server. The tick to get this done involves the following steps. First make a connection to the gateway system. On the gateway system start a program that returns a connection to the target system. Return this connection to the client.
Enough theory, here's the ~/.ssh/config setting I use to connect to my freedomboxblog VM over the internet:
Host freedomboxblog ProxyCommand ssh -p 99999 -qax firstname.lastname@example.org nc -w 1 freedomboxblog.freedom.box 22
I use ssh to log-in on the guest account of my internet module. Then the netcat program is used to make a connection to the freedomboxblog VM. This connection is returned and used by the SSH client to connect to “host freedomboxblog”.
On the internet module I only allow RSA authentication for the guest account. This is not only the most secure way, but it also prevents the password pop-up. With RSA authentication it is not possible to log-in if you don't have the private key. Unfortunately many people still try to log in by brute force. To prevent these attacks I use a non-standard SSH port (see my firewall article).
Edit the config file, add the following lines:
Host myhost ProxyCommand ssh -p 99999 -qax email@example.com nc -w 1 myhost.freedom.box 22
Create RSA authentication keys:
This command creates two keys with your username. The one ending with .pub is needed by the internet module on the FreedomBox.
scp yourusername.pub firstname.lastname@example.org:~
The internet module.
apt-get install netcat
Create a guest user:
useradd -m guest cd /home/guest
Add your public key to the authorized users of this account:
mkdir .ssh cd .ssh cat /root/yourusername.pub >> authorized_keys
Edit /etc/ssh/sshd_config so it has the following settings:
PasswordAuthentication no AllowUsers guest
Now you can only log-in using the guest account, and only if you have one of the private keys belonging to the public keys in /home/guest/.ssh/authorized_keys.
The next time you try:
Permission denied (publickey).
So in order to get root access you first have to log-in to the guest account and then use the su command.