Last Updated on 2017-05-13.
[:en]
Scenario
You have some webservers or mailservers in your LAN which you want to work with the Let’s Encrypt SSL service. It provides the creation of free SSL certificates which are known by most browsers.
The only drawback is, they are valid for only 90 days. So if you do not want to renew manually every 3 months, you can automate most parts of the process.
In this tutorial, we will create a certificate server which provides always up-to-date certificates, so they can be fetched by other servers in your LAN.
Steps
Certbot, the LetsEncrypt utility for getting certificates e.g. under Ubuntu, basically needs an open outgoing Port 80 TCP, and also an incoming Port 80 TCP. I didn’t want to open outgoing internet for all of the servers, so I decided to create a separate LetsEncrypt certificate server which runs certbot regularly.
Create a new Ubuntu Server virtual machine: Default setup, install Samba/CIFS, Apache2 and certbot.
Configure:
- Apache’s ports.conf and 000-default.conf to only listen on port 81, docroot: /share
- (Do not use port 80 because certbot needs it later)
- Samba’s smb.conf: Add a public read-only share “certs” for /share
You might already have another Apache webserver running which listens on your router’s public port 80, so we have to redirect certain request from there to the new cert server.
Modify every virtual host config of Apache which needs SSL certificates like in this example:
<VirtualHost *:80> DocumentRoot "/var/www" ServerName www ServerAlias * ErrorLog "/var/log/apache2/error.log" CustomLog "/var/log/apache2/access.log" common #letsencrypt ProxyPass /.well-known/acme-challenge/ http://certs/.well-known/acme-challenge/ ProxyPassReverse /.well-known/acme-challenge/ http://certs/.well-known/acme-challenge/ </VirtualHost>
Note: In this example, certbot always uses port 80! Make sure to consider all of your subdomains, e.g. also for your mailserver etc.
The following script can be run as a cronjob (crontab -e), it gets and renews the certificates from LetsEncrypt and creates password protected zip files for easy local distribution:
#!/bin/bash #www.dxsdata.com, 2017-05 #creates pw protected zip archives containing certificate files PW=somepw SHARE=/share CERTPATH=/etc/letsencrypt/live [email protected] declare -a DOMAINS=( "myfirst.example.com" "mysecond.example.com -d autodiscover.example.com" ) #halt on any error set -e #clean share rm -rf $SHARE/* for DOMAIN in "${DOMAINS[@]}" do MAINDOMAIN=`echo $DOMAIN | head -n1 | cut -d " " -f1` #echo $MAINDOMAIN certbot certonly --standalone -d $DOMAIN --preferred-challenges http --agree-tos -n -m $EMAIL --keep-until-expiring #create file for ms exchange server openssl pkcs12 -export -in $CERTPATH/$MAINDOMAIN/cert.pem -inkey $CERTPATH/$MAINDOMAIN/privkey.pem -out $CERTPATH/$MAINDOMAIN/cert.p12 -password pass:$PW zip -er --password $PW $SHARE/$MAINDOMAIN.zip $CERTPATH/$MAINDOMAIN -j done
The main part is done, we should be able to get the certificate zip files via CIFS and browser (port 81).
Now we want the “client” servers to fetch the certificates from the local certs server.
Example script for an Ubuntu Apache webserver “client”
#!/bin/bash #www.dxsdata.com, 2017-05 #gets SSL certificates from local certs server and replaces the existing/old ones PW=somepw REMOTECERTPATH="http://certs:81" CERTPATH=/certs/letsencrypt TMPPATH=/tmp/certzip declare -a DOMAINS=( "myfirst.example.com" ) mkdir -p $TMPPATH #halt on any error set -e for DOMAIN in "${DOMAINS[@]}" do wget -O $TMPPATH/$DOMAIN.zip $REMOTECERTPATH/$DOMAIN.zip unzip -o -P $PW $TMPPATH/$DOMAIN.zip -d $CERTPATH/$DOMAIN/ done apachectl configtest service apache2 restart
Make sure your Apache certificate config and the script’s certpath point to the same directory.
Example for MS Exchange 2010/2013/2016
This is not a functional Powershell script, but some useful commands to create one:
//Load zip file from \\certs\certs or http://certs:81, then: Get-ExchangeCertificate -> you get the Thumbprint Enable-ExchangeCertificate -> SMTP,IIS,IMAP,POP + Thumbprint from above (Alternative: Import-ExchangeCertificate)
[:]