adam.nz aboutpostsprojectscontact

SSH Tricks by Adam Shand

Using Multiple Jump Hosts

Sometimes you need to jump through multiple hosts to get somewhere.  You can do this using the  ProxyJump command in your ~/.ssh/config:

Host machine1 machine2 machine3
  ProxyJump head

You can do a double hop through two hosts if needed, like this:

Host machine1 machine2 machine3
  ProxyJump head,jump

Or match everything in a domain like this:

Match host "*.example.com" 
  ProxyJump head,jump

You can even do it depending on your current IP address:

Match host "*.example.com" !exec "ifconfig | grep -q ' 172.16.1.40 '"
  ProxyJump head,jump.example.com

Using ssh-copy-id with Jump Hosts

You can pass any ssh option to ssh-copy-id with the -o option. By using the ProxyJump option, you can use ssh-copy-id to copy your key to a host via jump host.

Here's an example where I copy my ssh key to leia.spack.org via the jump host jump.spack.org:

# ssh-copy-id -o ProxyJump=jump.spack.org leia.spack.org
adam@leia.spack.org's password:

Number of key(s) added:        1

And then test it with:

# ssh -J jump.spack.org leia.spack.org
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-42-generic x86_64)

Mitigating SSH Brute Force Attacks

Setup a server with an open SSH port, and you'll soon notice a steady stream of attempted logins as attackers try and brute force their way in. The actual risk is low so long as your users have good passwords, but it makes a mess in the logs.

Reading Debian Administration I came across this idea for using iptables to restrict how frequently an IP can try and connect via SSH to your server.

Here is a very simple script which only allows a single IP address to SSH to your server 5 times every 60 seconds. Any IP address or subnet listed in TRUSTED_HOSTS will be able to connect as many times as it wants.

#!/bin/bash
# Requires the ipt_recent kernel modules

TRUSTED_HOSTS="127.0.0.1 192.168.4.192/26"

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j SSH_WHITELIST
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 5 --rttl --name SSH -j ULOG --ulog-prefix SSH_brute_force
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 5 --rttl --name SSH -j DROP

for host in $TRUSTED_HOSTS; do
    iptables -A SSH_WHITELIST -s $host -m recent --remove --name SSH -j ACCEPT
done

If you need to connect more frequently, you can either whitelist your IP address or using the connection sharing feature in modern versions of OpenSSH.

Connection Sharing

Versions of OpenSSH greater than 4.0 have a new feature which allows you to reuse a single SSH connection for all subsequent connections to that same host. This has two primary advantages

  • New connections open nearly instantaneously after the first one. This is because all subsequent connections are using an already authenticated channel.
  • Since all your SSH connections appear as a single TCP session, you can work around any restrictions at the destination which limits the frequency of connections.

It's easy to implement, add these lines to your ~/.ssh/config, check the ssh man page for details:

Host *
    ControlMaster auto
    ControlPath ~/.ssh/sockets/%r@%h:%p

Update (8 Apr 08): I've been using this for a while now and the only downside I've found is that Subversion, using the svn+ssh protocol, doesn't clean up properly after itself and leaves a stale socket file behind when it closes the connection. There are two ways around this, make a normal ssh connection into the server before using Subversion (so Subversion is using the socket but isn't the master), or delete the socket and retry. The error looks like this:

overkill(shand)$ svn ci -m ""
Control socket connect(/Users/shand/.ssh/adam@joe.spack.org:22):

0 comments

Copyheart 1994–2024 Adam Shand. Sharing is an act of love.