wiki:Securing_a_website

Securing a website

Securing a website is usually one of the next steps after Apache presents the "It works!" page. This means enabling Apache to handle requests via https. The transport of data will be encrypted in both directions so reading whats on the wire will give a lot of encrypted text but no clear text passwords or other critical data no one else should see.

Enabling https requires installing certificates on which the encryption and decryption is based on. OpenSSL provides everything needed to create our own certificates and those certificates can be used by Apache. The downside is that these certificates are self-signed which means that we, as we create the certificate, sign the certificate as being valid. The problem is that browsers check for valid certificates. One critical check is whether the certificate is signed by a known "Certificate Authority". In this the Certificate Authority is providing assurance that the owner of the certificate, and other data associated with the certificate is valid.

So how do we get a valid certificate? One solution is to order a certificate from big companies like Thawte or DigiCert (this are just examples, not a recommendation). They will ask a lot of questions so they can be sure that you are really you and the certificate will be created for a real installation. Finally, they will send you an invoice along with the certificate. That's contradictory to the recommendation that every site should communicate encrypted as many site owners refused to pay money.

Fortunately, there is a organization called LetsEncrypt who issues standard certificates at no cost. This has increased the number of secured websites significantly. The certificates from LetsEncrypt are accepted by all of the browsers so using them will not bring up any complaints.

Prerequisites to get an "official" certificate

  • Site must be reachable from Internet
    If the site is not reachable from the internet, its hard to retrieve a LetsEncrypt certificate as the LetsEncrypt server will reach out to the site and query some special data. That means the site must be reachable from the internet. Note that 'reachable from internet' means that the server you want a certificate for must be created and reachable from internet on http port 80.
  • The Domain Name System (DNS) must be set up
    To reach the site, the DNS records need to be in place. That means that the site you want to secure with a LetsEncrypt certificate must have a name, usually something like 'www.yourdomain.tld' or so, and the IP address on your system must match the address in DNS. The reverse DNS lookup also needs to match the site name.

Verification process by LetsEncrypt (LE)

LE needs to know that you are the administrator of the site. Usually an administrator has access to the server and this is what LE is using. They will create a set of data (two cryptic strings) which needs to be placed as a file in a specific path using one of the strings as filename. The file itself must contain the other string. When done, LE can access this well known path and read the file and its content. If the file is there and the content matches, LE assumes that you really have access to that site (as you were able to create that file there). If this test succeeds, LE will create the certificate. The web server can now configured to use that certificate. After that is done, the port 80 can be closed and the requested file created before can be removed.

This process of placing some data somewhere can be used on other platforms, too. Another option - beside placing a file in the web servers path - is to modify DNS records. LE expects you to add a specific TXT value to the domain name entry. when this TXT value can be retrieved by LE using a command like 'dig', your authentication as the site administrator also succeeds. Updating DNS can be time consuming as it may last a while until the TXT record is propagated thru the world wide DNS hierarchy so LE is able to find it. That is the reason why most administrators will use the file-in-path variant.

Tools to access LetsEntrypt

LE provides an API which can be used for tools to request the tokens and guide you thru the creation process. There are several implementations, two of them are covered here. Only one of them is to be installed, choose one:

  1. certbot
    This is a feature-rich implementation of a client. It is the one recommended by LE. Due to the features built into the client, this package became quite big and has a large number of options.
  2. uacme
    Uacme is a nice and handy C-implementation which is quite easy to build and to use.

Note: In the following sections version numbers shown. This page is not updated on a regular basis, so it might happen that the versions are outdated and newer version of the packages are available. Using the newest available version is recommended. If the instructions no longer work with newer versions, tell us on the mailing list.

Note: Make sure that your web server works properly using http (port 80). It can be checked by pointing the browser to the URL you want to secure with the new certificate. In this example, point the browser to 'http://www.yourdomain.tld' and verify that this produces the expected content. Double check that port 80 (http) is used.

Certbot

To get https to work, first install certbot. The instructions are at https://certbot.eff.org/lets-encrypt/otherpip-apache

Note that augeas will also need to be installed. See below,

The certbot looks for a certain configuration, even if 'Other Linux' is selected:

