Christmas is coming and some hackers might like to digest Christmas delicacies while breaking into our servers. How to make it a bit more difficult for them this year?
Let’s assume we manage some servers and we connect to them using SSH (or git, rsync, or other programs that use secure shell internally). Do we really need many of these servers to expose port 22 (default SSH port) to the internet? With SSH Bastion concept, we do not.
SSH Bastion is a nickname for a server in our infrastructure, which sole purpose is to provide us with secure access to other servers. It should have minimal, hardened configuration, with no unnecessary user accounts and no running daemons, except for
sshd. Ports other than 22 should be closed. On the other hand, SSH Bastion should be the only server in our infrastructure, that does expose port 22 to the internet.
Let’s see our SSH Bastion server in action.
We have to make sure that public key authentication is set up correctly on the Bastion machine, as well as on all other servers we want to eventually have access to. There are many articles on this topic around the internet. Please note, that we never store our private keys on any of the servers.
Open SSH configuration file
~/.ssh/config on your client computer (we will call it
client), and enter the following configuration snippet to it, assuming our Bastion hostname is
internal is the hostname of a server we want to eventually connect to. In this example we also assume that we use a single SSH key
~/.ssh/id_rsa for both connections.
Host bastion IdentityFile ~/.ssh/id_rsa Host internal IdentityFile ~/.ssh/id_rsa ProxyCommand ssh user@bastion -W %h:%p
ProxyCommand configuration in place, we can connect to our
internal server using command
Behind the scenes, a parent SSH connection is created between
client and the
internal server, followed by a child connection between
bastion. The SSH daemon on
bastion machine then creates a TCP connection to the
This situation allows us to connect from our
client (or the internet in general) to our
internal machine. However, if we use the command
who to see who is who inside our
internal machine, we can see that the SSH connection actually comes from
bastion box. And that’s correct, since nobody should be able to connect to our
internal server directly.
There’s more we can do with SSH bastions to make networks more secure. Different SSH keys can be used for parent and child connections (specified as
IdentityFile in the code snippet above). Or if the SSH access is required only occasionally, stopping/starting
bastion machine on demand can temporarily disable SSH access to our entire network.
SSH bastion improves network security with elegance, transparency and simplicity. Highly recommended.