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.
The method.
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 guest@freedomboxblog.nl 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).
The configuration.
Client side:
cd ~/.ssh
Edit the config file, add the following lines:
Host myhost ProxyCommand ssh -p 99999 -qax guest@mydomain.com nc -w 1 myhost.freedom.box 22
Create RSA authentication keys:
ssh-keygen
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 root@internet.freedom.box:~
The internet module.
ssh root@internet.freedom.box
Install netcat:
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
Restart ssh:
/etc/init.d/ssh restart
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:
ssh root@internet.freedom.box
you get:
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.
4 comments
Skip to comment form ↓
Bjarni Rúnar
July 13, 2011 at 01:39 (UTC 2) Link to this comment
Hey!
I wanted to share with you a pointer to my project, PageKite, which provides this kind of functionality as well – PageKite is an AGPLv3-licensed dynamic reverse proxy server, where servers that want to receive requests ‘register for traffic’ using an outgoing TCP/IP connection. In this case you would be registering an SSH server, but you can also register HTTP and other protocols.
So PageKite is a generalized implementation of the architecture you just invented for SSH, and it implements a fair bit of the logic you were using nginx for as well.
Looking at your over-all architecture (which look quite cool by the way, congrats), it might actually be useful for you to run a PageKite front-end on your Internet Module, and then each virtual machine which wants to provide a public service can register with it to receive requests. This might simplify configuration quite a bit – both your WordPress modules and SSH servers for example could all be exposed to the wider Internet using the same solution. It might also allow you to move the Internet module to a VPS in the cloud (if you wanted) and still work even if your FreedomBox had no public IP at all.
Here is the page describing how to tunnel SSH over PageKite:
http://pagekite.net/wiki/Howto/SshOverPageKite/
And here is the free-software landing page for PageKite:
http://pagekite.org/
If you have any questions, we’re often on #pagekite – although I’m a bit absent myself these days because of attending RMLL…
robvanderhoeven
July 15, 2011 at 16:10 (UTC 2) Link to this comment
Hi Bjarni,
I think PageKite is a very clever idea. It can certainly be used in my internet module to make VM’s accessible from the internet. Should i use it? Don’t know at the moment. Most of my communication infrastructure is already in place. The programs i use are carefully chosen and work together to get maximum security (my first priority) and minimum configuration. SSH is an excellent example of this: When i create a new VM with the name abc it automatically gets an internal DNS name of abc.freedom.box. The client can use this internal name in the ProxyCommand SSH config. The only thing that the FreedomBox administrator must do is add the public key of the client to the SSH config of the internet module guest account.
Bjarni Rúnar
July 15, 2011 at 19:44 (UTC 2) Link to this comment
Yeah, you have made so much progress that I understand well that you might want to stick with your current design. I thought PageKite might make a nice addition to your toolkit, or that of your readers, which is why I mention it.
Anyway, thanks for your blog and keep up the good work!
Anders
April 1, 2012 at 18:26 (UTC 2) Link to this comment
I uses IPv6. Then I only need to open the right port in my FW.