How to Set Up Persistent Reverse SSH Tunneling for HTTP Access Behind NAT


6 views

When dealing with IoT devices like Raspberry Pi that frequently change networks, traditional port forwarding becomes impractical. The device needs to maintain a persistent connection that survives network transitions while remaining secure.

The most reliable approach is establishing a reverse SSH tunnel with these characteristics:

# On the Raspberry Pi (client side)
autossh -M 0 -N -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" \
-R 8080:localhost:80 -i ~/.ssh/tunnel_key user@rpi.example.com

On your public server (rpi.example.com), configure SSH to handle persistent connections:

# /etc/ssh/sshd_config
ClientAliveInterval 60
TCPKeepAlive yes
GatewayPorts clientspecified

Create a systemd service on the Raspberry Pi for automatic reconnection:

# /etc/systemd/system/ssh-tunnel.service
[Unit]
Description=AutoSSH tunnel service
After=network.target

[Service]
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 0 -N -o "ExitOnForwardFailure=yes" \
-o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" \
-R *:8080:localhost:80 -i /home/pi/.ssh/tunnel_key user@rpi.example.com
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target

While reverse SSH works well, consider these alternatives for specific cases:

  • Cloudflare Tunnels: Better for web services with HTTPS requirements
  • ngrok: Ideal for temporary development tunnels
  • WireGuard VPN: More efficient for high-bandwidth applications

Key problems and solutions:

# Check tunnel status
ssh -T user@rpi.example.com "netstat -tulpn | grep 8080"

# Debug connection issues
autossh -v -M 0 -N -R 8080:localhost:80 user@rpi.example.com

Essential security measures:

# On the public server, restrict SSH access
# /etc/ssh/sshd_config
AllowUsers tunnel_user
PasswordAuthentication no
PermitTunnel yes

When your Raspberry Pi (or any Linux device) frequently changes networks and sits behind NAT/firewalls, accessing its HTTP server becomes challenging. The device's dynamic IP address and network restrictions make traditional port forwarding unreliable.

Reverse tunneling creates a persistent pathway from your public server (rpi.example.com) back to your local device. Unlike regular SSH tunneling where the client initiates the connection to access remote resources, here the resource provider (your Pi) initiates the connection to the public server.

# Basic reverse tunnel command to run on your Pi:
ssh -N -R 8080:localhost:80 user@rpi.example.com

1. Public Server Configuration

On rpi.example.com, ensure these SSH settings in /etc/ssh/sshd_config:

GatewayPorts yes
ClientAliveInterval 60
ClientAliveCountMax 3

Then restart SSH: sudo systemctl restart sshd

2. Local Device Setup

Create an autostart script on your Pi (/etc/systemd/system/reverse-tunnel.service):

[Unit]
Description=Reverse SSH Tunnel
After=network.target

[Service]
ExecStart=/usr/bin/ssh -NT -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes \
-R *:8080:localhost:80 -i /home/pi/.ssh/tunnel_key user@rpi.example.com
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Enable with:

sudo systemctl daemon-reload
sudo systemctl enable reverse-tunnel
sudo systemctl start reverse-tunnel

3. HTTP Forwarding

On rpi.example.com, configure Nginx to forward requests:

server {
    listen 80;
    server_name rpi.example.com;

    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Connection Stability

For unreliable networks, consider these ssh options:

-o TCPKeepAlive=yes \
-o ServerAliveInterval=15 \
-o ServerAliveCountMax=3 \

Security Enhancements

1. Use SSH keys with passphrase protection
2. Restrict port binding to specific interfaces
3. Implement fail2ban on both ends

While reverse SSH works well, other approaches exist:

  • Cloudflare Tunnels (formerly Argo)
  • Ngrok/Tailscale
  • WireGuard VPN with static IP

The SSH method remains advantageous for its simplicity, no additional dependencies, and compatibility with existing infrastructure.