Skip to content

Latest commit

 

History

History
782 lines (579 loc) · 24.9 KB

File metadata and controls

782 lines (579 loc) · 24.9 KB

Server setup guide

Introduction

This file contains the Apache Server installation section of my personal guide to set up an Ubuntu server. The introduction to this guide as well as its full Table of Contents can be found on the README.md file of this repository. The Table of Contents of this section is listed below.

Table of Contents

  1. Software Installation

    1. Apache Server installation
      1. Install Apache
      2. Set up the firewall
      3. Check the Apache Server
      4. Change the Apache Server web root folder
      5. Set up the default directory to be served by Apache Web Server
      6. Set permissions for the Apache Server root folder
      7. Keep the Apache Server root folder access permissions consistent with a cron job
      8. Install & Configure ModSecurity

2.1. Apache Server installation

2.1.1. Install Apache

Install the Apache Server with the following commands:

sudo apt update && sudo apt install apache2

To confirm that the installation was successful and to get the installed Apache Server version, execute the following command:

apache2 -v

2.1.2. Set up the firewall

List the ufw application profiles wit the following command:

sudo ufw app list

Check the firewall status with the following command:

sudo ufw status

Enable the ufw profile that opens both port 80 (normal, unencrypted web traffic) and port 443 (TLS/SSL encrypted traffic) with the following command:

sudo ufw allow 'Apache Full'

Check again the firewall status with the following command:

sudo ufw status

2.1.3. Check the Apache Server

Check if the Apache Server service is active with the following command:

sudo systemctl status apache2.service -l --no-pager

If the Apache AH00558 configuration error is shown, it's necessary to edit the configuration file /etc/apache2/apache2.conf. Open the file with the following command:

sudo nano /etc/apache2/apache2.conf

Within this file, use the command CTRL + W to search for the directive ServerName. If it isn't present, as instructed on this Digital Ocean Tutorial, add to the bottom of the file the following snippet:

# Fix the Apache AH00558 configuration error
ServerName localhost

Save the changes with the command CTRL + O and then exit the nano text editor with the command CTRL + X.

After making the above-mentioned modifications in the Apache Server configuration, validate it with the following command:

sudo apachectl configtest

If everything is correct, make the changes effective, running the following command:

sudo systemctl restart apache2

Check if the Apache Server service is active with the following command:

sudo systemctl status apache2.service -l --no-pager

To check if Apache Server is running correctly, replace the placeholder in the below URL as appropriate and enter it into a browser’s address bar.

http://{SERVER_IP_ADDRESS}/

Palceholder Definition

  • {SERVER_IP_ADDRESS} : IP Address of the server that can be obtained with the command hostname -I or the command curl -4 icanhazip.com

2.1.4. Change the Apache Server web root folder

By default, the Apache Server root folder (where the Virtual Hosts are stored) is the folder /var/www/ but I prefer to use the folder /srv/www/ instead. To create this folder, execute the following commands:

sudo mkdir /srv/www

Check the output of the below command to verify that the folder was properly created.

ls --group-directories-first -la /srv/

The file /etc/apache2/apache2.conf must be edited to allow the Apache Server to access the folder /srv/www/. Use the nano text editor to edit the file apache2.conf with the following command:

sudo nano /etc/apache2/apache2.conf

Within the file, use the command CTRL + W to search for the <Directory directives and comment out the /var/www/ folder directive. When finished, it must look like the below snippet.

#<Directory /var/www/>
#   Options Indexes FollowSymLinks
#   AllowOverride None
#   Require all granted
#</Directory>

And then add the following directive:

<Directory /srv/www/>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

In the above directive, AllowOverride is set to All to allow .htaccess files in the virtual hosts.

Still within the file /etc/apache2/apache2.conf, add the bellow snippet immediately after the ServerName directive.

# Configure the DocumentRoot directive
DocumentRoot /srv/www

After introducing all the changes, save the file with the command CTRL + O and then exit the nano text editor with the command CTRL + X.

Validate the Apache Server configuration with the following command:

sudo apachectl configtest

If everything is correct, make the changes effective, running the following command:

sudo systemctl restart apache2

Check if the Apache Server service is active with the following commands:

sudo systemctl status apache2.service -l --no-pager
apachectl -S

2.1.5. Set up the default directory to be served by Apache Web Server

The directory /srv/www will be used as parent directory of all Virtual Hosts on the server, but the directory /var/www/html will be moved to /srv/www/ to serve as the default directory that is served if a client request doesn’t match any other sites.

Disable the Apache Server default Virtual Host, with the following commands:

sudo a2dissite 000-default.conf
sudo systemctl restart apache2

