Monday, November 28, 2016

STARTTLS with Let's Encrypt and PowerMTA

This is an update to my previous post. I tried using the same certificate to let PowerMTA secure our e-mail server using STARTTLS, but unfortunately, Let's Encrypt is still untrusted by our PHP front-end because Let's Encrypt is still a new certificate authority. The solution is to include IdentTrust's root certificate as it's already trusted by all clients.

This setup is specific to a server with Apache and PowerMTA. You can probably make this work without a web server. Simply adjust the paths and other things as necessary.

I'm pasting the previous steps in this post with some updates.

First, log in as root. It's supposed to be a bad practice to work directly on root, but what the heck:

# sudo su -

Then, download GetSSL to your box:

# mkdir -p /root/getssl /etc/letsencrypt

# cd /root/getssl

# curl -s https://raw.githubusercontent.com/srvrco/getssl/master/getssl > getssl

# chmod 700 getssl

Then, generate the default config files:

# ./getssl -c example.org 
Making domain directory - /root/.getssl/example.org 
creating domain config file in /root/.getssl/example.org/getssl.cfg

Edit the global config at: ~/.getssl/getssl.cfg. Pay particular attention to the followine line:
RELOAD_CMD="service httpd reload"

Depending on your system, it can be "service apache2 reload" or something similar. Update as necessary.

Uncomment the following line also:
CA="https://acme-v01.api.letsencrypt.org"

WARNING: The server has a limit of 5 certificates per 7 days, so use the staging server when experimenting. I hit the limit when writing this post. Lolz.

Edit the domain config at ~/.getssl/example.org/getssl.cfg and insert the following lines:

SANS=www.example.org
DOMAIN_KEY_CERT_LOCATION=/etc/letsencrypt/example.org.crt
SERVER_TYPE="https"
CHECK_REMOTE="true"
ACL=('/var/www/pub/.well-known/acme-challenge')
USE_SINGLE_ACL="true"

Adjust the paths as necessary.

The ACL variable above is the path for the Automatic Certificate Management Environment (ACME) challenge. It should point to a folder inside your web server's document root and should be accessible to the public via HTTP. The ACME challenge is used to prove that you control the web server.

Next, edit the Apache config and insert this in your SSL section:

Header always set Strict-Transport-Security "max-age=15768000"
SSLProtocol             all -SSLv2 -SSLv3
SSLCipherSuite          ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
SSLHonorCipherOrder     on
SSLCertificateFile /etc/letsencrypt/example.org.crt
SSLCertificateChainFile /etc/letsencrypt/le.crt

Manually download Let's Encrypt's certificate:

# curl -s https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > /etc/letsencrypt/le.crt


Next, we need to merge IdenTrust's root certificate with Let's Encrypt's. Open your browser and go to: https://www.identrust.com/certificates/trustid/root-download-x3.html

Then, edit /etc/letsencrypt/le.crt and paste IdenTrust's cert at the bottom of the cert. le.crt should look like:

-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----

For convenience, you can also paste the certificate above. Don't do this on sensitive websites though.


Then, execute GetSSL:

./getssl -u -a

Verify if your certificates are OK:

# openssl verify -CAfile /etc/letsencrypt/le.crt /etc/letsencrypt/example.org.crt
/etc/letsencrypt/example.org.crt: OK

Restart Apache:

# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:

Finally, edit your PowerMTA config:

smtp-server-tls-certificate /etc/letsencrypt/example.org.crt
smtp-server-tls-ca-file /etc/letsencrypt/le.crt

<source 0/0>
    allow-starttls yes
    require-starttls-before-auth yes
</source>

Reload PowerMTA:

# service pmta restart
Stopping PowerMTA:                                         [  OK  ]
Starting PowerMTA:                                         [  OK  ]

Let's Encrypt's certificate expires every 90 days, so you need to update your crontab:

# crontab -e

Insert the following line in the crontab:

0 0 1 * * /root/getssl/getssl -u -a

Remember to protect your private keys and set the appropriate permissions. Just leave a comment if I missed some steps.

Thursday, November 24, 2016

Let's Encrypt on RHEL 6.8

It's been almost 3 years since I've last posted in this blog. 2016 is almost over. I think I should make it a point to post regularly.

Anyway, I'd like to share something interesting. There's a certificate authority called Let's Encrypt that gives free certificates through an automated process. According to their website, they have a Python script called Certbot that fetches the certificates and updates your web server's configuration for you.

Usually, I just use StartSSL for project prototypes or paid certificates on production websites, so I'm pretty late on discovering this.

I'm currently tasked on setting up a server here in my work. The goal is to let others send information towards this server and automate the process of setting up PowerMTA configuration based on this information. The most straightforward and relatively secure way to do this is over HTTPS.

Problem: The particular server that I'm working on runs on Red Hat Enterprise Linux 6.8, and Certbot needs updated Python packages to run. After a couple of attempts to solve this, I realized that it's a lost cause so I abandoned it and looked for a more lightweight solution with little dependencies. The best client that I've found so far is GetSSL. It's a straightforward bash script, and I like it!

The server that I'm working on runs on Apache, but I can't find any step-by-step documentation on how to use GetSSL with Apache. Thus, I decided to make one.

First, download GetSSL to your box:

# curl --silent https://raw.githubusercontent.com/srvrco/getssl/master/getssl > getssl

# chmod 700 getssl

Then, generate the default config files:

# ./getssl -c example.org

Making domain directory - /root/.getssl/example.org
creating domain config file in /root/.getssl/example.org/getssl.cfg

Edit the global config at: ~/.getssl/getssl.cfg. Pay particular attention to the following line:

RELOAD_CMD="service httpd reload"


Depending on your system, it can be service apache2 reload or something similar. Update as necessary.

Then, edit the domain config at: ~/.getssl/example.org/getssl.cfg and insert the following lines:



SANS=www.example.org
DOMAIN_CERT_LOCATION="/etc/httpd/getssl/example.org.crt"
DOMAIN_KEY_LOCATION="/etc/httpd/getssl/example.org.key"
DOMAIN_CHAIN_LOCATION="/etc/httpd/getssl/example.org-chain.crt"
CA_CERT_LOCATION="/etc/httpd/getssl/le.crt"
SERVER_TYPE="https"
CHECK_REMOTE="true"
ACL=('/var/www/.well-known/acme-challenge'
     '/var/www/.well-known/acme-challenge')

Adjust the paths as necessary.

The ACL variable above is the path for the Automatic Certificate Management Environment (ACME) challenge. It should point to a folder inside your web server's document root and should be accessible to the public via HTTP. The ACME challenge is used to prove that you control the web server.

Finally, edit the Apache config and insert this in your SSL section:


SSLCertificateFile /etc/httpd/getssl/example.org-chain.crt
SSLCertificateKeyFile /etc/httpd/getssl/example.org.key
SSLCACertificateFile /etc/httpd/getssl/le.crt
Let's Encrypt's certificate expires every 90 days, so you need to update your crontab to automatically renew your certificate:

# crontab -e

Insert the following line in the crontab:

0 0 * * * /path/to/getssl -u -a -q

Save your changes and apply your changes:

service httpd reload

If everything is OK, go back to your global config at ~/.getssl/getssl.cfg and uncomment the following line to use the non-staging server:

CA="https://acme-v01.api.letsencrypt.org"

Then, reload Apache again:

service httpd reload

That's it! Your web server is now running HTTPS. This won't really protect you from being particularly targeted by the NSA (there was a couple of state-sponsored attacks on certificate authorities), but the goal is to make broad mass-surveillance uneconomical. Just leave a comment if I missed some steps. Enjoy, and encrypt all the things!