Here is a summary of some security-related configurations in nginx configuration.

Hide version number

1
2
3
http {
server_tokens off;
}

There are often security vulnerabilities targeting a certain version of nginx. Hiding the nginx version number has become one of the main security optimization methods. Of course, the most important thing is to upgrade and repair vulnerabilities in time.

Enable HTTPS

1
2
3
4
5
6
7
8
9
10
server {
listen 443;
server_name ops-coffee.cn;

ssl on;
ssl_certificate /etc/nginx/server.crt;
ssl_certificate_key /etc/nginx/server.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
}
  • ssl on: open https.
  • ssl_certificate: configure the path of nginx ssl certificate
  • ssl_certificate_key: configure the path of nginx ssl certificate key.
  • ssl_protocols: Specify the ssl protocol version used by the client to establish a connection. If you do not need to be compatible with TSLv1, just remove it.
  • ssl_ciphers: Specify the encryption algorithm used by the client to connect, you can configure a more secure algorithm here.

Add black and white list

Whitelist configuration

1
2
3
4
location /admin/ {
allow 192.168.1.0/24;
deny all;
}

The above means that only hosts in the 192.168.1.0/24 network segment are allowed to access, and all others are denied.

It can also be written as a blacklist to prohibit access to certain addresses and allow all others, for example.

1
2
3
4
location /ops-coffee/ {
deny 192.168.1.0/24;
allow all;
}

More often, client requests will go through layers of proxies, and we need to $http_x_forwarded_for restrict them by passing them, which can be written like this.

1
2
3
4
set $allow false;
if ($http_x_forwarded_for = "211.144.204.2") { set $allow true; }
if ($http_x_forwarded_for ~ "108.2.66.[89]") { set $allow true; }
if ($allow = false) { return 404; }

Add account verification

1
2
3
4
5
6
server {
location / {
auth_basic "please input user&passwd";
auth_basic_user_file key/auth.key;
}
}

limit request method

1
2
3
if ($request_method !~ ^(GET|POST)$ ) {
return 405;
}

$request_method can get the method that requests nginx.

The configuration only allows GET\POST method access, other methods return 405.

Deny User-Agent

1
2
3
if ($http_user_agent ~* LWP::Simple|BBBike|wget|curl) {
return 444;
}

Some lawbreakers may use tools such as wget/curl to scan our website, we can simply prevent it by prohibiting the corresponding user-agent.

The 444 status of Nginx is quite special. If it returns 444, the client will not receive the information returned by the server, just like the website cannot be connected.

Picture anti-leech

1
2
3
4
5
6
location /images/ {
valid_referers none blocked www.ops-coffee.cn ops-coffee.cn;
if ($invalid_referer) {
return 403;
}
}

valid_referers: Validate the referer, where none the referer is allowed to be empty, and blocked requests without protocols are allowed. Except for the above two types, only when the referer is www.ops-coffee.cn or ops-coffee.cn is allowed to access the image resources under images, otherwise return 403.

Of course, you can also redirect requests that do not meet the referer rules to a default image, such as the following.

1
2
3
4
5
6
location /images/ {
valid_referers blocked www.ops-coffee.cn ops-coffee.cn
if ($invalid_referer) {
rewrite ^/images/.*\.(gif|jpg|jpeg|png)$ /static/qrcode.jpg last;
}
}

Control the number of concurrent connections

ngx_http_limit_conn_module the number of concurrent connections of an IP can be limited by the module.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
http {
limit_conn_zone $binary_remote_addr zone=ops:10m;

server {
listen 80;
server_name ops-coffee.cn;

root /home/project/webapp;
index index.html;

location / {
limit_conn ops 10;
}

access_log /tmp/nginx_access.log main;
}
}

limit_conn_zone: $binary_remote_addr set the parameters of the shared memory space that saves the state of each key (for example ), zone=space name:size.

The calculation of the size is related to variables. For example, $binary_remote_addr the size of a variable is fixed at 4 bytes for recording IPV4 addresses, while it is fixed at 16 bytes for recording IPV6 addresses. The storage state occupies 32 or 64 bytes on a 32-bit platform, and occupies 32 or 64 bytes on a 64-bit platform. 64 bytes. 1m shared memory space can save about 32,000 32-bit states and 16,000 64-bit states.

limit_conn: Specify a shared memory space that has been set (such as ops the space named ), and the maximum number of connections for each given key value.

The above example means that only 10 connections are allowed at the same time for the same IP.

