Setting up a Bastion Host
02 Aug 2021 - Richard Horridge
I plan to set up a bastion host for secure remote access to my home network.
Restricting SSH access to certain IP address (ranges) is a good idea for security. I will avoid this by requiring SSH keys and setting the port number to a high value. Root login and password login will be disabled.
[ ]SSH key required
[ ]Disable root login
[ ]SSH port on high number (50000+)
We will also restrict access to the host itself. The best way will be to create a new SSH key for each client. This key will be stored (400) and resourced in a script each time it is needed.
[ ]New SSH keypair for each client
We will configure the firewall to only allow SSH connections from clients.
[ ]DROP anything but our port
We will configure fail2ban to blacklist failed attempts - this reduces the load on SSHD considerably.
[ ]Configure fail2ban
Configuring the Remote
A symmetric approach (each client can also be a server) seems the best and most flexible. It should allow accessing any machine from any other machine, anywhere in the world, from behind NAT, without port-forwarding (etc, etc..), as long as the machine has a private key which matches a public key on the bastion.
An additonal requirement is for another key (or the same one, but most likely a different one) to be able to access the remote. Going forward, I will assume this will be the user's default SSH key.
An SSH session must be opened from the remote to the bastion with
-R flag set, indicating a port on the bastion (another high number,
optionally configured per-remote) mapping to a port on the remote
(most likely the default SSH port, 22).
Optionally, the connection can be set up to retry if it fails - potentially useful is you are away for several weeks!
Importantly, the bastion server will not hold an SSH key which can connect to the remote - this is where the other key comes in!
[ ]Configure SSH reverse tunnel
It may be desirable to configure a firewall and fail2ban on the remote also.
[ ]Configure fail2ban on remote
[ ]Firewall configuration
Configuring the Local
Once a remote or several remotes are configured, all that remains is to connect to the remote via the bastion. This process is as follows:
- Establish SSH connection to the bastion using first key file
- Once connection is established, establish SSH connection to the remote using second key file
- Do whatever you need to do on the remote
- Close session(s)
This should be combined into a script, whereby all that the user needs to do is e.g.
Enhancements and Further Thoughts
This template sets out the basic (and hopefully secure) configuration for flexible bastion hosting for servers behind firewalls and NAT. The basic principle is simple SSH tunnelling, which in addition to being as secure as the SSH protocol itself (and its configuration, of course) is also far more flexible.
If we want to connect to e.g. a PostgreSQL database (port 5432) or a webserver (port 80, 8000, 8080, …) we can! All it takes is to use the second SSH hop to open another SSH connection, this time forwarding a local port to the remote. This could also be configured in the script e.g. through an additional parameter.