So I wanted to access my pimatic system from outside my apartment, wherever I am. I thought about just configuring port forwarding in my router, however just using passwords on plain http didn’t feel good, and also I’m not very confident pimatic is safe to open to the world wide web (sorry).
I decided to configure SSL client certificates to ensure only access to pimatic by devices being configured with the right SSL certificate. In this howto I like to share with you how I configured my system accordingly.
I will be updating this first post over time to keep all information in one place.
The global configuration looks as follows
- domain name
- pimatic
- nginx as a proxy http server handling SSL
- Let’s Encrypt for the SSL certificate of the webserver
- A self signed Certificate Authority to sign your client certificates
Configure a domain name
You need to have a (sub)domain name to be able to use Let’s Encrypt to create a SSL certificate for your configuration. There are many ways to do this. You could use a dynamic DNS service. I configured a subdomain on a domain I own, and since I have a fixed external IP address configured the subdomain to use that address. It’s up to you how to acquire and configure the needed domain.
For the sake of this howto I use the domain name pimatic.example.com.
If you do a nslookup of your pimatic domain your external IP address should be returned
nslookup pimatic.example.com
Depending on the configuration of your router you most probably now get a time out when you browse to the domain.
Run pimatic on a different port
You need to run pimatic on a different port number because nginx and pimatic can not run on the same port number. I decided to go for port 8080 but you can pick any available port other than port 80 and 443.
Stop pimatic
sudo service pimatic stop
and change the following snippet in your pimatic config.json
"httpServer": {
"enabled": true,
"port": 80
},
to
"httpServer": {
"enabled": true,
"port": 8080
},
Start pimatic after making these changes
sudo service pimatic start
Check if you can access and use pimatic using the internal IP address of your pimatic device and port 8080.
Install nginx
Just a straightforward sudo apt-get install nginx
will install NGINX.
Enable port forwarding
You need to forward port 80 (HTTP) and port 443 (HTTPS) to you pimatic device. Check the documentation of your router how to do this.
After this step you should be able to see the “Welcome to nginx on Debian!” screen when you browse to your pimatic domain.
Install Let’s Encrypt
I first created my own self signed certificate, but Android shows an annoying warning if you add your own Certificate Authority to the device which you can’t hide. So I decided to use the Let’s Encrypt service instead.
sudo su -
wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto
./certbot-auto
mv certbot-auto /usr/local/sbin/
exit
Run Let’s Encrypt
Generate the Let’s Encrypt certificate
sudo certbot-auto certonly --webroot -w /var/www/html/ -d pimatic.example.com
The Let’s Encrypt certificate is only valid for 90 days. To have the certificate automatically renewed every 60 days you have to schedule a task. Modify the root user crontab
sudo crontab -e
and add the following lines to the end
# at 4:47am/pm, renew all Let's Encrypt certificates over 60 days old
47 4,16 * * * /usr/local/sbin/certbot-auto renew --renew-hook "service nginx reload"
Configure nginx
Now we have an SSL certificate for our pimatic domain we can configure HTTPS
Update /etc/nginx/sites-enabled/default
to look like
# Default server configuration
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
server_name pimatic.example.com;
# Maintain the .well-known directory alias for Let's Encrypt renewals
location /.well-known {
alias /var/www/html/.well-known;
}
# Redirect to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS configuration
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
# Let's Encrypt signed certificates
ssl_certificate /etc/letsencrypt/live/pimatic.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pimatic.example.com/privkey.pem;
# Turn on OCSP stapling as recommended at
# https://community.letsencrypt.org/t/integration-guide/13123
# requires nginx version >= 1.3.7
ssl_stapling on;
ssl_stapling_verify on;
# Uncomment this line only after testing in browsers,
# as it commits you to continuing to serve your site over HTTPS
# in future
# add_header Strict-Transport-Security "max-age=31536000";
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name pimatic.example.com;
}
Reload the nginx configuration
sudo service nginx reload
After this step you should be able to see the “Welcome to nginx on Debian!” screen when you browse to your pimatic domain and HTTP is redirected to HTTPS.
Create self signed Certificate Authority
sudo su -
cd /etc/ssl/
openssl genrsa -des3 -out private/my_pimatic_CA.key 4096
openssl req -new -x509 -days 3650 -key private/my_pimatic_CA.key -out certs/my_pimatic_CA.crt
Update nginx Configuration
You now have to configure nginx to require a client certificate signed by the pimatic Certificate Authority.
Change the following snippet in /etc/nginx/sites-enabled/default
ssl_certificate /etc/letsencrypt/live/pimatic.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pimatic.example.com/privkey.pem;
to
ssl_certificate /etc/letsencrypt/live/pimatic.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pimatic.example.com/privkey.pem;
ssl_client_certificate /etc/ssl/certs/my_pimatic_CA.crt;
ssl_verify_client on;
When you now try to access your pimatic domain your browser is asked for a certificate. As you don’t have one yet you will be denied acces. Verify that this is the case as this is the whole basis on which the security is founded. Any device without a valid certificate should be denied access.
Create a client certificate
sudo su -
cd /etc/ssl/
openssl genrsa -des3 -out private/client.key 4096
openssl req -new -key private/client.key -out client.csr
openssl x509 -req -days 3650 -in client.csr -CA certs/my_pimatic_CA.crt -CAkey private/my_pimatic_CA.key -set_serial 01 -out certs/client.crt
openssl pkcs12 -export -clcerts -in certs/client.crt -inkey private/client.key -out client.p12
exit
Installing the client certificate on OS X
Copy the .p12 certificate to your OS X computer and double click the file in the Finder to open the certificate in Keychain Access.
When you now browse to your pimatic domain you should see the “Welcome to nginx on Debian!” screen again.
Installing the client certificate on Android
I just emailed the .p12 file to myself and opened the file in the Gmail app. The client certificate will automatically be installed.
Installing the client certificate on Windows
I don’t own any Windows devices, so please provide me with the needed instructions and I can update this post accordingly.
Installing the client certificate on iOS
I don’t own any iOS devices, so please provide me with the needed instructions and I can update this post accordingly.
Update nginx Configuration, again
The last thing to configure in nginx is the proxying to pimatic
Add the following snippet to your HTTPS configuration in /etc/nginx/sites-enabled/default
to be like
location / {
# Proxy requests to pimatic
proxy_pass http://127.0.0.1:8080;
}
Reload the nginx configuration
sudo service nginx reload
Getting rid of certificate pop-up in Chrome on OS X
Every time you want to access pimatic your Chrome browser will ask you which certificate you would like to use for authentication. This is obviously not what you want.
You can tell Chrome to always use a specific certificate for a given domain. In Terminal execute the following command.
write com.google.Chrome AutoSelectCertificateForUrls -array-add -string '{"pattern":"https://pimatic.example.com","filter":{"ISSUER":{"CN":"My pimatic CA"}}}'