When multiple limit_conn directives are configured, all connection limit will take effect.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
http {
limit_conn_zone $binary_remote_addr zone=ops:10m;
limit_conn_zone $server_name zone=coffee:10m;

server {
listen 80;
server_name ops-coffee.cn;

root /home/project/webapp;
index index.html;

location / {
limit_conn ops 10;
limit_conn coffee 2000;
}
}
}

The above configuration will not only limit the number of connections from a single IP source to 10, but also limit the total number of connections to a single virtual server to 2000.

Buffer overflow attack

Buffer overflow attacks are realized by writing data into the buffer beyond the buffer boundary and rewriting the memory segment. Limiting the buffer size can effectively prevent.

1
2
3
4
client_body_buffer_size  1K;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;

client_body_buffer_size: The default is 8k or 16k, indicating that the client requests the body to occupy the buffer size. If connection requests exceed the value specified by the cache, all or part of those request entities will attempt to write to a temporary file.

client_header_buffer_size: Indicates the buffer size of the client request header. In most cases, a request header will not be larger than 1k, but if there is a larger cookie from the wap client, it may be larger than 1k, Nginx will allocate a larger buffer to it, and this value can be set in large_client_header_buffers it.

client_max_body_size: Indicates the maximum acceptable body size requested by the client, which appears in the Content-Length field of the request header. If the request is larger than the specified value, the client will receive a “Request Entity Too Large” (413) error, usually There will be restrictions on uploading files to the server.

large_client_header_buffers indicates the number and size of buffers used by some relatively large request headers. The default buffer size is the size of the paging file in the operating system, usually 4k or 8k. The request field cannot be larger than a buffer size. If the client sends a comparison For large headers, nginx will return “Request URI too large” (414), the longest field of the request header cannot be larger than a buffer, otherwise the server will return “Bad request” (400).

At the same time, you need to modify the configuration of several timeouts.

1
2
3
4
client_body_timeout   10;
client_header_timeout 10;
keepalive_timeout 5 5;
send_timeout 10;

client_body_timeout: Indicates the timeout time for reading the request body. If the connection exceeds this time and the client does not respond, Nginx will return a “Request time out” (408) error.

client_header_timeout: Indicates the timeout period for reading the client request header. If the connection exceeds this time and the client does not respond, Nginx will return a “Request time out” (408) error.

keepalive_timeout: The first value of the parameter indicates the timeout period of the long connection between the client and the server. After this time, the server will close the connection. The optional second parameter indicates the time value of Keep-Alive: timeout=time in the Response header , this value can make some browsers know when to close the connection, so that the server does not have to close it repeatedly. If this parameter is not specified, nginx will not send Keep-Alive information in the response header.

send_timeout: Indicates the timeout period after sending the response to the client. Timeout means that it has not entered the fully established state, and only completed two handshakes. If the client does not respond beyond this time, nginx will close the connection.

Header settings

XSS attacks can be effectively prevented through the following settings.

1
2
3
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";

X-Frame-Options: The response header indicates whether the browser is allowed to load frame and other attributes. There are three configurations that DENY prohibit any web page from being embedded, SAMEORIGIN only allow nesting of this website, and ALLOW-FROMallow nesting of specified addresses.

X-XSS-Protection: Indicates that XSS filtering is enabled (filtering is disabled X-XSS-Protection: 0), mode=block which means that if an XSS attack is detected, the rendering of the page will be stopped.

X-Content-Type-Options: The response header is used to specify the browser’s guessing behavior for the true type of unspecified or wrongly specified Content-Type resources. nosniff means that no guessing is allowed.

In a normal request response, the browser will Content-Type distinguish the type of the response according to, but when the response type is not specified or wrongly specified, the browser will try to enable MIME-sniffing to guess the response type of the resource, which is very dangerous

For example, a .jpg image file is maliciously embedded with executable js code. When resource type guessing is enabled, the browser will execute the embedded js code, which may have unexpected consequences.

In addition, there are several security configurations about the request header that need attention

Content-Security-Policy: defines which resources the page can load,

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

The above configuration will restrict all external resources to be loaded only from the current domain name, which default-src defines the default loading strategy for all types of resources, self allowing content from the same source.

Strict-Transport-Security: will tell the browser to use the HTTPS protocol instead of HTTP to access the target site.

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

The above configuration means that when the user visits for the first time, a Strict-Transport-Security field containing the response header will be returned. This field will tell the browser that in the next 31536000 seconds, all requests of the current website will be accessed using the https protocol. The parameter includeSubDomains is Optional, indicates that all subdomains will also apply the same rules.