Version 3 (modified by 19 months ago) ( diff ) | ,
---|
Securing a website ¶
Securing a website is usually one of the next steps after the Apache is serving it "It works!" page. That 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 garbage but no cleartext passwords of other critical data noone else should see.
Enabling https
requires to install certificates on which the en- and decryption is based on. OpenSSL provides everything needed to create our own certificates and those certificates created by OpenSSL can be used by Apache pretty fine. The downside is that those certificates are self-signed which means that we, as we create the certificate, sign the certificate as being valid. All SSL engines complain about that (and so every browser does) as those certificates cannot really be trusted since everyone can quickly create one. How can a site verify that the certificate is valid when the only one who can be asked for that is the one who has created it? Technically, self-signed certificates are as good as commercial ones. The encryption based on self-signed certificates is as good - its just the fact that the origin of such a certificate cannot finally verified.
Solution is to order a certificate from big companies like Thawte or DigiCert (this are just examples, not a recommendation or so). 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 amount of secured websites significantly. The certificates emitted by LetsEncrypt are accepted by all of the browsers so using them will not bring up any complains.
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 LE-cert as LE 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 be created for must be reachable from internet onhttp
port 80. - Nameservice (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 LE-cert must have a name, usually something like 'www.yourdomain.tld' or so.
Verification process by LetsEncrypt ¶
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 webserver 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 webservers 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. Thats the reason why most admins 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:
- certbot
This is a feature-rich implementation of a client. It is the one recommended by LE. Due to the features built in into the client, this package became quite big and has an overwhelming amount of options. - uacme
Uacme is a nice and handy C-implementation which is quite easy to build and to use.
Note: In the following sections are 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 do no longer work with newer versions, tell us on the mailing list.
Note: Make sure that your webserver works fine on http (port 80). It might 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. Doublecheck that port 80 (http) is used.
Certbot ¶
Download: ...
MD5 checksum: ...
Dependencies: ...
Installation ¶
...
Usage ¶
...
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 \ -i uacme.1 \ -i 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 webserver 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 that cryptic 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 webserver 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 are a relatively short time valid (90? days) but they can refreshed so the operation of your website is not interrupted. 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
- 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 using a hook script to handle the output. With this, uacme can run unattended which is required when running as a cronjob. 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 - ??? 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 self-signed certs or something like that.