How to Configure Security Headers in Nginx

Covering the essentials of web server security, this guide will delve into how to configure security headers in Nginx, detailing the process to enhance your server’s defense mechanisms.

Nginx, a staple in modern web server technology, excels in handling high-volume traffic and offers versatile functionalities, especially in server environments. Central to maintaining robust server security is the proper configuration of security headers, which act as a first line of defense against common web threats.

Below are the key features and benefits of configuring these headers:

  • Robust Security Measures: Effectively counteract vulnerabilities like XSS and data injection attacks.
  • Content Security Policy (CSP): Crucial in dictating acceptable sources for content, and preventing malicious data loading.
  • X-Frame-Options: Shields your site from clickjacking by controlling the framing of your content.
  • Strict-Transport-Security (HSTS): Enforces secure connections, mandating the use of HTTPS over HTTP.
  • X-Content-Type-Options: Eliminates MIME type sniffing, thus ensuring files are handled correctly by browsers.
  • Referrer Policy: Manages the transmission of referral data to enhance privacy and security.

Implementing these security headers in Nginx not only fortifies your server against cyber threats but also aligns with best practices in web security management. Let’s proceed to the practical implementation steps to secure your Nginx server.

Implementing HTTP Strict Transport Security (HSTS) in NGINX

Understanding HSTS

HTTP Strict Transport Security (HSTS) is a crucial security protocol for websites, enforcing that connections to a domain are exclusively over HTTPS. It mitigates risks like man-in-the-middle attacks, ensuring integrity and confidentiality of data transmitted online. When a user attempts to access a site via HTTP, HSTS automatically upgrades the connection to HTTPS.

Configuring HSTS in NGINX

To set up HSTS in NGINX, you need to update the server block in the NGINX configuration file. This file typically resides at /etc/nginx/nginx.conf or within site-specific configurations at /etc/nginx/sites-available/. The update involves adding a header that instructs the browser to always use HTTPS for the specified domain.

In the server block for your domain, add the following line:

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

This line contains two components:

  • max-age=31536000: Instructs the browser to remember to use HTTPS for your site for the next 12 months.
  • includeSubDomains: Applies the HSTS policy to all subdomains of your site for comprehensive security.

Sample NGINX Configuration with HSTS

Your NGINX configuration with the HSTS header might 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;
    }
}

After adding this header, reload NGINX to enact the changes with sudo systemctl reload nginx or sudo nginx -s reload.

Additional NGINX Configuration Examples

For different scenarios, your NGINX configuration with HSTS might vary. Here are additional examples:

Multi-Domain Server

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

    location / {
        # Configuration details
    }
}

This configuration applies HSTS to multiple domains hosted on the same server. Each domain listed will enforce HTTPS connections.

Server with SSL Termination

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /path/to/certificate;
    ssl_certificate_key /path/to/private/key;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

    location / {
        # Configuration details
    }
}

This setup is for servers handling SSL termination. It configures HSTS on a secure port (443) with specified SSL certificates, reinforcing secure connections.

Configuring Content-Security-Policy (CSP) in NGINX

Implementing CSP in NGINX

Integrating a Content-Security-Policy (CSP) into NGINX is a strategic move to enhance web application security. It involves adding a specific header within the server block of your NGINX configuration file. Typically found at /etc/nginx/nginx.conf or in the /etc/nginx/sites-available/ directory, this file requires careful editing to effectively apply CSP.

For a fundamental CSP setup, add the following line in the server block:

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

This directive restricts content loading to the website’s own domain (‘self’), significantly reducing the risk of malicious external content execution.

Example NGINX Configuration with CSP

Your NGINX configuration with the basic CSP directive might 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;
    }
}

Reload NGINX with sudo systemctl reload nginx or sudo nginx -s reload after adding this directive.

Customizing CSP for Specific Needs

CSP can be tailored to address specific security needs of your website. Here are expanded configurations for different scenarios:

Allowing Images from Any Source

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

This configuration permits loading images from any source, maintaining strict control over other types of content.

Specific Scripts and Styles Configuration

add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://trustedscript.com; style-src 'self' 'unsafe-inline';";

This setting allows scripts from your own domain and a trusted external source, alongside inline styles, balancing functionality with security.

Exploring CSP Directives and Options

Directives in CSP

