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
# 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 :-)
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:
outer-bastion- your first bastion host - with the user name of
inner-bastion- another bastion, only reachable from
outer-bastion- with the user name of
destination- the host you really want to get to. Only reachable from
inner-bastion. Here you use the user name of
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
UserNamedirective. This means you do not have to remember your user names in different places - when you run
ssh 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 via
inner-bastion. So SSH goes recursive and does that. But how does it get to
inner-bastion? It has to go via
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