How to Configure Security Headers in Nginx

In this article, we will discuss how to improve the security of your web server by implementing various security headers in NGINX. By utilizing security headers, you can safeguard your website against a wide range of web-based attacks and ensure the protection of user data.

What are Security Headers in Nginx?

Security headers are a set of HTTP response headers that web servers, like NGINX, use to enhance the security of a website. These headers provide instructions to the user’s browser on handling content and establishing secure connections, ultimately mitigating potential vulnerabilities and attacks. By implementing security headers in your NGINX configuration, you can better protect your website and its users from common threats such as cross-site scripting, clickjacking, and man-in-the-middle attacks.

HTTP Strict Transport Security (HSTS)

HTTP Strict Transport Security (HSTS) is a security feature that ensures a domain can only be accessed using HTTPS. By implementing HSTS, the browser will strictly upgrade any connection to HTTPS, even if the user enters or follows a plain HTTP link.

Configuring HSTS in NGINX

To configure HSTS in NGINX, add the following line to the server block in your NGINX configuration file:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

Your NGINX configuration file should look like this:

upstream my_portal {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name example.com;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

    location / {
        proxy_pass http://my_portal;
    }
}

Save your changes and reload NGINX.

Content-Security-Policy (CSP)

Content-Security-Policy (CSP) is a powerful security feature that helps prevent a wide range of attacks, such as Cross-Site Scripting (XSS) and data injection attacks. It allows you to specify the sources of content that can be loaded and executed by a web page. By setting up a CSP, you can effectively mitigate the risk of content injection attacks.

Configuring CSP in NGINX

To configure CSP in NGINX, add the following line to the server block in your NGINX configuration file:

add_header Content-Security-Policy "default-src 'self';" always;

Your NGINX configuration file should look like this:

upstream my_portal {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name example.com;
    add_header Content-Security-Policy "default-src 'self';" always;

    location / {
        proxy_pass http://my_portal;
    }
}

Save your changes and reload NGINX.

Exploring CSP Policy Options

The above example is a basic CSP policy that only allows resources from the same origin. However, CSP offers various directives and options for fine-tuning your security policy.

Directives

CSP directives define the policy for specific types of content. Some common directives include:

  • default-src: Sets the default policy for most content types.
  • script-src: Defines the policy for JavaScript resources.
  • style-src: Specifies the policy for CSS resources.
  • img-src: Determines the policy for image resources.
  • connect-src: Sets the policy for XMLHttpRequest, WebSocket, and EventSource connections.

Source Expressions

Source expressions define the allowed sources for a specific directive. Some common source expressions are:

  • 'none': No sources are allowed.
  • 'self': Only resources from the same origin are allowed.
  • 'unsafe-inline': Allows the use of inline resources (e.g., <style> elements or javascript: URLs).
  • 'unsafe-eval': Allows the use of eval() and similar JavaScript functions.
  • https:: Allows resources from any HTTPS URL.

You can create custom CSP policies by combining various directives and source expressions. For example, to allow images from any source and only allow scripts from the same origin, you could use the following CSP policy:

add_header Content-Security-Policy "default-src 'self'; img-src *;" always;

Keep in mind that creating a strong CSP policy requires careful consideration of the specific security needs of your website or application. It’s essential to test your policy thoroughly to ensure it doesn’t inadvertently block legitimate content or create a false sense of security.

X-XSS-Protection

X-XSS-Protection, also known as the Cross-Site Scripting header, is used to defend against Cross-Site Scripting attacks. XSS Filter is enabled by default in modern web browsers such as Chrome, IE, and Safari. This header prevents pages from loading when they detect reflected cross-site scripting (XSS) attacks.

Configuring X-XSS-Protection in NGINX

To enable the X-XSS-Protection header in your NGINX web server, add the following line in your NGINX configuration file:

add_header X-XSS-Protection "1; mode=block";

Your NGINX configuration file should look like this:

upstream my_portal {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name example.com;
    add_header X-XSS-Protection "1; mode=block";

    location / {
        proxy_pass http://my_portal;
    }
}

Save your changes and reload NGINX.

X-Frame-Options

The X-Frame-Options header is used to defend your website from clickjacking attacks by disabling iframes on your site. Currently, it is supported by all major web browsers. With this header, you tell the browser not to embed your web page in frame/iframe.

Configuring X-Frame-Options in NGINX

To enable the X-Frame-Options header in your NGINX web server, add the following line in your NGINX configuration file:

add_header X-Frame-Options "DENY";

Your NGINX configuration file should look like this:

upstream my_portal {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name example.com;
    add_header X-Frame-Options "DENY";

    location / {
        proxy_pass http://my_portal;
    }
}

Save your changes and reload NGINX.

X-Content-Type-Options

The X-Content-Type-Options header prevents browsers from interpreting files with incorrect content types. This behavior might lead to otherwise “safe” content, such as images, being rendered as HTML, enabling cross-site scripting attacks in certain conditions.

