To reverse tunnel to a different local IP, you must configure the SSH client on the remote host to forward traffic through an intermediate gateway or directly to the target private address using the -R flag combined with the specific destination port and IP. This setup allows external services to reach internal resources that are not directly exposed to the public internet, bypassing standard NAT limitations by leveraging an outbound SSH connection.
Understanding Reverse Tunnel Architecture
When you establish a reverse tunnel, the direction of data flow is opposite to a standard forward tunnel. In a typical scenario, a client connects to a server. In a reverse tunnel, the client (often behind a firewall or NAT) initiates an outbound connection to a publicly accessible server, known as the jump host or gateway. The client then instructs the SSH daemon on the gateway to listen on a specific port and forward any incoming connections back through the encrypted channel to a target machine on the client's local network. This architecture is particularly useful for devices like Raspberry Pi units running motion detection software or OpenVPN clients that need to be accessed from outside the home network. Without this configuration, the internal IP addresses of these devices remain hidden behind the router's network address translation. By creating a reverse tunnel, you effectively punch a hole in the NAT, allowing controlled access to specific services without opening wide ports on your firewall. The core mechanism relies on the SSH protocol's ability to create dynamic port forwarding. When the SSH session is established, the remote side binds to a socket. Any traffic sent to that socket is encapsulated within the SSH stream, decrypted at the client end, and routed to the specified local IP and port. This ensures that the communication remains secure and authenticated, unlike direct TCP connections which might be blocked by restrictive firewalls.Configuring the SSH Command
The primary tool for establishing this connection is thessh command-line utility. You need to specify the reverse mapping using the -R option. The syntax generally follows the pattern: -R [bind_address:]port:host:hostport. Here, bind_address determines where the gateway listens. If you omit it, it defaults to localhost, meaning only the gateway itself can connect. To allow other hosts to connect to the tunnel, you may need to set bind_address to 0.0.0.0, though this requires server-side configuration changes as noted later.
For example, if you want to expose a local VNC service running on 192.168.1.50 at port 5900 via the gateway on port 5901, the command would look like this:
ssh -R 5901:192.168.1.50:5900 user@gateway-ip
In this command, user@gateway-ip represents the credentials and address of the public server. Once connected, anyone connecting to gateway-ip:5901 will have their traffic forwarded to 192.168.1.50:5900. It is crucial to verify that the target IP is reachable from the machine initiating the SSH session. If the target is on a different subnet within the same local network, ensure routing is configured correctly.
You can also use the -N flag to indicate that no remote command should be executed, and -f to put SSH in the background after authentication. This is ideal for daemons or persistent services. Combining these flags creates a robust background process:
ssh -f -N -R 5901:192.168.1.50:5900 user@gateway-ip
This approach minimizes resource usage on the client side while maintaining the tunnel. However, keep in mind that if the network connection drops, the tunnel will close, and you will need to reconnect. For production environments, consider using tools like autossh to automatically restart the tunnel upon failure.
Server-Side Configuration Requirements
By default, most SSH servers do not allow clients to bind to arbitrary ports on the gateway, especially those below 1024 or those intended for binding to all interfaces. You must modify thesshd_config file on the public gateway to permit these actions. Specifically, you need to adjust the GatewayPorts directive. Setting GatewayPorts yes allows remote ports to bind to non-loopback addresses, enabling external clients to connect to the forwarded port.
If you leave GatewayPorts set to no (the default), the tunnel will only listen on localhost on the gateway. This means you can only access the service by logging into the gateway itself and connecting locally. While more secure, this limits the utility of the reverse tunnel for remote access scenarios. After changing this setting, restart the SSH service on the gateway to apply the changes.
Additionally, ensure that the firewall on the gateway allows inbound traffic on the chosen forwarding port. For instance, if you are forwarding port 5901, you must open this port in the gateway's firewall rules. Tools like ufw on Linux or Windows Firewall can be used to permit this traffic. Without proper firewall configuration, even a correctly established tunnel will fail because the packets will be dropped before reaching the SSH daemon.
It is also advisable to restrict which users can create reverse tunnels. Using Match blocks in sshd_config allows you to apply specific settings to certain users or groups. This enhances security by limiting the attack surface. For example, you can allow only trusted users to bind to high ports while restricting others.
For more complex networking scenarios involving multiple hops or specific routing needs, refer to our guide on Routing Traffic Coming to OpenVPN Access Server to the VPN Not Working to understand how traffic flows through virtual interfaces.
Troubleshooting Common Issues
One of the most frequent issues is the "Connection Refused" error when trying to access the forwarded port. This usually indicates that either the SSH service on the gateway is not listening on the correct interface or the firewall is blocking the port. Check the gateway's active ports usingnetstat -tlnp or ss -tlnp to confirm that the port is bound to 0.0.0.0 if GatewayPorts is enabled.
Another common problem arises when the target local IP is unreachable. Ensure that the machine initiating the SSH tunnel has network connectivity to the target IP. You can test this by pinging the target IP from the client machine. If the ping fails, the issue lies within the local network configuration, not the SSH tunnel itself.
Sometimes, the tunnel works initially but disconnects after a period of inactivity. This is often due to NAT timeout settings on the router or intermediary networks. SSH keepalive messages can prevent this. Add ServerAliveInterval 60 and ServerAliveCountMax 3 to your SSH client configuration or command line to send periodic heartbeats. This keeps the NAT table entry alive and prevents silent disconnections.
If you are dealing with UDP traffic, such as for VoIP or gaming, standard SSH TCP tunnels will not work directly. You may need to encapsulate UDP within TCP or use specialized tools. See our article on Is it possible to OpenVPN connection UDP through SSH tunnel? for details on handling non-TCP protocols over SSH.
Finally, always verify that the services you are exposing are secured. A reverse tunnel provides access, but it does not encrypt application-layer data unless the service itself uses TLS or similar protocols. Ensure that passwords are strong and that unnecessary services are not exposed to the public internet.
Frequently Asked Questions
Can I use a reverse tunnel to access my home router's admin panel?
Yes, you can forward the router's administrative port (usually 80 or 443) to a public port on your gateway. However, this exposes sensitive configuration interfaces to the internet, which is a significant security risk. It is highly recommended to use a VPN instead for administrative access to avoid brute-force attacks and credential theft.What happens if my home internet connection resets?
The SSH tunnel will terminate immediately because the underlying TCP connection is lost. The client machine will attempt to reconnect if the SSH process is still running, but if the process crashes or the network interface goes down, you will need to manually restart the tunnel. Using a wrapper script orsystemd service can automate this recovery process.
Is it safe to set GatewayPorts to yes on my public server?
SettingGatewayPorts to yes allows anyone who knows the public IP and port to connect to your tunnel. This reduces security by removing the localhost restriction. A safer alternative is to use GatewayPorts clientspecified in newer OpenSSH versions, which allows you to specify exactly which IP addresses can bind to the remote port, offering finer control.
How do I monitor the status of my reverse tunnel?
You can check the status by looking at the SSH process on both the client and server sides. On the client, useps aux | grep ssh to see if the process is running. On the server, use ss -tlnp to verify that the forwarded port is still listening. Logging output from the SSH command to a file can also help track disconnection events and reconnection attempts.
Can I tunnel multiple services with one SSH connection?
Absolutely. You can add multiple-R flags to a single SSH command to forward several ports simultaneously. For example, you can forward VNC on one port and a web server on another within the same tunnel. This reduces overhead and simplifies management compared to maintaining multiple separate SSH sessions for each service.