Why Use Reverse Proxy vs. Port Forwarding?

I am currently planning to set up port forwarding to expose my Home Assistant to the internet. I have a Duckdns domain and Let’s Encrypt all set-up, and I planned to forward port 443 on my router to Home Assistant on port 8123.

Going through the forums, I noticed many people are setting up caddy and nginx as a reverse proxy to expose their Home Assistant instances. Based on what I read, I am under the impression that reverse proxy adds more security, but I’m not understanding how that is and what the benefits are to the increased complexity.

Since the same web interface will be exposed to the internet at the end of the day, right? Won’t something like 2-factor authentication add more security?

Would appreciate it if anyone can point out what I am missing here.

2 Likes

But why not use 2FA as well anyway?

Thanks David. When we say nginx intercepts requests: If I’m not exposing any of my network aside from Home Assistant’s web interface, would there be any requests nginx can block?

Security and anonymity – By intercepting requests headed for your backend servers, a reverse proxy server protects their identities and acts as an additional defense against security attacks.

Since only https requests are coming in, wouldn’t nginx just serve all the requests just as Home Assistant would?

It will only proxy web requests and sits behind your firewall

Great Question - I asked it myself a long time ago… and turns out the answer is this.

From a purely security standpoint…

If the reverse proxy isn’t:

  • Inspecting Traffic (MiM)
  • Filtering URLs (ex. preventing access to /admin) ; or
  • Requiring Authentication (at the proxy)

Then you might as well just port forward.
Because that’s essentially what you’re doing - forwarded unchecked traffic into your internal network (btw - not a great idea).

Note - there are 2 exceptions to this

  • A reverse proxy could provide a more scalable approach to publishing web services as you can publish multiple services with the same IP address (and cert) all over the same port - where as a traditional port forwarding configuration would only allow you to use one IP per Port
  • And the more modern use case is using a reverse proxy for translation from 443/to XYZ non-standard web port. This adds value because a web application running in linux over any port below 1024, requires the service run as root (your internet facing application SHOULD NEVER run with admin privileges).

Hope that helps,

(if anyone believes I’ve left anything out - or feels i’ve misstated something - please feel free to add/clarify)

5 Likes

Thanks, Dustin. That’s kind of what I suspected.

Since I am only opening the 433 port, any non web requests are rejected by default.

For authentication, I’ve read that people use client certificates or basic auth with reverse proxy to add security. But I believe you lose access to google assistant and there are some issues with iOS access.

Inspecting traffic and filtering URLs sees really interesting. Do you know if there are any applications to home assistant in particular, or if anyone has examples of how they did these?

For the first, you don’t have to. I (had) configured my reverse proxy so that access to the Google Assistant API path from Google’s IP ranges, with their user agent, wouldn’t require separate authentication. Of course, you can also pass the username and password in the URI structure when you configure it, which I did initially.

I’m moving towards URL filtering, the intent being to only allow access to specific APIs (probably with other requirements).

I do my SSL termination on the proxy anyway, so I could easily do inspection if I wanted to.

2 Likes

Wrong with both beliefs.

i recomment mostly to use a reverse proxy.
and i have the following reasons for it:

  1. most people start adding other things to their home automation, besides home assistant.
    the 1 i deal most with is appdaemon and HADashboard. a lot of them want HADashboard also to be reached outside but even if not it is more easy to connect stuff on the local network then when you got SSL in everything. some programs cant even have any ssl, and then they have real problems trying to get a connection with HA.
  2. duckdns inside HA with ssl makes that people cant reach their HA locally (by using the ip inside their homenetwork)
    thats a bad thing, because you dont want to be depending on an internet connection, or an outside DNS server when you are at home trying to reach HA.

i made a picture long ago to show why a reverse proxy is wise in a lot of cases:

6 Likes

That would be a big plus for me. Right now I have to ignore a bunch of security warnings to reach my HA locally.

It looks like there’s some real advantages to doing reverse proxy even if just for opening one web interface. This will be my next big HA project to work on.

Thanks everyone for all the helpful insights! I really appreciate the help!

1 Like

Do you have a guide for your reverse proxy?
I am using Hass.io, so I am hopping that I can just add the NGINX Home Assistant SSL proxy add on and that will cover it.

