03-14-2021, 04:29 PM
This is not an exhaustive list of everything someone should do on their web server but here's what I have learned and done some of these things in my setup. Also, I suggest against copying/pasting code here into your system, this is mostly meant to be strictly informational. There are far more complete guides. This assumes your conf files and such are in default locations.
This is assuming you're running a Debian/Ubuntu based distribution running Apache 2.4.xx (Looks like 2.4.41 is the latest on the Ubuntu repo at this time). Running MySQL 8, PHP 7.4.
For starters, it is generally a good practice to have a SSL certificate for each website. Apache can run multiple websites through virtual hosts. If you need or want to have multiple websites look at some tutorials about how to set up virtual hosts.
This also assumes you want SSH access remotely and have port 22 forwarded, this can be changed to a non-standard port which should result in much less chatter in your /var/log/auth.log.
If you are new to installing a SSL certificate on apache the general steps are
1. Buy the certificate
2. Prove domain ownership. This is done by either adding a DNS record to your domain and/or putting a file on your webserver. This tells the registrar that you have control over the domain.
3. Add the certificate files to your apache's configuration file, usually it is /etc/apache2/apache2.conf
4. Configure your website to use and force HTTPS.
5. For tighter security you can force strong ciphers, disabling SSLv3, TLS1.0, TLS1.1 and so on.
6. Enable HTTP2, this will help your webserver serve up pages faster than HTTP1.1, however a SSL certificate is required. You must also be running up to date versions of PHP and the CMS system you use (e.g. Wordpress).
If you are using SSH you will want to take advantage of key authentication. You can in combination use a passphrase with the key. A key size of 4096 bits is more than sufficient. You can go as large as 8192 but I don't know if all software will support that large and is pretty overkill. Finally, I like fail2ban. It is simple but it does discourage brute force attacks on SSH and website. If too many failed login attempts are detected it will block their IP address for a specified amount of time. Fail2ban requires iptables and if you're using something like ufw you do need to be aware of what order rules come in. So a basic understanding of iptables will be helpful.
At this point, I am going to assume you have bought your certificate and have your key file and intermediate key and so forth. It is best to follow the instructions from your provider for the OS you have. However, if you have multiple websites (perhaps consider a wildcard) you will go into your site's configuration file, usually that is /etc/apache2/sites-available/yourwebsite.conf
You will first want to make sure that apache has SSL support enabled, to do so enable the SSL mod...
Then in your website's conf file you will need to add a permanent redirect to force HTTPS... That can be done with the Redirect permanent...
Keep in mind that will force HTTPS, while in most cases that is what you want, if you want to allow non-secure traffic you can omit the Redirect line.
Next, since we want SSL, you need to have a VirtualHost running on port 443. Your config file should look similar to this. You need to have a path to your website's files shown on DocumentRoot, enable SSLEngine, provide paths to the certificate files. Couple notes, you may need to install and enable mods for apache in order SSL to work. You will also want to set the file permissions appropriately on the certificate files.
There may be other mods you may need to enable depending on your CMS and other software you run with your webserver, for instance if you're running PHP you might consider the fpm-fcgi mod, curl and so forth.
After you make sure your website is up and is happy (make sure to restart apache every time you make a configuration change). If something is wrong you can usually find out by doing
Or if you need more information you can refer to apache's log or the journalctl -xe
Now, if everything is good so far we can now move to enforce strong ciphers. Go back into your site's configuration file and add these:
Now, various cipher suites can change over time, I used this reference for cipher suite lists... Of course the "bad" is that disabling less secure cipher suites can break some older browsers or those who for some reason are still on unsupported OS'es like Windows XP or Windows 7.
Again, after you make this change, make sure to restart apache and verify your website is working as intended. I also would suggest testing with different browsers. Some browsers assume HTTPS while your web server might answer to insecure HTTP. I found this out when I thought the redirect rule wasn't necessary, likewise I put it back in.
If everything passes now you can look at enabling HTTP2. This one can break your website if you're running something like PHP5.6, which is no longer supported, or if your CMS or something about your configuration isn't compatible.
First, there are a couple things, the mods mpm_prefork, php must be disabled before you can enable http2, mpm_event. You may need to install php7.4-fpm, then enable the configuration.
I would check to make sure that apache was able to restart so check it's status
If it is running, check that your website is up and running and then we can make the configuration changes in your website's conf file so that apache uses HTTP2.
Go back into your website's conf file and add
This allows a HTTP 1.1 fallback.
Finally, restart apache and check your website. If you discover that your CMS or the software you use does not work with HTTP2 you can revert back to HTTP 1.1 by removing the Protocols directive from the config file. That alone should make things work, but you can do the following:
Doing the above should reverse the changes to enable HTTP along with removing the Protocols directive in the conf file.
Finally, if everything appears to be working with HTTP2, now you want to make sure that apache actually is serving your site with HTTP2. Now you can use curl, but there is a fair chance that the version of curl doesn't support HTTP2. So, one way is to use a 3rd party to show if it is working with HTTP2...
https://tools.keycdn.com/http2-test
I will do another post about enabling fail2ban. There are some additional filters you can put in place, such as with wordpress login attempts. There are plugins that can write out the login attempts to the auth.log allowing fail2ban to look for those and ban the associated IP. Now, fail2ban isn't magic, it is simply going to prevent brute force login attempts on things like SSH and other filters such as the wordpress logins and xmlrpc requests that are almost always malicious.
If I find I left something out of all this I will post it below.
This is assuming you're running a Debian/Ubuntu based distribution running Apache 2.4.xx (Looks like 2.4.41 is the latest on the Ubuntu repo at this time). Running MySQL 8, PHP 7.4.
For starters, it is generally a good practice to have a SSL certificate for each website. Apache can run multiple websites through virtual hosts. If you need or want to have multiple websites look at some tutorials about how to set up virtual hosts.
This also assumes you want SSH access remotely and have port 22 forwarded, this can be changed to a non-standard port which should result in much less chatter in your /var/log/auth.log.
If you are new to installing a SSL certificate on apache the general steps are
1. Buy the certificate
2. Prove domain ownership. This is done by either adding a DNS record to your domain and/or putting a file on your webserver. This tells the registrar that you have control over the domain.
3. Add the certificate files to your apache's configuration file, usually it is /etc/apache2/apache2.conf
4. Configure your website to use and force HTTPS.
5. For tighter security you can force strong ciphers, disabling SSLv3, TLS1.0, TLS1.1 and so on.
6. Enable HTTP2, this will help your webserver serve up pages faster than HTTP1.1, however a SSL certificate is required. You must also be running up to date versions of PHP and the CMS system you use (e.g. Wordpress).
If you are using SSH you will want to take advantage of key authentication. You can in combination use a passphrase with the key. A key size of 4096 bits is more than sufficient. You can go as large as 8192 but I don't know if all software will support that large and is pretty overkill. Finally, I like fail2ban. It is simple but it does discourage brute force attacks on SSH and website. If too many failed login attempts are detected it will block their IP address for a specified amount of time. Fail2ban requires iptables and if you're using something like ufw you do need to be aware of what order rules come in. So a basic understanding of iptables will be helpful.
At this point, I am going to assume you have bought your certificate and have your key file and intermediate key and so forth. It is best to follow the instructions from your provider for the OS you have. However, if you have multiple websites (perhaps consider a wildcard) you will go into your site's configuration file, usually that is /etc/apache2/sites-available/yourwebsite.conf
You will first want to make sure that apache has SSL support enabled, to do so enable the SSL mod...
Code:
sudo a2enmod ssl
sudo systemctl apache2 restart
Then in your website's conf file you will need to add a permanent redirect to force HTTPS... That can be done with the Redirect permanent...
Keep in mind that will force HTTPS, while in most cases that is what you want, if you want to allow non-secure traffic you can omit the Redirect line.
Next, since we want SSL, you need to have a VirtualHost running on port 443. Your config file should look similar to this. You need to have a path to your website's files shown on DocumentRoot, enable SSLEngine, provide paths to the certificate files. Couple notes, you may need to install and enable mods for apache in order SSL to work. You will also want to set the file permissions appropriately on the certificate files.
Code:
 GNU nano 4.8                                             yourwebsite.net.conf
