Last years, with modern IaC tools, ssh command and protocol feel less important. More tasks are done by crafting disposable software stacks in docker images, and by setting centralised observability solutions. And ssh acts as a «last resort» manual tool.
But software is still running on the servers, and we need access to those servers sometimes. Additionally, physical resource configuration still needs to be managed, and ssh is a standard way to do this.
Using ssh is easy. Public key authentication imposes some additional learning. After you'll get used to it, ssh becomes some transparent routine.
ssh allows you to customise configuration with a set of Host and Match rules in the config file. When the host alias matches one of those rules, the following configuration options apply to the connection. Some ssh configuration options can be used with percent interpolated variables, such as %h for user-requested host alias.
For DevOps, it's important to provide a uniform way to connect to lookalike services and I have struggled to find that way for some time. Host and Match rules help, but at scale, even for 5 hosts, you'll need a little more flexibility. You can add something to the host alias for connecting FQDN HostName, but you cannot modify anything within the host alias. And for this ProxyCommand can be used to call arbitrary shell script and further modify connection options whatever you like.
Little more than one year ago Apple shipped macOS Ventura which doesn't allow SSH connections to hosts with RSA keys. In fact, RSA keys are fine (for now) as long as they are rsa-sha2-256 or rsa-sha2-512 type and at least 2048 bits long. To be on the safe side and not to be mistaken by RSA abbreviation, it is better to use any elliptic curve algorithm (ED25519 better than ECDSA). Pretty funny that almost a decade ago in OpenSSH 7.0 DSA keys were considered unsafe and RSA is recommended, but now RSA is unsafe and EC DSA (which is Elliptic Curve DSA) is a possible replacement.
I don't want to configure every such host with legacy sshd. Some results from Google searches even recommend turning on RSA for all hosts which is probably not secure anymore.
What do we need to do? Just to add some options for specific hosts and make it visible that connections have reduced security.
How I'm doing this? Snippet from my ~/.ssh/config:
Host *+legacy *+legacy+* *+rsa *+rsa+*
KexAlgorithms +diffie-hellman-group1-sha1
HostkeyAlgorithms +ssh-rsa
PubkeyAcceptedKeyTypes +ssh-rsa
ProxyCommand nc $(HN="%h"; echo "${HN%%%%+*}") %p
ssh config snipped above allows me to connect any host with reduced security when I explicitly ask for this like this with a specific host suffix — +rsa:
$ ssh router-chaos-calmer+rsa
Shell expansion in ProxyCommand removes +rsa tail from the host alias and applies options to enable RSA for this particular connection.
https://stackoverflow.com/questions/33444349/ssh-config-substitutions
Azure VMs don't have support for ecdsa or ed25519 key types, Microsoft recommends…
To work around this issue, use other SSH keys for the VM, such as RSA
…which are deprecated from OpenSSH 8.8. Shame! Workaround:
I'm using ssh for many hosts. It is a known problem when you're trying to connect to the new host, but you can't — even with a proper password. One of the reasons can be that the preferred authentication method is the public key, host allows you 5 tries to authenticate, your ssh client tries ~/.ssh/id_{rsa,ecdsa,ed25519}, and a few keys from your ssh-agent. And you have no more authentication tries, you cannot enter the password because the host has already closed your SSH connection.
Usually solutions include one of three ssh options:
IdentitiesOnly yes— stops sendingid_*keys along with disabling of ssh-agent's usage; only keys explicitly defined in config or provided via-iswitch will be used.IdentityAgent none— only disables ssh-agent.PreferredAuthentications passwordorPubkeyAuthentication no— use only passwords and do not use public key authentication at all.
Third option with additional suffix:
Host *+password *+password+*
PubkeyAuthentication no
PreferredAuthentications password
ProxyCommand nc $(HN="%h"; echo "${HN%%%%+*}") %p
Usage example:
$ ssh 192.168.1.42+password
This suffix trick also works for combined suffixes:
$ ssh 192.168.1.42+rsa+password
Sometimes your hotel blocks everything, except web browsing. Worse, if your home provider blocks port 22 and doesn't like incoming VPN connections.
In such, situations I'm using some preconfigured TLS server with HTTPS and SSH service multiplexing. I'll describe a server configuration in the next article, stay tuned!
Host *+tls *+tls+*
ProxyCommand openssl s_client -verify_quiet -quiet -alpn 'ssh2' -servername $(HN="%h"; echo "${HN%%%%+*}") -connect $(HN="%h"; echo "${HN%%%%+*}"):443
Now with +tls suffix, it's possible to connect to my home network from a hotel room using overly restricted hotel WiFi.
When combining all the snippets above into ~/.ssh/config please note:
ssh_config(5):
# For each parameter, the first obtained value will be used
+rsa and +password suffixes above using ProxyCommand to cut suffix from the host alias and make reachable HostName. If you ever need to use +tls suffix with another suffix, +tls suffix section in the config file should be above +rsa or +password. It is because ProxyCommand for +tls not only replaces host alias suffix but also creates a TLS channel to your host.
For some hosts, you'll need to provide additional configuration, such as a key to connect. Usually, it looks like an additional Host or Match section with the host alias or template. Modify the Host declaration to allow the use of suffixes:
# Before
Host server
IdentityFile ~/.ssh/server
…
# After
Host server server+*
IdentityFile ~/.ssh/server
…
Host aliases in Host section match either of space-separated values. So, for example above, it's server or server+<something>. The Match section is a little trickier because every rule in that section should be truthful.