CSP directives are rules that define the policy for specific content types. Common directives include:

  • default-src: The default policy applied to most content types.
  • script-src: Governs the sources for JavaScript resources.
  • style-src: Specifies allowed sources for CSS resources.
  • img-src: Controls the sources for image resources.
  • connect-src: Sets policies for network connections like XMLHttpRequest, WebSocket, and EventSource.

Source Expressions in CSP

Source expressions define permissible sources for each directive:

  • 'none': Blocks all sources.
  • 'self': Permits resources from the same origin.
  • 'unsafe-inline': Allows inline resources such as styles or JavaScript URLs.
  • 'unsafe-eval': Permits JavaScript eval() functions and similar methods.
  • https:: Enables resources from any HTTPS URL.

Configuring X-XSS-Protection in NGINX

Introduction to X-XSS-Protection

X-XSS-Protection, known as the Cross-Site Scripting header, is essential for safeguarding web applications from XSS (Cross-Site Scripting) attacks. Supported by major web browsers like Chrome, Internet Explorer, and Safari, this header enhances web security by preventing the loading of pages when reflected XSS attacks are detected.

Enabling X-XSS-Protection in NGINX

Integrating the X-XSS-Protection header into your NGINX server configuration bolsters the browser’s native XSS protection. To enable this security feature, access your NGINX configuration file, typically located at /etc/nginx/nginx.conf or in the /etc/nginx/sites-available/ directory.

In the server block of your NGINX configuration file, insert this directive:

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

This directive comprises two parts:

  • 1: Activates the browser’s XSS Filter.
  • mode=block: Directs the browser to block the page if an XSS attack is detected, rather than attempting to sanitize it.

Example NGINX Configuration with X-XSS-Protection

An example NGINX configuration including X-XSS-Protection might appear as follows:

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;
    }
}

After adding this header, reload NGINX using either sudo systemctl reload nginx or sudo nginx -s reload.

Additional NGINX Configuration Scenarios

For a Server with SSL

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /path/to/certificate;
    ssl_certificate_key /path/to/private/key;
    add_header X-XSS-Protection "1; mode=block";

    # Further configuration
}

This setup is for servers with SSL, ensuring X-XSS-Protection is active on encrypted connections.

Handling Multiple Domains

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

    # Further configuration
}

This configuration applies X-XSS-Protection across multiple domains hosted on a single server.

Configuring X-Frame-Options in NGINX

The Role of X-Frame-Options

X-Frame-Options is an essential security header designed to protect websites from clickjacking attacks. It prevents web pages from being displayed in frames or iframes, which are often used in these types of attacks. Supported by all major web browsers, X-Frame-Options provides widespread protection, enhancing the security of your web presence across different platforms.

Implementing X-Frame-Options in NGINX

Incorporating the X-Frame-Options header in your NGINX server configuration is a crucial step in enhancing your site’s security. This task involves editing the NGINX configuration file, typically found at /etc/nginx/nginx.conf or in the /etc/nginx/sites-available/ directory.

To enable this security feature, add the following directive to the server block in your NGINX configuration file:

add_header X-Frame-Options "DENY";

This directive, set to “DENY,” instructs the browser to block any attempt to render the page in a frame or iframe, offering robust defense against clickjacking.

Example NGINX Configuration with X-Frame-Options

An example NGINX setup with the X-Frame-Options header is as follows:

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;
    }
}

Once you’ve added this header, it’s important to reload NGINX to activate the changes. This can be done using sudo systemctl reload nginx or sudo nginx -s reload.

Expanding NGINX Configuration for X-Frame-Options

For SSL-Enabled Servers

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /path/to/certificate;
    ssl_certificate_key /path/to/private/key;
    add_header X-Frame-Options "DENY";

    # Additional configuration
}

This configuration is for servers with SSL, ensuring X-Frame-Options is enforced on secure connections.

Handling Multiple Domains

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

    # Additional configuration
}

This setup applies the X-Frame-Options header across multiple domains on the same server, bolstering security for each domain.

Implementing X-Content-Type-Options in NGINX

Role of X-Content-Type-Options

X-Content-Type-Options is a vital security header in web security that prevents browsers from MIME type sniffing. This header reinforces that browsers respect the declared content type in HTTP headers, addressing security vulnerabilities that can arise when browsers misinterpret file types, such as treating image files as executable HTML, which could lead to cross-site scripting (XSS) attacks.

Setting Up X-Content-Type-Options in NGINX