Copy the content of the Apache Server default server block to the folder /srv/www with the following command:

sudo rsync -av /var/www/html /srv/www

To back up the default Virtual Host configuration file, execute the following command:

sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/000-default.conf.original

Start editing the Apache Server default Virtual Host configuration file with the following command:

sudo nano /etc/apache2/sites-available/000-default.conf

Replace the placeholder* in the below snippet as appropriate and use it to replace the existing directives in the default Virtual Host configuration file.

ServerAdmin {SERVER_ADMIN_EMAIL}
DocumentRoot /srv/www/html

Placeholder Definition

  • {SERVER_ADMIN_EMAIL} : The server's admin e-mail

After introducing all the changes, save the file with the command CTRL + O and then exit the nano text editor with the command CTRL + X.

Validate the Apache Server configuration with the following command:

sudo apachectl configtest

Enable the default Virtual Host configuration file with the following commands:

sudo a2ensite 000-default.conf
sudo systemctl restart apache2

Check if the Apache Server service is active with the following command:

sudo systemctl status apache2.service -l --no-pager

To check if Apache Server is running correctly, replace the placeholder in the below URL as appropriate and enter it into a browser’s address bar.

http://{SERVER_IP_ADDRESS}/

Placeholder Definition

  • {SERVER_IP_ADDRESS} : IP Address of the server that can be obtained with the command hostname -I or the command curl -4 icanhazip.com

2.1.5.1. Customize Apache Server default landing page

To customize Apache Server default landing page, download the custom index.html file to /srv/www/html with the following command:

sudo wget -O /srv/www/html/index.html https://raw.githubusercontent.com/EnduranceCode/server-setup-guide/master/system/srv/www/html/index.html

To check if the Apache Server default landing page was set correctly, replace the placeholder in the below URL as appropriate and enter it into a browser’s address bar.

http://{SERVER_IP_ADDRESS}/

Placeholder Definition

  • {SERVER_IP_ADDRESS} : IP Address of the server that can be obtained with the command hostname -I or the command curl -4 icanhazip.com

2.1.6. Set permissions for the Apache Server root folder

The default owner and group of Apache Server root folder is root:root and that is fine if the server is only serving static content. But, if server is intended to serve dynamic content, this needs to be changed. There's no absolute right way to set this configurations but this answer on ServerFault and this other answer on SuperUser were taken in consideration to set my own configuration.

A good solution for this problem is to use the Apache Server user and group as the owner and group of the server web root folder. On Ubuntu, the Apache Server user and group is www-data. Check the output of the below command to get the user and group of the Apache Server.

apachectl -S

Assuming that www-data is indeed the user that runs Apache Server, set the owner and group of the Apache Server root folder to www-data with the following command:

sudo chown -R www-data:www-data /srv/www

2.1.6.1. Standard permissions for the Apache Server root folder

Set the file permissions for the server root folder with the following commands:

sudo find /srv/www -type d -exec chmod -c 2755 {} +
sudo find /srv/www -type f -exec chmod -c 644 {} +

The umask has to be set accordingly the permissions level set with above command, therefore it must be set to 022. To check the current umaskvalue, execute the following command:

umask

To permanently set the umask value system-wide, open the /etc/profile file with nano text editor using the following command:

sudo nano /etc/profile

Within /etc/profile file, add the below snippet at the beginning of the file.

umask 022

To make the modifications effective, execute the following commands:

source /etc/profile
source ~/.bashrc

To verify if the new umask settings are working as intended, execute the below commands to create a new file and a new directory and then check its listed permissions.

mkdir /tmp/newfolder
touch /tmp/newfile
ls --group-directories-first -la /tmp

2.1.6.2. Add writing permissions on the Apache Server root folder to a regular user

With the standard permissions for the Apache Server root folder set as described above, a regular user won't have writing permissions on the Apache Server root folder. To give a user writing permissions on the Apache Server root folder it's now necessary to add the user to the www-data group. Replace the placeholder in the below command as appropriate and then execute it:

sudo usermod -aG www-data {USER}

Label Definition

  • {USER} : The user account to be added to the www-data group

As explained in this answer on StackExchange, changes to the user's group membership only takes effect when the user logs in. So the user needs to log out and log back in to make these modifications effective. If it is really necessary to force the previous group assignment to take effect without logging out, use the trick explained on this answer on StackExchange and execute the below commands. Otherwise, just logout the server and log back in.

newgrp www-data
newgrp $USER

Then, add writing permissions to the group of the Apache Server root folder with the following commands:

