A Bastion Host (or a jump server) is a dedicated computer used to access infrastructure resources and helps compartmentalize them. From a security perspective, a Bastion host is the only node in the network exposed for external access.
Remote access to databases and other servers is often required for administrative chores and troubleshooting. But exposing these servers for public access also exposes them to attacks.
Organizations instead designate a hardened intermediary server (or jump server) that is the only one open for external ssh access. All the other business-critical infrastructure is accessed through this bastion host. Access policies and audit infrastructure are set up just on the bastion host instead on each and every DB and server.
The below steps show how to create a simple AWS Bastion Host (or jump server) for your infrastructure. Later we also outline additional considerations for a more sophisticated setup.
Security groups on AWS are used to allow inbound connections on specified ports from specified IPs. Create a security group to allow SSH access to the bastion host from 0.0.0.0/0 and associate this security group with the bastion host.
Create another security group to allow SSH access only from the bastion host’s IP. Associate this security group with the rest of your infrastructure.
$ ssh -i aws.pem firstname.lastname@example.org
ssh: connect to host 188.8.131.52 port 22: Connection timed out
$ ssh -i aws.pem email@example.com
Linux ip-172-31-25-53 4.19.0-21-cloud-amd64 #1 SMP Debian 4.19.249-2 (2022-06-30) x86_64
Last login: Tue Jan 3 00:52:15 2023 from 184.108.40.206
admin@ip-172-31-25-53:~$ ssh -i aws.pem firstname.lastname@example.org
-J option can be used for connecting to the server in a single command.
The Bastion host's public IP is likely to change on machine restart. When this is an issue, consider allocating an Elastic IP (or Static IP) to the Bastion host.
If there is a fixed set of IP addresses from which the bastion host will be accessed, allow only those in the inbound rules.
Openssh on Linux includes logs of successful and failed login attempts, typically in
Jan 4 04:54:55 ip-172-31-25-53 sshd: Accepted publickey for admin from 220.127.116.11 port 53574 ssh2: RSA SHA256:ac6wLNaNL7NpWhfJSSD+T3nHnNQQeXJkyBJKi4kO9Zo
Jan 4 04:54:55 ip-172-31-25-53 sshd: pam_unix(sshd:session): session opened for user admin by (uid=0)
Jan 4 04:54:55 ip-172-31-25-53 systemd-logind: New session 42617 of user admin.
Jan 4 04:54:56 ip-172-31-25-53 sshd: pam_unix(sshd:session): session closed for user admin
Jan 4 04:54:56 ip-172-31-25-53 systemd-logind: Session 42617 logged out. Waiting for processes to exit.
Jan 4 04:54:56 ip-172-31-25-53 systemd-logind: Removed session 42617.
For an additional layer of security, put the bastion host in a public subnet and the remaining infra in a private subnet. Choose VPC and more when creating a new VPC to configure the subnets:
AWS’s Reference Deployment provides a reference implementation.
Terraform scripts for a similar setup are also available here.
An AWS Bastion Host is a good start to securing infrastructure access for a company from external threats, but implementing it, especially for larger organization sizes has some major challenges that need to be considered:
In rare situations, a single bastion host can also be a single point of failure for accessing the internal systems. If your infrastructure lives in multiple availability zones, consider creating one bastion host for each.
As your company infrastructure grows, each with its credentials and maintenance, the use of bastion hosts can become cumbersome.
Bastion hosts don’t solve the problem of key management, as whoever needs access to the one server also needs the keys to access the bastion host and the server itself.
There are different alternatives to Bastion Hosts that can be implemented based on the company’s requirements and size to manage their infrastructure access and security -
A VPN or Virtual Private Network allows the client host to become part of the company’s internal infrastructure dynamically. This also means that once inside a VPN one has access to all the hosts in the internal network. It is relatively harder to set up and use.
The combination of VPN and Bastion Host provides more security by addressing their limitations when either is used in isolation. The Bastion host limits access to infra within the VPN. And the VPN limits access to the Bastion host on the public internet. While more robust, it may be overkill for an organization with few infrastructure resources.
A SOCKS Proxy can also be used to access internal applications behind a firewall that allows SSH connections only. e.g. the following ssh command starts a proxy on port 9999 on the local host.
$ ssh -i~/.ssh/aws.pem -D9999 email@example.com
Remote applications behind the firewall can then be securely accessed by specifying the proxy to use e.g. the following accesses the remote application running on port 8888 via the proxy started above:
$ all_proxy="socks5://127.0.0.1:9999" curl 127.0.0.1:8888
Bastion hosts are a way to provide a low-cost layer of security for a company’s infrastructure. They don’t necessarily solve all of the access management issues, but can be a good starting point for a company to secure its infrastructure access, only necessitating replacement with a more comprehensive solution when your company grows.