Recommended Steps To Harden Apache HTTP on FreeBSD 12.0

The author selected the Free and Open Source Fund to receive a donation as part of the Write for DOnations program.


Although the default installation of an Apache HTTP server is already safe to use, its configuration can be substantially improved with a few modifications. You can complement already present security mechanisms, for example, by setting protections around cookies and headers, so connections can’t be tampered with at the user’s client level. By doing this you can dramatically reduce the possibilities of several attack methods, like Cross-Site Scripting attacks (also known as XSS). You can also prevent other types of attacks, such as Cross-Site Request Forgery, or session hijacking, as well as Denial of Service attacks.

In this tutorial you’ll implement some recommended steps to reduce how much information on your server is exposed. You will verify the directory listings and disable indexing to check the access to resources. You’ll also change the default value of the timeout directive to help mitigate Denial of Service type of attacks. Furthermore you’ll disable the TRACE method so sessions can’t be reversed and hijacked. Finally you’ll secure headers and cookies.

Most of the configuration settings will be applied to the Apache HTTP main configuration file found at /usr/local/etc/apache24/httpd.conf.


Before you begin this guide you’ll need the following:

  • A FreeBSD 12 server set up by following this tutorial on How To Get Started with FreeBSD.

  • A firewall set up following the Configuring a Firewall Section in the Recommended Steps for New FreeBSD 12.0 Servers article.

  • A complete FAMP stack installed by following How To Install an Apache, MySQL, and PHP (FAMP) Stack on FreeBSD 12.0 tutorial.

  • A Let’s Encrypt certificate installed by following the tutorial How To Secure Apache with Let’s Encrypt on FreeBSD.

With the prerequisites in place you have a FreeBSD system with a stack on top able to serve web content using anything written in PHP, such as major CMS software. Furthermore, you’ve encrypted safe connections through Let’s Encrypt.

Reducing Server Information

The operating system banner is a method used by computers, servers, and devices of all kinds to present themselves into networks. Malicious actors can use this information to gain exploits into the relevant systems. In this section you’ll reduce the amount of information published by this banner.

Sets of directives control how this information is displayed. For this purpose the ServerTokens directive is important; by default it displays all details about the operating system and compiled modules to the client that’s connecting to it.

You’ll use a tool for network scanning to check what information is currently revealed prior to applying any changes. To install nmap run the following command:

  • sudo pkg install nmap

To get your server’s IP address, you can run the following command:

  • ifconfig vtnet0 | awk '/inet / {print $2}'

You can check the web server response by using the following command:

  • nmap -sV -p 80 your-server-ip

You invoke nmap to make a scan (hence the -s flag), to display the version (the -V flag) on port 80 (the -p flag) on the given IP or domain.

You’ll receive information about your web server, similar to the following:

