What You'll Build and Why It Matters
You'll establish a secure tunnel from your Raspberry Pi to an AWS EC2 cloud server, giving you persistent access to your device from anywhere on the planet. This solution works behind even the most restrictive NAT configurations and requires zero router configuration.
NAT Traversal Made Simple
Works behind any router without port forwarding. Your Raspberry Pi initiates the connection outbound—no exposed ports in your home network.
Rock-Solid Reliability
Automatic reconnection on network hiccups. The systemd service monitors your tunnel and brings it back up within 10 seconds of any disruption.
Security by Design
ED25519 keys for all connections. Dedicated unprivileged tunnel user on EC2 for proper isolation. Defense in depth from the ground up.
Multiple Access Patterns
Three connection methods: two-hop manual, direct via ProxyCommand, and streamlined SSH config. Pick what fits your workflow.
Understanding Reverse SSH
Traditional SSH requires your server (Raspberry Pi) to be directly accessible from the internet. But home routers block inbound connections, and port forwarding creates security vulnerabilities you'd rather avoid.
Reverse SSH flips the script: your Raspberry Pi establishes an outbound connection to a public EC2 server and keeps that tunnel alive. The server forwards port 2222 back to your device's port 22. You connect to the server, then hop through the tunnel to your Pi.
The Core Principle
Your Raspberry Pi initiates an outbound connection (which NAT happily allows) and holds it open. EC2 listens on port 2222 and tunnels traffic back through that persistent connection. Elegant and effective.
Solution Architecture
Your Computer
Anywhere worldwide
EC2 Bridge
100.64.0.0:2222
Raspberry Pi
Behind home router
System Components
AWS EC2 Instance
Your public-facing bridge server in the cloud. Always reachable via static IP.
- IP Address: 100.64.0.0
- Operating System: Ubuntu Server 22.04 LTS
- Instance Type: t2.micro (Free Tier eligible)
Raspberry Pi 5
Your home device that initiates and maintains the tunnel connection.
- Username: a528fe2
- Local Network Address: raspberrypi.local
- SSH Port: 22 (standard)
SSH Tunnel
Encrypted channel between Raspberry Pi and EC2, managed by systemd service.
- EC2 Port: 2222 (forwards to RPI:22)
- Type: Remote Port Forwarding (-R flag)
- Auto-start: systemd unit reverse-tunnel.service
Requirements and Preparation
Pre-flight Checklist
- •AWS account with EC2 access and ability to create Security Groups
- •Raspberry Pi with OS installed (Raspberry Pi OS, Ubuntu) and local SSH access
- •Basic SSH knowledge and terminal comfort (Linux/macOS/WSL on Windows)
- •Text editor familiarity (vim or nano for config editing)
Port Reference Guide
Port | Purpose | Where Open |
---|---|---|
22 | Standard SSH port for direct server access | EC2 (restricted via Security Group) |
2222 | Tunnel port for Raspberry Pi access | EC2 (open to 0.0.0.0/0) |
22 | SSH server on Raspberry Pi | Raspberry Pi (accessible only via tunnel) |
Step 1: Setting Up Your EC2 Instance
1.1 Launching the Instance
- Open the AWS Console and navigate to EC2
- Click Launch Instance
- Name it:
rpi-tunnel-server
- Choose AMI: Ubuntu Server 22.04 LTS (HVM), SSD Volume Type
- Instance type: t2.micro (perfect for Free Tier)
- Key pair: create a new one named
rpi-tunnel-key
Critical: Guard that private key
The rpi-tunnel-key.pem
file will download automatically. Without it, you're locked out of your EC2 instance. Store it somewhere safe and secure.
1.2 Security Group Configuration
Create a Security Group with these inbound rules:
Type | Port | Source | Purpose |
---|---|---|---|
SSH | 22 | My IP | Your direct server access |
Custom TCP | 2222 | 0.0.0.0/0 | Tunnel access from anywhere |
1.3 Securing Your Key Locally
On your local machine (Linux/macOS or WSL):
1# Move the key to your SSH directory
2mv ~/Downloads/rpi-tunnel-key.pem ~/.ssh/
3
4# Set restrictive permissions (SSH demands this)
5chmod 400 ~/.ssh/rpi-tunnel-key.pem
Quick Reference: chmod 400
Permissions 400
mean: owner can read, nobody else can do anything. SSH refuses to use keys with loose permissions—it's picky about security, which is good.
1.4 First Connection Test
Once your instance launches, AWS assigns it a public IP. In our example, that's 100.64.0.0
:
1ssh -i ~/.ssh/rpi-tunnel-key.pem ubuntu@100.64.0.0
On first connection, SSH will ask you to verify the fingerprint—type yes
.
Step 2: Configuring the SSH Server
2.1 System Updates
Once connected to EC2, bring the system up to date:
1sudo apt update && sudo apt upgrade -y
2.2 SSH Server Configuration
Open the SSH daemon configuration:
1sudo vim /etc/ssh/sshd_config
Find and modify these parameters:
1# Allow port forwarding to external interfaces
2GatewayPorts yes
3
4# Send keepalive packets every 60 seconds
5ClientAliveInterval 60
6
7# Drop connection after 3 unanswered keepalives
8ClientAliveCountMax 3
Deep Dive: GatewayPorts
By default, SSH only binds forwarded ports to localhost. Setting GatewayPorts yes
allows binding port 2222 to all network interfaces, which is essential for external access to your tunnel.
Save and exit: hit Esc
, type :wq
and press Enter
.
Restart the SSH service:
1sudo systemctl restart ssh
2.3 Creating a Dedicated Tunnel User
Let's create an unprivileged user specifically for tunnel management:
1sudo adduser tunnel
Set a password (e.g., TunnelPass2025!
). You can skip the other fields by pressing Enter
.
Why a separate user?
Principle of least privilege in action. The tunnel
user exists solely for the tunnel and has no access to system resources. This limits blast radius if something goes sideways.
2.4 Setting Up authorized_keys
Switch to the tunnel user:
1sudo su - tunnel
Create the SSH directory with proper permissions:
1mkdir .ssh
2chmod 700 .ssh
3touch .ssh/authorized_keys
4chmod 600 .ssh/authorized_keys
SSH Permission Requirements
700
on.ssh
— owner can read, write, and execute600
onauthorized_keys
— owner can read and write only- SSH strictly enforces these permissions and will refuse to work otherwise
Keep this terminal open—you'll return here after generating keys on your Raspberry Pi.
Step 3: Raspberry Pi Configuration
3.1 Connecting to Your Pi
Connect to your Raspberry Pi locally or via SSH on your home network:
1ssh a528fe2@raspberrypi.local
Password: 0fa65eb3e31c
About .local Addresses
raspberrypi.local
works via mDNS (Multicast DNS). If it doesn't resolve, use the Pi's local IP address instead (e.g., 192.168.1.100
). Check your router's DHCP leases if needed.
3.2 Generating SSH Keys for the Tunnel
On your Raspberry Pi, create a fresh ED25519 key pair:
1ssh-keygen -t ed25519 -f ~/.ssh/id_tunnel
When prompted for a passphrase, just hit Enter
(no passphrase needed for automated connections).
Why ED25519?
ED25519 is a modern elliptic curve algorithm that's faster and more secure than RSA. Keys are significantly shorter (256 bits vs 2048-4096 bits for RSA) while providing equivalent or better security. It's the gold standard for SSH keys today.
3.3 Extracting the Public Key
Display the public key:
1cat ~/.ssh/id_tunnel.pub
Copy the entire output (starts with ssh-ed25519 AAAA...
).
3.4 Adding the Key to EC2
Return to your EC2 terminal where you're logged in as the tunnel
user:
1vim .ssh/authorized_keys
Press i
to enter insert mode, paste the public key, then hit Esc
, type :wq
and press Enter
.
Exit back to the ubuntu user:
1exit
3.5 Testing Key-Based Authentication
Back on your Raspberry Pi, verify you can connect to EC2 with the new key:
1ssh -i ~/.ssh/id_tunnel tunnel@100.64.0.0
If prompted "Are you sure?", type yes
. The connection should succeed without asking for a password.
Key Authentication Working
If you connected without a password prompt—excellent! Key-based auth is configured correctly. Exit with exit
.
Step 4: Creating a Persistent Tunnel
4.1 Manual Tunnel Test
On your Raspberry Pi, start the tunnel in background mode:
1ssh -i ~/.ssh/id_tunnel -fN -R 2222:localhost:22 tunnel@100.64.0.0
SSH Flags Explained
-i ~/.ssh/id_tunnel
— specifies which private key to use-f
— backgrounds the process after successful connection-N
— don't execute any commands on the remote server (tunnel only)-R 2222:localhost:22
— Remote Port Forwarding: forward remote port 2222 to local port 22
4.2 Verifying the Tunnel
Connect to your EC2 instance:
1ssh -i ~/.ssh/rpi-tunnel-key.pem ubuntu@100.64.0.0
Check that port 2222 is listening:
1sudo ss -tulpn | grep 2222
You should see a line showing port 2222 in LISTEN state. Now try connecting to your Raspberry Pi through the tunnel:
1ssh -p 2222 a528fe2@localhost
Enter your Raspberry Pi password: 0fa65eb3e31c
Tunnel Operational!
If you're now on your Raspberry Pi—congratulations! The tunnel is working perfectly. Exit twice (exit
from RPI, exit
from EC2).
4.3 Automating with systemd
On your Raspberry Pi, create a systemd service for automatic tunnel startup:
1sudo vim /etc/systemd/system/reverse-tunnel.service
Insert this configuration (press i
, paste, then Esc
→ :wq
):
1[Unit]
2Description=Reverse SSH Tunnel to EC2
3After=network-online.target
4Wants=network-online.target
5
6 [Service]
7Type=simple
8User=a528fe2
9ExecStart=/usr/bin/ssh -i /home/a528fe2/.ssh/id_tunnel -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -o StrictHostKeyChecking=no -N -R 2222:localhost:22 tunnel@100.64.0.0
10Restart=always
11RestartSec=10
12
13 [Install]
14WantedBy=multi-user.target
systemd Service Breakdown
After=network-online.target
— wait for full network initializationType=simple
— process runs in foregroundRestart=always
— automatically restart on failureRestartSec=10
— wait 10 seconds before restartingServerAliveInterval=60
— send keepalive every 60 secondsExitOnForwardFailure=yes
— exit if port forwarding fails
Enable and start the service:
1sudo systemctl daemon-reload
2sudo systemctl enable reverse-tunnel.service
3sudo systemctl start reverse-tunnel.service
Check the status:
1sudo systemctl status reverse-tunnel.service
You should see active (running)
. If there are errors, check the logs:
1sudo journalctl -u reverse-tunnel.service -n 50
Step 5: Connection Methods
Method 1: Two-Hop Connection
Connect to EC2 first, then hop to your Raspberry Pi:
1# Step 1: Connect to EC2
2ssh -i ~/.ssh/rpi-tunnel-key.pem ubuntu@100.64.0.0
3
4# Step 2: From EC2, connect to RPI through the tunnel
5ssh -p 2222 a528fe2@localhost
6# Password: 0fa65eb3e31c
When to Use This
Great for debugging and understanding the flow. Lets you inspect the tunnel state on EC2 before connecting to your Pi. Also useful when you need to check EC2 logs or system state.
Method 2: Direct Single-Command Connection
Connect directly to your Raspberry Pi through EC2:
1ssh -i ~/.ssh/rpi-tunnel-key.pem ubuntu@100.64.0.0 -t "ssh -p 2222 a528fe2@localhost"
Understanding the -t Flag
The -t
flag forces pseudo-terminal allocation. Required for interactive sessions when you're running a command on a remote server that itself needs a terminal (like nested SSH). Without it, you'd get weird behavior or hangs.
Method 3: Streamlined SSH Config (Recommended)
Configure SSH for effortless access. On your local machine:
1vim ~/.ssh/config
Add these sections (press i
, paste, Esc
→ :wq
):
1Host ec2-tunnel
2HostName 100.64.0.0
3User ubuntu
4IdentityFile ~/.ssh/rpi-tunnel-key.pem
5
6Host rpi
7HostName localhost
8Port 2222
9User a528fe2
10ProxyCommand ssh -i ~/.ssh/rpi-tunnel-key.pem -W localhost:2222 ubuntu@100.64.0.0
ProxyCommand Magic
ProxyCommand
tells SSH how to reach the target host. The -W
flag creates a tunnel for traffic forwarding. SSH connects to EC2 first, then forwards your connection through to localhost:2222. It's like a VPN but smarter.
Set proper permissions on your config:
1chmod 600 ~/.ssh/config
Now you can connect with a simple command:
1ssh rpi
Enter your Raspberry Pi password (0fa65eb3e31c
), and you're in!
Next Level: Passwordless Access
After setting up key-based auth (Step 6), you won't need the password anymore—ssh rpi
will connect instantly without prompting.
Step 6: Key-Based Authentication Setup
Let's eliminate password prompts by setting up SSH key authentication for your Raspberry Pi.
6.1 Generate a Key on Your Local Machine
On your computer:
1ssh-keygen -t ed25519 -f ~/.ssh/id_rpi
Skip the passphrase (press Enter
) for automatic login.
6.2 Extract the Public Key
Display the public key:
1cat ~/.ssh/id_rpi.pub
Copy the output (starts with ssh-ed25519
).
6.3 Add the Key to Your Raspberry Pi
Connect to your Raspberry Pi:
1ssh -i ~/.ssh/rpi-tunnel-key.pem ubuntu@100.64.0.0 -t "ssh -p 2222 a528fe2@localhost"
Enter your RPI password (0fa65eb3e31c
). On the Raspberry Pi, run:
1mkdir -p ~/.ssh
2chmod 700 ~/.ssh
3echo "YOUR_PUBLIC_KEY_HERE" >> ~/.ssh/authorized_keys
4chmod 600 ~/.ssh/authorized_keys
5exit
Replace YOUR_PUBLIC_KEY_HERE
with the text you copied from id_rpi.pub
.
6.4 Update Your SSH Config
Open ~/.ssh/config
and add the IdentityFile
line to your rpi host:
1Host rpi
2HostName localhost
3Port 2222
4User a528fe2
5IdentityFile ~/.ssh/id_rpi
6ProxyCommand ssh -i ~/.ssh/rpi-tunnel-key.pem -W localhost:2222 ubuntu@100.64.0.0
Now connect without a password:
1ssh rpi
You're All Set!
The command ssh rpi
now connects you instantly to your Raspberry Pi from anywhere in the world—no passwords, no friction, just seamless access.
Monitoring and Diagnostics
Checking Status on Raspberry Pi
Verify the tunnel service status:
1sudo systemctl status reverse-tunnel.service
Confirm the SSH tunnel process is running:
1ps aux | grep "ssh.*tunnel@100.64.0.0"
Verifying Port on EC2
Connect to EC2 and check that port 2222 is listening:
1sudo ss -tulpn | grep 2222
You should see a line showing LISTEN
state with sshd
.
Restarting the Tunnel
If the tunnel hangs or becomes unstable:
1sudo systemctl restart reverse-tunnel.service
Live Log Monitoring
Watch the service logs in real-time:
1sudo journalctl -u reverse-tunnel.service -f
Press Ctrl+C
to exit the log viewer.
Handy Monitoring Commands
systemctl is-active reverse-tunnel.service
Quick check: returns active
or inactive
journalctl -u reverse-tunnel.service --since today
All logs from today
systemctl list-timers
Useful if you've set up periodic health checks via systemd timers
Troubleshooting Guide
Connection refused when connecting through tunnel
Root Cause: The tunnel isn't running or has crashed on your Raspberry Pi.
Fix: On your RPI, check sudo systemctl status reverse-tunnel.service
. If it's inactive or failed, restart it: sudo systemctl restart reverse-tunnel.service
Permission denied (publickey) on connection attempt
Root Cause: Wrong key, incorrect permissions, or key not in authorized_keys.
Fix:
- Verify key permissions:
chmod 400 ~/.ssh/id_tunnel
- Ensure public key is in
~/.ssh/authorized_keys
on target host - Check directory permissions:
~/.ssh
(700) and~/.ssh/authorized_keys
(600)
Tunnel keeps dropping and won't reconnect
Root Cause: Unstable internet connection or incorrect SSH parameters.
Fix: Verify your systemd unit includes ServerAliveInterval=60
and Restart=always
. For flaky connections, increase RestartSec
to 30 seconds.
Port 2222 not accessible from outside
Root Cause: EC2 Security Group doesn't allow inbound traffic on port 2222.
Fix: In AWS Console, check your instance's Security Group. You need a rule: Type: Custom TCP, Port: 2222, Source: 0.0.0.0/0.
How do I change the tunnel port?
If port 2222 is occupied or you need a different port, update it in three places:
- In systemd unit on RPI: change
-R 2222:localhost:22
to-R NEW_PORT:localhost:22
- In EC2 Security Group: add rule for the new port
- In SSH config on your machine: update
Port 2222
to new value
Is it safe to open port 2222 to the world?
Reasonably safe since access is protected by SSH keys and your Pi's password. To harden further:
- Disable password auth on RPI (keys only)
- Restrict port 2222 in Security Group to your IP or IP range
- Install fail2ban on EC2 to block brute-force attempts
- Keep both systems updated with security patches
Architecture Summary
Your Computer (anywhere worldwide) connects to EC2 via SSH using rpi-tunnel-key.pem
EC2 Server (100.64.0.0) accepts the connection and forwards traffic to port 2222
Through the SSH Tunnel, traffic flows to your Raspberry Pi (user a528fe2) behind your home router
Quick Reference Credentials:
- EC2 Access: ubuntu @ 100.64.0.0, key ~/.ssh/rpi-tunnel-key.pem
- EC2 Tunnel User: tunnel @ 100.64.0.0, password TunnelPass2025!
- RPI Access: a528fe2 @ raspberrypi.local, password 0fa65eb3e31c
- Magic Command: ssh rpi