Forward Services With SSH Tunnels
2024-05-09 20:44 WIB - Hendrik Lie
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 120Then 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/.