Ubiquiti provides a brief guide on using a custom SSL certificate with UniFI but this process produces a certificate without a Subject Alternative Name (SAN) extension. Chrome will produce certificate errors for any sites using a certificate without a SAN.
The reason this happens is because the certificate signing request (CSR) generated through ace.jar does not contain the SAN extension. Since the CSR doesn’t contain a SAN the signed certificate won’t contain a SAN either.
# create new certificate (with csr)
java -jar lib/ace.jar new_cert <hostname> <company> <city> <state> <country>
It is possible to add the SAN attributes to a CSR that does not contain them but this is generally not best practice and there are some problems with taking this approach.
You can add the SAN attributes by using the additional attributes field of the Microsoft Certificate Authority web enrollment page but this requires that the CA is configured with the EDITF_ATTRIBUTESUBJECTALTNAME2 flag. After enabling the flag you can enter the SAN attributes you wish to add in the attributes box.
There are some serious security risks associated with enabling this flag and it is not recommended to enable it on a enterprise CA.
There is another complicated option for adding a SAN to a CSR that involves using an enrollment agent certificate, but there is an easier way.
The best solution I’ve found is to simply generate a new CSR using OpenSSL that contains the SAN field. You can then have the CSR signed for your CA and import the signed certificate (along with the associated private key) directly into the UniFi keystore file.
Step 1: Generate a new private key
Since we’re not going to use the existing UniFI private key to create a CSR a new key must be created.
openssl genrsa -out /etc/ssl/private/unifi.key 2048
Step 2: Create a text file with the certificate attributes
Create a new text file named request.conf using the template below. Change the fields in the dn section for your organization. The SAN field is specified in the req_ext section. You should also list the FQDN of the CN here first, then any alternative names you wish to add.
[ req ]
default_bits = 4096
prompt = no
encrypt_key = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ dn ]
CN = server.domain.com
emailAddress = email@example.com
O = Organization
OU = Unit
L = City
ST = State
C = US
[ req_ext ]
subjectAltName = DNS: server.domain.com, DNS: server
Step 3: Generate a CSR
Generate a certificate singing request using OpenSSL and the config file created in the previous step. The CSR will be signed by the private key created in step 1.
openssl req -new -config request.conf -key unifi.key -out unifi.csr
Step 4: Verify the CSR
Before you proceed to having the CSR signed by your CA it’s a good idea to take a look and make sure that it contains the fields you want.
You can use one of the many online CSR decoders to take a look at the contents of the request.
Step 5: Have the CSR Signed by a CA
Next have the certificate request signed by a certificate authority. In my case the CA was a local Microsoft CA running on Windows Server.
After submitting the request your CA will provide you with the signed certificate file. You’ll also need a copy of the root certificate for the CA and any intermediate certificates.
Step 6: Convert Signed Certificate to PEM Format
The next step requires the signed certificate be in PEM format. If your certificate is in DER or Base64 it will need to be converted to PEM. Luckily OpenSSL makes this conversion easy.
openssl x509 -inform der -in unifi-signed.cer -out unifi-signed.pem
Step 7: Generate a PKCS12 File
Using the signed certificate in PEM format, the new private key (from step 1), and the root certificate, generate a PKCS12 file using OpenSSL. If you have any intermediate certificates they will need to be included here as well. The example below is for a certificate signed directly by a root CA without any intermediary.
openssl pkcs12 -export -in unifi-signed.pem -inkey unifi.key -out unifi.p12 -name unifi -CAfile rootcert.cer -caname root -password pass:aircontrolenterprise
Step 8: Backup the Existing Keystore
Before proceeding it’s a good idea to backup the existing keystore. If you need to revert the changes later you can restore from the backup file. Adjust the path as needed to point to your UniFi base directory, or use find/locate to find the location of the file.
cp /opt/UniFI/data/keystore /opt/UniFI/data/keystore.backup
Step 9: Import the PKCS12 File To the Keystore
The PKCS12 file generated in the previous step can now be imported directly into the UniFi keystore. Adjust the path to your keystore as needed. It should be located in <unifi_base> inside the data directory. Keytool is included with Java but it may not be in your path, you may have to call it directly if it isn’t (ex: /opt/java/jdk1.8.0_112/bin/keytool).
You may see a message about overwriting the unifi alias, if so go ahead and overwrite it.
keytool -importkeystore -deststorepass aircontrolenterprise -destkeypass aircontrolenterprise -destkeystore /opt/UniFi/data/keystore -srckeystore unifi.p12 -srcstoretype PKCS12 -srcstorepass aircontrolenterprise -alias unifi
Step 10: Restart the UniFI Service
To make the changes take effect you will need to restart the UniFi service.
service unifi restart
It everything worked correctly you should no longer see a certificate warning in the web interface.
If you see ERR_SSL_PROTOCOL_ERROR then something is wrong with the keystore. You’ll also see this message if you load a certificate but the private key is not installed properly. If this happens restore the keystore using the backup file and restart the service to regain access to the web interface.