sudo find /srv/www -type d -exec chmod -c 2775 {} +
sudo find /srv/www -type f -exec chmod -c 664 {} +

The umask has to be set accordingly the permissions level set with above command, therefore it must be set to 002. To check the current umaskvalue, execute the following command:

umask

To permanently set the umask value system-wide, open the /etc/profile file with nano text editor using the following command:

sudo nano /etc/profile

Within /etc/profile file, add the below snippet at the beginning of the file.

umask 002

For the changes to take effect, execute the following commands:

source /etc/profile
source ~/.bashrc

To verify if the new settings are working as intended, execute the below commands to create a new file and a new directory and then check its listed permissions.

mkdir /tmp/newfolder
touch /tmp/newfile
ls --group-directories-first -la /tmp

2.1.7. Keep the Apache Server root folder access permissions consistent with a cron job

Over the time, there will be some inconsistencies on the permissions of the Apache Server root folder. On the folder system/usr/local/bin of this repository there are two scripts (fixApacheWebRootPermissions.sh and cronJobFixApacheWebRootPermissions.sh) that resets the chosen permissions on the Apache Server root folder. To download and make these scripts executable and available on the system start by downloading it to the /usr/local/bin folder with the following commands:

sudo wget -P /usr/local/bin/ https://raw.githubusercontent.com/EnduranceCode/server-setup-guide/master/system/usr/local/bin/fixApacheWebRootPermissions.sh
sudo wget -P /usr/local/bin/ https://raw.githubusercontent.com/EnduranceCode/server-setup-guide/master/system/usr/local/bin/cronJobFixApacheWebRootPermissions.sh

To check if the files were properly copied, check the output of the following command:

ls --group-directories-first -la /usr/local/bin/

The file /usr/local/bin/fixApacheWebRootPermissions.sh will probably need some modifications to ensure its compatibility with the desired Apache Server root folder permissions. Use the below command to open the file fixApacheWebRootPermissions.sh with the nano text editor.

sudo nano /usr/local/bin/cronJobFixApacheWebRootPermissions.sh

Check if the script is correct, make all the needed (if any) modifications and then save the file with the command CTRL + O and exit the nano text editor with the command CTRL + X.

Repeat the previous process for the file /usr/local/bin/cronJobFixApacheWebRootPermissions.sh with the following command:

sudo nano /usr/local/bin/cronJobFixApacheWebRootPermissions.sh

Make these scripts executable with the following commands:

sudo chmod +x /usr/local/bin/fixApacheWebRootPermissions.sh
sudo chmod +x /usr/local/bin/cronJobFixApacheWebRootPermissions.sh

Check the output of the below command to confirm that the files were properly made executable.

ls --group-directories-first -la /usr/local/bin/

If everything was properly set, both scripts are available to be executed from anywhere in the system.

With these two scripts made executable, it's time to create a cronjob to automate the execution of the script (cronJobFixApacheWebRootPermissions.sh) everyday at 3:00. Edit the root's crontab with the following command:

sudo crontab -e

The above command will open a text editor in the terminal. Append the below snippet to the file opened with the previous command.

#
#
# Daily fix of the Apache's root folder permissions
0 3 * * * /usr/local/bin/cronJobFixApacheWebRootPermissions.sh

After checking that the added commands are correct and well suited for the system, save and close the file. To list the cron jobs created, execute the following command:

sudo crontab -l

2.1.8. Install & Configure ModSecurity

Install the Apache ModSecurity module:

sudo apt update
sudo apt install libapache2-mod-security2

Enable the ModSecurity module:

sudo a2enmod security2

Restart Apache to apply the changes into effect:

sudo systemctl restart apache2

Check if the module is loaded:

apachectl -M | grep security

If the output prints security2_module, it indicates that ModSecurity has been successfully installed and enabled.

By default, ModSecurity runs in a passive "DetectionOnly" mode, so we need to set it to blocking mode:

sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

Edit file /etc/modsecurity/modsecurity.conf with the nano text editor to set ModSecurity to blocking mode:

sudo nano /etc/modsecurity/modsecurity.conf

Within the file, use the command CTRL + W to search for the SecRuleEngine directive and change its value from DetectionOnly to On. When finished, it must look like the following snippet:

SecRuleEngine On

After introducing all the changes, save the file with the command CTRL + O and then exit the nano text editor with the command CTRL + X.

While the default package installation may include an old version of CRS, it is safer to use the files provided by the OWASP CRS Project and available at the OWASP CRS repository. Move to folder /etc/modsecurity/ and clone the repository:

cd /etc/modsecurity/
sudo git clone https://github.com/coreruleset/coreruleset.git