ln -s apachectl /usr/sbin/apache2ctl
ln -s httpd /etc/apache2

mkdir -p /etc/httpd/sites-enabled
cd       /etc/httpd/sites-enabled
ln -s ../vhosts.d/<site.domain.topleveldomain>.conf 

In /etc/httpd/httpd.conf ensure 'LoadModule rewrite_module...' is not commented.

Now install augeas (http://download.augeas.net/http://download.augeas.net/)

Run as root:

certbot --apache --must-staple --redirect --hsts --uir --staple-ocsp \
        -d <site.domain.topleveldomain>

This will update vhosts.d/<site.domain.topleveldomain>.conf and add

<site.domain.topleveldomain>-le-ssl.conf

Restart apache

Uacme

Download: https://github.com/ndilieto/uacme/archive/refs/tags/v1.7.4/uacme-1.7.4.tar.gz
MD5 checksum: 0a8ff9a73e1d8006d4eee9908ca5f035
Dependencies: curl
Optional: gnutls

Installation

Modify a path matching the BLFS installation of the Apache server:

sed -e "s;/var/www/;/srv/www/;" \
    -i uacme.sh \
       uacme.1  \
       docs/uacme.html

Compile the package by executing

autoreconf                 &&
./configure --prefix=/usr  \
            --disable-docs &&
make

Now, install the package by executing the following as the root user:

make install

Usage

First, create an account and a private key. The directory used in the subsequent command (/etc/uacme.d) can be freely chosen. The certificates will be stored there and the web server should have read access to it.

uacme -v -c /etc/uacme.d new

Next, initiate creating a certificate for your domain

uacme -v -c /etc/uacme.d issue www.yourdomain.tld

Several status and informational messages scroll on the screen until it halts and waits for your input. At this stage, look for a line beginning with uacme: challenge=http-01 ident=www.yourdomain.tld .... The whole line might look like

uacme: challenge=http-01 ident=www.yourdomain.tld token=kZjqYgAss_sl4XXDfFq-jeQV1_lqsE76v2BoCGegFk4 key_auth=kZjqYgAss_sl4XXDfFq-jeQV1_lqsE76v2BoCGegFk4.2evcXalKLhAybRuxxE-HkSUihdzQ7ZDAKA9EZYrTXwU

The data of token= and key_auth= are essential. We need them to create the authentication file. The (sample) data of above are used in the next commands. Execute them in a new terminal (as the actual one is allocated by the waiting uacme program:

mkdir /srv/www/.well-known/acme-challenge
echo "kZjqYgAss_sl4XXDfFq-jeQV1_lqsE76v2BoCGegFk4.2evcXalKLhAybRuxxE-HkSUihdzQ7ZDAKA9EZYrTXwU" \
   > /srv/www/.well-known/acme-challenge/kZjqYgAss_sl4XXDfFq-jeQV1_lqsE76v2BoCGegFk4

Both of those hashed string values are taken from the output of the uacme program. The filename is the value of token and its content is taken from key-auth.

After the file has been created, verify that the web server has access to it by pointing your browser to http://www.yourdomain.tld/.well-known/acme-challenge/kZjqYgAss_sl4XXDfFq-jeQV1_lqsE76v2BoCGegFk4. The value of the key-auth should appear as simple text in your browser.

If done and the response in the browser is ok, switch back to the terminal where uacme is waiting for an answer.

Press 'y' + Enter

and the program will continue to run. When finished, the certificate is placed in /etc/uacme.d/www.yourdomain.tld/cert.pem and the private key is stored in /etc/uacme.d/private/www.yourdomain.tld/key.pem. The '.well-known' directory can now be deleted as its content is usable only one time so there is no use in keeping it:

rm -rf /srv/www/.well-known

todo:

  • Show how uacme can be automated (avoid the manual input and file creation, can be done by a hook script included in the uacme package; used in cron below, but can also be used for initial setup)
  • Configure Apache (valid for both, certbot & uacme)

Refresh certificates

LE certificates have a relatively short validity time (90 days) but they can refreshed so the operation of your website is not interrupted. The best way is to setup a cron job which checks whether there are certificates expiring soon and if there are any, renew them.

A typical crontab entry might look like

  • for certbot:
    $ ls /etc/cron.weekly/
    certbot.sh
    
    $ cat /etc/cron.weekly/certbot.sh
    #!/bin/bash
    date                                        > /tmp/certbot
    /usr/bin/certbot --quiet renew
    ret=$?
    #echo "certbot return value=$ret"           >> /tmp/certbot
    
    # Restart daemons that use certs
    #echo "Restarting apache from cron.weekly"  >> /tmp/certbot
    /usr/sbin/apachectl -k restart 2>&1        >> /tmp/certbot 
    
    #echo "Restarting postfix from cron.weekly" >> /tmp/certbot
    /etc/init.d/postfix reload 2>&1            >> /tmp/certbot 
    ret=$?
    #echo "/etc/init.d/postfix reload return value=$ret" >> /tmp/certbot
    
    #echo "Restarting dovecot from cron.weekly" >> /tmp/certbot
    #/etc/init.d/dovecot reload 2>&1            >> /tmp/certbot
    pid=$(cat /run/dovecot/master.pid)
    kill -HUP $pid
    ret=$?
    #echo "dovecot 'kill -HUP' return value=$ret" >> /tmp/certbot
    

You can uncomment the echo statements above for debugging and logging.

  • for uacme:
    6 15 * * * /usr/bin/uacme -c /etc/uacme.d -h /usr/share/uacme/uacme.sh issue www.yourdomain.tld
    
    The argument -h /usr/share/uacme/uacme.sh makes uacme use a hook script to handle the output. With this,

uacme can run unattended which is required when running as a cron job. To automate reloading any service which uses the certificates, reload them if the call to uacme terminates with result code 0:

6 15 * * * /usr/bin/uacme -c /etc/uacme.d -h /usr/share/uacme/uacme.sh issue www.yourdomain.tld && /path/to/reload-script.sh

Configure Apache http

When certificates are created they are stored in

  • /etc/uacme.d/www.yourdomain.tld/ when using uacme, or
  • /etc/letsencrypt/ when using certbot

Apache needs to be configured to use those certificates in order to enable access to the site via https.

Enable SSL at all by loading the ssl_module in /etc/httpd/httpd.conf:

LoadModule ssl_module /usr/lib/httpd/modules/mod_ssl.so
...
Include /etc/httpd/extra/httpd-ssl.conf
...
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>

Now, setup SSL for the virtual hosts in /etc/httpd/extra/httpd-ssl.conf:

<VirtualHost _default_:443>

#   General setup for the virtual host
DocumentRoot "/srv/www"
ServerName www.yourdomain.tld:443
...

#   SSL Engine Switch:
#   Enable/Disable SSL for this virtual host.
SSLEngine on

#   Server Certificate:
#   Point SSLCertificateFile at a PEM encoded certificate.  If
#   the certificate is encrypted, then you will be prompted for a
#   pass phrase.  Note that a kill -HUP will prompt again.  Keep
#   in mind that if you have both an RSA and a DSA certificate you
#   can configure both in parallel (to also allow the use of DSA
#   ciphers, etc.)
#   Some ECC cipher suites (http://www.ietf.org/rfc/rfc4492.txt)
#   require an ECC certificate which can also be configured in
#   parallel.
SSLCertificateFile "/etc/uacme.d/www.yourdomain.tld/cert.pem"

#   Server Private Key:
#   If the key is not combined with the certificate, use this
#   directive to point at the key file.  Keep in mind that if
#   you've both a RSA and a DSA private key you can configure
#   both in parallel (to also allow the use of DSA ciphers, etc.)
#   ECC keys, when in use, can also be configured in parallel
SSLCertificateKeyFile "/etc/uacme.d/private/www.yourdomain.tld/key.pem"
...
</VirtualHost>

After restarting Apache by issuing

/etc/rc.d/init.d/httpd restart

or

systemctl restart httpd

access to the website via https should be ok and the browser should not complain any longer about certificate validity.

Last modified 12 months ago Last modified on 10/10/2023 12:26:19 AM
Note: See TracWiki for help on using the wiki.