Skip to content

Instantly share code, notes, and snippets.

@txoof
Last active December 28, 2023 06:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save txoof/d09c464258fcd8463c557541bab6a5d5 to your computer and use it in GitHub Desktop.
Save txoof/d09c464258fcd8463c557541bab6a5d5 to your computer and use it in GitHub Desktop.
Tunnel ssh connections through firewalls

SSH Tunnels

Situation: Local Network Firewall blocks outgoing connections to remote hosts on port 22

In this situation it is not possible to connect to remote hosts (e.g. github.com) for managing repos over ssh. A tunnel through a remote host (tunnel.myhost.com) can remedy this. An ssh configuration file can be added to the ~/.ssh/config directory to specify a specific command for connecting github.com. See also How to setup SSH Tunneling

Setup

  1. create a tunnel host that accepts incomming connections:
    • tunnel.myhost.com
  2. install nc
    • apt install nc
  3. create a tunnel user on remote host:
    • tunnel@tunnel.myhost.com
  4. create an ssh key and add public remote keys on tunnel.myhost.com
    • [tunnel]$ ssh-keygen
  5. add appropriate public keys to tunnel user
    • ~/.ssh/authorized_hosts
  6. on local host add the following configuration to ~/.ssh/config
Host github.com
  ProxyCommand ssh -q -p 5223 tunnel@tunnel.myhost.com nc %h %p
  1. use git as normal git git@github.com:bar/foo.git

Situation: Network prevents connections to other devices on local network

The network prevents opening an SSH connection to another device on the same physical network. Local Device A (LA) cannot connect to Local Device B (LB). The solution is to use an intermediary Remote Host C (RC) that supports SSH tunnels. From LA, create a remote tunnel into RC; from LB SSH to RC and then connect back to LA through the LA<==>RC tunnel.

The solution to this problem is to create a long-standing auto-renewing SSH tunnel using autossh. Autossh will monitor the ssh connection and reestblish it as needed from a system daemon.

Local Device A (LA)

This device will be accessible via SSH. I use this for headless Raspberry Pis that are deployed in environments that do not allow direct local connections.

  1. Generate ssh keypairs if they do not alreay exist
    • ssh-keygen
  2. Install autossh on LA
  3. Test autossh by making an outgoing connection to RC
    • autossh -M 5112 -N -R 50505:localhost:22 user@remotehost.foo -p 22
    • -M xxxx Sets the monitoring port; autossh monitors the status of the tunnel on this port. Choose any port outside of the reserved range (>1024)
    • -N Do not execute a remote command; this is for setting up port forwards
    • -R yyyyy:localhost:zz setup the remote port forward; yyyyy (anything outside of the reserved range) is the outgoing port and zz (typically 22 for SSH) is the incoming port on RC.
    • user@remotehost.foo standard ssh user@host
    • -p zzzz incoming port to use on remote host; this is only necessary if RC does not accept SSH connections on port 22.
  4. Connect to RC and add public key to the authorized_hosts file
  5. Configure the autosshd daemon using a unit file in /etc/systemd/system/autossh-tunnel.service (see below)
    • Update the ExecStart portion to match your configuration
  6. Enable the daemon with sudo systemctl enable autossh-tunnel.service
  7. Reload the daemon units with sudo systemctl daemon-reload, then (re)start the daemon with sudo systemctl restart autossh-tunnel.service

autossh-tunnel.service unit file

[Unit]
Description=AutoSSH tunnel service to remote.foo on port 443 (remote 50505)
Wants=network-online.target
After=network-online.target

[Service]
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 5122 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -N -R 50505:localhost:22 user@remote.foo -p 443
User=your_local_user
Group=your_local_user
Restart=always

[Install]
WantedBy=multi-user.target

Remote Host C (RC)

  1. Ensure that SSH is setup and configured

Local Device B (LB)

This is typically the device you are using (e.g. a Laptop) that will establish the ssh connection to LA via RC.

  1. Connect to RC using ssh
    • ssh user@remote.foo
  2. Establish a connection to LA through the SSH tunnel
    • ssh LA_user@localhost -p 50505
    • the ssh connection will be sent over localhost tunnel on port 50505. This match the port settings in the Local Device A setup.
  3. Work on remote machine as expected

Tips

  • View all active tunnels:
    • sudo ss -ltp |grep sshd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment