There are two types of SSH tunnel: backward tunnel and forward tunnel
A backward tunnel connection can be initialized with
-R flag in a
From PC client, run
ssh -R \*:2222:firewalled:2200 server.
Note: firewalled is looked up from client. Hence, if firewalled is
localhost, it will become the client itself.
From now, any access (send/receive) to server:2222 from anywhere, is equivalent to access to firewalled:2200 from client. This is extremely useful if firewalled is closed from public and only accessible from the client machine.
More interestingly, the firewalled can be
localhost, then, with this tunnel connection, you can connect to any port of the client machine without access permission to the NAT router. For example, I can expose SSH connection from any machine which has internet connection, or be able to reach the server machine.
Full real-life example
autossh -o "ServerAliveInterval 30" -o "ServerAliveCountMax 100" -R \*:2222:localhost:22 -fNT transang.me
autossh: same command interface as
ssh, except that
autosshautomatically restarts the
sshcommand if terminated.
autosshneeds to manually be installed (
sudo apt install autossh). This command can be replaced with
o "ServerAliveInterval 30": for each 30 seconds, send a ping package to server in order to prevent the ssh connection from being terminated due to inactivity.
-o "ServerAliveCountMax 100": number of server alive messages sent when the server does not response, before terminating the connection.
-R: reverse tunnel
localhost: the firewalled, this can be
localhostor replaced with IP address of any machine in the same LAN network of the client PC (i.e. the PC where this command is executed)
transang.me: the center machine (the server machine), which should be public and must be reachable from the client machine. This machine is latter used to connect to the
localhost( firewalled) machine specified above.
-C: compress data
-q: quite mode, no warning
-N: open SSH connection with no command to be executed
-f: run background
-T: do not allocate a TTY-terminal, save a tiny amount of memory.
Use the tunnel
After running the above command, access to the server (i.e.
transang.me server). From the server PC command line, run
ssh username_at_firewalled@localhost -p 2222.
localhost here refers to the server machine itself, and its meaning is different from the
localhost ( firewalled)
Direct access to firewalled
By default, Ubuntu blocks forwarding packing if you access directly to server:2222. Unless config following configuration, you have to login to the server, and access to localhost:2200. Edit
/etc/ssh/sshd_config, append following content
Match User root GatewayPorts yes AllowTcpForwarding yes
sudo systemctl restart sshd.
Disable firewall at port 2222/TCP with
ufw allow 2222/tcp && ufw reload.
For example, with the above real-life example, now you can do
ssh firstname.lastname@example.org -p 2222 -l username_at_server.
The mechanism is mostly same as backward tunnel
In backward tunnel, the ssh tunnel command runs in client and target to server. In forward tunnel, the tunnel command runs in the server and target to the client.
ssh -L \*:2222:firewalled:2200 client
This command is useful when server is the unique machine is allowed to access to the client and its local network.
You can create a script containing those above commands, execute the script whenever the
client PC startups to enable these tunnel connections forever.
Refer to this blog post to know how to create a startup script.