Nginx Security: How to Secure Your Nginx Server- 15 Ways

Nginx Security: How to Secure Your Nginx Server- 15 Ways. Nginx is a powerful web server that serves millions of websites globally. It sits between the client and the server, handling traffic and http requests. This web server is lightweight an handles huge traffic seamlessly, and serves as a load balancer, cache, and reverse proxy.

To harness the power of Nginx, you must ensure it’s secure at all times. By securing the Nginx server, you protect your websites from malicious compromise. 

This article discusses 15 ways on how to secure your Nginx server. Read on!

15 ways of How to Secure Your Nginx Server

1. Run Nginx as a Non-Root User

There are 2 types of system users: root and non-root users. Root users perform system configurations and non-root users cannot. Running Nginx as the root user is the default setting. When you run it this way, you expose it to various potential security risks. Because anyone who has root access can make configuration changes. 

Running Nginx as root introduces several security risks. It leads to privilege escalation, where attackers gain complete system control, compromising data and system integrity. Root access allows for harmful file system changes, including altering or deleting critical files, disrupting services or compromising components. It also heightens the risk of network attacks, with unauthorized access and data interception becoming more likely.

Always run Nginx as a non-root user at all times. To achieve this, create a new non-root user and edit the Nginx configuration file (sudo nano /etc/nginx/nginx.conf) to instruct Nginx to run as the new user.

2. Use Strong SSL/TLS Settings

Both SSL and TLS are secure data transfer protocols that encrypt data transmitted over an internet connection. Using SSL/TLS encrypts the data transmitted between Nginx and the user’s browser. With this on your HTTP traffic, the protocol changes from HTTP to HTTPS, indicating the presence of a security certificate.

After implementing SSL/TLS, the URL that reaches end users changes from http to https. To configure SSL/TLS make some changes in the server block of the Nginx configuration file. 

An example:

				
					server {
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
    ssl_protocols       TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ...
}

				
			

The ‘listen‘ directive is set to port 443 with the ‘ssl’ parameter to handle HTTPS traffic. The ‘server_name’ directive specifies the domain. The ssl_certificate and ssl_certificate_key directives point to the TLS certificate and its corresponding key. On the other hand, The ssl_protocols and ssl_ciphers directives define the allowed TLS versions and cipher suites.

3. Use GeoIP Blocking

On some occasions, your web server can be targeted by malicious actors from specific locations. In this case block such locations using your GeoIP blocking. Enable GeoIP blocking by determining the user’s location through their IP address. When a user attempts to access a website, their IP address is checked against a database that maps IP addresses to geographic locations. 

To enable this blocking edit the ngx_http_geo_module in the configuration file. This module allows the server administrator to define rules that assign values to variables based on the client’s IP address. It’s crucial to avoid blocking access from the US as the Googlebot resides there, as this can make your website unreachable.

Here is a demonstration of the ngx_http_geo_module:

				
					http {
    # Define a geo block to set values based on client IP
    geo $geo {
        default        0;        # Default value for IPs not listed below
        127.0.0.1      2;        # Specific IP with a unique value
        192.168.1.0/24 1;        # CIDR notation for a range of IPs
        10.1.0.0/16    1;        # Another range using CIDR
        ::1            2;        # IPv6 address example
        2001:0db8::/32 1;        # IPv6 CIDR range
    }

    # Example of a server block using the $geo variable
    server {
        location / {
            # Conditional behavior based on the $geo value
            if ($geo = 0) {
                return 403; # Deny access for IPs not matching any rule
            }
            # Other configurations...
        }
    }
}

				
			

In the above configuration, you define a variable and assign it values based on the client’s IP address. For non-matching IPs, assign a default value of 0. In the server block, the configuration uses this $geo variable to control access. In the event that the variable equals 0, the server returns a 403 Forbidden response. This means that the client’s IP didn’t match any specified range, and therefore, blocks access.

4. Configure Error Pages

Nginx’s error_page module allows you to handle HTTP errors and provide custom responses to various error codes. By customizing error pages, you avoid exposing server details or specific error messages that could be used maliciously.

To configure error pages, create HTML files that define each error type. For example, custom_404.html for a 404 error. Then, include these files in the /usr/share/nginx/html directory. Under etc/nginx/sites-enabled/, edit the error_page directive to specify each error code and the path to the corresponding custom error page.

