Chapter 12
Web Server with Apache

 12.1 Prerequisites
  12.1.1 Assumed Knowledge
  12.1.2 Linux and Network Setup
 12.2 Installing and Running Apache Web Server
  12.2.1 Installing the Web Server
  12.2.2 Important Files
  12.2.3 Testing the Web Server
  12.2.4 Creating Fake Domain Names
  12.2.5 Managing the Web Server
  12.2.6 Viewing Log Files
 12.3 HTTPS and Certificates
  12.3.1 HTTPS Step 1: Create a Certificate Authority
  12.3.2 HTTPS Step 2: Create a Certificate for our Web Server
  12.3.3 HTTPS Step 3: Enable HTTPS in Apache
  12.3.4 HTTPS Step 4: Load the CA Certificate in the Client
  12.3.5 Testing our Web Server

File: nsl/apache.tex, r1670

This chapter demonstrates setting up the Apache web server, including enabling HTTPS with a digital certificate. While system administrators must be able to setup web servers, it is also a valuable skill for software developers and network engineers, as they can be very useful for development and testing. The steps for enabling security features, in particular HTTPS, are quite involved, but serve as an excellent demonstration of security concepts such as public key cryptography, digital signatures and certificates.

12.1 Prerequisites

12.1.1 Assumed Knowledge

This chapter assumes you have knowledge of:

Basic Linux command line skills, as covered in Chapter 4, are assumed. You will need to be able to:

12.1.2 Linux and Network Setup

While a web server is setup on a single computer, to test it is beneficial if you have at least one other computer for a client (the client and server can be on the same computer, but then it is harder to observe communications between the two).

The recommended virtnet (Chapter 3) topology is:

The instructions in this chapter refer to topology 5, where node1 is the client (web browser), node2 is the router and node3 is the server (running Apache web server). The example domains are those pre-configured in virtnet (but can be easily changed by editing the /etc/hosts file—see Section 9.11.2).

12.2 Installing and Running Apache Web Server

12.2.1 Installing the Web Server

You may first need to install Apache web serve (it may already be installed, e.g. on virtnet nodes; trying to install it again won’t hurt):

network@node3:~$ sudo apt install apache2

We can use systemctl (described further in Section 12.2.5) to check if it is running. It should be displayed as “active (running)” when performing:

network@node3:~$ sudo systemctl status apache2

Video: Apache Web Server and HTTPS on Linux (47 min)

12.2.2 Important Files

There are various files and directories that you may need to access when managing the web server. Those you will initially most likely access are:

The main configuration directory for Apache is:

/etc/apache2/

The main configuration file for Apache is:

/etc/apache2/apache2.conf

You can edit these file if you use sudo and your favourite text editor.

Other important configuration files are in the directories:

/etc/apache2/conf.d/
/etc/apache2/sites-available/

In this section we do not try to explain all the details of the apache2.conf file. The default settings are suitable for a basic web server.

An important file specific to the web site is:

/etc/apache2/sites-available/default

This file contains configuration options specific to a site. (You can potentially host multiple sites on the one Apache server).

The web server documents (e.g. the HTML pages that are available via the server) are stored in a base directory:

/var/www/html/
                                                                                      
                                                                                      

By default there is a file called index.html. You can browse the server by entering the URL http://127.0.0.1/ or http://localhost/ to view the web page and test that your server is working.

You can create any files/directories in the base directory which will then be accessible by the web server.

Finally, log files are stored in /var/log/apache2/. Section 12.2.6 gives a brief explanation of the Apache web server log.

12.2.3 Testing the Web Server

Use a web browser, e.g. lynx, wget, to access the web server by IP address. For example, if the web server has IP address 192.168.2.22 and you are on node1 in virtnet:

network@node1:~$ lynx http://192.168.2.22/

12.2.4 Creating Fake Domain Names

As we do not have a real DNS server, we are limited to using just IP addresses to other computers. However you may manually setup fake domain names by editing the /etc/hosts file on all computers. For example, if the web server has IP address 192.168.2.22, on the client we can add the following line to /etc/hosts (Section 9.11.2):

192.168.2.22   www.example.com

You may add multiple IP/domain values, e.g. if you have multiple servers on different IPs. Note that these fake domain names can only be used on computers that have /etc/hosts setup. Section 9.11.2 explains the format of /etc/hosts.

12.2.5 Managing the Web Server

When you install Apache, the web server automatically starts. You may stop, start or restart Apache using the command systemctl