Configuring X-Content-Type-Options in NGINX

To enable the X-Content-Type-Options header in your NGINX web server, add the following line in your NGINX configuration file:

add_header X-Content-Type-Options "nosniff";

Your NGINX configuration file should look like this:

upstream my_portal {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name example.com;
    add_header X-Content-Type-Options "nosniff";

    location / {
        proxy_pass http://my_portal;
    }
}

Save your changes and reload NGINX.

Referrer-Policy

The Referrer-Policy header controls the amount of information included in the Referer header when navigating from your site to other sites. This header helps protect user privacy by preventing the amount of referrer information sent with requests.

Configuring Referrer-Policy in NGINX

To enable the Referrer-Policy header in your NGINX web server, add the following line in your NGINX configuration file:

add_header Referrer-Policy "no-referrer";

Your NGINX configuration file should look like this:

upstream my_portal {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name example.com;
    add_header Referrer-Policy "no-referrer";

    location / {
        proxy_pass http://my_portal;
    }
}

Save your changes and reload NGINX.

Feature Policy

Feature Policy is a security feature that allows you to selectively enable or disable browser features and APIs on your website. However, the Permissions-Policy header has replaced the Feature Policy header as of 2020. The Permissions-Policy header provides similar functionality, giving you more control over browser features and APIs while enhancing security and privacy. Since Feature Policy is considered obsolete, it is recommended to use the Permissions Policy instead.

Permissions-Policy

The Permissions-Policy header lets you control which browser features and APIs can be used on your site. By configuring this header, you can enhance the security and privacy of your site by limiting the use of certain features.

Configuring Permissions-Policy in NGINX

To enable the Permissions-Policy header in your NGINX web server, add the following line in your NGINX configuration file:

add_header Permissions-Policy "geolocation=(); midi=(); notifications=(); push=(); sync-xhr=(); accelerometer=(); gyroscope=(); magnetometer=(); payment=(); usb=(); vr=(); camera=(); microphone=(); speaker=(); vibrate=(); ambient-light-sensor=(); autoplay=(); encrypted-media=(); execute-clipboard=(); document-domain=(); fullscreen=(); imagecapture=(); lazyload=(); legacy-image-formats=(); oversized-images=(); unoptimized-lossy-images=(); unoptimized-lossless-images=(); unsized-media=(); vertical-scroll=(); web-share=(); xr-spatial-tracking=();";

Your NGINX configuration file should look like this:

upstream my_portal {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name example.com;
    add_header Permissions-Policy "geolocation=(); midi=(); notifications=(); push=(); sync-xhr=(); accelerometer=(); gyroscope=(); magnetometer=(); payment=(); usb=(); vr=(); camera=(); microphone=(); speaker=(); vibrate=(); ambient-light-sensor=(); autoplay=(); encrypted-media=(); execute-clipboard=(); document-domain=(); fullscreen=(); imagecapture=(); lazyload=(); legacy-image-formats=(); oversized-images=(); unoptimized-lossy-images=(); unoptimized-lossless-images=(); unsized-media=(); vertical-scroll=(); web-share=(); xr-spatial-tracking=();";

    location / {
        proxy_pass http://my_portal;
    }
}

Save your changes and reload NGINX.

Verify Security Header with Curl Command

You can use the curl command to check the headers for your website and confirm that your security headers are correctly configured.

Run the following command in your terminal, replacing “example.com” with your domain:

curl -I http://example.com

You should see output similar to the following, which includes the security headers you configured:

HTTP/1.1 200 OK
Server: nginx
Date: Mon, 20 Mar 2023 00:00:00 GMT
Content-Type: text/html
Connection: keep-alive
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self';
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: no-referrer
Permissions-Policy: geolocation=(); midi=(); notifications=(); push=(); sync-xhr=(); accelerometer=(); gyroscope=(); magnetometer=(); payment=(); usb=(); vr=(); camera=(); microphone=(); speaker=(); vibrate=(); ambient-light-sensor=(); autoplay=(); encrypted-media=(); execute-clipboard=(); document-domain=(); fullscreen=(); imagecapture=(); lazyload=(); legacy-image-formats=(); oversized-images=(); unoptimized-lossy-images=(); unoptimized-lossless-images=(); unsized-media=(); vertical-scroll=(); web-share=(); xr-spatial-tracking=();"

This output confirms that your security headers are correctly set up.

Conclusion

Implementing security headers in NGINX is crucial to improving your website’s security. By following the steps outlined in this article, you can configure various security headers, such as HSTS, CSP, X-XSS-Protection, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, and Permissions-Policy. These headers will better protect your website against common web-based attacks and vulnerabilities.

Relevant Links and Additional Resources

By exploring these resources, you can gain further knowledge and insights into configuring and optimizing security headers for your website.

Share to...