#1: Keep Nginx up to date
#2: Remove Unnecessary Modules in Nginx
To explicitly remove modules from Nginx while installing from source, do:
# ./configure --without-module1 --without-module2 --without-module3
For example:
# ./configure --without-http_dav_module --withouthttp_spdy_module
As you will probably guess, removing modules from a previous Nginx installation from source requires performing the compilation again.
A word of caution: Configuration directives are provided by modules. Make sure you don’t disable a module that contains a directive you will need down the road! You should check the nginx docs for the list of directives available in each module before taking a decision on disabling modules.
#3: Disable server_tokens Directive in Nginx
The server_tokens
directive tells Nginx to display its current version on error pages. This is not desirable since you do not want to share that information with the world in order to prevent attacks at your web server caused by known vulnerabilities in that specific version.
To disable the server_tokens
directive, set if to off inside a server block:
server { listen 192.168.0.25:80; Server_tokens off; server_name example.com www.example.com; access_log /var/www/logs/example.access.log; error_log /var/www/logs/example.error.log error; root /var/www/example.com/public_html; index index.html index.htm; }
Restart nginx and verify the changes:
#4: Deny HTTP User Agents in Nginx
A HTTP user agent is a software that is used for content negotiation against a web server. This also includes malware bots and crawlers that may end up impacting your web server’s performance by wasting system resources.
In order to more easily maintain the list of undesired user agents, create a file (/etc/nginx/blockuseragents.rules
for example) with the following contents:
map $http_user_agent $blockedagent { default 0; ~*malicious 1; ~*bot 1; ~*backdoor 1; ~*crawler 1; ~*bandit 1; }
Next, place the following line before the server block definition:
include /etc/nginx/blockuseragents.rules;
And an if statement to return a 403 response if the user agent string is in the blacklist defined above:
include /etc/nginx/blockuseragents.rules; server { listen 192.168.0.25:80; Server_tokens off; server_name example.com www.example.com; access_log /var/www/logs/example.access.log; error_log /var/www/logs/example.error.log error; root /var/www/example.com/public_html; index index.html index.htm; }
Restart nginx, and all user agents whose string matches the above will be blocked from accessing your web server. Replace 192.168.0.25 with your server’s IP and feel free to choose a different string for the --user-agent
switch of wget:
# wget http://192.168.0.25/index.html # wget --user-agent "I am a bandit haha" http://192.168.0.25/index.html
#5: Disable Unwanted HTTP Methods in Nginx
Also known as verbs, HTTP methods indicate the desired action to be taken on a resource served by Nginx. For common web sites and applications, you should only allow GET, POST, and HEAD and disable all others.
To do so, place the following lines inside a server block. A 444 HTTP response means an empty response and is often used in Nginx to fool malware attacks:
if ($request_method !~ ^(GET|HEAD|POST)$) { return 444; }
To test, use curl to send a DELETE request and compare the output to when you send a regular GET:
# curl -X DELETE http://192.168.0.25/index.html # curl -X POST http://192.168.0.25/index.html
#6: Set Buffer Size Limitations in Nginx
To prevent buffer overflow attacks against your Nginx web server, set the following directives in a separate file (create a new file named /etc/nginx/conf.d/buffer.conf
, for example):
client_body_buffer_size 1k; client_header_buffer_size 1k; client_max_body_size 1k; large_client_header_buffers 2 1k;
The directives above will ensure that requests made to your web server will not cause a buffer overflow in your system. Once again, refer to the docs for further details on what each of them does.
Then add an include directive in the configuration file:
include /etc/nginx/conf.d/*.conf;
#7: Limit the Number of Connections by IP in Nginx
In order to limit the connections by IP, use the limit_conn_zone
(in a http context or at least outside the server block) and limit_conn (in a http, server block, or location context) directives.
However, keep in mind that not all connections are counted – but only those that have a request processed by the server and its whole request header has been read.
For example, let’s set the maximum number of connections to 1
(yes, it’s an exaggeration, but it will do the job just fine in this case) in a zone named addr (you can set this to whatever name you wish):
limit_conn_zone $binary_remote_addr zone=addr:5m; limit_conn addr 1;
#8: Setup Monitor Logs for Nginx
#9: Prevent Image Hotlinking in Nginx
Image hotlinking happens when a person displays in another site an image hosted on yours. This causes an increase in your bandwidth use (which you pay for) while the other person happily displays the image as if it was his or her property. In other words, it’s a double loss for you.
For example, let’s say you have a subdirectory named img
inside your server block where you store all the images used in that virtual host. To prevent other sites from using your images, you will need to insert the following location block inside your virtual host definition:
location /img/ { valid_referers none blocked 192.168.0.25; if ($invalid_referer) { return 403; } }
#10: Disable SSL and only Enable TLS in Nginx
Whenever possible, do whatever it takes to avoid SSL in any of its versions and use TLS instead. The following ssl_protocols
should be placed in a server or http context in your virtual host file or is a separate file via an include directive (some people use a file named ssl.conf
, but it’s entirely up to you):
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#11: Create Certificates in Nginx
First off, generate a key and a certificate. Feel free to use a different type of encryption if you want:
# openssl genrsa -aes256 -out example.key 1024 # openssl req -new -key example.key -out example.csr # cp example.key example.key.org # openssl rsa -in example.key.org -out example.key # openssl x509 -req -days 365 -in example.csr -signkey example.key -out example.crt
Then add the following lines inside a separate server block in preparation for the next tip (http --> https
redirection) and move the SSL-related directives to the new block as well:
server { listen 192.168.0.25:443 ssl; server_tokens off; server_name example.com www.example.com; root /var/www/example.com/public_html; ssl_certificate /etc/nginx/sites-enabled/certs/example.crt; ssl_certificate_key /etc/nginx/sites-enabled/certs/example.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; }
In the next tip we will verify how our site is now using a self-signed cert and TLS.
#12: Redirect HTTP traffic to HTTPS in Nginx
Add the following line to the first server block:
return 301 https://$server_name$request_uri;
The above directive will return a 301 (Moved permanently) response, which is used for permanent URL redirection whenever a request is made to port 80 of your virtual host, and will redirect the request to the server block we added in the previous tip.
The image below shows the redirection and confirms the fact that we are using TLS 1.2 and AES-256 for encryption: