nginx常用功能配置范例

nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev.

隐藏版本号

1
2
3
http {
server_tokens off;
}

nginx Basic 认证

  • 生成用户密码

    1
    htpasswd -c /usr/local/nginx/conf/nginx.passwd.db admin
  • 更新密码

    1
    htpasswd /usr/local/nginx/conf/nginx.passwd.db admin
  • 配置内容

    1
    2
    3
    4
    location / {
    auth_basic "View is cheap,show me the password!";
    auth_basic_user_file nginx.passwd.db;
    }

限制$http_x_forwarded_for

1
2
3
4
5
6
7
8
9
10
set $allow false;
if ($http_x_forwarded_for = "185.199.111.153") {
set $allow true;
}
if ($http_x_forwarded_for ~ "10.0.0.*") {
set $allow true;
}
if ($allow = false) {
return 404;
}

限制请求方法

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

过滤特殊UA

if ($http_user_agent ~* sqlmap|wget|curl) {
return 403;
}

图片防盗链

1
2
3
4
5
6
7
8
9
10
11
12
13
location /images/ {
valid_referers none blocked lengyuewusheng.com www.lengyuewusheng.com;
if ($invalid_referer) {
return 403;
}
}

location /images/ {
valid_referers blocked lengyuewusheng.com www.lengyuewusheng.com;
if ($invalid_referer) {
rewrite ^/images/.*\.(gif|jpg|jpeg|png)$ /error.html last;
}
}
  • “Referer”请求头为指定值时,内嵌变量$invalid_referer被设置为空字符串, 否则这个变量会被置成”1”。查找匹配时不区分大小写。
  • valid_referers:验证referer
    • none: 允许referer为空,
    • blocked: 允许不带协议的请求.

