Mon 02 January 2023 in ssh by Regalis
Last update: Sat 11 February 2023
Configuring the SSH client
This part of the SSH series will cover the configuration of the OpenSSH client.
Configuration sources
The ssh
client obtains configuration data from the following sources (in the
following order):
- command-line options,
- user's configuration file (
~/.ssh/config
), - global, system-wide configuration file (
/etc/ssh/ssh_config
).
The client will use the first obtained value for each parameter. Configured
options will be used not only by the ssh
itself, but by a lot of other tools
as well. That is, among others: scp
, sftp
, sshfs
, git
, ansible
and
any other tool which uses the OpenSSH
library/suite.
Format of the configuration files
The configuration file contains key-value pairs, one per line.
The ssh_config(5)
manual page reference the keys as keywords and
values as arguments. The keywords are case-insensitive, arguments are
case-sensitive.
There are two special keywords which restricts all the following declarations
to be used only when the specified conditions are satisfied. These are a Host
and a Match
keywords. Any declarations following these keywords will be
applied up to the next Host
or Match
keyword or until the end of file.
Here is a small example:
1 2 3 4 5 |
|
Assuming the user placed a content in the ~/.ssh/config
file, it is now
possible to use ssh
like this:
1 |
|
Instead of:
1 |
|
Commonly used options
Here is a list of some commonly used options:
- ConnectionAttempts - specifies the number of tries to make before exiting (default is 1),
- ConnectTimeout - specifies the connection timeout in seconds,
- DynamicForward - specifies that a TCP port on the local machine be forwarded over the secure channel (application level port forwarding - SOCKS4 and SOCKS5 proxy),
- ExitOnForwardFailure - specifies whether a SSH client should terminate the connection if it cannot set up all requested port forwardings (any of dynamic, tunnel, local or remote),
- GSSAPIAuthentication - specifies whether user authentication based on GSSAPI is allowed (default is no),
- Hostname - specifies the real host name to log into. This option,
together with the
Host
orMatch
keywords can be used to create aliases for remote hosts, for examplemy-jump-host
andmy-jump-host-with-proxy
, - IdentitiesOnly - specifies that ssh should only use the configured authentication identity and certificate files (ssh keys),
- IdentityFile - specifies a file from which the user's identity is read (in most cases this may refer to a user's RSA private key),
- LocalCommand - specifies a command to execute on the local machine after the SSH client successfully connects to the server. The command will be executed with the local user's shell,
- LocalForward, RemoteForward - specifies that a TCP port on the local/remote machine be forwarded over the secure channel to the specified host and port from the local/remote machine,
- ProxyJump - specifies one or more jump hosts (multiple proxies may be separated with comma characters),
- ServerAliveInterval - sets a timeout interval in seconds after which if no data has been received from the server, the ssh client will send a message to request a response from the server. The default is 0 (disabled),
- User - specifies the user to log in as,
For a complete list of supported options - please consult the ssh_config(5)
manual page.
Examples
I have prepared the few real life examples illustrating commonly used SSH scenarios. I will start with basic examples and continue extending them with more use cases.
Using different logins/usernames for different groups of servers
Let's say we have multiple groups of servers (for example production
,
staging
and testing
) and we use our personal username (for example
mkowalski
) for production
and staging
servers, and the test
username
for the group of servers in testing
environment. We can prepare the following
configuration file:
1 2 3 4 5 |
|
Now we can use the SSH client without bothering with the username:
1 2 |
|
Configuring jump hosts
We can use a configuration file to enable smooth, transparent use of jump
hosts. Let's say our production
and staging
group of servers needs to be
accessed through the jump.regalis.tech
host, and the testing
group of
servers through the dc01.regalis.tech
host. What's more, both jump hosts
accepts only the public key authentication. We can extend our configuration
file like this:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Now you can use the SSH just like before but the SSH client will
automatically use the appropriate jump host, for example you can copy a local
file to the srv01.prod.regalis.tech
by simply using scp
like this:
1 |
|
In the example above, the ssh client will first make a SSH connection to the configuration-specified jump host and then establish a TCP forwarding to the target host from there.
Please note: this operation does not require to start a shell on the jump host, what we need is just a secure port forwarding.
The user must authenticate to both the jump host and the target host. Depending on the authentication methods - this may result in several separate password prompts.
Using aliases
Sometimes it is easier to refer to a host by a short alias rather then by a
long FQDN or IP address. The SSH provides this functionality, we can use this
by combining a Host
keyword with a Hostname
option:
1 2 3 4 5 6 |
|
Now you can simply use the following commands:
1 2 3 |
|
The -J bastion
option will use bastion
(defined in the configuration file)
as a jump host while connecting to the web01.infra.example.com
.
SSH hosts autocompletion
GNU Bash has a powerful hosts autocompletion feature (available in most
GNU/Linux distributions as a separate package, usually called
bash-completion
) which covers not only already visited hosts (from the
known hosts files) but also user-defined aliases.
Configuring local dynamic application-level port forwarding (SOCKS proxy)
It is very common that some of the network services are available only from
the specified locations (for example from the jump host or from a specified
server inside the testing environment). What is more, the user may want to
contact these kind of services using a HTTP(S) client - curl
or what is
sometimes more important - a full featured web browser like Firefox.
Well, this is exactly the case for the local dynamic application-level port forwarding feature of SSH.
Given the following infrastructure, let's consider the user on the local
station want to access HTTP servers on the 10.0.0.2
, 10.0.0.3
and the
app.fakedomain.com
from the local web browser:
It this scenario, we need to configure the SSH to connect to the
webapp.testing.regalis.tech
via the jump host dc01.regalis.tech
and act as
a SOCKS proxy server. Again, we don't need to execute any command on both
the jump host and the target host.
All user connections made via the proxy server will be
forwarded through the secure channel (provided by the SSH connections) and
handled on the remote end (in our case on the webapp.testing.regalis.tech
).
The user may use the following command to accomplish this task:
1 |
|
However in real world scenarios, it will be inconvinient to provide separate usernames and port numbers for each connection. That is why we can extend our configuration file and make it similar to this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Please note the CanonicalizeHostname option - this is required when we need to force SSH to re-read the configuration file and apply additional configuration options for the real hostname provided with the Hostname option.
The SessionType option has been set to none to prevent the execution of a remote command (the ssh client will not start an interactive shell).
The ExitOnForwardFailure option will cause the SSH to terminate the connection if it cannot set up the requested dynamic port forwarding.
Now we can simply use the following command:
1 |
|
The SOCKS proxy will be available at localhost:9999
, we can use it like this:
1 2 3 |
|
Note about hostnames resolution
Please note that the hostname resolution will be performed on the remote
end, so a local station is not required to be able to resolve
app.fakedomain.com
.
You can even start a dedicated web browser that will make all connections through the proxy:
1 |
|
More information about the port forwardings will be available in the dedicated article from the series about Secure Shell Protocol.
Debugging configuration
You can execute the SSH client with the -v
flag to see what
options are beeing used:
1 2 3 4 5 |
|
Temporarily disabling the configuration file
You can use -F
option to specify an alternative configuration file, if set to
none
- no configuration files will be read.
1 2 3 |
|