This article will describe how to set up and utilize SSH tunnels.
Note: This page has previously been posted as the following page on SSH Tunnels. The publication date is replicated here.
Problem
We have some services that we would like to be made available at office for convenience reason. The service is available from a certain port in our home computer. For security purposes we have to use ssh tunnels instead of exposing the port from our home network’s port forwarding.
At our disposal is a cloud server we control that we utilized as a bridge between our home computer and office computer. Both our home computer and work computer are connected to the cloud server. However, how do we configure the connection between our home computer and office computer?
Case Study
For the purpose of this article, we assumes that we want to expose our locally available Syncthing GUI configured in homecomputer to listen only to localhost:8384.
The service would not be available from outside, as our syncthing configuration would reject any connection not coming from localhost.
This is a security feature, that the service is only available locally, as it allows access to sensitive files.
homecomputeris our home computerworkcomputeris our work computercloudserveris our cloud server
Solution
With SSH tunnels, from workcomputer we can access homecomputer:8384 as if we are connecting from localhost.
We can achieve this by setting up a matching pair of SSH tunnels between homecomputer and workcomputer through a single common local port on cloudserver.
From homecomputer we configured a reverse SSH tunnel to cloudserver, and from workcomputer we configured a SSH tunnel to cloudserver.
As a bonus, to have a clean URL when accessing from a browser in workcomputer, we can configure a reverse proxy in a local nginx at workcomputer.
A reverse proxy configuration would take a certain URL path and would configure a local port to serve the URL path.
By pointing the reverse proxy configuration to the port in workcomputer we configured as a SSH tunnel to cloudserver that is forwarded to homecomputer, we can then access a service available locally in homecomputer as if we are connecting to it locally.
SSH Tunnels
Therefore we just have to configure a SSH reverse tunnel from homecomputer:
# file .ssh/config at homecomputer
# Equivalent to: ssh -R 8385 localhost:8384 username@cloudserver
Host liecorp-tunnel
User username
HostName cloudserver
RemoteForward 8385 localhost:8384
ServerAliveInterval 120
Then from workcomputer we configured a SSH tunnel:
# file ~/.ssh/config at workcomputer
# Equivalent to: ssh -L 8485:localhost:8385 username@cloudserver
Host liecorp-tun
User username
HostName cloudserver
LocalForward 8485 localhost:8385
ServerAliveInterval 120
What we did from homecomputer is basically to open a listening port cloudserver:8385 that would correspond to homecomputer:8384.
Then from workcomputer we forward connection from port workcomputer:8485 to cloudserver:8385, which in turn, is forwarded to homecomputer:8384.
Therefore to reach homecomputer:8384 from workcomputer, we can point our browser to http://localhost:8485 and our service at homecomputer:8384 would be available from workcomputer.
Nginx reverse proxy
To make everything tidy, we can even set a reverse proxy configuration on nginx at workcomputer:
# File /etc/nginx/sites-available/server.conf
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
index index.html
include "/etc/nginx/default.d/*.conf";
location / {
try_files $uri $uri.html $uri/ /fallback/index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
location /syncwork0/ {
proxy_pass http://127.0.0.1:8384/;
include proxy_params;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
location /synchome/ {
proxy_pass http://127.0.0.1:8485/;
include proxy_params;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
}
Therefore we can now access homecomputer:8384 by pointing our browser to http://localhost/synchome/ instead of http://localhost:8485/.
Conclusion
To connect to a service available only to localhost at homecomputer from workcomputer, we:
- Configure SSH Tunneling from both
homecomputerandworkcomputertocloudserver, where the traffic would go throughcloudserver:8385. The routecloudserver:8385corresponds to a listening porthomecomputer:8384, and forwarded traffic fromworkcomputer:8485. Therefore connecting tolocalhost:8485fromworkcomputerwould get us tolocalhost:8384athomecomputer. Tosyncthing, we are accessing fromlocalhost, and therefore is allowed to access the service. - Configure Nginx reverse proxy to have a clean URL without having to type ports.
We set up a reverse proxy address for URL
/synchome/that would be served byhttp://127.0.0.1:8485/. Therefore we can access the service fromhttp://localhost/synchome/.