<VirtualHost *:80>
    DocumentRoot /var/www/yourwebsite.net
    ServerName www.yourwebsite.net
    Redirect permanent / https://www.yourwebsite.net
</VirtualHost>
<VirtualHost *:443>
    ServerName www.yourwebsite.net
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/yourwebsite.net
    SSLEngine On
    SSLCertificateFile /certs/yourwebsite.net/certificate.crt
    SSLCertificateKeyFile /certs/yourwebsite.net/private-key.key
    SSLCertificateChainFile /certs/yourwebsite.net/intermediate.crt
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
There may be other mods you may need to enable depending on your CMS and other software you run with your webserver, for instance if you're running PHP you might consider the fpm-fcgi mod, curl and so forth.
After you make sure your website is up and is happy (make sure to restart apache every time you make a configuration change). If something is wrong you can usually find out by doing
Code:
sudo systemctl apache2 status
Or if you need more information you can refer to apache's log or the journalctl -xe
Code:
tail /var/log/apache2/error.log
Code:
journalctl -xe
Now, if everything is good so far we can now move to enforce strong ciphers. Go back into your site's configuration file and add these:
Code:
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-R>
SSLHonorCipherOrder on
SSLCompression off
SSLSessionTickets off
Now, various cipher suites can change over time, I used this reference for cipher suite lists... Of course the "bad" is that disabling less secure cipher suites can break some older browsers or those who for some reason are still on unsupported OS'es like Windows XP or Windows 7.
Again, after you make this change, make sure to restart apache and verify your website is working as intended. I also would suggest testing with different browsers. Some browsers assume HTTPS while your web server might answer to insecure HTTP. I found this out when I thought the redirect rule wasn't necessary, likewise I put it back in.
If everything passes now you can look at enabling HTTP2. This one can break your website if you're running something like PHP5.6, which is no longer supported, or if your CMS or something about your configuration isn't compatible.
First, there are a couple things, the mods mpm_prefork, php must be disabled before you can enable http2, mpm_event. You may need to install php7.4-fpm, then enable the configuration.
Code:
sudo apt update && sudo apt install php7.4-fpm
Code:
sudo a2dismod mpm_prefork
sudo a2dismod php
sudo systemctl apache2 restart
sudo a2enmod mpm_event
sudo a2enconf php7.4-fpm
sudo a2enmod http2
sudo systemctl apache2 restart
I would check to make sure that apache was able to restart so check it's status
Code:
sudo systemctl apache2 status
If it is running, check that your website is up and running and then we can make the configuration changes in your website's conf file so that apache uses HTTP2.
Go back into your website's conf file and add
Code:
Protocols h2 h2c http/1.1
This allows a HTTP 1.1 fallback.
Code:
<VirtualHost *:443>
    ServerName www.yourwebsite.net
    ServerAdmin webmaster@localhost
    Protocols h2 h2c http/1.1
    DocumentRoot /var/www/yourwebsite.net
    SSLEngine On
    SSLCertificateFile /certs/yourwebsite.net/cerficate.crt
    SSLCertificateKeyFile /certs/yourwebsite.net/private-key.key
    SSLCertificateChainFile /certs/yourwebsite.net/intermediate.crt
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-R>
    SSLHonorCipherOrder on
    SSLCompression off
    SSLSessionTickets off
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Finally, restart apache and check your website. If you discover that your CMS or the software you use does not work with HTTP2 you can revert back to HTTP 1.1 by removing the Protocols directive from the config file. That alone should make things work, but you can do the following:
Code:
sudo a2dismod mpm_event
sudo a2dismod http2
sudo a2disconf php7.4-fpm
sudo systemctl apache2 restart
sudo a2enmod php
sudo a2enmod mpm_prefork
sudo systemctl apache2 restart
Doing the above should reverse the changes to enable HTTP along with removing the Protocols directive in the conf file.
Finally, if everything appears to be working with HTTP2, now you want to make sure that apache actually is serving your site with HTTP2. Now you can use curl, but there is a fair chance that the version of curl doesn't support HTTP2. So, one way is to use a 3rd party to show if it is working with HTTP2...
https://tools.keycdn.com/http2-test
I will do another post about enabling fail2ban. There are some additional filters you can put in place, such as with wordpress login attempts. There are plugins that can write out the login attempts to the auth.log allowing fail2ban to look for those and ban the associated IP. Now, fail2ban isn't magic, it is simply going to prevent brute force login attempts on things like SSH and other filters such as the wordpress logins and xmlrpc requests that are almost always malicious.
If I find I left something out of all this I will post it below.
"I’m not expecting to grow flowers in a desert, but I can live and breathe and see the sun in wintertime"
Check out my stuff!
Check out my stuff!