Accessing Remote Devices Without a Public IP — Tunneling, Reverse Proxy, and CGNAT Solutions
How to reach IoT devices, servers, and equipment behind NAT or CGNAT without a public IP address — using reverse tunnels, VPN, and cloud relay services.
The Problem: No Public IP
Many IoT devices, home servers, and remote equipment sit behind Network Address Translation (NAT) or Carrier-Grade NAT (CGNAT). Without a public IP address, incoming connections from the internet cannot reach the device directly.
Common Scenarios
- ISP uses CGNAT — your router gets a private IP (like 100.64.x.x)
- Device is behind multiple NAT layers (double NAT)
- Corporate firewall blocks all inbound connections
- 4G/LTE modem with no public IP option
- Remote railway/industrial equipment on private networks
Why Not Just Get a Public IP?
- Many ISPs no longer offer public IPs (IPv4 exhaustion)
- Static public IPs are expensive or unavailable
- Security risk — public IP exposes the device to internet scanning
- Not always possible on cellular (4G/LTE) connections
Solutions Overview
| Solution | Complexity | Cost | Latency | Best For | |----------|-----------|------|---------|----------| | Reverse SSH Tunnel | Low | Free | Low | Quick access to 1-2 services | | Cloudflare Tunnel | Low | Free tier | Low | Web services, HTTP/HTTPS | | WireGuard VPN (via relay) | Medium | VPS cost ($5/mo) | Low | Full network access | | Tailscale / ZeroTier | Low | Free tier | Low | Multi-device mesh network | | FRP (Fast Reverse Proxy) | Medium | VPS cost | Low | Multiple services, TCP/UDP | | MQTT-based access | Low | Free (broker) | Medium | IoT command & control |
Solution 1: Reverse SSH Tunnel
The simplest approach — the device initiates an outbound SSH connection to a server with a public IP, creating a reverse tunnel:
[Remote Device] ──SSH──→ [Public VPS] ←──SSH──── [Your PC]
(No public IP) (Has public IP)
The device opens a tunnel from inside → out
You connect to the VPS, traffic flows back through the tunnel
Setup
# On the remote device (no public IP):
ssh -R 8022:localhost:22 -R 8080:localhost:80 user@your-vps.com -N -f
# This maps:
# VPS:8022 → Remote device:22 (SSH)
# VPS:8080 → Remote device:80 (Web interface)
# On your PC, connect through the VPS:
ssh -p 8022 user@your-vps.com # SSH to remote device
curl http://your-vps.com:8080 # Access remote web interfaceMaking It Persistent with autossh
# Install autossh
sudo apt install autossh
# Create a systemd service
sudo cat > /etc/systemd/system/reverse-tunnel.service << 'EOF'
[Unit]
Description=Reverse SSH Tunnel
After=network-online.target
Wants=network-online.target
[Service]
User=tunnel
ExecStart=/usr/bin/autossh -M 0 -N -o "ServerAliveInterval 30" \
-o "ServerAliveCountMax 3" -o "ExitOnForwardFailure yes" \
-R 8022:localhost:22 user@your-vps.com
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now reverse-tunnelSolution 2: Cloudflare Tunnel
Cloudflare Tunnel (formerly Argo Tunnel) creates an encrypted tunnel from your device to Cloudflare's network, exposing local services via a domain name:
[Remote Device] ──→ [Cloudflare Edge] ──→ [Your Browser]
cloudflared HTTPS tunnel device.yourdomain.com
Setup
# Install cloudflared
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o cloudflared
chmod +x cloudflared
# Authenticate
./cloudflared tunnel login
# Create tunnel
./cloudflared tunnel create my-device
# Configure (config.yml)
tunnel: <tunnel-id>
credentials-file: /root/.cloudflared/<tunnel-id>.json
ingress:
- hostname: device.yourdomain.com
service: http://localhost:80
- hostname: ssh.yourdomain.com
service: ssh://localhost:22
- service: http_status:404
# Run
./cloudflared tunnel run my-deviceBenefits: Free, encrypted, no VPS needed, access control via Cloudflare Zero Trust.
Solution 3: WireGuard VPN via Relay Server
Set up a WireGuard VPN server on a cheap VPS. All devices connect to it, forming a private network:
[Remote Device 1] ──WG──→ [VPS WireGuard Server] ←──WG── [Your PC]
[Remote Device 2] ──WG──→ (10.0.0.1) ←──WG── [Phone]
All devices on 10.0.0.0/24
VPS Configuration
# /etc/wireguard/wg0.conf (VPS - Server)
[Interface]
PrivateKey = <server-private-key>
Address = 10.0.0.1/24
ListenPort = 51820
# Remote Device 1
[Peer]
PublicKey = <device1-public-key>
AllowedIPs = 10.0.0.2/32
# Your PC
[Peer]
PublicKey = <pc-public-key>
AllowedIPs = 10.0.0.3/32Remote Device Configuration
# /etc/wireguard/wg0.conf (Remote Device)
[Interface]
PrivateKey = <device-private-key>
Address = 10.0.0.2/24
[Peer]
PublicKey = <server-public-key>
Endpoint = your-vps.com:51820
AllowedIPs = 10.0.0.0/24
PersistentKeepalive = 25 # Keeps NAT mapping aliveNow you can SSH to 10.0.0.2 from your PC (10.0.0.3) — both connected through the VPS relay.
Solution 4: Tailscale / ZeroTier (Zero-Config Mesh VPN)
The easiest option for non-experts. Tailscale creates a peer-to-peer mesh VPN using WireGuard under the hood:
# Install on every device
curl -fsSL https://tailscale.com/install.sh | sh
# Authenticate
sudo tailscale up
# That's it! Devices can reach each other by Tailscale IP or hostname
ssh user@remote-device # Uses Tailscale's 100.x.x.x addressesFeatures:
- NAT traversal handled automatically (STUN/DERP relay)
- No VPS required (peer-to-peer when possible)
- Access control via admin console
- MagicDNS for hostname resolution
- Free for personal use (up to 100 devices)
Solution 5: FRP (Fast Reverse Proxy)
Open-source reverse proxy for exposing multiple services:
# On VPS (frps - server)
# frps.toml
bindPort = 7000
auth.token = "your-secret-token"
# On remote device (frpc - client)
# frpc.toml
serverAddr = "your-vps.com"
serverPort = 7000
auth.token = "your-secret-token"
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6022
[[proxies]]
name = "web"
type = "http"
localPort = 80
customDomains = ["device.yourdomain.com"]Solution 6: MQTT-Based Remote Access (IoT)
For IoT devices that only need command-and-control (not full network access):
[IoT Device] ──MQTT──→ [MQTT Broker (cloud)] ←──MQTT── [Your Dashboard]
subscribe: device/commands publish: device/commands
publish: device/telemetry subscribe: device/telemetry
The device and your dashboard both connect outbound to the MQTT broker. No inbound connections needed. This is ideal for:
- Sending commands to remote sensors/actuators
- Collecting telemetry data
- Over-the-air firmware updates
- Configuration changes
Security Best Practices
Regardless of which solution you use:
- Always encrypt — Never expose services over unencrypted tunnels
- Authentication — Use SSH keys, not passwords; enable MFA where possible
- Limit exposure — Only forward the ports you need
- Firewall — Restrict tunnel server access to known IPs where possible
- Monitor — Log all tunnel connections and review regularly
- Update — Keep tunnel software and remote device OS updated
Comparison: Which Should You Use?
| Need | Best Solution | |------|---------------| | Quick SSH access to one device | Reverse SSH tunnel | | Expose web service with domain | Cloudflare Tunnel | | Full network access to multiple devices | WireGuard VPN or Tailscale | | Non-technical users | Tailscale (easiest) | | Multiple TCP/UDP services | FRP | | IoT telemetry and commands | MQTT | | Enterprise/zero-trust | Cloudflare Zero Trust |
Conclusion
Not having a public IP is no longer a blocker for remote device access. From simple SSH tunnels to zero-trust solutions like Cloudflare Tunnel and Tailscale, there are options for every use case and skill level. Choose based on your security requirements, number of devices, and the type of access you need.
Related: L2 VPN Guide and Network Monitoring Best Practices.