An example of an error_page handling in Nginx. Ensure you’ve created those custom error pages and the edit the file under /etc/nginx/sites-enabled/:

				
					server {
    listen 80 default_server;
    server_name your_domain.com;

    # Root directory for your website
    root /var/www/your_domain.com/html;

    # Custom error page for 404 Not Found
    error_page 404 /custom_404.html;
    location = /custom_404.html {
        root /usr/share/nginx/html;
        internal;
    }

    # Custom error pages for 500 level errors
    location = /custom_50x.html {
        root /usr/share/nginx/html;
        internal;
    }

    # Other server configuration...
}

				
			

In the above configuration, you create custom HTML error pages and place them in the /usr/share/nginx/html directory. Then, configure the Nginx server block, typically located in /etc/nginx/sites-available/ to use these pages. The error_page directive specifies custom error pages for different HTTP status codes.

After editing, test the configuration for syntax errors using the sudo nginx -t command. If the test is successful, restart Nginx to apply the changes. This process ensures that custom error pages are served in response to specific HTTP errors to conceal server details.

5. Utilize Secure Headers

Security headers in Nginx provide instructions to the browser on how to handle content and establish secure connections. This helps improve websites security and mitigating vulnerabilities.

The top security headers include:

  • HTTP Strict Transport Security (HSTS): Your domain is only accessible using HTTPS. It upgrades any connection to HTTPS, even if the user enters a plain HTTP link. To set this header, add add_header Strict-Transport-Security “max-age=31536000; includeSubDomains”; to the server block in the configuration file.
  • Content-Security-Policy (CSP): Helps protect your server from malicious injections and Cross-Site Scripting (XSS) by specifying where content can be loaded from. To configure CSP, add add_header Content-Security-Policy “default-src ‘self’;” always; to the server block.
  • X-XSS-Protection: Defends the server against XSS attacks by preventing pages from loading when reflected XSS attacks are detected. Configure it with the add_header X-XSS-Protection “1; mode=block”; option.
  • X-Frame-Options: Protects your server against clickjacking attacks by disabling iframes. Include the add_header X-Frame-Options “DENY”; option to enable this configuration.
  • X-Content-Type-Options: Ensures that browsers won’t misinterpret files with incorrect content types as they often lead to XSS attacks. To configure, add the following line in the server’s config file: add_header X-Content-Type-Options “nosniff”;.
  • Referrer-Policy: Controls the amount of referrer information sent with requests, enhancing privacy. Add this line in the config file: add_header Referrer-Policy “no-referrer”;.

Each of these headers plays a specific role in securing your server. After configuring, ensure you test them to ensure they are correctly set up.

6. Implement Fail2Ban to Mitigate Security Threats

Another important aspect of Nginx Security: How to Secure Your Nginx Server- 15 Ways is to implement Fail2Ban. An intrusion prevention software that helps secure your Nginx servers against brute-force attacks. It monitors log files for suspicious behavior: repeated failed login attempts, and then bans the source IP addresses for a specified duration. Upon detecting suspicious activity, Fail2Ban automatically modifies the server’s firewall rules to temporarily ban the offending IP address. This ban prevents the attacker from making further attempts.

Moreover, Fail2Ban allows customization of security policies. Define the number of failed attempts to trigger a ban, the duration and even specify actions like sending email alerts. To configure Fail2Ban, set up “jails” for various services. Each jail specifies the log file to monitor, the patterns to look for alongside actions to take upon detecting a pattern.

7. Use NGINX App Protect

NGINX App Protect is a robust security solution that integrates into DevOps environments, offering both web application firewall (WAF) and Layer 7 Denial-of-Service (DoS) defense capabilities. Designed to be platform-agnostic, effective in distributed architectures and hybrid environments.

Exceeds basic OWASP Top 10 protection by incorporating over 7,500 advanced signatures, bot signatures, and threat campaign protection, making it a robust choice for modern web security needs.

 Its high performance with lower latency compared to alternatives like AWS WAF ensures efficient operation with reduced compute costs.

8. Disable Unused Nginx Modules

This helps improve the security of your server. By default NGINX, includes many modules that may not be necessary for all use cases. 

To disable, begin by identifying which modules you don’t need. Use the –without-<module-name>_module option to exclude specific modules. You must be sure that when disabling a module, you won’t negatively impact other essential server functions.

