I try to limit the services I expose from my home network to the internet, but also find that it is helpful to have a backup plan if one fails. Wireguard is the primary tool I use for connecting to my network when I’m remote but there are times it is blocked and on some rare occasions when it is offline. This is when it is helpful to have SSH as a backup.

This is just an example of connecting to my Unifi controller’s web interface remotely over SSH. The same idea applies to any type of remote access which you want to be able to do over a TCP connection.

Remote Troubleshooting with SSH Forwarding

I primarily use my Unifi firewall device as my Wireguard server. It generally has been reliable but after a recent update I found that I couldn’t connect remotely via Wireguard. I wanted to troubleshoot it while I was still remote and needed to connect to the Unifi admin web interface on the controller itself. This is where SSH Forwarding/Tunneling comes in to access my Unifi controller remotely.

Prerequisites

This setup requires:

  • running something like ddclient to publish a DNS record of my public IP address of my home network
  • exposing a port on my firewall to forward SSH connections to a SSH server running on a Linux host in my home network
  • running ssh to forward a port on my LOCAL machine through the SSH tunnel to the Unifi controller on my home network

Connecting Remotely

Now I can run SSH.

ssh -p 10000 -L 8443:192.168.0.1:443 ssh.example.com

In this example ssh.example.com is the DNS entry pointing to the public IP of my home network, 10000 is the port on my firewall that forwards to a SSH server on my network, 8443 is the port on my local machine forwarded over the SSH tunnel, 192.168.0.1 is the local IP of the Unifi controller on my home network, and 443 (the standard TLS or https port) is the port running the Unifi admin web interface on the controller.

I can then test to see if it is working by using curl in verbose(-v) mode. Because my Unifi admin web interface is running over TLS (i.e. https), I also use the --insecure flag to skip checking TLS/HTTPS certificates.

curl -v --insecure https://127.0.0.1:8443

This should show some output like below - note the successful connection and HTTP response at the bottom.

*   Trying 127.0.0.1:8443...
* Connected to 127.0.0.1 (127.0.0.1) port 8443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / RSASSA-PSS
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=firewall.example.com
*  start date: Jun  2 15:32:30 2025 GMT
*  expire date: Aug 31 15:32:29 2025 GMT
*  issuer: C=US; O=Let's Encrypt; CN=R10
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
*   Certificate level 0: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://127.0.0.1:8443/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: 127.0.0.1:8443]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.9.1]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: 127.0.0.1:8443
...
< 
* Connection #0 to host 127.0.0.1 left intact
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="robots" content="noindex"><link rel="icon" href="/favicon.ico?v3" sizes="any"><link rel="icon" href="/favicon.svg?v3" type="image/svg+xml"><link rel="apple-touch-icon" href="/apple-touch-icon.png?v3"><title>UniFi OS</title><meta name="viewport" content="width=device-width,initial-scale=1"><script>window.UNIFI_OS_MANIFEST = {"model":{"id":"UDRULT","shortName":"UCG Ultra","longName":"UniFi Cloud Gateway Ultra"},"images":[{"size":1024,"url":"/assets/images/1024.png?udrult-3.0.0"},{"size":64,"url":"/assets/images/64.png?udrult-3.0.0"},{"size":48,"url":"/assets/images/48.png?udrult-3.0.0"}]}</script><script defer="defer" src="/main.7aebd10b6b4dfa6965c6.js"></script><link href="/main.2129f854.css" rel="stylesheet"></head><body id="portal-body"><div id="portal-root"></div></body></html>% 

Hosts File Entry

In order to get the TLS certificates to work as normal I can then add an DNS entry in my local machine hosts file to point firewall.example.com to my localhost IP address. Since my local machine is Linux I add this line to /etc/hosts.

127.0.0.1 firewall.example.com

Now I can go to a browser on my local machine and type the URL of https://firewall.example.com:8443 and access my Unifi Controller to troubleshoot why Wireguard isn’t working.