So, I’ve now got a bunch of things running on my home server and I want to access them when I’m out and about. That means exposing my server to the internet.
Scary stuff!
So, how to do it securely?
The basics are straightforward – port forwarding from the router and a dynamic DNS service. My router supports no-ip and dnyDNS, so that bit was easy. Managing security is the harder bit.
I want to be able to access my web applications – Django, Grafana and ZoneMinder so far – as well as call Zato ESB integrations from outside of my network.
Rather than multiple ports, I’m just forwarding port 443 to the server and handling everything in Apache. Yes, I know that Nginx might be a better option for some of my use cases but I’m comfortable with Apache. I’ve been working with it since version one point something, and there’s only so much new stuff I can get to grips with at once.
I’m using a self signed certificate, which ensures that data is encrypted but does generate browser warnings. Chrome in particular seems to hate them and won’t grant permanent exceptions, always showing them as red:
It’s annoying. It is a private connection, I know the certificate and showing it as a red alarm only serves to get me used to seeing those red alarms and perhaps be just that little bit less vigilant of them.
Firefox lets you grant an exemption, and shows it accordingly:
It is possible to work around Chrome’s lack of proper exemptions, but it means importing the certificate into the keystore of your device – whether that be Windows, OSX or Android (I have no idea if it’s even possible on iOS).
So with my self signed certificate ensuring that communication is encrypted, the next thing I did was put HTTP Basic Authentication in place. This is handled by the web server and sits in front of any application specific authentication. It adds an additional layer of security without any major inconvenience as you can tell the browser to remember it (although Chrome doesn’t seem to like remembering credentials for sites with self signed certs, which is another reason to prefer Firefox for this)
Apache’s fine for ZoneMinder, which runs as a CGI program, and my Django based apps which are running under Apache’s mod_wsgi.
For Zato, I’m proxying from an external URL handled by Apache to the internal Zato URL. I’m also choosing to allow only certain APIs to be called from outside of the network.
To do this, I’m creating HTTP channels in Zato with a URL path that starts /external to indicate that they are accessible externally and then proxying only those URLs. It’s easier to explain when you see the Apache conf:
ProxyPass /apis http://<myserverip:11223/external ProxyPassReverse /apis http://<myserverip>:11223/external <Location /apis> AuthUserFile /path/to/htpasswd AuthType basic AuthName 'Please authenticate' Order allow,deny Allow from <myserverip> Require valid-user Satisfy Any </Location>
And in Zato:
If we take the example of my Android notification service, this allows me to call:
https://<mydynamicdnsname>/apis/android
Apache will forward the request to:
http://<myserverip>:11223/external/android
If I’m accessing from outside of my network (i.e. anything other than an 192.168.1.x address) it will require basic authentication within Apache.
This approach makes it really easy to control which Zato services I expose to the internet.
I can do the same for Grafana:
ProxyPass /grafana http://<myserverip>:3000 ProxyPassReverse /grafana http://<myserverip>:3000
For this to work, /grafana has to be specified as the root URL in /etc/grafana.ini:
# The full public facing url root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana/
And finally, obviously, it goes without saying that it’s important to do all of the usual Apache hardening things and keep up to date with system patches.
With all that in place, I’m reasonably happy with my home server security. It’s not bulletproof – it’s important to remember that nothing on the internet is totally secure. You only have to look at the number of well publicised incidents to realise that, but then there’s actually very little sensitive data in the system.
I don’t think the temperature profile of various points in my house would be of great use or interest to anyone other than me…
in Home Automation