network@node3:~$ sudo systemctl stop apache2
network@node3:~$ sudo systemctl start apache2
network@node3:~$ sudo systemctl restart apache2
                                                                                      
                                                                                      

You can also see the current status, e.g. if it is running:

network@node3:~$ sudo systemctl status apache2

When you make changes to the web server configuration files, those changes do not take effect until you reload the configuration (or restart the server):

network@node3:~$ sudo systemctl reload apache2

Finally, Apache is automatically started when your computer boots. You may disable automatic startup (and similarly, you may enable it):

network@node3:~$ sudo systemctl disable apache2

Video: Managing Apache Web Server with systemctl (5 min; Apr 2018)

12.2.6 Viewing Log Files

Another important file is the log produced by Apache. Apache logs (records) all requests for content on this server. The log is a text file:

/var/log/apache2/access.log

The format of this log file is a space separated file with each line showing details of a single request for a web page on the server. Each line has the following fields:

You should not edit the access.log file. Instead use less or tail to display its contents. less will display the file, page by page:

network@node3:~$ less access.log

The command tail will display the last 10 lines of the file:

network@node3:~$ tail access.log

Video: Apache Web Server Access Log (10 min; Apr 2018)

12.3 HTTPS and Certificates

The remaining steps are enabling HTTPS and creating a certificate for the web server. In the following instructions we assume the IP of the server is 192.168.2.22 and of the client is 192.168.1.11. The domain of the server is www.example.com. The steps are:

  1. Create our own Certificate Authority (CA) on the server. In a real scenario this step would be skipped. Instead we would use another organisation as CA.
  2. Create a certificate for our web server.
  3. Enable HTTPS in Apache.
  4. Load the CA certificate in the client. In a real scenario this step would be skipped. Instead if we use a common CA, the certificate would already be load. It is only needed since we are using our own private CA.

Finally we can test HTTPS using a web browser.

Video: Apache Web Server and HTTPS on Linux (47 min)

12.3.1 HTTPS Step 1: Create a Certificate Authority

In practice, a CA would be an external node. However for this simple demo we will use server as both the CA and the actual web server. So now lets setup the CA on the server.

First our root CA needs its own, self-signed certificate. Generate a RSA public/private key pair. Here we generate a 20148-bit RSA private key using a public exponent (e) of 65537. The key is NOT encrypted with DES (or other ciphers).

network@node3:~$ openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 -out cakey.pem

Next create a self-signed certificate. Enter the details for your CA.

network@node3:~$ openssl req -new -x509 -key cakey.pem -out cacert.pem -days 1095

You will be prompted for information and should set appropriate values, such as:

Now we setup the CA to handle certificate signing requests from other entities (i.e. our web server). OpenSSL uses some default files and directories, which are specified in /usr/lib/ssl/openssl.cnf. Lets create them with the following commands:

network@node3:~$ cd
                                                                                      
                                                                                      
network@node3:~$ mkdir demoCA
network@node3:~$ mkdir demoCA/certs
network@node3:~$ mkdir demoCA/crl
network@node3:~$ mkdir demoCA/newcerts
network@node3:~$ mkdir demoCA/private
network@node3:~$ touch demoCA/index.txt
network@node3:~$ echo 02 > demoCA/serial
network@node3:~$ mv cacert.pem demoCA/
network@node3:~$ mv cakey.pem demoCA/private

The above commands create the necessary directory structure to run a CA. If you make a mistake, then the CA will not be able to correctly issue certificates. In that case, the best approach is to delete the entire demoCA directory (rm -fR ~/demoCA/) and repeat the above commands.

Lastly for the CA setup, OpenSSL has strict policies on the details of the CA matching that of the requesting server. For example, it requires the state of the CA and server to be identical. We can change the policy by editing /usr/lib/ssl/openssl.cnf, in particular the “For the CA policy” section. Edit the configuration file:

network@node3:~$ sudo nano /usr/lib/ssl/openssl.cnf

Find the section “For the CA policy”. Change the values to look like this:

# For the CA policy
[ policy_match ]
countryName             = match
stateOrProvinceName     = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

Now the CA is setup and ready to process certificate signing requests.

12.3.2 HTTPS Step 2: Create a Certificate for our Web Server

To create a certificate for the www.example.com website, first generate a RSA public/private key pair. Here we generate a 2048-bit RSA private key using a public exponent (e) of 65537. The key is NOT encrypted with DES (or other ciphers).

network@node3:~$ openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 -out privkey-www.example.com.pem

