## Store this configuration in https.conf for example:listen10.240.20.2:443ssl;ssl_certificate/etc/nginx/master/_server/example.com/certs/nginx_example.com_bundle.crt;ssl_certificate_key/etc/nginx/master/_server/example.com/certs/example.com.key;## Include this file to the server section:server{include/etc/nginx/master/_listen/10.240.20.2/https.conf;## And other:include/etc/nginx/master/_static/errors.conf;include/etc/nginx/master/_server/_helpers/global.conf;...server_namedomain.comwww.domain.com;...
server{## This block will be processed:listen192.168.252.10; ## --> 192.168.252.10:80...}server{listen80; ## --> *:80 --> 0.0.0.0:80server_nameapi.random.com;...}
防止使用未定义的服务器名称处理请求
Nginx 应该阻止使用未定义的服务器名称(也使用 IP 地址)处理请求。它可以防止配置错误,例如流量转发到不正确的后端。通过创建默认虚拟虚拟主机可以轻松解决该问题,该虚拟虚拟主机可以捕获带有无法识别的主机标头的所有请求。
## Place it at the beginning of the configuration file to prevent mistakes:server{## For ssl option remember about SSL parameters (private key, certs, cipher suites, etc.);## add default_server to your listen directive in the server that you want to act as the default:listen10.240.20.2:443default_serverssl;## We catch:## - invalid domain names## - requests without the "Host" header## - and all others (also due to the above setting) ## - default_server in server_name directive is not required - I add this for a better understanding and I think it's an unwritten standard
## ...but you should know that it's irrelevant, really, you can put in everything there.server_name_""default_server;...return444;## We can also serve:## location / {## static file (error page):## root /etc/nginx/error-pages/404;## or redirect:## return 301 https://badssl.com;## return 444;## }}server{listen10.240.20.2:443ssl;server_namedomain.com;...}server{listen10.240.20.2:443ssl;server_namedomain.org;...}
不要在 listen 或 upstream 中使用 hostname
通常,在 listen 或上游指令中使用主机名是一种不好的做法。
在最坏的情况下,Nginx 将无法绑定到所需的 TCP 套接字,这将完全阻止 Nginx 启动。
最好和更安全的方法是知道需要绑定的 IP 地址,并使用该地址代替主机名。 这也可以防止 Nginx 查找地址并消除对外部和内部解析器的依赖。
TLS 服务器名称指示扩展名(SNI,RFC 6066)是在单个 IP 地址上运行多个 HTTPS 服务器的更通用的解决方案,它允许浏览器在 SSL 握手期间传递请求的服务器名称,因此,服务器将知道哪个用于连接的证书。
另一个好主意是将常用服务器设置移到单独的文件(即 common / example.com.conf)中,然后将其包含在单独的服务器块中。
示例:
## Store this configuration in e.g. https.conf:listen192.168.252.10:443default_serversslhttp2;ssl_protocolsTLSv1.2;ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384";
ssl_prefer_server_cipherson;ssl_ecdh_curvesecp521r1:secp384r1;...## Include this file to the server context (attach domain-a.com for specific listen directive):server{include/etc/nginx/https.conf;server_namedomain-a.com;ssl_certificatedomain-a.com.crt;ssl_certificate_keydomain-a.com.key;...}## Include this file to the server context (attach domain-b.com for specific listen directive):server{include/etc/nginx/https.conf;server_namedomain-b.com;ssl_certificatedomain-b.com.crt;ssl_certificate_keydomain-b.com.key;...}
使用 geo/map 模块替代 allow/deny
使用地图或地理模块(其中之一)可以防止用户滥用您的服务器。这样就可以创建变量,其值取决于客户端 IP 地址。
map $http_user_agent $device_redirect {default"desktop";~(?i)ip(hone|od) "mobile";~(?i)android.*(mobile|mini) "mobile";~Mobile.+Firefox"mobile";~^HTC"mobile";~Fennec"mobile";~IEMobile"mobile";~BB10"mobile";~SymbianOS.*AppleWebKit"mobile";~Opera\sMobi"mobile";}## Turn on in a specific context (e.g. location):if ($device_redirect = "mobile") {return301https://m.domain.com$request_uri;}
## Turn on in a specific context, e.g.:## - global - for global logging## - http - for http and all locations logging## - location - for specific locationerror_log/var/log/nginx/error-debug.logdebug;
error_log/var/log/nginx/debug.logdebug;...http{server{## To enable debugging:error_log/var/log/nginx/domain.com/domain.com-debug.logdebug;## To disable debugging:error_log/var/log/nginx/domain.com/domain.com-debug.log;... }}
## It is more efficient to define them explicitly:server{listen192.168.252.10:80;server_nameexample.orgwww.example.org*.example.org;...}## Than to use the simplified form:server{listen192.168.252.10:80;server_name.example.org;...}
server{server_namewww.domain.com;return301 $scheme://domain.com$request_uri;## If you force your web traffic to use HTTPS:## 301 https://domain.com$request_uri;...}server{listen192.168.252.10:80;server_namedomain.com;...}
try_files is definitely a very useful thing. You can use try_files directive to check a file exists in a specified order.
You should use try_files instead of if directive. It's definitely better way than using if for this action because if directive is extremely inefficient since it is evaluated every time for every request.
The advantage of using try_files is that the behavior switches immediately with one command. I think the code is more readable also.
try_files allows you:
to check if the file exists from a predefined list
to check if the file exists from a specified directory
to use an internal redirect if none of the files are found
## Matches the query / only and stops searching:
location = / {
...
}
## Matches the query /v9 only and stops searching:
location = /v9 {
...
}
...
## Matches any query due to the fact that all queries begin at /,
## but regular expressions and any longer conventional blocks will be matched at first place:
location / {
...
}
使用 limit_conn 改善对下载速度的限制
Nginx provides two directives to limiting download speed:
Nginx 提供了两个指令来限制下载速度:
limit_rate_after - 设置 limit_rate 指令生效之前传输的数据量
limit_rate - 允许您限制单个客户端连接的传输速率
此解决方案限制了每个连接的 Nginx 下载速度,因此,如果一个用户打开多个(例如) 视频文件,则可以下载 X * 连接到视频文件的次数 。
示例:
## Create limit connection zone:
limit_conn_zone $binary_remote_addr zone=conn_for_remote_addr:1m;
## Add rules to limiting the download speed:
limit_rate_after 1m; ## run at maximum speed for the first 1 megabyte
limit_rate 250k; ## and set rate limit after 1 megabyte
## Enable queue:
location /videos {
## Max amount of data by one client: 10 megabytes (limit_rate_after * 10)
limit_conn conn_for_remote_addr 10;
...
In this chapter I will talk about some of the Nginx hardening approaches and security standards.
🔰 始终保持Nginx为最新
基本原理
Nginx is a very secure and stable but vulnerabilities in the main binary itself do pop up from time to time. It's the main reason for keep Nginx up-to-date as hard as you can.
A very safe way to plan the update is once a new stable version is released but for me the most common way to handle Nginx updates is to wait a few weeks after the stable release.
Before update/upgrade Nginx remember about do it on the testing environment.
Most modern GNU/Linux distros will not push the latest version of Nginx into their default package lists so maybe you should consider install it from sources.
It is recommended to disable any modules which are not required as this will minimise the risk of any potential attacks by limiting the operations allowed by the web server.
The best way to unload unused modules is use the configure option during installation. If you have static linking a shared module you should re-compile Nginx.
Use only high quality modules and remember about that:
Unfortunately, many third‑party modules use blocking calls, and users (and sometimes even the developers of the modules) aren’t aware of the drawbacks. Blocking operations can ruin Nginx performance and must be avoided at all costs.