2019/03/26

Automating SSH tunnels

I need a persistent port forwarding configuration between two systems, where there may be more than one SSH jump between the two.  I want systemd to make sure it's running all the time.

A solution:
    # Systemd unit file for an SSH Tunnel service
    #
    [Service]
    Type=simple

    User=tunnel
    ExecStart=/usr/bin/ssh -F /home/tunnel/ssh-config-for-tunnel -vN tunnel.%i

    # On failure, wait 10 seconds to restart
    Restart=always
    RestartSec=10

    # 20 failures within a 10 minute window marks this service as failed.
    StartLimitInterval=600
    StartLimitBurst=20

    [Unit]
    Description="SSH Tunnel to %i"
    Requires=network-online.target

    [Install]
    WantedBy=multi-user.target
From here, I create a trusted keypair with
ssh-keygen -t ed25519
and configure the ssh-config-for-tunnel file:
# Configuration of the SSH tunnel from here to there
# Requirements:
#   This file in /home/tunnel/ssh-config-for-tunnel

#   Service /etc/systemd/system/ssh-tunnel@.service enabled and started
#
#   Additional tunnels can be enabled as ssh-tunnel@elsewhere.service

# Special defaults for tunnels
Host *
    ControlMaster no
    ExitOnForwardFailure yes
    IdentitiesOnly yes

#####################################################################
# Configure Tunnel:
#####################################################################
Host tunnel.myservice
    ### Connection:
    # Private IP of ultimate destination
    HostName 172.31.92.114
    # Identity on the CB master
    IdentityFile ~/.ssh/id_master
    # Public IP of Jump 1 bastion
    ProxyJump 192.168.100.142

    ### Tunnels:
    # Take near port :18443 and send it to master's listener
    LocalForward 8444 localhost:8443
    # Take far port :6100 and bring it back to local listener
    RemoteForward 6100 161.134.130.247:6100

# Jump configurations
Host 192.168.100.142
    # Configuration for the bastion system
    IdentityFile ~/.ssh/id_ed25519
    ProxyJump 10.192.107.33

Host 10.192.107.33
    IdentityFile ~/.ssh/id_ed25519

This example connects from localhost to 10.192.107.33, then from there to 192.168.100.142, then from there to 172.31.92.114, the server that I need the tunnel to, and it sets up port forwarding from end to end, without trying to get the ports on the series of jump servers.