The output file (privkey-www.example.com.pem) is plaintext. It contains the private key, encoded as Base64, in between two lines indicating the begin and end of the key.

Next create a certificate request that will be sent to the Certificate Authority. This takes a private key as input (i.e. the file generated above) and produces a .csr certificate request file as output. This is a new certificate request.

network@node3:~$ openssl req -new -key privkey-www.example.com.pem -out certreq-www.example.com.csr

You will be prompted to enter your certificate information:

You will also be prompted for a challenge password. You do NOT want a password - just press ENTER to continue. The value of Common Name MUST be the domain of the website, e.g. www.example.edu. The other values may be different, depending on the policy of the OpenSSL CA.

Send your certificate request file to the CA. Since in this demo both the server and CA are on the same Linux VM, there is no actual sending (the file already is available to the CA).

Now the CA processes the certificate signing request using the following command. Make sure all the file names are correct and the certificate is successfully committed to the database of the CA.

network@node3:~$ openssl ca -in certreq-www.example.com.csr -out cert-www.example.com.pem

The CA will be prompted to sign the certificate (choose y for yes) and commit to the database (choose y for yes).

Finally lets copy the CAs certificate from the demoCA directory, renaming the extension to .crt (which is expected by Apache).

network@node3:~$ cp demoCA/cacert.pem cert-ourca.crt
                                                                                      
                                                                                      

To check all the steps were successful, verify the server certificate:

network@node3:~$ openssl verify -CAfile cert-ourca.crt cert-www.example.com.pem

The output should show OK, e.g.:

cert-www.example.com.pem: OK

12.3.3 HTTPS Step 3: Enable HTTPS in Apache

Now you need to enable HTTPS in Apache, including making both certificates available. First lets copy the files into appropriate directories for Apache to read:

network@node3:~$ sudo cp cert-www.example.com.pem /etc/ssl/certs/
network@node3:~$ sudo cp cert-ourca.crt /etc/ssl/certs/
network@node3:~$ sudo cp privkey-www.example.com.pem /etc/ssl/private/

You should set the permissions on the private key so that no-one else can access it (i.e. only root can).

Now edit the configuration file for the Secure Sockets Layer (SSL) enable website:

network@node3:~$ sudo nano /etc/apache2/sites-available/default-ssl.conf

You need to add in the following line (after the ServerAdmin line):

ServerName www.example.com:443

And you need to comment out the snakeoil certificates and add in three lines:

# SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
# SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
SSLCertificateFile /etc/ssl/certs/cert-www.example.com.pem
SSLCertificateKeyFile /etc/ssl/private/privkey-www.example.com.pem
SSLCACertificateFile /etc/ssl/certs/cert-ourca.crt

Finally, enable the SSL module, the SSL-based website and restart the server:

network@node3:~$ sudo a2enmod ssl
network@node3:~$ sudo a2ensite default-ssl
network@node3:~$ sudo systemctl reload apache2

You can now try testing access to the website with lynx on the client.

12.3.4 HTTPS Step 4: Load the CA Certificate in the Client

Although the web server has its own certificate, signed by a CA, we still get a warning message when accessing the web site from the client. This is because the client (192.168.1.11 in our example) does not trust the CA that signed the servers certificate. We will now add the CA’s certificate to the list of CA certificates trusted by the client.

Perform the following on the client.

Copy the CAs certificate from the server to the client (change the IP address and directory as necessary):

network@node1:~$ scp 192.168.2.22:/home/steven/cert-ourca.crt .

Ubuntu keeps are store of trusted CAs certificates, which is used by lynx when it accesses websites. We need to create a directory for extra CA’s, add our CAs certificate to it, and then re-configure the store to include the new certificate:

network@node1:~$ sudo mkdir /usr/share/ca-certificates/extra
network@node1:~$ sudo cp cert-ourca.crt /usr/share/ca-certificates/extra/
network@node1:~$ sudo dpkg-reconfigure ca-certificates

After running the dpkg-reconfigure command you will be given several options about trust—choose the default—and then presented with a list of CA’s. Scroll down to the bottom until you find cert-ourca.crt and then mark it by pressing space. Then ok.

That’s it. Now test again with lynx and you should find no errors/warnings when connecting to the secure web server.

12.3.5 Testing our Web Server

Of course you can use your web browser on node1 (e.g. lynx) to access the website. You can also test using openssl directly on the client:

network@node1:~$ openssl s_client -connect www.example.com:443

Press Ctrl-C to exit. This command should show details of the certificate and SSL communications.