Sometimes companies' security policies dictate the use of "bastion hosts": Hosts that you have to "jump through" to get to the network behind the host - i.e. you cannot connect directly to a host "behind" the bastion host.
This does improve security a bit, but the most visible effect is usually to make life more difficult for people who regularly need to jump through the bastion host.
So you end up having to do things like:
you@laptop $ ssh -A bastion
...
you@bastion $ ssh real-destination
...
you@real-destination $ # Do whatever you came here to do
This is mildly annoying for interactive sessions. And it is a death knell to any automation needing to take the same route: Scripting this is not that trivial.
It is even worse if you want to copy a log file to examine locally (because the tools for analysing the file is not available on the remote network) - because then you have to copy it in two steps (and remember to clean up as you go):
you@laptop $ ssh -A bastion
you@bastion $ scp real-destination:/var/log/somelog.log ./
...
you@bastion $ exit
you@laptop $ scp bastion:./somelog.log ./
you@laptop $ ssh bastion rm ./somelog.log
you@laptop $ less somelog.log # examine the log file locally
(ok: Bad example, as "less" would generally be available, but the point is made)
The same applies if you want to upload a file to the real destination: This too has to be a two-step process.
This is a common enough scenario so SSH has support for using bastion hosts automatically. But you have to configure your SSH client accordingly to benefit from this.
If you were to add this to your $HOME/.ssh/config
:
# Requires OpenSSH version >= 7.3
Host real-destination
ProxyJump bastion
If you are running an older version of OpenSSH (e.g. if you are on a Mac or even Windows, in which case you have my sympathies), then hope is not lost:
# Requires OpenSSH version >= 5.4
Host real-destination
ProxyCommand ssh -W %h:%p bastion
Then the nightmare of getting a log file can be reduced to the much simpler and intuitive:
you@laptop $ scp real-destination:/var/log/somelog.log ./
you@laptop $ less somelog.log # examine the log file locally
In other words, you can interact with real-destination
just like any
other host. As if there was no bastion getting in the way. Things like
vanilla SSH also works:
you@laptop $ ssh real-destination
you@real-destination $ # do your stuff here
This does not bypass the security requirement of using the bastion host: The bastion host is being used exactly as designed. If your account is disabled on the bastion host, then you're stuck - just as you would have been before.
The only difference is that you no longer have to conciously interact with it. You can (in your mind) ignore it and concentrate your brain cycles on what you were actually trying to do instead. Possibly while snorting derisively and contemplating the fact that the nasty security guys failed to break your workflow and no longer cause any inconvenience to you :-)
Chaining Jumps
Using a bastion host like above is usually sufficient. But what if you need to jump through a series of bastion hosts to get to your destination?
SSH supports this too - you simply "chain" then together, using the same primitives as above.
Imagine we have a complicated scenario with multiple bastions, and that your user name varies between them:
-
Your laptop
-
outer-bastion
- your first bastion host - with the user name ofyou-outer
-
inner-bastion
- another bastion, only reachable fromouter-bastion
- with the user name ofyou-inner
-
destination
- the host you really want to get to. Only reachable frominner-bastion
. Here you use the user name ofyou-destination
This SSH config will helps with this:
Host destination
UserName you-destination
ProxyJump inner-bastion
Host inner-bastion
UserName you-inner
ProxyJump outer-bastion
Host outer-bastion
UserName you-outer
There are two tricks in play here:
-
Putting the "correct" user name in the configuration with the
UserName
directive. This means you do not have to remember your user names in different places - when you runssh outer-bastion
(without explicitly specifying a user name) it picks up the user name from the configuration.) Less things for you to remember. -
Chaining of the bastions: when you run
ssh destination
, the SSH configuration tells SSH to ProxyJump viainner-bastion
. So SSH goes recursive and does that. But how does it get toinner-bastion
? It has to go viaouter-bastion
first.
The end result is that you no longer need to clutter your brain with details about which-hoops-to-jump-through and and concentrate on your work:
you@laptop $ ssh destination
...
you@destination $ # do whatever you came to do
Enjoy!