SSH through Jump Box on AWS

Jump Box

If you have an application running on cloud, you might want to consider using a Jump Box for SSH connections to your instance. This creates an additional layer of protection and reduces the attack surface of your instances. Since the instance is not exposed directly to public network, it can be only reached from a trusted Jump Box on the same private subnet.

“A jump server, jump host or jump box is a system on a network used to access and manage devices in a separate security zone. A jump server is a hardened and monitored device that spans two dissimilar security zones and provides a controlled means of access between them.” — Wikipedia

An attacker now needs to have access these three things simultaneously in order to be able to access to your protected instance:

  • SSH key for the Jump Box
  • SSH key for Application Server
  • Have connection to your Local Network

Configuring a Jump Box

Start a new EC2 instance. Save the private keys. SSH into Jump Box.

Open the ssh config file and uncomment the port line and change the port and save the file. When you restart the ssh service, custom port will be active. Be careful, don’t forget to change firewall rules accordingly if you change the default SSH port. Otherwise you will be locked out!

$ sudo nano /etc/ssh/sshd_config> #port 22  # uncomment this line and change port number to 2222$ sudo systemctl restart sshd

Go to AWS EC2 Console > Security Groups and create an inbound rule for custom SSH port 2222. Update the source with your public ip. This rule will allow incoming connection on port 2222 for only from the specified ip address block (You can read more on CIDR blocks on wikipedia)

Update the inbound rule for Jump Box on EC2 Security Groups

It is important to update the firewall rules for application server allowing ssh only from jump box private ip. Go to AWS EC2 Console > Security Groups and change the source with the private ip of your Jump Box

Inbound Rule for App Server

Our Jump Box configuration is now done and ready for testing. When you try to make ssh connection directly to App server from any public ip, you will see that the ssh port is closed.

SSH connection through Jump Box

First we have to connect to the Jump Box.

Keep in mind that storing the ssh keys on Jump Box would beat the purpose of using it at the first place. So instead we store all ssh keys on our local machine and use agent forwarding when connecting by adding -A flag to our ssh command. It simply allows using our local keys on the Jump Box:

Local machine > Jump Box > App Server

# Local machine
yagiz@Ubuntu:/$ sudo ssh-add -k JumpboxPrivateKey.pem
yagiz@Ubuntu:/$ sudo ssh-add -k AppServerPrivateKey.pem
yagiz@Ubuntu:/$ ssh -A admin@<JumpBox-Public-IP>
# Connected to Jump Box
admin@JumpBox:/$ ssh admin@<AppServer-Private-IP>
# Connected to App Server
admin@AppServer:/$

Instead of manually running the ssh command twice, we can combine in a single chain command as below. Notice that the first hop has a custom port defined with -p flag. It is because we previously configured a custom SSH port 2222 on our Jump Box, instead of using the default port 22.

$ ssh -A -t admin@<JumpBox-Public-IP> -p 2222 \
ssh -t admin@<AppServer-Private-IP>
# Connected to AppServer
admin@AppServer:/$

For making it easier, we can also create a script instead of typing the command every time when we are connecting to the App Server

# create a script file including the chain command above
$ sudo nano ssh_jump.sh
# make it executable
$ sudo chmod +x ssh_jump.sh

Next time when connecting to the App Server, just run the script with the following command:

$ . ssh_jump.sh

Extra: SSH multi-hop port forwarding

Lets say we have a Redis service running on a docker container on App Server port 6379 and we want to access this service as it was running on our local machine. It is possible with ssh port forwarding.

localhost:8000> Jumpbox:6379> AppServer:6379 > RedisContainer:6379

# Remember our jumpbox has custom ssh port 2222$ ssh -A -t -l admin <JumpBox-Public-IP> -p 2222 \
-L 8000:localhost:6379 \
ssh -A -t -l admin <AppServer-Private-IP> \
-L 6379:localhost:6379

Now from our local machine port 8000, we can access to Redis service running in a docker container on a protected EC2 instance behind a firewall.

# Test redis connection$ redis-cli -p 8000

Extra: Routing web traffic over SSH Socks tunnel

We can also route any web traffic over SSH without VPN. Simply configuring ssh connection with binding port on our localhost. Don’t forget to change <user@remote-machine> with the actual username and remote machine.

$ ssh -D 5555 -C -q -N <user@remote-machine>

Test your socks proxy connection with curl request:

# without socks proxy
$ curl -v https://ipecho.net/plain
# with socks proxy
$ curl -v -x socks5://localhost:5555 https://ipecho.net/plain

Configure Socks proxy in Firefox > Options > Network Settings

Now any traffic in your browser will be routed over your remote machine.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Yagiz Cemberci

Yagiz Cemberci

Founder at Phenixio ⚡ Building tools for Bitcoin & Lightning Network 🚀 I write about software & bitcoin