SSH tunneling as a VPN alternative

Image for post
Image for post

It’s not uncommon that VPN connection to our client’s boxes either breaks mid testing or is blocked by some firewall or IDS. SSH tunneling can be used as a back up connection to already existing VPN connection or as a decent lightweight alternative.

Things we’ll need:

  1. AWS instance for pivoting
  2. Target box on the network we are ̶h̶a̶c̶k̶i̶n̶g̶ testing.

First, we need to set up the AWS instance to use as the initial jump box:

  1. Open port 8080 in the security rules
  2. Create new user: adduser revconnect (or whatever user name) and give the user sudo privileges: usermod -aG sudo revconnect
  3. sudo su revconnect
  4. Run ssh-keygen for that user. I’d recommend using non default name for the key to avoid conflicts.
  5. Make sure there is an authorized_keys file in revconnect/.ssh with your keys in it.
  6. Enable GatewayPorts: in /etc/ssh/sshd_configset GatewayPortsto yes

Next, create the script to be executed on the client’s box. The script will be password protected and served to the client at the end. All the client would need to do is to curl the script and pipe it to bash. Lets go:

  1. Create ~/www/
  2. In order to build the script we first need to set up a couple variables:

Get base64 of the public key:

PUBLIC_KEY_B64="$(cat /home/revconnect/.ssh/ | base64 -w 0)"

echo "PUBLIC_KEY_B64='${PUBLIC_KEY_B64}'"

Encrypt the keys:

cat /home/revconnect/.ssh/your_key | openssl enc -aes-256-cbc -in — -out your_key.enc

Get base64 of that:

B64_KEY="$(cat your_key.enc | base64 -w 0)";

echo "ENCRYPTED_KEY_B64='${B64_KEY}'"

Add the variables to the script:

#!/bin/bashset -e;

You could totally do without encryption, but we are all about security here😏.

Next, check if .ssh folder exists and create it, if it doesn’t: cont'd...if [[ ! -d $HOME/.ssh ]]; then
mkdir $HOME/.ssh;

We then grab the encrypted key we created, decode it on the other end, and change permissions to 400 to protect it against accidental overwriting. cont'd...echo “$ENCRYPTED_KEY_B64” | base64 -d > ${KEY_PATH}.enc;
openssl enc -aes-256-cbc -d -in ${KEY_PATH}.enc -out $KEY_PATH;
chmod 400 $KEY_PATH;
sleep 1s;

add it to the authorized_keys file cont'd...
echo “$PUBLIC_KEY_B64” | base64 -d >> $HOME/.ssh/authorized_keys

Next, we want to set up tunnel as systemd service. Inspiration for this part is taken from this gist I found: cont'd...SYSTEMD_FILE=$(cat << EOF
Description=Setup a secure tunnel
ExecStart=/usr/bin/ssh -i $KEY_PATH -NT -o StrictHostKeyChecking=no -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -R ${AWS_USER}@${AWS_IP}

Lastly, we reload the daemon and start the tunnel: cont'd...echo “$SYSTEMD_FILE” | sudo tee ‘/etc/systemd/system/sshtunnel@.service’;
sudo systemctl daemon-reload;
sudo systemctl enable sshtunnel@$REV_PORT;
sudo systemctl start sshtunnel@$REV_PORT;

Cool, the script is done. Lets password protect the file:

cat /home/revconnect/.ssh/your_key | openssl enc-aes-256-cbc -in — -outyour_key.enc

and serve the script to the client: cd ~/www && python3 -m http.server 8080

Now we can ask our client to run the script, or you run it on the target box if you have access to it: curl “http://aws_ip:8080/” | bash

The script will prompt to enter the password you created for

Once the client (or you) ran the script and the tunnel is created, you can ssh into the AWS instance, then run ssh -p 2222 root@localhost

Done! If you get permission denied error, your keys probably don’t match. Try to use the same key consistently on your local machine, AWS instance and the target box.

Good luck!

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