9. Disable Nginx Server Tokens

 Revealing the Nginx version could lead to exposure of the information, allowing unauthorized users to identify the specific version of Nginx you are running. This can be a security risk if that version has known vulnerabilities.

To disable server_tokens, modify the Nginx configfil. e as follows:

				
					http {
    ...
    server_tokens off;
    ...
}
				
			

Then, restart the server to apply the changes.

10. Configure Logging

Nginx server logs ensure that you capture detailed information about both errors and processed requests. The error log is particularly important; as it records issues alongside severity levers. The error_log by default, includes all messages above the specified severity level. For instance, set the level at which you receive warning for certain errors. 

11. Control Resources and Limits

Setting resource limitations helps avoid DoS attacks. Here are some of the resource limits to configure:

Buffer Size Limits

  • client_body_buffer_size: Specifies the client request body buffer size. Set it to a lower value, like 1k to manage memory usage more effectively, especially under high load.
  • client_header_buffer_size: Determines the buffer size for the client request header. A size of 1k is usually sufficient for most requests.
  • client_max_body_size: Sets the maximum acceptable body size for a client request. Increase this value to cater for file uploads.
  • large_client_header_buffers: Configures the maximum number and size of buffers for reading large client request headers. For instance, large_client_header_buffers 2 1k allows a maximum of 2kB of data for URI.

Here is a simple illustration:

				
					http {
    # Other http configurations...

    client_body_buffer_size 1k;

    client_header_buffer_size 1k;

    client_max_body_size 8m;  # Example value, adjust as needed

    large_client_header_buffers 2 1k;  # Allows up to 2kB for request URI

    # Other server configurations...

}

				
			

Request Rate Limit

The limit_req parameter helps control the rate of requests. It allows you to set a maximum request rate, often in requests per second.

Connection Limit

Use the limit_conn directive to restrict the number of connections to a specific proxied resource. For example, limit_conn my_resource 10; in the HTTP block limits connections to 10 for my_resource.

12. Install ModSecurity

ModSecurity is an open-source web application firewall that protects Nginx server from various attacks such as SQL injections and Cross Site Scripting. it works by  applying a set of predefined or custom rules to detect and mitigate various types of web application attacks.

Below is how to configure on Nginx server:

  • Install the necessary dependencies :
				
					sudo apt-get install bison build-essential ca-certificates curl dh-autoreconf doxygen \
flex gawk git iputils-ping libcurl4-gnutls-dev libexpat1-dev libgeoip-dev liblmdb-dev \
libpcre3-dev libpcre++-dev libssl-dev libtool libxml2 libxml2-dev libyajl-dev locales \
lua5.3-dev pkg-config wget zlib1g-dev zlibc libxslt libgd-dev

				
			
  • Clone the ModSecurity repository and build it from the GitHub repository below. With these repositories, you can clone the ModSecurity repository, initialize submodules, and build the ModSecurity library:
				
					git clone https://github.com/SpiderLabs/ModSecurity
cd ModSecurity
sudo git submodule init
sudo git submodule update
sudo ./build.sh
sudo ./configure
sudo make
sudo make install

				
			
  • Clone the ModSecurity-nginx connector using the command below:
				
					cd /opt &amp;&amp; sudo git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git

				
			
  • Then, build the build the ModSecurity module with the actual Nginx version:
				
					nginx -v
cd /opt &amp;&amp; sudo wget http://nginx.org/download/nginx-[your-version].tar.gz
sudo tar -xvzf nginx-[your-version].tar.gz #your-version is the actual Nginx version
cd nginx-[your-version]

				
			
  • After extracting Nginx, compile the ModSecurity module:
				
					sudo ./configure --add-dynamic-module=../ModSecurity-nginx [your-configure-arguments]
sudo make modules

				
			
  • Create a directory for the ModSecurity module and copy the compiled module:
				
					sudo mkdir /etc/nginx/modules
sudo cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules

				
			
  • Then, edit the /etc/nginx/nginx.conf file to load the module:
				
					load_module /etc/nginx/modules/ngx_http_modsecurity_module.so;
				
			

Setup OWASP-CRS

  • Set up OWASP-CRS
				
					sudo rm -rf /usr/share/modsecurity-crs
