Openssl Letsencrypt

  1. Add Letsencrypt Openssl
  2. Openssl Let's Encrypt Files
  3. Openssl Letsencrypt Windows
  4. Openssl Letsencrypt Verify
  • LetsEncrypt is a free certificate authority. OpenSSL is a software package for generating certificates. The LetsEncrypt scripts use OpenSSL to generate certificates and sign them with the LetsEncrypt service.
  • Let’s Encrypt is a free, automated, and open certificate authority brought to you by the non-profit Internet Security Research Group (ISRG). On the other hand, OpenSSL is detailed as ' Full-featured toolkit for the Transport Layer Security and Secure Sockets Layer protocols '. It is a robust, commercial-grade, and full-featured toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols.
Let's Encrypt provides free SSL certificates, which can be used for hMailserver. However, the certificates are valid only for 90 days, and there is a scripted validation process that can be challenging to set up. Most scripts that are available are designed for validation using a webserver, and not mailservers. The following enables SSL full certificate request and installation for hMailserver without a separate webserver, with renewals every 85 days.

Requirements:

  1. hMailserver needs to be installed on Windows 10, with a working WSL (Windows Subsystem for Linux). If you need help to enable WSL, see the instructions for setting up Windows 10 Bash . In this page, we will be calling Windows 10 Bash, as Bash.
  2. You will need to migrate your DNS Nameserver to CloudFlare. You can use an alternate service provider if it is supported as a dehydrated hook, but will need to modify the scripts provided on this page to make the other DNS provider work.
  3. The scripts here assume that hMailserver is installed in c:Program Files (x86)hMailServer if you have it installed in a different location, you will need to modify the batch file to use the correct path.

Prerequisites:

In Windows 10 bash, install the required packages:
sudo apt-get install openssl curl sed grep mktemp git build-essential
sudo apt-get install python-dev curl libffi-dev libssl-dev python-pip

But then I tried to install the certificate to IIS 6.1 and I realized that Windows did not want that type of file. With some research on the Internet I found a solution, using the command openssl (in Linux): openssl pkcs12 -export -out certificateforwindows.pfx -inkey privkey.pem -in cert.pem -certfile fullchain.pem. I wish this helps someone.

* You may also need the following (to be verified):
sudo apt-get install python-setuptools
sudo easy_install pip

NOTE: Python 3.x in the current distribution will not work, since it is called python3, etc.
Decide on your workspace folder and create it in Windows Explorer. A folder without any spaces in its entire path is recommended (I have not tested names with spaces). The folder needs to be accessible to non-admins, since currently there seems to be some issues with Windows 10 Bash access to restricted folders. For example, lets consider something like c:UsersmyUserNameDocumentsNetworkinghmailserver_letsencrypt (change myUserName to your username). We will call this your script folder on this page.

One-time initial setup

