The quick, bad and dirty way to automate SSH jump connections.

As you probably know on many setups the hosts are not directly accessible but there is an SSH gateway on the between (also known as…

As you probably know on many setups the hosts are not directly accessible but there is an SSH gateway on the between (also known as bastion server) which has security enhancements and is configured to allow / disallow access based on IP filtering.

The manual way

to connect to a host over an SSH gateway is to use the -J parameter that defines the gateway$ ssh -J user@ssh-gateway-server user@server1

But this is unproductive because you will need to write a lot of things each time you want to connect to a host, like usernames, the gateway ip addresses etc.

The good and correct way

to do this is to create entries on the ssh_config file like this!### The SSH Gateway host
Host ssh-gw1
 HostName ssh-gw1
 User username### Host accessible over SSH Gateway
Host server1
 HostName server1
 ProxyJump ssh-gw1
 User username

But this way has a managerial problem, needs initial configuration and needs maintenance to stay up to date, this is ok on a small scale environment or for an an organization that has a dedicated team to maintain this, but it can backfire and have access problems which can led to more serious problems hard to track in case of emergency.

The quick and dirty way

You can avoid any configuration and use some “shell script magic”, the only configuration you need to apply is the list of the SSH gateway servers and the script will check if the server that you want to connect is accessible with one of the SSH gateways, if it is it will establish the connection, you can also pass any parameters that you normally would pass to an SSH command.

Parameters:

  • host_username: the username that will used to connect to the remote server
  • gw_username: the username that will used to connect to the SSH gateway
  • use_ssh_pass: if “true” will read the ssh password from file in ~/pass (very bad practice)
  • gw: this list is the SSH gateway list of server#!/bin/bashif [ "$1" = "" ]; then
       exit
    fi# Username, addapt this to match your needs
    declare -a host_username="username"# Gateway username
    declare -a gw_username="username"# Enable or Disable sshpass
    declare -a use_ssh_pass="true"# SSH Gateways
    declare -a gw=("gw1" "gw2" "gw3" "gw4")for gateway in "${gw[@]}"
    do
       if [ "$use_ssh_pass" == "true" ]; then
           SSH_RESULT=$(sshpass -f ~/pass ssh -J $gw_username"@"$gateway $host_username"@"$1 'echo OK' 2>&1)
           SSH_CAN_CONNECT=$(echo $SSH_RESULT | tr -s " " | rev | cut -d " " -f1 | rev)if [ "$SSH_CAN_CONNECT" == "OK" ]; then
               sshpass -f ~/pass ssh -J $gw_username"@"$gateway $host_username"@"$1 ${@:2}
               exit
           fi
       else
           SSH_RESULT=$(ssh -J $gw_username"@"$gateway $host_username"@"$1 'echo OK' 2>&1)
           SSH_CAN_CONNECT=$(echo $SSH_RESULT | tr -s " " | rev | cut -d " " -f1 | rev)if [ "$SSH_CAN_CONNECT" == "OK" ]; then
               ssh -J $gw_username"@"$gateway $host_username"@"$1 ${@:2}
               exit
           fi
       fidone

How to install the script

Execution rights are needed for this script, also its good to be placed to a PATH directory.$ chmod +x <script_name>
$ cp script_name /usr/bin

How to use the script

You can use it like the normal ssh command, but there will be significant slower because it will try in sequence to connect with an SSH gateway, but after connection this will work like normal SSH$ <script_name> ssh_host

You can even pass commands like usual ssh$ <script_name> ssh_host ls
file1.txt
file2.txt

I really hope that you will not need such an ugly hack, but in real life often we need a compromise of best practices and effectiveness.

Join Medium with my referral link - Konstantinos Patronas
As a Medium member, a portion of your membership fee goes to writers you read, and you get full access to every story…