How To Use SSH Tunnel To Expose A Local Server To The Internet


As the R&D Lead at Go Wombat I often have to deal with various tasks. Now I want to share our experience of using SHH tunnel to expose a local server.
We have a local server at Go Wombat. And there is no access to that server outside of the local network. We decided to deploy one of our internal tools on the virtual machine inside that local server. And use one of the remotely hosted servers to gain access to that tool through the internet.
It’s a good and free alternative to tools like Ngrok or Serveo.
TL;DR Daemon service for Tunnel
On the local server. Create a file in the /etc/systemd/system/
with the name like tool-tunnel.service
[Unit]
Description=AutoSSH tunnel to remote server
After=network.target
[Service]
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 20000 -N -i /home/tool/.ssh/id_rsa user@[IP] -R 8080:localhost:80 -C
[Install]
WantedBy=multi-user.target
On the remote server — add your public SSH key to the authorized_keys
Remote server
Giving access
To be able to create SSH tunnel to that remote server you need to give your local server SSH access. You need to generate a key (or just use the existing one if you have) using ssh-keygen
command. After it is done add you public key from local server to the ~/.ssh/authorized_keys
on the remote server.
You can test if it works by trying to SSH on the remote server from the local server (caution, possible word “server” overdose): ssh username@[IP]
Local server
SSH Tunnel
Finally, the SSH tunnel itself. Use a command like that:
ssh -N -i /home/tool/.ssh/id_rsa user@[IP] -R 8080:localhost:80 -C
So, let’s go through all the arguments:
-N
: Do not execute a remote command. It’s useful for just forwarding ports.-i /home/tool/.ssh/id_rsa
: Which identity (key) to use.user@[IP]
: user — username on the remote server, IP — ip of the remote server-R 8080:localhost:80
: This allows anyone on the remote server to connect to TCP port 8080 on the remote server. The connection will then tunneled back to the client host, and the client then makes a TCP connection to port 80 on thelocalhost
-C
: Enables data compression
Now you can try to test it by opening your URL in the browser. Or sending some requests. Don’t forget to launch your application 😉
AutoSSH
Also, we need to make a tunnel persistent — make sure the tunnel will always run. For example, once your ssh connection times out (By server-side timeout), your tunnel should be re-established automatically.
There is a tool that will help us — AutoSSH.
Autossh is a program to start a copy of ssh and monitor it, restarting it as necessary should it die or stop passing traffic.
The command I come up with is next:
autossh -M 20000 -N -i /home/tool/.ssh/id_rsa user@[IP] -R 8080:localhost:80 -C
The only things that added are autossh
instead of ssh and argument -M 20000
, which means that AutoSSH uses port 20000 to check the connection.
Service
To make sure that the tunnel will be established automatically after server reboot and to have control over the process, we need to set up a systemd
service.
Create a file in the /etc/systemd/system/
with the name like tool-tunnel.service
(you can change tool
to something more descriptive 😉 )
[Unit]
Description=AutoSSH tunnel to remote server
After=network.target
[Service]
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 20000 -N -i /home/tool/.ssh/id_rsa user@[IP] -R 8080:localhost:80 -C
[Install]
WantedBy=multi-user.target
P.S. Don’t forget to change [IP] in the command.
After the file it’s done, run:
sudo systemctl daemon-reload
sudo systemctl start tool-tunnel # To start your service
sudo systemctl enable tool-tunnel # To make it start automatically
Now you can check it with sudo systemctl status tool-tunnel
.
Done!
If you don’t want to use Nginx
By default, OpenSSH only allows connecting to remote forwarded ports from the server host. However, you can change that behavior.
For that, you need to change the GatewayPorts
configuration file sshd_config (Usually this file is /etc/ssh/sshd_config). Simply cahnge it to yes
:
GatewayPorts yes
Unlock Success with Premium Software Development
Contact us


If you want to use Nginx
Remote server
First, we need to prepare the remote server to handle requests and redirect them to port that used in the SSH tunnel. We used Nginx to set it up.
In /etc/nginx/sites-available/
you need to create a file that contains config for your site.
The contents are pretty simple:
server {
listen 80;
server_name tool.gowombat.team;
access_log /var/log/nginx/tool-proxy.log;
error_log /var/log/nginx/tool-proxy.error.log;
client_max_body_size 32m;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
}
After you done it — you need to add it to /etc/nginx/sites-enabled/
, best way — using symlink:
ln -s /etc/nginx/sites-available/tool /etc/nginx/sites-enabled/
Local server
On the local server, we’re used Nginx as well to serve applications and static files. But if you have something simple or something that doesn’t need static files, you can skip that part.
The config file needs to be put in the same directory as before.
server {
listen 80;
server_name tool.gowombat.team;
access_log /var/log/nginx/tool.log;
error_log /var/log/nginx/tool.error.log;
client_max_body_size 32m;
location /static/ {
alias /home/tool/tool-backend/collected_static/;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/tool/tool-backend/tool_backend.sock;
}
}
This is how we did it at Go Wombat. If you have any questions please let us know!
How can we help you ?


