How to Harden your Nginx or Apache Server Configuration

Alex Bobes
7 min readJun 22, 2022

--

Securing your NGINX or APACHE web server requires careful consideration of many factors. A good place to begin is by checking your HTTP security headers to see if you are following industry best practices.

A minor change to the web server configuration is often all that’s needed. An additional layer of protection is provided by HTTP security headers, which help to reduce the risk of attacks and security vulnerabilities. For the purpose of this post, we’ll take a closer look at a few of them to show you how to put them into action.

What are HTTP security headers?

Content and HTTP response headers are sent back to the browser whenever a web server responds to a browser request for a page. Headers like Content-Encoding, Cache-Control and Status Codes contain meta data.

HTTP security headers are also included, which tell your browser how to handle your website’s content. Strict-Transport-Security, for example, forces the browser to use HTTPS exclusively. Here, in no particular order, are examples of HTTP security headers that you should know about and consider implementing.

1. X-XSS-Protection

The X-XSS-Protection header is designed to enable modern web browsers’ built-in cross-site scripting (XSS) filtering. Usually this is enabled by default. Internet Explorer 8+, Chrome, and Safari all support X-XSS-Protection. The following is an example of how the header looks like: X-XSS-Protection: 1; mode=block

Enable X-XSS-Protection in NGINX

add_header X-XSS-Protection “1; mode=block” always;

Enable X-XSS-Protection in Apache

header always set X-XSS-Protection “1; mode=block”

2. Content Security Policy

Content security policies are currently supported by all major browsers. This won’t cause any issues if the content is delivered to an older browser; it will just be ignored.

Content-Security-Policy has a wide range of directives that can be used. Scripts from both the current domain (defined by ‘self’) and alexbobes.com are allowed in this example: Content-Security-Policy: script-src ‘self’ https://alexbobes.com

OWASP provides the following list of CSP directives, along with a brief description of each:

  • default-src Define loading policy for all resources type in case of a resource type dedicated directive is not defined (fallback),
  • script-src Define which scripts the protected resource can execute,
  • object-src Define from where the protected resource can load plugins,
  • style-src Define which styles (CSS) the user applies to the protected resource,
  • img-src Define from where the protected resource can load images,
  • media-src Define from where the protected resource can load video and audio,
  • frame-src Define from where the protected resource can embed frames,
  • frame-ancestors Specifies valid parents that may embed a page using <frame>, <iframe>, <object>, <embed>, or <applet>.
  • font-src Define from where the protected resource can load fonts,
  • connect-src Define which URIs the protected resource can load using script interfaces,
  • form-action Define which URIs can be used as the action of HTML form elements,
  • sandbox Specifies an HTML sandbox policy that the user agent applies to the protected resource,
  • script-nonce Define script execution by requiring the presence of the specified nonce on script elements,
  • plugin-types Define the set of plugins that can be invoked by the protected resource by limiting the types of resources that can be embedded,
  • reflected-xss Instructs a user agent to activate or deactivate any heuristics used to filter or block reflected cross-site scripting attacks, equivalent to the effects of the non-standard X-XSS-Protection header,
  • report-uri Specifies a URI to which the user agent sends reports about policy violation

3. X-Frame-Options

The X-Frame-Options header prevents iframes from loading on your website, preventing clickjacking. Browsers that support it include Internet Explorer 8, Google Chrome 4, Mozilla Firefox 3, Apple Safari 4, and Opera 10.5. The following is an example of a X-Frame-Options header: X-Frame-Options: SAMEORIGIN

Enable X-Frame-Options in NGINX

add_header X-Frame-Options “SAMEORIGIN” always;

Enable X-Frame-Options in Apache

header always set X-Frame-Options “SAMEORIGIN”

4. HTTP Strict Transport Security

For extra security, web browsers can only communicate with web servers over HTTPS. This ensures that the connection cannot be established via an insecure HTTP connection that could be vulnerable to attacks.

All modern browsers except Opera Mini and older versions of Internet Explorer support HTTP strict transport security.

Enabling HTTP Strict Transport Security on your origin server is a prerequisite before you can proceed with setting it up. The web server will start adding an additional response header to tell the browser to only communicate over HTTPS once it is enabled on the server side. The response header will look something similar to: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload.

  • max-age: it specifies the maximum number of seconds for which the web server should only deliver via HTTPS.
  • includeSubDomains: not mandatory; all of the site’s subdomains will also be protected by HSTS as a result of defining this directive
    preload: not mandatory; it is possible for the site owner to add their website to Chrome’s “preload list,” which is a list of HTTPS-only sites that have been hardcoded into the browser

Any subsequent visits to http://domain.com will be redirected to https://domain.com if the HTTP Strict Transport Security header is present on the website you are visiting. As long as the expiration time has not expired, the browser will continue to do so. However, the expiration time is updated and refreshed each time the header is delivered to the browser, aiding in the prevention of expiration.