Go to the script folder that you created, then:
1.In Bash, get the dehydrated script and the related Cloudflare hook by running the following. (If you are using a supported DNS service hook other than cloudflare, you will need to make changes for installing the hook and its dependencies):
git clone https://github.com/lukas2511/dehydrated
cd dehydrated
mkdir hooks
git clone https://github.com/kappataumu/letsencrypt-cloudflare-hook hooks/cloudflare
sudo pip install -r hooks/cloudflare/requirements-python-2.txt
cd ..
2. In Bash, create an executable script named hmailCert.sh by following:
a. In bash run:
cat > ./hmailCert.sh
b. Then paste the following (mouse right click if you have enabled Quick Edit). NOTE: You will need to modify
CF_EMAIL, CF_KEY, HMAILSERVER_DOMAIN to be the correct values for your Cloudflare account login email, Cloudflare API key, and MX domain name. The MX domain name is the domain name that you are getting SSL certs for, which is where your hMailserver is running and has for its SSL Certificate. ( (If you are using a supported DNS service hook other than cloudflare, you will need to make changes call the correct hook instead of cloudflare's):

#!/bin/bash
export CF_EMAIL='[email protected]'
export CF_KEY='yourCloudflareAPIKey'
export HMAILSERVER_DOMAIN='yourMXDomainNameLike_mail.mydomain.com'
dehydrated -c -d $HMAILSERVER_DOMAIN -t dns-01 -k 'hooks/cloudflare/hook.py'
cp dehydrated/certs/$HMAILSERVER_DOMAIN/privkey.pem $HMAILSERVER_DOMAIN.letsencrypt.key
cp dehydrated/certs/$HMAILSERVER_DOMAIN/fullchain.pem $HMAILSERVER_DOMAIN.letsencrypt.crt



chmod 777 ./hmailCert.sh

3. In Windows, go to your scrupt folder and create a batch file named hmailCert.bat with the following content. NOTE: change the second line with the address of your script folder.

set HMAILSERVER_DOMAIN='yourMXDomainNameLike_mail.mydomain.com'cd c:UsersmyUserNameDocumentsNetworkinghmailserver_letsencrypt
bash -c './hmailCert.sh'
copy %HMAILSERVER_DOMAIN%.letsencrypt.key 'c:Program Files (x86)hMailServer'
copy %HMAILSERVER_DOMAIN%.letsencrypt.crt 'c:Program Files (x86)hMailServer'
net stop hMailServerLetsencrypt openssl s_client
net start hMailServer

4. In Windows run everything for the first time to see if it works or if there are any issues, by opening a Command Prompt (CMD) as Administrator (right click on Command Prompt in the Windows 10 (start) menu and click Run as Administrator). Go to your script folder
cd c:UsersmyUserNameDocumentsNetworkinghmailserver_letsencrypt
and run the batch file:
hmailCert.bat

If no errors, you should have a new .key and a .crt file in your hMailServer folder.

5. Install the server certificate for the domain that hMailServer manages by going in hMailServer Admin GUI:
  1. Add the server's certificate (.crt) and the server's private key (.key) in Settings>Advanced>SSL Certificates.
  2. Set SMTP/POP3/IMAP to use the above SSL Certificate
    • Settings>Advanced>TCP/IP Ports:
      • SMTP: set Connection security to STARTLS (Optional), and then pick the SSL Certificate.
      • POP3/IMAP: set Connection security to STARTLS (Required), and then pick the SSL Certificate
6. Load the initial certificates by restarting hMailServer. You can do this in CMD (Run as Administrator) by the following two commands:
net stop hMailServer
net start hMailServer

Automate Certificate Renewals

1. Go to Windows Task Scheduler, and create a new task, to run the hmailCert.bat with the following settings:
  • General Tab:
    • Run whether user is logged on or not (At the end when you click OK, it will ask you to enter windows credentials. Make sure to use an Admin account)
    • Run with highest privileges
    • Configure for: Windows 10
  • Trigger
    • Daily at some time every 85 days, Enabled
  • Action
    • Start a program
    • Program/script (update with your script folder): c:UsersmyUserNameDocumentsNetworkinghmailserver_letsencrypt/hmailCert.bat
    • Start in: c:UsersmyUserNameDocumentsNetworkinghmailserver_letsencrypt
  • Conditions
    • Start the task only if the computer is idle for: 10 minutes
  • Settings
    • Allow task to be run on demand
    • Run task as soon as possible after a scheduled start is missed
    • Stop the task if it runs longer than 8 hours
    • If the running task does not end when requested, force it to stop.

Ever since Google announced that Chrome would mark non-https connections as ‘Not Secure’ I’ve begun to fret about ssl certificates. These serve two purposes. First, they encrypt your data and prevent Man-in-the-middle attacks, and secondly, they verify that the site you visit is the site it claims to be. I used to think that the former was more important, but now I am more of the opinion that identity verification is most important, now that phishing attacks are commonplace. LetsEncrypt has recently stepped in to help solve this problem.

With this in mind, when I saw that my UniFi controller was marked:

I wanted to fix it.

For a long time, certificates have been sold by certificate authorities, but now you can get them for free from LetsEncrypt. However, there are some provisos to be aware of.

First while you used to be able to get a 3 year certificate from a vendor, LetsEncrypt certs are 90 days, and must be renewed. Secondly, you have to be able to prove you control the name that the certificate is for. This makes things more complicated.

In effect, you either need to be able to prove you control the DNS entry of your server, or the server itself. This works great if you have a publicly-facing web site, but it’s more complex when you want to secure servers that are not accessible, like my internal UniFicontroller. Fortunately, pfSense makes this reasonably easy. I’m using *nix servers, so it’s really not. I’ll walk through what I did.

I’m pretty ok with the 90 day lifecycle, since it conforms to most password-rotation rules. It’s good security.

How LetsEncrypt Works (in my case)

There are several ways that LetsEncrypt will work, and since I can’t update my DNS via API, I chose to use the ‘Standalone HTTP server’ option. Essentially, you create a dns entry for the server behind the firewall you want:

unifi.barclayhowe.com

And I made this a cname that points to my firewall server. LetsEncrypt expects to find an HTTP server there on port 80, and it wants to see a secret on that server to show that the requester, DNS owner, and server owner are all the same. You will basically clutter up your DNS records with some extra aliases, but I think that’s ok, too.

LetsEncrypt will only let you do 5 calls per hour, so they have a staging environment that allows building and testing your solution.

Concept

The basic concept here is as follows:

  1. Add DNS entry
  2. Add acme (the LetsEncrypt client) to pfSense
  3. Set up a port forward from port 80 to some random port (port 80 is already in use on my pfSense server on the LAN side, so the LetsEncrypt server can’t use it)
  4. Set up the acme client to request a certificate for your internal server.
  5. Extract, move and install the certificate on the internal server

Easy, right? Or course it is…

Let’s Do it

I assume that you have a DNS service and can add your entry, and if you’re using PFSense, you can add a package.

Adding the LetsEncrypt Staging Server

First, navigate to the Services -> Acme Certificates Service.

Then, click on ‘Account Keys’:

and click ‘Add’.

This is a form that requires a few actions to complete. It looks like this at first:

Give it a name (I’d include ‘staging’ or ‘production’ in the name, as it helps out later), optionally a description, and an email address. I chose the Acme V2 staging server (it supports some new stuff) Then Click ‘+ Create Account Key’:

Then click ‘Register ACME account key’.

When the key icon becomes a check, you are ready to ask for a certificate. Click ‘Save’

Then switch to the ‘General Settings’ tab and set both checkboxes:

These will enable your renewal, and the extraction of the certificates to a folder so you can easily move them to another server.

Then go to the ‘Certificates’ tab and click ‘+Add’:

The only important note here is that set my DomainName to unifi.barclayhowe.com, and I picked a random port (18882) to listen on that is not 80. I needed to do a port forward from port 80 on my WAN interface to port 18882 on my LAN interface for this to work, you will too. I don’t like having open port forwards in my firewall, but this is pretty benign. After you do something like this, I recommend an external port scan to check that you are still secure. The acme service will start a temporary HTTP server when it renews, then tear it down when it’s done.

Now click ‘Save’, and exit to the list screen and see your certificate setup ready to request its first certificate:

Now click ‘Issue/Renew’ next to your new certificate. The gear will turn, and after a bit you’ll see a lot of green text. If there is block that looks like:

You did it. Now you can now ssh into your server and type:

ls /conf/acme/unifi*

You will see:

Putting Them Where They Belong

Now that you have them, you need to get them to the server where the controller is. Doing this requires the following steps:

  1. Package them into a p12 package. It’s a way of gluing several certificate components together into one file.
  2. Copy them to the new server.
  3. Run commands on that server to install the certificates into the controller’s java web server.

Up front, as a regular user, you can practice this with (all one line):

This will package the three files into a single file with a password that is ‘test1234’. The password is required by the java keystore – it won’t work without it.

Scp the file to the internal server:

scp /conf/acme/unifi.p12 [email protected]:~/unifi.p12

Then, on that server:

systemctl restart unifi

Seems simple, but since we need to renew this every 90 days, we need to take advantage of the acme service’s ability to run scripts once it has renewed the certificate.

Scripting it

Aside from a bit of scripting skill ( my scripts are definitely rough), we need a trusted user that can connect from the pfSense server to the internal server in order to copy the file. We’ll end up with two scripts:

copyUnifiCertificate.sh, which will be called from the certificate renewal page, and:

installUnifiCertificate.sh which will live in the home folder of the user on the internal server to install the certificate.

User setup

On your internal server, run the following commands:

adduser pfSenseCertCopier

su pfSenseCertCopier

cd

ssh-keygen -t ed25519 -a 100

When prompted : Enter file in which to save the key (/home/pfSenseCertCopier/.ssh/id_dsa): Press enter.

When prompted:

Enter passphrase (empty for no passphrase):
Enter same passphrase again:

Press enter twice. You don’t want a password here, since it will run winout user input.

Openssl letsencrypt windows

ls -la .ssh

this will list the contents of the /ssh hidden folder, and it has 2 keys, a private and a public.

then copy the key you created to the ssh authorized keys folder for that user:

cp .ssh/id_ed25519.pub .ssh/authorized_keys

Set ownership and permissions: the user needs to own those files, and the directory has to be globally executable, and the authorized keys has to be globally readable. This lets the ssh service see them:

chown -R pfSenseCertCopier:pfSenseCertCopier /home/ pfSenseCertCopier/.ssh

chmod 700 /home/pfSenseCertCopier/.ssh

chmod 600 /home/pfSenseCertCopier/.ssh/authorized_keys

copy the private key to the firewall server:

scp .ssh/id_ed25519 [email protected]:~

then test:

ssh [email protected] ought to fail. You have no defined password.

ssh -i id_ed25519 [email protected]

Should work, since you have the private key. Success!

Then the script on the Internal server

Openssl vs letsencrypt

First, you will need the copier user to be able to use sudo with no password to only execute one command, so execute:

sudo visudo on your internal server

and add the following line, which will allow this user to only be able to run 2 commands without a password:

Then edit your script:

cd /home/pfSenseCertCopier

su pfSenseCertCopier

vi installUnifiCertificate.sh

then

chmod 700 installUnifiCertificate.sh

Test it:

./installUnifiCertificate.sh

and it should return nothing, but when you open your controller, you should be greeted with:

Remote Testing

OK, lets see if our user can do this remotely:

From your firewall server, run:

ssh -t -i id_ed25519 [email protected] ./installUnifiCertificate.sh

This will use ssh to authenticate with your private key and run the command remotely. It should complete, and your unifi controller should still work.

Final Script

Add Letsencrypt Openssl

Now, one more script on your firewall server, in your root home folder:

Copy the private key to a better-named file:

Letsencrypt

Openssl Let's Encrypt Files

mv id_ed25519 pfSenseCertCopier.id_ed25519

vi copyUnifiCertificate.sh

then

chmod 700 copyUnifiCertificate.sh

and test:

vi copyUnifiCertificate.sh

And the entire orchestration will run.

Now To Tie It Together

Letsencrypt

Back in pfSense, add the command /root/copyUnifiCertificate.sh to the actions list:

save, and click the ‘Issue/Renew’ button once more. On your internal server, if you run:

ls -la

in the home folder of your copier user, you should see a freshly-updated certificate.

And your controller should work.

I think this is a pretty secure way of doing this, and you should be able to re-use the script on the internal server to update any arbitrary certificate usage. I looked at a lot of sites for this exact process, and hopefully this helps, since I could only find prices.

Update 10/14/18: I moved my controller to Ubuntu, so here is how to do that.

Update 1/6/19: Also added a guide for installing to Kibana.

Openssl Letsencrypt Windows

What I’m listening to as I do this:

Openssl Letsencrypt Verify

Gogol Bordello’s Gypsy Punks Underdog World Strike. Many years ago I was just getting into European Metal, especially some folk- and ancient music-influenced bands like In Extremo, when a friend suggested it. It’s crazy good, and it defies description. It’s a good uptempo album for linux work.