OutputStarting Nmap 7.80 ( ) at 2020-01-22 00:30 CET Nmap scan report for Host is up (0.054s latency).  PORT   STATE SERVICE VERSION 80/tcp open  http    Apache httpd 2.4.41 ((FreeBSD) OpenSSL/1.1.1d-freebsd  Service detection performed. Please report any incorrect results at . Nmap done: 1 IP address (1 host up) scanned in 7.59 seconds 

This output shows that information such as the operating system, the Apache HTTP version, and OpenSSL are visible. This can be useful for attackers to gain information about the server and choose the right tools to exploit, for example, a vulnerability in the software running on the server.

You’ll place the ServerTokens directive in the main configuration file since it doesn’t come configured by default. The lack of this configuration makes Apache HTTP display the full information about the server as the documentation states. To limit the information that is revealed about your server and configuration, you’ll place the ServerTokens directive inside the main configuration file.

You’ll place this directive following the ServerName entry in the configuration file. Run the following command to find the directive

  • grep -n 'ServerName' /usr/local/etc/apache24/httpd.conf

You’ll find the line number that you can then search with vi:

Output226    #ServerName 

Run the following command:

  • sudo vi +226 /usr/local/etc/apache24/httpd.conf

Add the following highlighted line:


. . . #ServerName ServerTokens Prod 

Save and exit the file with :wq and ENTER.

Setting the ServerTokens directive to Prod will make it only display that this is an Apache web server.

For this to take effect restart the Apache HTTP server:

  • sudo apachectl restart

To test the changes, run the following command:

  • nmap -sV -p 80 your-server-ip

You’ll see similar output to the following with more minimal information on your Apache web server:

OutputStarting Nmap 7.80 ( ) at 2020-01-22 00:58 CET Nmap scan report for WPressBSD ( Host is up (0.056s latency).  PORT   STATE SERVICE VERSION 80/tcp open  http    Apache httpd  Service detection performed. Please report any incorrect results at . Nmap done: 1 IP address (1 host up) scanned in 7.59 seconds 

You’ve seen what information the server was announcing prior to the change and you’ve now reduced this to the minimum. With this you’re providing fewer clues about your server to an external actor. In the next step you’ll manage the directory listings for your web server.

Managing Directory Listings

In this step you’ll ensure the directory listing is correctly configured, so the right parts of the system are publicly available as intended, while the remainder are protected.

Note: When an argument is declared it is active, but the + can visually reinforce it is in fact enabled. When a minus sign - is placed the argument is denied, for example, Options -Indexes.

Arguments with + and/or - can not be mixed, it is considered bad syntax in Apache HTTP and it may be rejected at the start up.

Adding the statement Options -Indexes will set the content inside the data path /usr/local/www/apache24/data to not index (read listed) automatically if an .html file doesn’t exist, and not show if a URL maps this directory. This will also apply when using virtual host configurations such as the one used for the prerequisite tutorial for the Let’s Encrypt certificate.

You will set the Options directive with the -Indexes argument and with the +FollowSymLinks directive, which will allow symbolic links to be followed. You’ll use the + symbol in order to comply with Apache’s HTTP conventions.

Run the following command to find the line to edit in the configuration file:

  • grep -n 'Options Indexes FollowSymLinks' /usr/local/etc/apache24/httpd.conf

You’ll see output similar to the following:

Output263 :    Options Indexes FollowSymLinks 

Run this command to directly access the line for editing:

  • sudo vi +263 /usr/local/etc/apache24/httpd.conf

Now edit the line as per the configuration:


. . . # Options -Indexes +FollowSymLinks  # . . . 

Save and exit the file with :wq and ENTER.

Restart Apache HTTP to implement these changes:

  • sudo apachectl restart

At your domain in the browser, you’ll see a forbidden access message, also known as the 403 error. This is due to the changes you’ve applied. Placing -Indexes into the Options directive has disabled the auto-index capability of Apache HTTP and therefore there’s no index.html file inside the data path.

You can solve this by placing an index.html file inside the VirtualHost you enabled in the prerequisite tutorial for the Let’s Encrypt certificate. You’ll use the default block within Apache HTTP and place it in the same folder as the DocumentRootthat you declared in the virtual host.


<VirtualHost *:80>     ServerAdmin [email protected]     DocumentRoot "/usr/local/www/apache24/data/"     ServerName     ServerAlias     ErrorLog "/var/log/"     CustomLog "/var/log/" common </VirtualHost> 

Use the following command to do this:

  • sudo cp /usr/local/www/apache24/data/index.html /usr/local/www/apache24/data/

Now you’ll see an It works! message when visiting your domain.

In this section you’ve placed restrictions to the Indexes directive to not automatically enlist and display content other than what you intend. Now if there is not an index.html file inside the data path Apache HTTP will not automatically create an index of contents. In the next step you’ll move beyond obscuring information and customize different directives.

Reducing the Timeout Directive Value

The Timeout directive sets the limit of time Apache HTTP will wait for new input/output before failing the connection request. This failure can occur due to different circumstances such as packets not arriving to the server or data not being confirmed as received by the client.

By default the timeout is set to 60 seconds. In environments where the internet service is slow this default value may be sensible, but one minute is quite a long time particularly if the server is covering a target of users with faster internet service. Furthermore the time during which the server is not closing the connection can be abused to perform Denial of Service attacks (DoS). If a flood of these malicious connections occurs the server will stumble and possibly become saturated and irresponsive.

To change the value you’ll find the Timeout entries in the httpd-default.conf file:

  • grep -n 'Timeout' /usr/local/etc/apache24/extra/httpd-default.conf

You’ll see similar output to:

Output 8  # Timeout: The number of seconds before receives and sends time out. 10  Timeout 60 26  # KeepAliveTimeout: Number of seconds to wait for the next request from the 29  KeepAliveTimeout 5 89  RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500 

In the output line 10 sets the Timeout directive value. To directly access this line run the following command:

  • sudo vi +10 /usr/local/etc/apache24/extra/httpd-default.conf

You’ll change it to 30 seconds, for example, like the following:


# # Timeout: The number of seconds before receives and sends time out. # Timeout 30 

Save and exit the file with :wq and ENTER.

The value of the Timeout directive has to balance a time range large enough for those events to allow a legitimate and successful connection to happen, but short enough to prevent undesired connection attempts.

Note: Denial of Service attacks can drain the server’s resources quite effectively. A complementary and very capable counter measure is using a threaded MPM to get the best performance out of how Apache HTTP handles connections and processes. In this tutorial How To Configure Apache HTTP with MPM Event and PHP-FPM on FreeBSD 12.0 there are steps on enabling this capability.

For this change to take effect restart the Apache HTTP server:

  • sudo apachectl restart

You’ve changed the default value of the Timeout directive in order to partially mitigate DoS attacks.

Disabling the TRACE method

The Hypertext Transport Protocol was developed following a client-server model and as such, the protocol has request methods to retrieve or place information from/to the server. The server needs to understand these sets of methods and the interaction between them. In this step you’ll configure the minimum necessary methods.

TheTRACE method, which was considered harmless, was leveraged to perform Cross Site Tracing attacks. These types of attacks allow malicious actors to steal user sessions through that method. The method was designed for debugging purposes by the server returning the same request originally sent by the client. Because the cookie from the browser’s session is sent to the server it will be sent back again. However, this could potentially be intercepted by a malicious actor, who can then redirect a browser’s connection to a site of their control and not to the original server.

Because of the possibility of the misuse of the TRACE method it is recommended to only use it for debugging and not in production. In this section you’ll disable this method.

Edit the httpd.conf file with the following command and then press G to reach the end of the file:

  • sudo vi /usr/local/etc/apache24/httpd.conf

Add the following entry path at the end of the file:


. . . TraceEnable off 

A good practice is to only specify the methods you’ll use in your Apache HTTP web server. This will help limit potential entry points for malicious actors.

LimitExcept can be useful for this purpose since it will not allow any other methods than those declared in it. For example a configuration can be established like this one:


DocumentRoot "/usr/local/www/apache24/data" <Directory "/usr/local/www/apache24/data">     Options -Indexes +FollowSymLinks -Includes     AllowOverride none      <LimitExcept GET POST HEAD>        deny from all     </LimitExcept>     Require all granted </Directory> 

As declared within the LimitExcept directive only the GET, POST, and HEAD methods are allowed in the configuration.

  • The GET method is part of the HTTP protocol and it is used to retrieve data.
  • The POST method is also part of the HTTP protocol and is used to send data to the server.
  • The HEAD method is similar to GET, however this has no response body.

You’ll use the following command and place the LimitExcept block inside the file:

  • sudo vi +272 /usr/local/etc/apache24/httpd.conf

To set this configuration you’ll place the following block into the DocumentRoot directive entry where the content will be read from, more specifically inside the Directory entry:


. . . <LimitExcept GET POST HEAD>    deny from all </LimitExcept> . . . 

To apply the changes restart Apache HTTP:

  • sudo apachectl restart

The newer directive AllowedMethods provides similar functionality, although its status is still experimental.

You’ve seen what HTTP methods are, their use, and the protection they offer from malicious activity leveraging the TRACE method as well as how to declare what methods to use. Next you’ll work with further protections dedicated to HTTP headers and cookies.

Securing Headers and Cookies

In this step you’ll set specific directives to protect the sessions that the client machines will open when visiting your Apache HTTP web server. This way your server will not load unwanted content, encryption will not be downgraded, and you’ll avoid content sniffing.

Headers are components of the requests methods. There are headers to adjust authentication, communication between server and client, caching, content negotiation, and so on.

Cookies are bits of information sent by the server to the browser. These bits allow the server to recognize the client browser from one computer to another. They also allow servers to recognize user sessions. For example, they can track a shopping cart of a logged-in user, payment information, history, and so on. Cookies are used and retained in the client’s web browser since HTTP is a stateless protocol, meaning once the connection closes the server does not remember the request sent by one client, or another one.

It is important to protect headers as well as cookies because they provide communication between the web browser client and the web server.

The headers module comes activated by default. To check if it’s loaded you’ll use the following command:

  • sudo apachectl -M | grep 'headers'

You’ll see the following output:

Outputheaders_module (shared) 

If you don’t see any output, check if the module is activated inside Apache’s httpd.conf file:

  • grep -n 'mod_headers' /usr/local/etc/apache24/httpd.conf

As output you’ll see an uncommented line referring to the specific module for headers:


. . . 122  LoadModule headers_module libexec/apache24/ . . . 

Remove the hashtag at the beginning of the line, if present, to activate the directive.

By making use of the following Apache HTTP directives you’ll protect headers and cookies from malicious activity to reduce the risk for clients and servers.

Now you’ll set the header’s protection. You’ll place all these header values in one block. You can choose to apply these values as you wish, but all are recommended.

Edit the httpd.conf file with the following command and then press G to reach the end of the file:

  • sudo vi /usr/local/etc/apache24/httpd.conf

Place the following block at the end of the file:


. . . <IfModule mod_headers.c>   # Add security and privacy related headers   Header set Content-Security-Policy "default-src 'self'; upgrade-insecure-requests;"   Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"   Header always edit Set-Cookie (.*) "$1; HttpOnly; Secure"   Header set X-Content-Type-Options "nosniff"   Header set X-XSS-Protection "1; mode=block"   Header set Referrer-Policy "strict-origin"   Header set X-Frame-Options: "deny"   SetEnv modHeadersAvailable true </IfModule> 
  • Header set Strict-Transport-Security "max-age=31536000; includeSubDomains": HTTP Strict Transport Security (HTSTS) is a mechanism for web servers and clients (mainly browsers) to establish communications using only HTTPS. By implementing this you’re avoiding man-in-the-middle attacks, where a third party in between the communication could potentially access the bits, but also tamper with them.

  • Header always edit Set-Cookie (.*) "$1; HttpOnly; Secure": The HttpOnly and Secure flags on headers help prevent cross-site scripting attacks, also known as XSS. Cookies can be misused by attackers to pose as legitimate visitors presenting themselves as someone else (identity theft), or be tampered.

  • Header set Referrer-Policy "strict-origin": The Referrer-Policy header sets what information is included as the referrer information in the header field.

  • Header set Content-Security-Policy "default-src 'self'; upgrade-insecure-requests;": The Content-Security-Policy header (CSP) will completely prevent loading content not specified in the parameters, which is helpful to prevent cross-site scripting (XSS) attacks. There are many possible parameters to configure the policy for this header. The bottom line is configuring it to load content from the same site and upgrade any content with an HTTP origin.

  • Header set X-XSS-Protection "1; mode=block": This supports older browsers that do not cope with Content-Security-Policy headers. The ‘X-XSS-Protection’ header provides protection against Cross-Site Scripting attacks. You do not need to set this header unless you need to support old browser versions, which is rare.

  • Header set X-Frame-Options: "deny": This prevents clickjacking attacks. The 'X-Frame-Options’ header tells a browser if a page can be rendered in a <frame>, <iframe>, <embed>, or <object>. This way content from other sites cannot be embedded into others, preventing clickjacking attacks. Here you’re denying all frame render so the web page can’t be embedded anywhere else, not even inside the same web site. You can adapt this to your needs, if, for example, you must authorize rendering some pages because they are advertisements or collaborations with specific websites.

  • Header set X-Content-Type-Options "nosniff": The 'X-Content-Type-Options’ header controls MIME types so they’re not changed and followed. MIME types are file format standards; they work for text, audio, video, image, and so on. This header blocks malicious actors from content sniffing those files and trying to alter the file types.

Now restart Apache for the changes to take effect:

  • sudo apachectl restart

To check the security levels of your configuration settings, visit the security headers website. Having followed the steps in this tutorial, your domain will score an A grade.

Note: If you make your headers check by visiting and get an F grade it could be because there is no index.html inside the DocumentRoot of your site as instructed at the end of Step 2. If checking your headers you get a different grade than an A or an F, check each Header set line looking for any misspelling that may have caused the downgrade.

In this step you have worked with up to seven settings to improve the security of your headers and cookies. These will help prevent cross-site scripting, clickjacking, and other types of attacks.


In this tutorial you’ve addressed several security aspects, from information disclosure, to protecting sessions, through setting alternative configuration settings for important functionality.

For further resources on hardening Apache, here are some other references:

  • Apache’s HTTP security tips
  • Mozilla’s security guidelines
  • Center for Internet Security audit recommendations for Apache HTTP

For extra tools to protect Apache HTTP:

  • mod_evasive is a useful tool to help mitigate DoS attacks. You can find more detail in the How To Protect Against DoS and DDoS with mod_evasive for Apache tutorial.

  • fail2ban is an intrusion prevention software useful to block repeated login attempts from non-authorized users. You can read more in the How To Protect an Apache Server with Fail2Ban tutorial.

  • ModSecurity is a Web Application Firewall (or WAF) and as such it provides a wide range of possibilities based on predefined rules written by SpyderLabs and community members. You can read more about this in the How To Set Up ModSecurity with Apache tutorial.