sudo git clone https://github.com/coreruleset/coreruleset /usr/local/modsecurity-crs
sudo mv /usr/local/modsecurity-crs/crs-setup.conf.example /usr/local/modsecurity-crs/crs-setup.conf
sudo mv /usr/local/modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example /usr/local/modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf

				
			
  • Create a ModSecurity directory in Nginx and copy necessary files
				
					sudo mkdir -p /etc/nginx/modsec
sudo cp /opt/ModSecurity/unicode.mapping /etc/nginx/modsec
sudo cp /opt/ModSecurity/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf
				
			
  • Then, enable ModSecurity in the configuration file:
				
					sudo cp /etc/nginx/modsec/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf
				
			
  • Edit /etc/nginx/modsec/modsecurity.conf to set ‘SecRuleEngine On’. In your site’s Nginx configuration file (e.g., /etc/nginx/sites-available/default), enable ModSecurity:
				
					modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
				
			

Finally, restart Nginx to apply the changes.

13. Monitor Nginx Access Logs

Access logs in NGINX help monitor traffic patterns and server performance by analyzing request patterns. They also play a key role in troubleshooting into HTTP request and response errors for effective problem-solving. Additionally, they provide valuable audit trails for compliance and post-incident analysis in various regulatory contexts.

To configuring NGINX access logs set up the log_format and access_log directives to customize the information that gets logged and the location/format of the log file:

				
					http {
    log_format compression '$remote_addr - $remote_user [$time_local] '
                           '"$request" $status $body_bytes_sent '
                           '"$http_referer" "$http_user_agent" "$gzip_ratio"';

    server {
        gzip on;
        access_log /spool/logs/nginx-access.log compression;
        ...
    }
}

				
			

Tailor the NGINX access logs to your specific needs.

14. Set Up JWT Authentication

JWT (JSON Web Token) encodes user data and state in a compact, URL-safe format. Mainly used for securely transmitting information across parties, particularly useful in stateless authentication scenarios like APIs and microservices. To secure your Nginx server with JWT validate the tokens provided by clients to ensure they have the necessary permissions. 

To set up use the ngx_http_auth_jwt_module. A basic example of how to configure it:

				
					http {
    # Load the JWT module
    load_module modules/ngx_http_auth_jwt_module.so;

    # Server configuration
    server {
        # Other server configurations...

        # Location block where you want to enable JWT authentication
        location /protected {
            # Enable JWT authentication
            auth_jwt "closed area";
            auth_jwt_key_file conf/keys/jwt.key;  # Path to the key file

            # Other configurations...
        }
    }
}

				
			

In this example, auth_jwt enables JWT authentication for the specified location. On the other hand, auth_jwt_key_file specifies the path to the key file used for validating the JWTs.

This setup ensures that only requests with a valid JWT can access to the protected resources. Any requests without a valid JWT or with an invalid JWT won’t gain access.

15. Limit Bandwidth

Limiting bandwidth in NGINX helps manage server resources and ensure fair usage among clients. You prevent individual users from consuming excessive bandwidth. Especially important in shared hosting environments or when serving large files. Also, it helps mitigate resource hogging and potential DoS attacks.

To implement bandwidth limiting, use the limit_rate directive. This directive sets the maximum data transfer rate per connection. For example, to limit the download speed to 200 kilobytes per second in a specific location, configure it as follows:

				
					location /download/ {
    limit_rate 200k;
}
				
			

Also restrict the number of connections. The limit_conn directive allows you to set a maximum number of connections per IP address:

				
					location /download/ {
    limit_conn addr 1;  # One connection per IP
    limit_rate 200k;     # Limit rate to 200 kilobytes per second
}

				
			

Thank you for reading Nginx Security: How to Secure Your Nginx Server- 15 Ways. Let’s conclude the topic. 

Nginx Security: How to Secure Your Nginx Server- 15 Ways Conclusion

The above are some of the ways you secure your Nginx server. As evident, most of the security happens on the configuration files. Ensure that your config files are well implemented so as to prevent server attacks. Also, it’s crucial to implement continuous server monitoring to be up to date with all server activities.

Avatar for Dennis Muvaa
Dennis Muvaa

Dennis is an expert content writer and SEO strategist in cloud technologies such as AWS, Azure, and GCP. He's also experienced in cybersecurity, big data, and AI.

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x