To enhance your web server’s security with the X-Content-Type-Options header, a straightforward modification to the NGINX configuration file is required. This file is usually found at /etc/nginx/nginx.conf or within site-specific configurations in /etc/nginx/sites-available/.

Incorporate this header by adding the following line to the server block of your NGINX configuration:

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

The "nosniff" setting directs the browser to strictly follow the server’s specified content type, preventing alternative interpretations of the content.

Example NGINX Configuration with X-Content-Type-Options

An NGINX configuration with X-Content-Type-Options might be structured as follows:

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;
    }
}

After updating your configuration, ensure to reload NGINX for the changes to take effect, using sudo systemctl reload nginx or sudo nginx -s reload.

Expanded NGINX Configuration Examples

Configuration for SSL/TLS

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /path/to/certificate.pem;
    ssl_certificate_key /path/to/key.pem;
    add_header X-Content-Type-Options "nosniff";

    # Additional SSL configurations and locations
}

This setup is for servers with SSL/TLS, applying X-Content-Type-Options on secure connections to enhance security.

Multi-Domain Server Configuration

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

    # Additional configurations for multiple domains
}

This configuration applies the X-Content-Type-Options header across multiple domains hosted on the same server, ensuring consistent security settings across all domains.

Configuring Referrer-Policy in NGINX

The Function of Referrer-Policy

Referrer-Policy is an essential HTTP header for enhancing user privacy and security on the web. It controls how much referral information is included in the Referer header when users navigate from your site to others, protecting sensitive information from exposure in web requests.

Setting Up Referrer-Policy in NGINX

To implement the Referrer-Policy header in your NGINX server, modify the NGINX configuration file, typically found at /etc/nginx/nginx.conf or in the /etc/nginx/sites-available/ directory. Add the following directive to the server block:

add_header Referrer-Policy "no-referrer";

This directive, set to "no-referrer", ensures no referrer information is sent during site navigation, maximizing privacy.

Example NGINX Configuration with Referrer-Policy

Your NGINX configuration with the Referrer-Policy header could 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;
    }
}

After adding this header, reload NGINX with commands like sudo systemctl reload nginx or sudo nginx -s reload.

Referrer-Policy Options and Definitions

  • no-referrer: No referrer information is sent.
  • no-referrer-when-downgrade (default): Sends referrer information for same-origin destinations or for secure (HTTPS) destination URLs from a secure page.
  • origin: Sends the origin (scheme, host, and port) only.
  • origin-when-cross-origin: Sends full URL for same-origin requests but only the origin for other cases.
  • same-origin: Sends a full referrer for same-origin requests but no header for cross-origin requests.
  • strict-origin: Sends the origin for HTTPS requests but no header for HTTP requests.
  • strict-origin-when-cross-origin: Sends full referrer to same-origin requests, origin to HTTPS destinations from HTTPS pages, and no header to HTTP destinations.
  • unsafe-url: Sends full URL regardless of origin or security (not recommended).

Expanded NGINX Configuration Examples

SSL/TLS Configuration

server {
    listen 443 ssl;
    server_name secure.example.com;
    ssl_certificate /path/to/certificate.pem;
    ssl_certificate_key /path/to/key.pem;
    add_header Referrer-Policy "no-referrer";

    # Additional SSL configurations
}

This configuration applies the Referrer-Policy header in a secure, SSL/TLS-enabled environment, enhancing privacy on encrypted connections.

Multi-Domain Server Configuration

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

    # Additional configurations for each domain
}

This setup ensures that the Referrer-Policy header is applied across multiple domains hosted on the same server, maintaining consistent privacy settings.

Implementing Permissions-Policy in NGINX

Understanding Permissions-Policy

The Permissions-Policy header empowers web administrators with precise control over browser features and APIs on their websites. Configuring this header significantly bolsters site security and privacy, enabling feature restrictions such as geolocation, camera, and microphone based on your site’s specific needs.

Configuring Permissions-Policy in NGINX

To incorporate the Permissions-Policy header in your NGINX server, modify the NGINX configuration file, usually located at /etc/nginx/nginx.conf or within the /etc/nginx/sites-available/ directory.

Add the following directive to the server block:

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=();";

This directive lists various browser features and APIs, setting them all to () which effectively disables them. This configuration provides a comprehensive approach to limiting features that could compromise user privacy or security.

Sample NGINX Configuration with Permissions-Policy

