SSH tunnels in Ubuntu
TLDR;
There are two types of SSH tunnels:
- Reverse tunnel = remote port forwarding:
ssh -R [int:]dport:uhost:uport server
. - Forward tunnel = local port forward:
ssh -L [int:]dport:uhost:uport server
.
Where:
int:dport
: listening/downstream interface:port that will be occupied (at remote or local), needed to be available.uhost:uport
: The (upstream) host:port that will be used to forward requests.
Usually, -NT
flags are used with these commands.
-N
: do not execute command, do port forwarding only.-T
: do not allocate pseudo-terminal.
How to remember and interpret these commands:
- Rule 1: group them by
int:dport
anduhost:uport
. - Rule 2: For
-R
emote, a remote (server's) port is opened, for-L
ocal, a local port is opened, for listening. The specified port must be available. - Rule 3: because
int
erface value is optional. The port that comes with it must be the port to be occupied. Based on this rule, we know thatdport
is the port to be occupied for request listening. - Rule 4: the rest is the destination for request forwarding. When opening port at remote server,
uhost:uport
is relative to local, and vice versa.
Examples
GatewayPorts config
From sshd_config reference:
GatewayPorts
Specifies whether remote hosts are allowed to connect to ports forwarded for the client. By default, sshd(8) binds remote port forwardings to the loopback address. This prevents other remote hosts from connecting to forwarded ports. GatewayPorts can be used to specify that sshd should allow remote port forwardings to bind to non-loopback addresses, thus allowing other hosts to connect. The argument may be ''no'' to force remote port forwardings to be available to the local host only, ''yes'' to force remote port forwardings to bind to the wildcard address, or ''clientspecified'' to allow the client to select the address to which the forwarding is bound. The default is ''no''.
In sshd_config, there are 3 values of GatewayPorts config
- (default)
"no"
: always force to loopback interface. "yes"
: always force to wildcard interface."clientspecified"
: up to client, i.e., theint
option in the previous section of this post.
To allow the access from other host, such as from a different machine or from a docker container host, you must change the default GatewayPorts option in /etc/ssh/sshd_config
and restart the sshd server with systemctl restart sshd
.
To start the tunnel in background
autossh -o "ServerAliveInterval 30" -o "ServerAliveCountMax 100" -R \*:2222:localhost:22 -fNT transang.me
To start the tunnel when startup, refer to this post.
Command explanation:
autossh
: same command interface asssh
, except thatautossh
automatically restarts thessh
command if terminated.autossh
needs to manually be installed (sudo apt install autossh
). This command can be replaced withssh
.o "ServerAliveInterval 30"
: for every 30 seconds, send a ping package to the server in order to prevent the ssh connection from being terminated due to inactivity.-o "ServerAliveCountMax 100"
: the number of server alive messages sent when the server does not respond, before terminating the connection.-R
: reverse tunnellocalhost
: the firewalled, this can belocalhost
or 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 later used to connect to thelocalhost
( firewalled) machine specified above.-C
: compress data-q
: quiet 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.
(Optional) SSH to forwarded server
By default, the ssh server disallows forwarding, which means you cannot ssh to the forwarded server by ssh(ing) directly to the forwarded port from another client machine.
To explicitly allow it, edit /etc/ssh/sshd_config
, append following content
Match User root
GatewayPorts yes
AllowTcpForwarding yes
Restart sshd
via sudo systemctl restart sshd
.
Also, remember to open the forwarding port with, for example, port 2222, with ufw allow 2222/tcp && ufw reload
.
To ssh to the forwarded machine by directly ssh(ing) to from another client machine:ssh my_username_at_firewalled@transang.me -p 2222 -l username_at_server
.