Computers‎ > ‎Tools‎ > ‎

SSH Tunnel

How SSH Tunnel works

Browser / SSH client <== secure tunnel ==> SSH server <--->

> NOTE: ONLY the communication between SSH client and SSH server is encrypted.

SSH Client

OpenSSH CLI (ssh, sshd, ssh-add, ssh-agent, ssh-copy-id, ssh-keygen, ssh-keyscan, scp, sftp) for all platform.

Optional: PuTTY. Cygwin (mintty) for Windows - highly recommended.

Recommended Terminal Emulators
  • Linux
    GNOME Terminal, Konsole, Terminology, lx-terminal, guake (GNOME),
    Yakuake (KDE),  finalterm, alacritty etc...
  • macOS
    or OS X
  • Windows
    Cygwin (mintty), MobaXterm (good GUI for SSH TCP Forwarding)

How to establish SSH connection, secure tunnel and a SOCKS5 Proxy

ssh -g -qfnNT -D 1080 <SSH_SERVER>

Options explained:
  • -q Quiet mode.
  • -T Disable pseudo-terminal allocation.
  • -f Requests ssh to go to background just before command execution. This is useful if ssh is going to ask for passwords or passphrases, but the user wants it in the background.
  • -n Redirects stdin from /dev/null (actually, prevents reading from stdin). This MUST be used when ssh is running in the background.
  • -N Do not execute remote command
  • -D specifies a local "dynamic" application level port forwarding (DynamicForward in ssh_config)
  • -g Allows remote hosts to connect to local forwarded ports, share the SOCKS5 proxy across the network (GatewayPorts in ssh_config)
In addition on a slow connection you can gain performance by enabling compression with the -C option. In addition, putty-tools package provides plink which is very useful, here is a simple sample which shares the tunnel with all other hosts in the LAN.

NOTE: If you feel the options are too hard to remember, just use a simple version:
ssh -g -D 1080 <SSH_SERVER>

Alternative - plink (Provided by putty on Arch, Red Hat based distros, putty-tools on Debian based)

Linux/Mac OS X
plink -C -A -N user@ssh_host  -D

plink.exe -C -A -N user@ssh_host  -D

Options explained:
  • -C Enable SSH Compression
  • -A Enable agent forwarding
  • -N Don't start a remove command or shell at all
  • -D Dynamic port forwarding, same as -D for ssh
It is the same as ticking - Tunnels - Local ports accept connections from other hosts. Others in the same LAN will be able to share the ssh tunnel as well.

Note: -D means to bind all interfaces (most likely eth{0..n}) so that other hosts in the same network will be able to use the tunnel.

How to surf the Internet via the tunnel (SOCKS5 proxy)?

Firefox Proxy Selector
Multiproxy Swith add-on
Note: set network.proxy.socks_remote_dns to true, use remote socks5 proxy (SSH Host) to lookup DNS instead of local DNS. This is normally used to avoid GFW DNS pollution/spoofing in China mainland. If NOT in PRC, it protects your privacy;-)


Option 1: Proxy SwitchySharp or Proxy SwitchyOmega

Option 2: pass the parameter when launching chrome, create a launcher or shortcut

Linux in Terminal
google-chrome --proxy-server=socks5://localhost:port

Mac OS X (doesn't work as expected...)
/Application/Google\\ Chrome --proxy-server=socks5://host:port

Windows in Command Line Prompt
%userprofile%\AppData\Local\Google\Chrome\Application\chrome.exe --proxy-server=socks5://localhost:port
Otherwise, use Proxy Switchy! extension to switch proxy settings.
Recommended: Extension: Proxy Switchy!

Use SSH Port Forwarding (Tunnel) To Access Server Behind Firewall/NAT

SSH Client (Laptop) <======Internet======> EC2 instance / DigitalOcean droplet <====== Firewall ======> Linux Server (behind firewall)
  1. On the middle EC2 instance (Linux), set GatewayPorts yes in sshd_config (/etc/ssh/sshd_config), restart sshd (systemctl restart sshd.service).
    RTFM: man sshd_config
  2. Establish SSH connection from Linux Server (behind firewall) to the EC2 instance
    On the Linux Server behind firewall (reverse direction)
    ssh -R 22222:*:22 user@EC2_instance
  3. Block access to port 22222 on public facing network interfaces (elastic IP, this can be done by using security group, too, but at a different layer - Linux bridge + iptables in hypervisor dom0) by using iptables, e.g.
    iptables -A INPUT -p tcp -i <interface> --dport 22222  -j DROP
  4. On the laptop, establish SSH connection to the EC2 instance (optionally acts as SOCKS server using -D which does dynamic application level port forwarding)
    ssh -D 1080 user@EC2_instance
    NOTE: applications can use localhost:1080 as SOCKS5 proxy, communication between laptop and the EC2 instance is encrypted and secure.
  5. Then in the already established SSH session (on the EC2 instance), open a tmux session and connect to port 22222 binded to the loopback address
    ssh -p 22222 user_on_linux_server_behind_firewall@localhost
  6. If public key or host-based authentication is configured, you should be now into the Linux Server through the middle man ;-D
NOTE: In this case the SSH client (laptop) cannot directly access the Linux server (SSH port 22) behind firewall (no access to do port forwarding on the firewall/gateway), however, the Linux server can ssh to the EC2 instance (of course via NAT) in the reverse direction. That's why we use the -R option.

VPN (IPsec using strongSwan recommended) is always a better option, security MUST be hardened on the middleman if you really want to use this ;-D

Hardening OpenSSH