多地点双层NAT后Ubuntu服务器的SSH远程访问方案咨询
Absolutely, this is totally achievable—and it’s exactly how tools like TeamViewer work behind the scenes. Since both your remote Ubuntu servers and central hub are trapped behind NAT (including carrier-grade and internal NAT), direct connections aren’t possible, but reverse tunneling with a relay server will solve this problem. Let’s break down practical, actionable solutions tailored to your SSH access needs.
TeamViewer relies on two core tricks to get around NAT restrictions:
- Reverse Connections: Devices behind NAT can’t receive incoming connections, but they can initiate outgoing ones. Your remote servers will start and maintain a persistent connection to a publicly accessible relay server.
- Relay Routing: When your central hub wants to access a remote server, it connects to the same relay, which then routes traffic between the hub and the remote server through the pre-established reverse tunnel.
Option 1: FRP (Open-Source, Self-Hosted, Stable)
FRP is my go-to for this use case—it’s lightweight, customizable, and built specifically for reverse tunneling. You’ll need a small VPS with a public IP to act as your relay server.
Step 1: Set Up the FRP Server (Relay)
- Download the latest FRP release for your relay’s architecture (example for AMD64):
wget https://github.com/fatedier/frp/releases/download/v0.52.1/frp_0.52.1_linux_amd64.tar.gz tar -zxvf frp_0.52.1_linux_amd64.tar.gz cd frp_0.52.1_linux_amd64 - Edit the server config (
frps.ini) to secure and configure the service:[common] bind_port = 7000 # Port for FRP client-server communication token = your_secure_unique_token # Add a token to block unauthorized clients - Start the FRP server, and set it to run on boot with systemd for reliability:
./frps -c ./frps.ini
Step 2: Set Up FRP Clients (Remote Ubuntu Servers)
- Repeat the download/unzip steps on each remote server.
- Edit the client config (
frpc.ini) to connect to your relay:[common] server_addr = your_relay_public_ip server_port = 7000 token = your_secure_unique_token # Match the server's token [ssh] type = tcp local_ip = 127.0.0.1 local_port = 22 # Local SSH port on the remote server remote_port = 6000 # Relay port mapped to this server's SSH (use unique ports for multiple servers) - Start the FRP client, and configure systemd to auto-start it on boot:
./frpc -c ./frpc.ini
Step 3: Access from Your Central Hub
To SSH into a remote server directly:
ssh -p 6000 your_remote_server_username@your_relay_public_ip
For SSH tunnels (e.g., to access a local service on the remote server), add the tunnel flags like usual:
ssh -L 8080:localhost:80 -p 6000 your_remote_server_username@your_relay_public_ip
Option 2: Ngrok (Quick Testing, Free Tier)
If you need a temporary solution without setting up your own relay, Ngrok works out of the box. The free tier is great for testing, but has limitations (random ports, bandwidth caps).
- On your remote Ubuntu server, install Ngrok and run this command to expose the SSH port:
ngrok tcp 22 - Ngrok will output a public address (e.g.,
tcp://0.tcp.ngrok.io:12345). From your central hub, connect using:ssh your_remote_server_username@0.tcp.ngrok.io -p 12345
Option 3: Pure SSH Reverse Tunneling (No Extra Tools)
You can achieve this using only SSH, no third-party software. The downside is you’ll need autossh to keep the tunnel alive if it drops unexpectedly.
Step 1: Prepare the Relay Server
Edit /etc/ssh/sshd_config to allow gateway ports (required for reverse tunneling):
GatewayPorts yes
Restart the SSH service to apply changes:
sudo systemctl restart sshd
Step 2: Establish Persistent Reverse Tunnel from Remote Server
First install autossh on the remote server:
sudo apt install autossh
Then create the persistent tunnel:
autossh -M 50000 -fN -R 6000:127.0.0.1:22 your_relay_username@your_relay_public_ip
-M 50000: A monitoring port to check tunnel health and restart it if it drops-fN: Run in the background without executing a remote command-R 6000:127.0.0.1:22: Maps relay port 6000 to the remote server’s local SSH port 22
Step 3: Access from Central Hub
Connect to the remote server via the relay:
ssh your_remote_server_username@your_relay_public_ip -p 6000
- Firewall Rules: Make sure your relay server’s firewall allows incoming traffic on the ports you’re using (e.g., 7000, 6000 for FRP, 22 for SSH).
- Security: Always use SSH key authentication instead of passwords, and add unique tokens/credentials to your tunneling configs to prevent unauthorized access.
- Multiple Servers: For multiple remote servers, just use unique
remote_portvalues in FRP or SSH tunnel configs (e.g., 6000 for Server A, 6001 for Server B).
内容的提问来源于stack exchange,提问作者Sagar Khatiwada

