> ## Content Index
> Fetch the complete content index at: https://snubmonkey.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# SSH Tunneling — Part 2: Remote Port Forwarding.
- URL: https://snubmonkey.com/ssh-tunneling-remote-port-forwarding/
- Published: 2026-09-09T00:04:39.000Z
- Updated: 2026-10-17T00:34:51.000Z
- Description: Learn how to route connections through an encrypted SSH tunnel using remote port forwarding (`-R`). Explore reverse tunnels, bind addresses, `GatewayPorts`, bastion hosts, connection management, troubleshooting, and security best practices.
- Author: SNUBmonkeyteam
- Tags: how to 🪄, ethical hacking 🤖, SSH 🕳, security 🦾🦿

In [Part 1](https://snubmonkey.com/ssh-tunneling-local-port-forwarding/#): **Local Port Forwarding**, we used SSH local port forwarding (`-L`) to access remote services from our local machine.

In this article, we'll **reverse the forwarding direction**.   
*How reverse SSH tunnels make local services accessible from remote systems*

**Remote port forwarding (`-R`)** creates a listening port on the remote SSH server and forwards incoming connections through the SSH tunnel to a destination reachable from the machine running the SSH client.

This technique, commonly called a **reverse SSH tunnel**, is useful when a local service needs to be accessed remotely but cannot accept direct inbound connections.

##   
  
1\. Understanding Remote Port Forwarding

SSH supports three primary forwarding modes:

- **Local forwarding (`-L`)**: Creates a listener on the local machine that forwards traffic to a remote-side destination.
- **Remote forwarding (`-R`)**: Creates a listener on the remote side that forwards traffic to a client-side destination.
- **Dynamic forwarding (`-D`)**: Creates a SOCKS proxy for dynamically routing TCP connections through SSH.

The main difference between `-L` and `-R` is **where the listening port is created**.

**Local forwarding (`-L`):**

```
Local Machine                  Remote Server

localhost:8080 ─── SSH ──────► localhost:3000
```

**Remote forwarding (`-R`):**

```
Remote Server                  Local Machine

localhost:8080 ─── SSH ──────► localhost:3000
```

The SSH connection still originates from the local machine and connects to the remote server. With `-R`, however, the listening port is created on the remote side.  

## 2\. The Basic SSH Command

The general syntax is:

```
$ ssh -N -R [REMOTE_BIND_ADDRESS:]REMOTE_PORT:DESTINATION_HOST:DESTINATION_PORT user@REMOTE_SERVER
```

For example, suppose a web application is running on your local machine at `localhost:2399`, and you want to access it through a remote server.

Create the reverse tunnel:

```
$ ssh -N -R 2393:localhost:2399 user@REMOTE_SERVER_IP
```

This command establishes an SSH connection to the remote server and requests a listener on port `2393`.

The traffic flows as follows:

```
Remote Server
127.0.0.1:2393
      │
      │ SSH tunnel
      ▼
Your Local Machine
127.0.0.1:2399
      │
      ▼
Web Application
```

A process on the remote server can now connect to `127.0.0.1:2393`, and SSH forwards the connection to port `2399` on your local machine.

### Understanding the options

- `-R`: Enables remote port forwarding.
- `-N`: Prevents execution of a remote command or opening of an interactive shell.
- `2393`: The listening port on the remote server.
- `localhost:2399`: The destination as seen from the machine running the SSH client.

**The key distinction:** the SSH connection travels from your machine to the remote server, but connections arriving at the remote listener are forwarded back through that existing connection.  

## 3\. Why Reverse SSH Tunneling Is Useful

Reverse tunneling is particularly useful when your machine cannot accept inbound connections because it is behind:

- Network Address Translation (NAT).
- A home router or corporate firewall.
- Carrier-Grade NAT (CGNAT).
- A restrictive network.

Normally, a remote server cannot directly connect to a service on your laptop.

However, if your laptop can establish an outbound SSH connection, it can create a reverse tunnel.

```
Your Laptop
     │
     │ Outbound SSH connection
     ▼
Remote Server
     │
     │ Connection to forwarded port
     ▼
SSH Tunnel
     │
     ▼
Your Laptop's Service
```

No direct inbound connection to your laptop is required.

Common use cases include remote development, temporary service access, testing web applications, and reaching services behind restrictive network boundaries.  

## 4\. Forwarding to Another Host

The destination does not have to be `localhost`. It can be another host reachable from the machine running the SSH client.

For example:

```
$ ssh -N -R 8080:10.10.20.50:80 user@REMOTE_SERVER
```

The remote server listens on port `8080`. Incoming connections travel through SSH to `10.10.20.50:80`, accessed from your local machine's network environment.

```
Remote Server
127.0.0.1:8080
      │
      │ SSH tunnel
      ▼
Your Local Machine
      │
      ▼
10.10.20.50:80
```

This is useful when your local machine can reach an internal service that the remote server cannot access directly.  

## 5\. Controlling Access to the Remote Port

By default, OpenSSH remote forwarding typically binds the listening port to the remote server's loopback interface.

For example:

```
$ ssh -N -R 8080:localhost:2399 user@REMOTE_SERVER
```

The listener is normally accessible through:

```
127.0.0.1:8080
```

This means processes running on the remote server can access the forwarded service, but other machines generally cannot connect directly to that port.

To specify loopback binding explicitly:

```
$ ssh -N -R 127.0.0.1:8080:localhost:2399 user@REMOTE_SERVER
```

This is the recommended default when the forwarded service only needs to be accessed locally on the remote server.  

## 6\. Understanding `GatewayPorts`

The SSH server's `GatewayPorts` setting controls whether remote forwarded ports can accept connections from other machines.

It is configured in:

```
/etc/ssh/sshd_config
```

The main options are:

### `GatewayPorts no`

This is the default in OpenSSH.

Remote forwarded ports are restricted to loopback addresses, making them accessible only from the remote server itself.

### `GatewayPorts yes`

Allows remote forwarded ports to bind to wildcard addresses, potentially making them accessible through the server's network interfaces.

For example:

```
0.0.0.0:8080
```

If the server is publicly reachable and its firewall permits access, the forwarded service may become accessible from the internet.

### `GatewayPorts clientspecified`

Allows the SSH client to request a specific remote listening address, subject to server configuration and available interfaces.

For example:

```
$ ssh -N -R 0.0.0.0:8080:localhost:2399 user@REMOTE_SERVER
```

This requests a listener on all remote IPv4 interfaces. It requires compatible server configuration, such as `GatewayPorts clientspecified`.

**Important:** changing `GatewayPorts` affects the exposure of forwarded services. Enable broader access only when necessary, and restrict it with appropriate firewall rules and SSH access controls.  

## 7\. Security Considerations

A reverse tunnel can provide convenient access to a private service, but it can also expose that service to unintended users.

For example:

```
Private Service
127.0.0.1:2399
      │
      │ SSH tunnel
      ▼
Remote Server
Port 8080
      │
      ▼
Potential external access
```

If the remote listener is bound to a public interface, anyone who can reach that port may be able to access the forwarded service.

Follow these practices:

- Bind remote forwards to `127.0.0.1` unless external access is required.
- Restrict SSH access to authorized users.
- Apply firewall rules to limit access to forwarded ports.
- Avoid exposing administrative interfaces or sensitive services.
- Audit persistent tunnels and their destinations.
- Protect SSH keys and use least privilege.
- Keep SSH clients, servers, and destination applications updated.

A reverse tunnel is a network access mechanism, not a substitute for application security.  

## 8\. Running a Reverse Tunnel in the Background

To run the tunnel without keeping an interactive terminal session open, use `-f`:

```
$ ssh -f -N \
$   -R 127.0.0.1:2393:localhost:2399 \
$   user@REMOTE_SERVER
```

The SSH process moves into the background after authentication.

The remote server can then access the local application through:

```
127.0.0.1:2393
```

To inspect listening ports on the remote Linux server:

```
$ ss -lntp
```

Depending on your permissions, process details may require elevated privileges.  

## 9\. Keeping Reverse Tunnels Alive

For long-running tunnels, SSH keepalives help detect unresponsive connections.

```
$ ssh -N \
$   -o ServerAliveInterval=30 \
$   -o ServerAliveCountMax=3 \
$   -R 127.0.0.1:2393:localhost:2399 \
$   user@REMOTE_SERVER
```

The options configure SSH to send keepalive messages every 30 seconds and terminate the connection after three consecutive unanswered messages.

Keepalives detect failures but do not automatically reconnect a terminated session.

For automatic recovery, use `autossh`:

```
$ autossh -M 0 -N \
$   -o ServerAliveInterval=30 \
$   -o ServerAliveCountMax=3 \
$   -R 127.0.0.1:2393:localhost:2399 \
$   user@REMOTE_SERVER
```

For production environments, consider managing persistent tunnels through a service manager such as `systemd`.  

## 10\. Troubleshooting

If a reverse tunnel fails, enable verbose SSH output:

```
$ ssh -vvv -N \
$   -R 127.0.0.1:2393:localhost:2399 \
$   user@REMOTE_SERVER
```

On the remote server, check whether the listening port exists:

```
$ ss -lntp
```

Test the forwarded endpoint from the remote server:

```
$ curl http://127.0.0.1:2393
```

If the connection fails, verify that the destination service is reachable from the machine running the SSH client:

```
$ curl http://127.0.0.1:2399
```

Common causes include:

- The local application is not running.
- The destination host or port is incorrect.
- The remote listening port is already occupied.
- The SSH server rejects remote forwarding.
- The requested bind address is not permitted.
- Firewall rules prevent access to the remote listener.

**Troubleshooting principle:** verify the remote listener, the SSH connection, the destination service, and any applicable network restrictions separately.  

## Quick Reference

**Basic reverse tunnel**

```
$ ssh -N -R 8080:localhost:3000 user@server
```

**Explicit loopback binding**

```
$ ssh -N -R 127.0.0.1:8080:localhost:3000 user@server
```

**Forward to another host reachable from your machine**

```
$ ssh -N -R 8080:10.10.20.50:80 user@server
```

**Background tunnel**

```
$ ssh -f -N -R 127.0.0.1:8080:localhost:3000 user@server
```

**Debugging**

```
$ ssh -vvv -N -R 127.0.0.1:8080:localhost:3000 user@server
```

##   
  
The Mental Model

Local and remote forwarding differ primarily in where the listener is created.

**Local forwarding (`-L`):**

```
Local Listener
      │
      ▼
Remote Destination
```

**Remote forwarding (`-R`):**

```
Remote Listener
      │
      ▼
Destination Reachable from the SSH Client
```

Remember:

- **`-L`: Listen locally, forward remotely.**
- **`-R`: Listen remotely, forward back through SSH.**

The SSH connection itself still originates from the client:

```
Local Machine ──────────► SSH Server
```

With remote forwarding, connections arriving at the remote listener travel back through that existing connection to the destination.

We hope this was helpful.  
**Keep learning. Keep exploring. Stay sharp.**

## What's Next?

In [Part 1](https://snubmonkey.com/ssh-tunneling-local-port-forwarding/), we explored local port forwarding (`-L`).   
In this article, we used remote port forwarding (`-R`) to make local services accessible through a remote SSH server without requiring direct inbound connectivity.

[Next](https://snubmonkey.com/ssh-tunneling-part-3-dynamic-port-forwarding-and-socks-proxies/), we'll move beyond fixed port mappings with **dynamic port forwarding (`-D`) and SOCKS proxies**, allowing applications to route TCP connections through an SSH server.