配置反向代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
http {

...

upstream realservers {
server 10.0.0.1:8080 weight=3;
server 10.0.0.2:8080 weight=7;
}

server {
location /admin/ {
proxy_pass http://realserver;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}

nginx开启keepalive

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
upstream realserver {
server 10.0.0.1:8080;
keepalive 10;
keepalive_timeout 60s; # This directive appeared in version 1.15.3.
keepalive_requests 100; # This directive appeared in version 1.15.3.
}
http {
keepalive_timeout 75s;
server {
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://realserver;
...
}
}
}
  • keepalive: 指定每个nginx worker可以保持的最大连接数量为1024,默认不设置,即nginx作为client时keepalive未生效。

  • proxy_http_version 1.1: 开启keepalive要求HTTP协议版本为HTTP 1.1。

  • proxy_set_header Connection “”: 为了兼容老的协议以及防止http头中有Connection close导致的keepalive失效,这里需要及时清掉HTTP头部的Connection。

  • keepalive_requests: 设置可通过一个保持连接提供服务的最大请求数。在发出最大请求数后,连接将关闭。

  • keepalive_timeout:

    • upstream中的keepalive_timeoute是ngx_http_upstream_module模块中的功能,是1.15.3后的新特性,设置空闲保持连接的超时时间。
    • upstream外的keepalived是ngx_http_core_module模块中的功能,第一个参数是保持活动的客户机连接将在服务器端保持打开状态的超时时间。0表示禁用保持活动的客户端连接。可选的第二个参数在”Keep-Alive: timeout=time”响应头字段中设置一个值。两个参数可以不同。

nginx开启目录查看

1
2
3
4
5
6
7
server {
location /download/ {
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
}
}
  • autoindex_exact_size: 为on(默认)时显示文件的确切大小,单位是byte;改为off显示文件大概大小,单位KB或MB或GB

  • autoindex_localtime: 为off(默认)时显示的文件时间为GMT时间;改为on后,显示的文件时间为服务器时间

浏览器不显示文件内容直接下载文件

1
2
3
if ($request_filename ~* ^.*?\.(txt|pdf)$) {
add_header Content-Disposition 'attachment';
}

nginx获取用户真实IP

1
2
3
4
5
6
7
set_real_ip_from  10.0.0.0/8;               #真实服务器上一级代理的IP地址或者IP段,可以写多行。
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For; #从哪个header头检索出要的IP地址。
real_ip_recursive on; #递归的排除所配置中的可信IP。
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  • X-Forwarded-For 变量,是squid开发的,用于识别请求通过了哪些HTTP代理或负载平衡器,记录相应IP地址列表的非rfc标准,如果设置了X-Forwarded-For,那么每次经过proxy转发请求后都会有记录。

nginx 强制跳转https

1
2
3
4
5
6
7
if ( $scheme = http ){
return 301 https://$server_name$request_uri;
}

if ( $scheme = http ){
rewrite ^(.*)$ https://$host$1 permanent;
}

防恶意抓取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
http {
geo $limited
{
default 1;
10.0.0.0/8 0;
123.207.144.220/32 0;
36.110.170.248/30 0;
118.184.170.248/30 0;
}

map $limited $limit {
1 $binary_remote_addr;
0 "";
}
limit_req_zone $limit zone=reqids:100m rate=10r/s;

server {
limit_req zone=reqids burst=2 nodelay;
}
}
  • geo设置白名单

nginx健康检查机制

check_http_expect_alive [ http_2xx | http_3xx | http_4xx | http_5xx ]
返回指定HTTP code,符合预期就算检测成功

通过nginx查看txt文本文件乱码

  • 文件后缀必须是.txt而不是.html,否则换行显示会有问题
    1
    2
    3
    server:
    default_type 'text/html';
    charset utf-8,gbk;

nginx代理文件下载以及时间显示问题

1
2
3
4
location / {
autoindex on;
autoindex_localtime on;
}

nginx 重置错误状态码

1
2
将限制抓取导致的503重置成204
error_page 503 =204 /50x.html;

nginx steam log(以代理etcd为例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
stream {
log_format basic '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time';

log_format advanced '$remote_addr [$time_local] '
'$protocol $status $connection $hostname $remote_addr:$remote_port->$server_addr:$server_port $bytes_sent $bytes_received '
'$session_time $pid';

log_format mini '$time_local $status $connection $session_time $hostname $bytes_sent $bytes_received';

access_log /var/logs/nginx/etcd.local_access_log advanced buffer=32k;
access_log /var/logs/nginx/status_log mini buffer=32k;

upstream stream_etcd {
hash $remote_addr consistent;
server etcd01.local:3490 max_conns=1000 weight=5 max_fails=2 fail_timeout=30s;
server etcd02.local:3490 max_conns=1000 weight=5 max_fails=2 fail_timeout=30s;
server etcd03.local:3490 max_conns=1000 weight=5 max_fails=2 fail_timeout=30s;
}

server {
listen 2379;
proxy_pass stream_etcd;
proxy_timeout 3600s;
proxy_connect_timeout 3600s;
}
}

nginx try_files & location @

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
location / {
try_files $uri $uri/index.html $uri.html =404;
}
---
location / {
alias html/;
try_files $uri $uri/index.html =404;
}
---
location / {
try_files $uri $uri/ @rewriting;
}
location @rewriting {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/WEB-INF/entry.php;
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
}

nginx缓存配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
proxy_cache_path /dev/shm/nginx/proxy_cache/  levels=2:2 keys_zone=keys_zone_name:1024m max_size=12g inactive=1h;
server
{
......
proxy_cache_key $server_name$uri;
proxy_cache_valid 200 1h;
proxy_cache_min_uses 3;
location ~ /purge(/.*)
{
allow 10.0.0.0/8;
deny all;
proxy_cache_purge keys_zone_name $server_name$1$is_args$args;
}
location /
{
proxy_cache keys_zone_name;
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}

nginx 根据UA灰度

1
2
3
4
5
6
7
8
9
10
location /
{
if ($http_user_agent = "Mozilla/5.0 (xxxx)") {
proxy_pass http://bk_gray;
}
proxy_pass http://bk_main;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

nginx 根据cookie灰度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
set $upstream "upstream_default";
if ($http_cookie ~* "xxxx"){
set $upstream upstream_a;
}

if ($http_cookie ~* "yyyy"){
set $upstream upstream_b;
}
location / {
proxy_pass http://$upstream;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

nginx存活检测

1
2
3
4
5
6
7
8
9
upstream backend {
server 127.0.0.1:80;
check interval=3000 rise=2 fall=5 timeout=1000 default_down=false type=tcp;
}
# interval:检查请求时间间隔
# fall:标记失败前的连续检查失败次数
# rise: 标记成功迁的连续检查成功次数
# timeout: 检查请求的超时时间
# type: 检查协议类型 tcp/http/mysql/ssl_hello/smtp/pop3/imap

nginx upstream backup机制

1
2
3
4
rewrite_log on;
proxy_ignore_client_abort on;

expires epoch;

default_type

1
2
3
4
location ^~ / {
default_type text/html;
return 200;
}
  • 直接return 200, 返回的Content-Type: application/octet-stream,浏览器默认会下载一个空文件,如果不希望浏览器下载,需要加default_type text/html;配置。

nginx日志自动切分日志配置

1
2
3
4
5
6
7
8
9
10
if ( $time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})" ) {
set $year $1;
set $month $2;
set $day $3;
set $hour $4;
set $minutes $5;
set $seconds $6;
}

access_log logs/${server_name}.$year-$month-$day-$hour-access_log main;

fastcgi开启长连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
upstream fastcgi_backend {
server 127.0.0.1:9000;
keepalive 8;
}

server {
...
location /fastcgi/ {
fastcgi_pass fastcgi_backend;
fastcgi_keep_conn on;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

nginx代理websocket:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# ------
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
...

location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 86400s;
}
}

nginx解决前端跨域拦截

1
2
3
4
5
6
7
8
9
server {
……
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
# add_header Referrer-Policy unsafe-url;
add_header Referrer-Policy origin-when-cross-origin;
……
}

Chrome plans to switch its default policy from no-referrer-when-downgrade to strict-origin-when-cross-origin, starting in version 85.
Starting with Firefox 87, we set the default Referrer Policy to ‘strict-origin-when-cross-origin’ which will trim user sensitive information accessible in the URL.

相关资料