Nginx Tips and Tricks and Security Configuration - NETSEC

Latest

Learning, Sharing, Creating

Cybersecurity Memo

Monday, March 30, 2020

Nginx Tips and Tricks and Security Configuration

Here are some basic configuration I used in my lab:
1. Configure Nginx to do load balancer
2. Configure a backup server
3. Hide Nginx Version Information from Hacker
4. Verify Nginx.conf configuration before apply
5. Reload Nginx.conf without restart service
6. Domain Rewrite
7. Disable Obsolete SSL/TLS Protocols
8. Enable HTTPS
9. Add black and white list
10. Limit request method
11. Deny User-Agent
12. Picture anti-theft chain
13. Controlling the number of concurrent connections
14. Buffer overflow attack
15. Header settings
16. Reverse Proxy Basic Configuration




1. Configure Nginx to do load balancer


If you have multiple sites, you can configure Nginx to load balance between multiple servers.
There are two files you will need to change:

root@f0e9bd28fe02:/# cat /etc/nginx/nginx.conf
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}


http {  upstream mysec {
ip_hash;
    server 3.81.70.239:30000 weight=3;
    server 34.73.78.142:80 weight=2;
  }

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
root@f0e9bd28fe02:/#

root@f0e9bd28fe02:/# cat /etc/nginx/conf.d/wordpress.conf
server {
    listen       80;
    server_name  www.51sec.org;

location / {
    proxy_pass       http://mysec;
    proxy_redirect             off;
    proxy_http_version         1.1;
    proxy_set_header Upgrade   $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host      $host;
    proxy_set_header X-Real-IP $remote_addr;
}
}
root@f0e9bd28fe02:/#
Another simple Nginx Load Balance Configuration in /etc/nginx/nginx.conf
http {
  upstream project1 {
    server 127.0.0.1:8000 weight=3;
    server 127.0.0.1:8001 weitht=2;
    server 127.0.0.1:8002;
  }

  server {
    listen 80;
    server_name www.51sec.org;
    location / {
      proxy_pass http://project1;
    }
  }
}

There is a default file at /etc/nginx/sites-enabled if it is Ubuntu systems. If you already defined your wordpress configuration file under this folder, you might want to delete this default file.



 It also can configured if NGINX fails to send a request to a server or does not receive a response from it 3 times in 30 seconds, it marks the server as unavailable for 30 seconds:
upstream backend {
    server 12.12.12.12:10000;
    server 13.13.13.13 max_fails=3 fail_timeout=30s;
}

But it wont be able to detect the backend MySQL connection error issue and wont cause a load balance triggered.



On Debian and Ubuntu systems you’ll need to remove the default symbolic link from the sites-enabled folder.
sudo rm /etc/nginx/sites-enabled/default
CentOS hosts don’t use the same linking, instead, simply rename the default.conf in the conf.d/directory to something that doesn’t end with .conf, for example:
sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.disabled
Then use the following to restart nginx.
sudo systemctl restart nginx
sudo /etc/init.d/nginx restart
sudo /etc/init.d/nginx reload
2. Configure a backup server

ip_hash parameter is not working with backup command. In following configuration, server 3.81.70.239 will not be hit until server 34.73.78.142 is unavailable.
Ip_hash balancer does not support backup servers and weight.

root@f0e9bd28fe02:/# cat /etc/nginx/nginx.conf
.....

http {  upstream mysec {
##ip_hash;
##  server 3.81.70.239:30000 weight=3;
    server 34.73.78.142:80 weight=2;
    server 3.81.70.239:30000 backup  }

.....

3. Hide Nginx Version Information from Hacker
There are often security vulnerabilities for 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 the vulnerability in a timely manner. Before the change:

vi /etc/nginx/nginx.conf

http {
server_tokens off;
}

After enabled server_token off :



4. Valid Nginx.conf configuration before apply
nginx -t


5. Reload Nginx.conf without restart service
nginx -s reload

/etc/init.d/nginx reload



6. Domain Rewrite

If you are having a existing domain www.test.com, you would like to change it to blog.51sec.com. The purpose is to keep all contents no change, only domain will be changed automatically.
For example, if a user visits www.test.com/a/b/1.html, it will automatically redirect to blog.51sec.com/a/b/1.html page. 
Method 1:

Method 2:

redirect matches regular expression patterns in parenthesis. It then references the matched text in the redirect destination using $1 expression, where 1 is the first group of matched text. In more complex examples, subsequent matched groups are given numbers sequentially.
For example, if you wanted to temporarily redirect every page within www.domain1.com to www.domain2.com, you could use the following:

Temporary redirect with rewrite
server {
    . . .
    server_name www.domain1.com;
    rewrite ^/(.*)$ http://www.domain2.com/$1 redirect;
    . . .
}



7. Disable Obsolete SSL/TLS Protocols

ssl_protocols TLSv1.1 TLSv1.2;


8. Enable HTTPS

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: enable https

ssl_certificate: configure nginx ssl certificate path
ssl_certificate_key: configure the path of the nginx ssl certificate key
ssl_protocols: specifies the ssl protocol version used by the client to establish a connection. If it is not compatible with TSLv1, just remove it
ssl_ciphers: specify the encryption algorithm used when the client connects, you can configure a more secure algorithm here


9. Add black and white list

Whitelist configuration:

location / admin / {
allow 192.168.1.0/24;
deny all;
}
The above indicates that only hosts on 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 some addresses and allow all others, such as

location / ops-coffee / {
deny 192.168.1.0/24;
allow all;
}
More often, client requests go through layers of proxies. We need to limit them through $ http_x_forwarded_for, which can be written like this

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 authentication

server {
location / {
auth_basic "please input user & passwd";
auth_basic_user_file key / auth.key;
}
}


10. Limit request method

if ($ request_method! ~ ^ (GET | POST) $) {
return 405;
}
$ request_method can get the method of requesting nginx

The configuration allows only GETPOST method access, other methods return 405


11. Deny User-Agent

if ($ http_user_agent ~ * LWP :: Simple | BBBike | wget | curl) {
return 444;
}
There may be some outlaws who scan our website with tools such as wget / curl, we can simply prevent it by banning the corresponding user-agent

Nginx's 444 status is special. If it returns 444, the client will not receive the information returned by the server, just like the website cannot connect.

12. Picture anti-theft chain

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 allows the referer to be empty, and blocked allows requests without a protocol. In addition to the above two types, only the referer is allowed to access image resources under images when www.ops-coffee.cn or ops-coffee.cn Otherwise it returns 403

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

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



13. Controlling the number of concurrent connections

You can limit the number of concurrent connections of an IP through the ngx_http_limit_conn_module module

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: set the parameter of shared memory space that saves the state of each key (such as $ binary_remote_addr), zone = space name: size

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

limit_conn: Specify a set of shared memory space (for example, the space with name ops), and the maximum number of connections for each given key value

The example above shows that only 10 connections are allowed at the same time at the same IP

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

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

14. Buffer overflow attack

Buffer overflow attacks are implemented by writing data to the buffer beyond the buffer boundary and rewriting memory fragments. Limiting the buffer size can effectively prevent

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, which indicates that the client requests the body to occupy the buffer size. If the connection request exceeds the value specified in the cache, then all or part of these requesting 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 large cookie from the wap client, it may be larger than 1k. Nginx will allocate a larger buffer to it. This value can be set in large_client_header_buffers.

client_max_body_size: indicates the maximum acceptable body size of the client request. It 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 Restricted when uploading files to the server

large_client_header_buffers indicates the number and size of buffers used by some 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 in the request header cannot be larger than a buffer, otherwise the server will return "Bad request" (400)

Need to modify the configuration of several timeouts at the same time

client_body_timeout 10;
client_header_timeout 10;
keepalive_timeout 5 5;
send_timeout 10;
client_body_timeout: indicates the timeout 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 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 parameter indicates the value of the Keep-Alive: timeout = time This value can enable some browsers to know when to close the connection so that the server does not need to close repeatedly. If this parameter is not specified, nginx will not send Keep-Alive information in the Response header.

send_timeout: indicates the timeout after the response is sent to the client. Timeout refers to the fact that it has not entered the fully established state and only completed the two handshake. If the client does not respond after this time, nginx will close the connection.

15. Header settings

The following settings can effectively prevent XSS attacks

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. Deny prohibits any webpage from being embedded. SAMEORIGIN only allows nesting of this website, and ALLOW-FROM allows nesting of specified addresses.

X-XSS-Protection: indicates that XSS filtering is enabled (X-XSS-Protection: 0 is disabled), mode = block indicates that if an XSS attack is detected, the page will stop rendering

X-Content-Type-Options: The response header is used to specify the browser's guessing behavior for the unspecified or incorrectly specified Content-Type resource. Nosniff indicates that no guessing is allowed.

In the usual request response, the browser will distinguish the type of the response based on the Content-Type, but when the response type is not specified or incorrectly 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. With resource type guessing turned on, 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 can be loaded on the page,

add_header Content-Security-Policy "default-src 'self'";
The above configuration will limit all external resources and can only be loaded from the current domain name. The default-src defines the default loading policy for all types of resources, and self allows content from the same source.

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

add_header Strict-Transport-Security "max-age = 31536000; includeSubDomains";
The above configuration indicates that when the user first visits, a field containing the Strict-Transport-Security response header will be returned. This field will tell the browser that in the next 31536000 seconds, all requests for the current website will use https Protocol access, the parameter includeSubDomains is optional, meaning that all subdomains will also adopt the same rules


16. Nginx used as Reverse Proxy

Nginx反代配置,直接添加到配置文件即可。
#在配置文件里添加
location / {
     proxy_pass http://127.0.0.1:5000;
     proxy_redirect off;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }





No comments:

Post a Comment