Here is an example of how your NGINX configuration might look with the Permissions-Policy header:

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;
    }
}

This directive comprehensively lists various browser features and APIs, setting them to () to effectively disable them.

Sample NGINX Configuration with Permissions-Policy

Your NGINX configuration including Permissions-Policy might appear 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;
    }
}

Reload NGINX with sudo systemctl reload nginx or sudo nginx -s reload after making these changes.

Permissions-Policy Options Explained

The Permissions-Policy header allows you to customize the usage of various features:

  • geolocation: Controls access to geolocation data.
  • midi: Manages access to MIDI devices.
  • notifications: Governs display of notifications.
  • push: Affects push notification functionality.
  • sync-xhr: Relates to synchronous XMLHTTPRequest.
  • accelerometer: Dictates access to the device’s accelerometer.
  • gyroscope: Controls the gyroscope access.
  • magnetometer: Manages access to the device’s magnetometer.
  • payment: Applies to payment request features.
  • usb: Governs access to USB devices.
  • vr: Pertains to virtual reality features.
  • camera: Manages camera access.
  • microphone: Dictates microphone access.
  • speaker: Controls access to speaker devices.
  • vibrate: Affects vibration API.
  • ambient-light-sensor: Relates to the ambient light sensor.
  • autoplay: Controls autoplay of media.
  • encrypted-media: Manages encrypted media access.
  • execute-clipboard: Governs clipboard read/write access.
  • document-domain: Pertains to the document.domain feature.
  • fullscreen: Dictates fullscreen access.
  • imagecapture: Controls image capture functionality.
  • lazyload: Affects lazy loading of images.
  • legacy-image-formats: Relates to legacy image formats.
  • oversized-images: Governs loading of oversized images.
  • unoptimized-lossy-images: Manages unoptimized lossy images.
  • unoptimized-lossless-images: Pertains to unoptimized lossless images.
  • unsized-media: Controls media without explicit size.
  • vertical-scroll: Affects vertical scrolling.
  • web-share: Relates to web sharing features.
  • xr-spatial-tracking: Governs XR spatial tracking.

Advanced Configurations of Permissions-Policy in NGINX

Configuring Permissions-Policy with Specific Domains and Wildcards

Beyond the basic setup of disabling features using (), Permissions-Policy in NGINX can be tailored to permit certain features from specific domains or using wildcards. This advanced configuration allows more nuanced control over what your website can access and from where.

Example: Allowing Features from Specific Domains

server {
    listen 80;
    server_name example.com;
    add_header Permissions-Policy "geolocation=(https://trusteddomain.com), microphone=(https://alloweddomain.com)";

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

This configuration allows geolocation data access only from https://trusteddomain.com and microphone access solely from https://alloweddomain.com, enhancing security by restricting these sensitive features to trusted sources.

Example: Using Wildcards for Broad Permissions

server {
    listen 80;
    server_name example.com;
    add_header Permissions-Policy "camera=*; fullscreen=*";

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

The wildcard * in this setup permits camera access and fullscreen mode from any domain. This approach offers broader permissions, suitable for websites that require extensive feature access from various sources.

Example: Combining Restrictions and Permissions

server {
    listen 80;
    server_name example.com;
    add_header Permissions-Policy "accelerometer=(); gyroscope=(self https://example2.com); payment=*";

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

In this configuration, accelerometer access is disabled, gyroscope access is allowed from the same domain and https://example2.com, and payment requests are permitted from all domains.

Verifying Security Headers with Curl Command in NGINX

Using Curl to Check Security Headers

The curl command is a valuable tool for verifying the configuration of security headers in your NGINX server. It allows you to inspect the headers of your website, confirming that the security headers are correctly set up. This verification step is crucial for ensuring that your web server’s security measures are active and functioning as intended.

Executing the Curl Command for Header Verification

To check the headers of your website, execute the following command in your terminal:

curl -I http://example.com

Replace example.com with your domain name. This command requests the headers from your server, providing insight into the active security configurations.

Expected Output and Interpretation

Upon running the curl command, you should receive output that resembles the following:

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 the presence and correct configuration of various security headers like Strict-Transport-Security, Content-Security-Policy, X-XSS-Protection, and others on your server. Each header listed in the output plays a specific role in securing your web server and protecting it from various web vulnerabilities.

Conclusion

Learning how to configure 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.

Leave a Comment


Your Mastodon Instance
Share to...