Imagine you are travelling and need to reach a web interface that only exists on your home network – a NAS, a home automation dashboard, or a development server. A reverse SSH tunnel lets your Android phone act as a bridge, pulling a connection from your home server back to the phone, so you can reach those internal services from anywhere. This tutorial walks you through the entire process using only free, open‑source tools that run in Termux, without requiring root access.
Termux:Boot (free add‑on) to start the tunnel automatically after a reboot.pkg update && pkg upgrade -y
pkg install openssh autossh -y
termux-api if you want to control the tunnel via Android intents later:
pkg install termux-api -y
These packages are pure user‑space binaries, so no root is required. autossh monitors the tunnel and restarts it automatically if the connection drops.
.ssh directory:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""
Leave the passphrase empty for automated scripts, but protect the private key with file permissions (600).
ls -l ~/.ssh
The public key is stored in ~/.ssh/id_rsa.pub. You will copy this to the home server so it can authenticate the phone without a password.
ssh user@your-home-server "mkdir -p ~/.ssh && chmod 700 ~/.ssh"
scp from Termux:
scp ~/.ssh/id_rsa.pub user@your-home-server:~/phone_key.pub
~/.ssh/authorized_keys and set correct permissions:
cat ~/phone_key.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
rm ~/phone_key.pub
ssh -i ~/.ssh/id_rsa user@your-home-server "echo connected"
You should see connected without being prompted for a password.
If the connection fails, double‑check that the server’s sshd_config permits PubkeyAuthentication yes and that the authorized_keys file is owned by the user.
A reverse tunnel forwards a port on the remote server (REMOTE_PORT) to a port on the Android device (LOCAL_PORT). For example, to expose the phone’s local web server (port 8080) as localhost:9000 on the home server, use:
ssh -N -R 9000:127.0.0.1:8080 -i ~/.ssh/id_rsa user@your-home-server
Explanation of flags:
-N – do not execute a remote command; we only want port forwarding.-R 9000:127.0.0.1:8080 – on the remote side, bind port 9000 to the phone’s 127.0.0.1:8080.-i ~/.ssh/id_rsa – use the private key we generated.Replace 9000 with any unused port on the home server, and 8080 with the local service you want to expose (e.g., a local web UI, an SSH daemon on the phone, etc.).
autosshNetwork interruptions are inevitable. autossh watches the tunnel and restarts it automatically. The basic command looks like this:
autossh -M 0 -N -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" \
-R 9000:127.0.0.1:8080 -i ~/.ssh/id_rsa user@your-home-server
Key options:
-M 0 disables the monitoring port (simpler for mobile use).ServerAliveInterval 30 sends a keep‑alive packet every 30 seconds.ServerAliveCountMax 3 tells SSH to consider the connection dead after three missed keep‑alives.Save this command in a script file so you can launch it easily.
mkdir -p ~/scripts
start_reverse_tunnel.sh with the following content:
#!/data/data/com.termux/files/usr/bin/bash
# Adjust variables as needed
REMOTE_USER="user"
REMOTE_HOST="your-home-server"
REMOTE_PORT=9000
LOCAL_PORT=8080
SSH_KEY="$HOME/.ssh/id_rsa"
autossh -M 0 -N \
-o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" \
-R ${REMOTE_PORT}:127.0.0.1:${LOCAL_PORT} \
-i "${SSH_KEY}" ${REMOTE_USER}@${REMOTE_HOST}
Make the script executable:
chmod +x ~/scripts/start_reverse_tunnel.sh
Run the script with ~/scripts/start_reverse_tunnel.sh. You should see no output – the tunnel runs in the foreground. Press Ctrl+C to stop it.
To keep the tunnel running after you close the Termux session, use nohup or Termux’s built‑in termux-wake-lock to prevent the device from sleeping.
termux-wake-lock (it is part of the Termux app, just call it):
termux-wake-lock
nohup:
nohup ~/scripts/start_reverse_tunnel.sh > ~/tunnel.log 2>&1 &
ps -ef | grep autossh
The tunnel.log file will contain any error messages. If you ever need to stop the tunnel, find the process ID (PID) from the ps output and kill it:
kill PID
Termux:BootManually starting the tunnel each time is tedious. Termux:Boot runs scripts placed in ~/.termux/boot whenever the device finishes booting.
mkdir -p ~/.termux/boot
ln -s ~/scripts/start_reverse_tunnel.sh ~/.termux/boot/start_reverse_tunnel.sh
chmod +x ~/.termux/boot/start_reverse_tunnel.sh
~/tunnel.log) to confirm the tunnel started.If the tunnel does not start, open Termux, run termux-wake-lock manually, and inspect tunnel.log for error messages. Common reasons are missing network connectivity at boot or battery‑optimisation killing Termux.
From a computer on your home network (or via SSH into the server), test the forwarded port:
curl http://localhost:9000
If the Android phone is running a local web service on port 8080, you should see the HTML output. For a generic test, you can also use nc -zv localhost 9000 to check if the port is open.
Now that the tunnel is stable, you can access any service that runs on the phone (or any other device reachable from the phone) by connecting to localhost:REMOTE_PORT on the home server. Some practical examples:
127.0.0.1:8123 on the phone, then reach it from anywhere via http://your-home-server:9000.-R 2222:127.0.0.1:22. Then from any remote machine: ssh -p 2222 user@your-home-server.python -m http.server 8080) and fetch files through the reverse tunnel.ssh-keygen -lf ~/.ssh/id_rsa vs. ssh-keygen -lf ~/.ssh/authorized_keys)./etc/ssh/sshd_config for PubkeyAuthentication yes and AuthorizedKeysFile .ssh/authorized_keys..ssh directory and authorized_keys file have permissions 700 and 600 respectively.If the server reports “address already in use”, pick a different REMOTE_PORT (e.g., 9010). You can also list used ports with ss -ltnp on the server.
termux-wake-lock as shown earlier to keep the CPU awake while the tunnel is active.ServerAliveInterval and ServerAliveCountMax are set; they prevent idle disconnections.Some devices enable Wi‑Fi after the Termux:Boot script runs. Add a short wait loop at the start of your script:
while ! ping -c1 -W1 8.8.8.8 >/dev/null; do
sleep 5
done
This loops until the device can reach the internet.
These often appear when the remote side tries to bind to a privileged port (< 1024). Use ports >1024 for the reverse side unless you run the SSH daemon as root on the server.
~/.ssh/id_rsa should be readable only by you (chmod 600). Do not share it.127.0.0.1 on the server (default) so only local processes can reach it. Avoid -R *:PORT:… unless you explicitly need remote access.ufw deny 9000/tcp or similar.authorized_keys.If you have several phones, give each a distinct REMOTE_PORT (e.g., 9000, 9001, 9002). You can also use a unique identifier in the SSH key comment to keep track of which key belongs to which device.
When your home network’s public IP changes, a dynamic DNS service (e.g., DuckDNS) keeps a constant hostname. Update the REMOTE_HOST variable in the script to the DNS name.
If your home router forwards SSH on a port other than 22, add -p PORT to the autossh command:
autossh -p 2222 -M 0 -N ...
You can start a temporary HTTP server directly from Termux:
python -m http.server 8080 --bind 127.0.0.1
Then the reverse tunnel will expose that server to the home side.
autosshIf autossh is unavailable, you can wrap the SSH command in a simple while true loop with a short sleep. However, autossh handles edge cases like “broken pipe” more gracefully.
By following the steps above you now have a reliable reverse SSH tunnel that starts automatically on your Android device and stays alive across network hiccups. This setup gives you secure, on‑demand access to any service running on the phone—or any other device reachable from the phone—without ever rooting the hardware or exposing ports to the public internet.
Remember to keep your SSH keys safe, monitor battery‑optimisation settings, and adjust firewall rules on your home server. With those safeguards in place, the reverse tunnel becomes a powerful, low‑maintenance bridge between your mobile world and your home network.