The browser will not let the user access the website if a secure connection cannot be established. An error message will be displayed.

Enable HTTP Strict Transport Security in NGINX

A few simple steps are all that is required to implement HSTS on your server. For information on configuring the web server to use this directive, see the instructions listed below.

add_header Strict-Transport-Security “max-age=63072000; includeSubdomains; preload”;

Enable HTTP Strict Transport Security in Apache

<VirtualHost 0.0.0.0:443>
Header always set Strict-Transport-Security “max-age=63072000; includeSubdomains; preload”
</VirtualHost>

The HSTS response header can be checked by running a curl command:

curl -I https://alexbobes.com/main.css HTTP/1.1 301 Moved Permanently Server: nginx Date: Wednesday, 22 Jul 2022 04:07:45 GMT Content-Type: text/html Content-Length: 178 Connection: keep-alive Location: https://alexbobes.com/main.cssStrict-Transport-Security: max-age=31536000; includeSubdomains; preload

The bottom line is that implementing HTTP Strict Transport Security will help keep your website’s users safe. Insecure HTTP content can be delivered for a variety of reasons, but HSTS helps eliminate that risk, preventing communication interception by attackers.

5. Expect-CT

With the Expect-CT header, websites can report and optionally enforce Certificate Transparency requirements, preventing the use of incorrectly issued certificates. Activating this header tells the browser to check the public CT logs for the certificate’s existence. The following is an example of a header:

Expect-CT: max-age=604800, enforce, report-uri=”https://alexbobes.com/learn"

Enable HTTP Strict Transport Security in NGINX

add_header Expect-CT “max-age=604800, enforce, report-uri=’https://alexbobes.com/learn' always;

Enable HTTP Strict Transport Security in Apache

header always set Expect-CT “max-age=604800, enforce, report-uri=” https://alexbobes.com/learn

6. X-Content-Type-Options

This header prevents browsers like Internet Explorer and Google Chrome from detecting any response other than what is declared in the Content-Type declaration. Drive-by downloads are less likely, and the content is better taken care of as a result. Example of what the header looks like: X-Content-Type-Options: nosniff

Enable X-Content-Type-Options in NGINX

add_header X-Content-Type-Options “nosniff” always;

Enable X-Content-Type-Options in Apache

header always set X-Content-Type-Options “nosniff”

7. Feature-Policy

The Feature-Policy header can be used to allow or deny browser features in its own frame or content or within inline elements like the <iframe>. Feature-Policy headers allows web developers to control how APIs and web features behave in the browser by enabling or disabling them. The header looks like this: Feature-Policy: autoplay ‘none’; camera ‘none’

Enable Feature-Policy in NGINX

add_header Feature-Policy “autoplay ‘none’; camera ‘none’” always;

Enable Feature-Policy in Apache

header always set Feature-Policy “autoplay ‘none’; camera ‘none’”

8. Other Security Improvements for NGINX and Apache

Install ModSecurity for Your Web Server

ModSecurity is a free, open-source module acting like a web application firewall. Filtering, server identity masking, and null-byte attack prevention are some of its features. Real-time traffic monitoring is another feature provided by the module. Following the ModSecurity guide to install mod security will help you strengthen your security options.

Configure SSL and Cipher Suites

NGINX’s default configuration allows the use of insecure older versions of the TLS protocol (ssl protocols TLSv1 TLSv1.1 TLSv1.2 according to official documentation). Attacks like the BEAST attack could result as a result of this. Because of it, I advise you to stop using older TLS protocols and instead switch to newer, more secure TLS versions in your configuration.

Diffie-Hellman key exchange

Using Diffie-Hellman key exchange, even if attackers get their hands on your server’s private key, it will be exponentially more difficult for them to decipher communication between the server and its clients.

Navigate to /etc/ssl/certs/ and generate your DH with OpenSSL: openssl dhparam -out dhparam.pem 4096
Add the following to your Nginx configuration: ssl_dhparam /etc/ssl/certs/dhparam.pem;

Update Your Server Regularly

You should always keep your NGINX or APACHE web server up to date, just like you would with any other piece of software. The directory traversal vulnerability (CVE-2009–3898) that existed in NGINX versions prior to 0.7.63 and 0.8.x versions prior to 0.8.17 was fixed in recent updates. New security features and enhancements are frequently included in software updates as well. The nginx & apache websites have a dedicated section for security advisories, as well as news about the most recent updates.

Originally published at https://alexbobes.com on June 22, 2022.

--

--

Alex Bobes

Technology expert. I’m writing about Web 3.0, Crypto, Blockchain, AI, and other topics. We’re now living in the age of the algorithm.