How to Setup SSH Tunneling?
If you are connecting with a different Linux device on a different network then you would have to expose it to the public internet and that may put your system and files at risk.
SSH Tunneling or SSH port forwarding is useful for transporting data via internet services that use an unencrypted protocol, such as VNC or FTP, bypassing firewalls, or accessing geo-restricted content. Any TCP port and all traffic can be tunneled over a secure SSH connection.
SSH forwarding is primarily of three types,
- Local forwarding: Forwards from client to SSH server, to the destination port.
- Remote forwarding: Forwards from server to client port, and then on to destination port.
- Dynamic forwarding: Creates a SOCKS proxy server allowing communication over multiple ports.
SSH Local Port Forwarding
Local forwarding is when we forward a port from the client (i.e. local machine) to the server (i.e. remote machine) and then forward it to the destination.
The client checks for connections on a given port, and when it receives a connection request, it will tunnel the request onto a port on the server. The server then connects to a different destination machine on the specified port.
It is mainly used to connect a remote service on an internal network domain to a machine from the outside like a database. It is also used for remote file share over the internet and through jump servers.
Let's say for example that you are restricted by a firewall to access an application running on a remote network on port 4000. Now, we will forward a local port (i.e. 8000), for local access.
For local forwarding, the ssh
command is used with the -L
flag, and the command is of the format:
ssh -L [LOCAL_IP:]LOCAL_PORT:DESTINATION:DESTINATION_PORT [USER@]SSH_SERVER
[LOCAL_IP:]
LOCAL_PORT
: IP, and port number of the client. Only ports greater than 1024 can be used.
DESTINATION:
DESTINATION_PORT
: IP, and port number of the destination.
[USER@]SSH_
SERVER
: Username, and server address or IP.
To run this command in the background, we use the -f
flag.
Hence, for the example above, we get
ssh -L 8000:server1.example.com:4000 admin@server.example.com
Now we can access server1.example.com:3000
, using localhost:8000
, in the browser.
Remote Forwarding
Remote forwarding is the opposite of local forwarding. Instead of tunneling a client port, to the server, and on to the destination, we tunnel a server port, to a client, which is forwarded on to the destination.
By default, remote forwarding is disabled in SSH. To enable it, we need to enable it in our SSH config file (sshd_config, for server configs).
Open the SSH config file using your editor.
sudo vim /etc/ssh/sshd_config
Search for GatewayPorts and set it as yes.
GatewayPorts yes
Save the changes, and restart your server.
sudo systemctl restart sshd
Once remote forwarding is enabled, we use the -R
flag, and the command is of the following format.
ssh -R [REMOTE:]REMOTE_PORT:DESTINATION:DESTINATION_PORT [USER@]SERVER
[REMOTE:]REMOTE_PORT
: Remote IP, and port number.
DESTINATION:DESTINATION_PORT
: Destination IP, and port number.
[USER@]SSH_SERVER
: Username, and server address or IP.
For example,
ssh 8080:127.0.0.1:3000 admin@server.example.com
Remote port forwarding is used when someone from outside is to be given access to an internal service.
Dynamic Port Forwarding
Local and Remote forwarding allows communication and tunneling only in one direction, but dynamic forwarding can tunnel over multiple ports.
It creates a socket on the local machine that works as a SOCKS proxy server, and by default listens on port 1080. When a server connects to this port, it is forwarded to the remote machine, then to the dynamic machine on a dynamic port.
SOCKS is an internet protocol, defining how a client connects to a server via proxy (SSH in this case). To enable dynamic port forwarding we use the -D
flag. The command for dynamic port forwarding is of the following format.
ssh -D [LOCAL_IP:]LOCAL_PORT [USER@]SSH_SERVER
[LOCAL_IP:]LOCAL_PORT
: Local IP address, and port number.
[USER@]SSH_SERVER
: Username, and remote IP, or name.
For example, to connect to remote host, by starting a proxy on port 1080, we run
ssh -D 1080 admin@server.example.com
To tunnel an ssh session over the SOCKS proxy on localhost and port 9699
ssh -o "proxyCommand netcat -x 127.0.0.1:9699 -X 4 %h %p" admin@server.example.com
Conclusion
SSH tunneling is used to encrypt and secure a connection, and share data securely, or to access geo-restricted content via proxy.