Copy and rename the repository's example configuration file so ModSecurity knows to load it:

sudo cp /etc/modsecurity/coreruleset/crs-setup.conf.example /etc/modsecurity/coreruleset/crs-setup.conf

To ensure that Apache is instructed to load the main ModSecurity configuration (modsecurity.conf), the new CRS setup file (crs-setup.conf) and all the individual attack rules (rules/*.conf), edit the file /etc/modsecurity/modsecurity.conf with the nano text editor:

sudo nano /etc/apache2/mods-enabled/security2.conf

Within the file, use the command CTRL + W to search for the block and update its content in order to look like the following snippet:

<IfModule security2_module>
    # Default Debian dir for modsecurity's persistent data
    SecDataDir /var/cache/modsecurity

    # Include the main ModSecurity configuration
    IncludeOptional /etc/modsecurity/modsecurity.conf

    # CRITICAL: Include the CRS setup file FIRST
    IncludeOptional /etc/modsecurity/coreruleset/crs-setup.conf 

    # CRITICAL: Include all the actual attack rules
    IncludeOptional /etc/modsecurity/coreruleset/rules/*.conf
</IfModule>

Note: Remove (or comment) the previous IncludeOptional lines that point to the default package CRS rules and configuration

After introducing all the changes, save the file with the command CTRL + O and then exit the nano text editor with the command CTRL + X.

The crs-setup.conf file available defines several Paranoia Levels that determines how aggressively the CRS blocks traffic. To start low and increase slowly, edit the file crs-setup.conf with the nano text editor:

sudo nano /etc/modsecurity/coreruleset/crs-setup.conf

Within the file, use the command CTRL + W to search for the rule tx.blocking_paranoia_level and uncomment it to set the Paranoia Level 1. It should be similar to the following snippet:

SecAction \
    "id:900000,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    tag:'OWASP_CRS',\
    ver:'OWASP_CRS/4.22.0-dev',\
    setvar:tx.blocking_paranoia_level=1"

Use the command CTRL + W to search for the rule tx.allowed_methods and uncomment it. The rule should be similar to the following snippet:

SecAction \
    "id:900200,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    tag:'OWASP_CRS',\
    ver:'OWASP_CRS/4.22.0-dev',\
    setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'"

Note: If necessary, edit the list for the tx.allowed_methods variable

Use the command CTRL + W to search for the rule tx.max_num_args and uncomment it. The rule should be similar to the following snippet:

SecAction \
    "id:900300,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    tag:'OWASP_CRS',\
    ver:'OWASP_CRS/4.22.0-dev',\
    setvar:tx.max_num_args=255"

Use the command CTRL + W to search for the rule tx.arg_length and uncomment it. The rule should be similar to the following snippet:

SecAction \
    "id:900320,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    tag:'OWASP_CRS',\
    ver:'OWASP_CRS/4.22.0-dev',\
    setvar:tx.arg_length=400"

Use the command CTRL + W to search for the rule tx.total_arg_length and uncomment it. The rule should be similar to the following snippet:

SecAction \
    "id:900330,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    tag:'OWASP_CRS',\
    ver:'OWASP_CRS/4.22.0-dev',\
    setvar:tx.total_arg_length=64000"

Use the command CTRL + W to search for the rule tx.max_file_size and uncomment it. The rule should be similar to the following snippet:

SecAction \
    "id:900340,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    tag:'OWASP_CRS',\
    ver:'OWASP_CRS/4.22.0-dev',\
    setvar:tx.max_file_size=1048576"

Note: If necessary, edit the value for the tx.max_file_size variable

Use the command CTRL + W to search for the rule tx.combined_file_sizes and uncomment it. The rule should be similar to the following snippet:

SecAction \
    "id:900350,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    tag:'OWASP_CRS',\
    ver:'OWASP_CRS/4.22.0-dev',\
    setvar:tx.combined_file_sizes=1048576"

Note: If necessary, edit the value for the tx.combined_file_sizes variable

Go through the rest of the configuration, with special care on the HTTP Policy Settings, and, if necessary, change the defaults to comply with the server's traffic requirement.

After introducing all the changes, save the file with the command CTRL + O and then exit the nano text editor with the command CTRL + X.

Test the configuration syntax:

sudo apachectl configtest

If you see errors, double-check the file paths and the other modifications made in the previous steps. If you see Syntax OK, proceed and restart the Apache web server:

sudo systemctl restart apache2

Replace the placeholders in the below command as appropriate and verify if ModSecurity is functioning as intended:

curl -I {URL}/?test='1+OR+1=1'

Placeholder Definition

  • {URL} : The domain served by the Apache Server;