Not really a good explanation on the addon.

there is a lot on the forum, and nginx is even in the docs.
but i have read from several people who struggled with nginx and they found caddy more simple.

i cant help out with hassio addons, because i never used hassio.

Caddy is way more simple. It’s what I use.

It will be nice if you can share your nginx config, thanks

2 Likes

Everything is on my GitHub

1 Like

Another great reason to use Reverse Proxy is that you can make it really difficult for hackers who stumble upon your internet front door to actually get in. You do this by creating long and complicated endpoint names in the proxy, with e.g. a UUID along the lines of /7cbc1ac3-4b46-4aea-8f0e-69f227963918 or such that needs to be added to the path-name after the base URL and port. Now, if somebody brute forces your external DDNS name like myexternalddnsname.ddns.net by effectively guessing the myexternalddnsname part, just trying a port scan won’t get them face to face with your internal server. There’s still a kazillion guesses to find that UUID and without it there’s no coming in.

Apache also works great as a Reverse Proxy. Here’s an example of a very secure reverse proxy to a Domoticz instance (it even adds more security by requiring the user to log in and in my case I have a UUID as password too so no dictionary attack possible):

<VirtualHost *:443>

  ServerName myexternalddnsname.ddns.net
  SSLEngine on

  ProxyPass /7cbc1ac3-4b46-4aea-8f0e-69f227963918/domoticz/json.htm http://192.168.1.123:8080/json.htm
  ProxyPassReverse /7cbc1ac3-4b46-4aea-8f0e-69f227963918/domoticz/ http://192.168.1.123:8080/

  SSLCertificateFile /etc/letsencrypt/live/myexternalddnsname.ddns.net/cert.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/myexternalddnsname.ddns.net/privkey.pem
  SSLCertificateChainFile /etc/letsencrypt/live/myexternalddnsname.ddns.net/chain.pem

  # Turn on Basic Authentication
 <Location />
  AuthType Basic
  AuthName "joebloggs"
  AuthUserFile /etc/apache2/.htpasswd
  Require valid-user
 </Location>

<Directory "/">
    Require all denied
</Directory>

</VirtualHost>

You can have several reverse-proxy statements within the same virtualhost, each with a unique UUID to allow access to other servers in your house. This stuff goes into your ‘000-default.conf’ file in the ‘/etc/apache2/sites-available’ directory. you also need the mod_proxy module installed.

Please remember boys and girls:

Obscurityis not the same thing as actual “Security


Meaning - a more appropriate solution would be to configure a reverse proxy (nginx) to require a client certificate (x509 authentication) to allow the traffic to pass - thus requiring an attacker to actually obtain the certificate (unlikely) or guess the actual key, which would take a bit more than a “kazillion guesses” .

Guide on mentioned solution

1 Like

Obscurity is always additive to any scheme, even x509. With a UUID in the path to the endpoint, that’s 128bit level security which even today is unhackable (a billion tries a second takes 100 years). I was not proposing obscuring an open door, just hiding a closed one even better. How closed it is for starters is a separate discussion.

2 Likes

Very interesting thread.

I tried 2 alternatives. The reserve proxy one with Nginx and more recently a VPN connection. For the moment I’m sticking with the VPN.

I have a server with Esxi running several VMs and docker. I run hassio on a container but also a number of other services like Unify, Roon, OwnCloud, and FreeNAS (on a dedicated VM) among others.

All these were configured as backends in Nginx based on ports or sub-domain identifiers but in the end I wondered if I was not exposing too many services to the internet, especially since I couldn’t filter the incoming IP as I would want to be able to connect from anywhere mobile.

So I tried the VPN route using OpenVPN-AS on a container and only leaving that port open. It’s a UDP connection, shared keys certificate with the device I use to connect, and a strong password.

OpenVPN-AS is straighforward to install and there a number of available docker images. There are mobile and PC clients which make the device setup very easy. And it works like a charm.

Once connected into the network, I can just call HA and any other service from within. Using mobile app on the device or the browser if I prefer.

I can’t definitely affirm this configuration is more secure than reverse proxy, but for me it is now simpler to maintain and to use, and with the certificate/strong password access controls I fell I’ve got sufficient security.

Looking forward to comments.

1 Like