NGinx配置汇总

一、安全相关

1.1 版本号隐藏

http {
    server_tokens off;
}

1.2 HTTPS

server {

    listen 443;
    server_name test.com.cn;

    ssl_certificate  conf/ssl/1_test.com.cn_bundle.crt;
    ssl_certificate_key conf/ssl/2_test.com.cn.key;
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;
}

1.3 黑白名单

#只允许192.168.1.0/24网段的主机访问,拒绝其他所有
location /admin/ {
    allow 192.168.1.0/24;
    deny all;
}

#当客户端请求会经过层层代理,我们需要通过$http_x_forwarded_for来进行限制;
location /admin/ {
    set $allow false;
    if ($http_x_forwarded_for = "10.0.0.3") { set $allow true; }
    if ($http_x_forwarded_for ~ "10.0.1.10") { set $allow true; }
    if ($allow = false) { return 403; }
}

1.4 账号认证

#yum install -y httpd-tools
#htpasswd -c auth.key admin
#-c创建文件,第一次执行需要
server {
    #authkey可以使用httpasswd
    location / {
        auth_basic "please input user&passwd";
        auth_basic_user_file key/auth.key;
    }
}

1.5 请求方法限制

#$request_method能够获取到请求nginx的method
#配置只允许GETPOST方法访问,其他的method返回405
if ($request_method !~ ^(GET|POST)$ ) {
     return 405;
}

1.6 限制agent访问

#Nginx的444状态比较特殊,如果返回444那么客户端将不会收到服务端返回的信息,就像是网站无法连接一样
#把使用IE 6.0 的客户端禁止访问
#验证: curl -A "baidu" -x127.0.0.1:80 www.test.com/index.html -I
location / {
     #禁止useragent为baidu、360和sohu,~*表示不区分大小写匹配
    if ($http_user_agent ~* 'baidu|360|sohu')
    {
       return 403;
    }
    root html;
    index index.html;
}

1.7 防盗链

#valid_referers: 验证referer,其中none允许referer为空,blocked允许不带协议的请求
#仅允许referer为www.test.com或test.com时访问wish下的资源,否则返回403
location /wish/ {
    valid_referers none blocked www.test.com test.com;
    if ($invalid_referer) {
        return 403;
        #或者给不符合要求的重定向另一个资源
        #rewrite ^/images/.*.(gif|jpg|jpeg|png)$ /static/qrcode.jpg last;
    }
}

1.8 缓冲区大小

http {

    #client_body_buffer_size: 默认8k或16k,表示客户端请求body占用缓冲区大小。如果连接请求超过缓存区指定的值,那么这些请求实体的整体或部分将尝试写入一个临时文件。
    client_body_buffer_size 8k;

    #client_header_buffer_size: 表示客户端请求头部的缓冲区大小。绝大多数情况下一个请求头不会大于1k,不过如果有来自于wap客户端的较大的cookie它可能会大于 1k,Nginx将分配给它一个更大的缓冲区,这个值可以在large_client_header_buffers里面设置
    client_header_buffer_size 1m;

    #client_max_body_size: 表示客户端请求的最大可接受body大小,它出现在请求头部的Content-Length字段, 如果请求大于指定的值,客户端将收到一个"Request Entity Too Large" (413)错误,通常在上传文件到服务器时会受到限制;
    client_max_body_size 2m;

    #large_client_header_buffers 表示一些比较大的请求头使用的缓冲区数量和大小,默认一个缓冲区大小为操作系统中分页文件大小,通常是4k或8k,请求字段不能大于一个缓冲区大小,如果客户端发送一个比较大的头,nginx将返回"Request URI too large" (414),请求的头部最长字段不能大于一个缓冲区,否则服务器将返回"Bad request" (400)
    large_client_header_buffers 4 8k;


    #client_body_timeout: 表示读取请求body的超时时间,如果连接超过这个时间而客户端没有任何响应,Nginx将返回"Request time out" (408)错误
    client_body_timeout 20;

    #client_header_timeout: 表示读取客户端请求头的超时时间,如果连接超过这个时间而客户端没有任何响应,Nginx将返回"Request time out" (408)错误
    client_header_timeout 10;

    #keepalive_timeout: 参数的第一个值表示客户端与服务器长连接的超时时间,超过这个时间,服务器将关闭连接,可选的第二个参数参数表示Response头中Keep-Alive: timeout=time的time值,这个值可以使一些浏览器知道什么时候关闭连接,以便服务器不用重复关闭,如果不指定这个参数,nginx不会在应Response头中发送Keep-Alive信息
    keepalive_timeout 50 50;

    #send_timeout: 表示发送给客户端应答后的超时时间,Timeout是指没有进入完整established状态,只完成了两次握手,如果超过这个时间客户端没有任何响应,nginx将关闭连接
    send_timeout 30;
}

1.9 防止XSS攻击

#1.X-Frame-Options: 响应头表示是否允许浏览器加载frame等属性,有三个配置DENY禁止任何网页被嵌入,SAMEORIGIN只允许本网站的嵌套,ALLOW-FROM允许指定地址的嵌套
#2.X-XSS-Protection: 表示启用XSS过滤(禁用过滤为X-XSS-Protection: 0),mode=block表示若检查到XSS攻击则停止渲染页面
#3.X-Content-Type-Options: 响应头用来指定浏览器对未指定或错误指定Content-Type资源真正类型的猜测行为,nosniff 表示不允许任何猜测

http {
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; #告诉浏览器使用https代理http访问
}

1.10 跨域访问

http {

    #使用变量 $http_origin取得当前来源域
    add_header 'Access-Control-Allow-Origin' $http_origin;

    #为 true 的时候指请求时可带上Cookie,自己按情况配置;
    add_header 'Access-Control-Allow-Credentials' 'true';

    #OPTIONS一定要有,另外一般也就GET和POST,如果你有其它的也可加进去;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

    #一定要包含自定义的http头字段(就是说前端请求接口时,如果在http头里加了自定义的字段,这里配置一定要写上相应的字段)
    add_header 'Access-Control-Allow-Headers' 'DNT,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';

    #可选设置,看网上大致意思是默认只能获返回头的6个基本字段,要获取其它额外的,先在这设置才能获取它;
    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';

    #谷歌浏览器不识别上述的跨域参数,需要添加如下配置
    add_header X-Frame-Options "ALLOW-FROM https://test.com";
    add_header Content-Security-Policy "frame-ancestors https://test.com";

    #因为浏览器判断是否允许跨域时会先往后端发一个options请求,然后根据返回的结果判断是否允许跨域请求,所以这里单独判断这个请求,然后直接返回;
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
    }
}

二、服务相关

2.1 浏览器缓存

server {

    if ($request_filename ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$){
        #access_log off;
        expires 15d;    #保存15天
    }
}

2.2 静态资源

http {

    #on,允许header中参数包含下划线,该属性默认为off,表示如果header name中包含下划线,则忽略掉。
    underscores_in_headers on;

    # 这个将为打开文件指定缓存,默认是没有启用的,max 指定缓存数量,
    # 建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存。
    open_file_cache max=204800 inactive=20s;

    # open_file_cache 指令中的inactive 参数时间内文件的最少使用次数,
    # 如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个
    # 文件在inactive 时间内一次没被使用,它将被移除。
    open_file_cache_min_uses 1;

    # 这个是指多长时间检查一次缓存的有效信息
    open_file_cache_valid 30s;

    # 默认情况下,Nginx的gzip压缩是关闭的, gzip压缩功能就是可以让你节省不
    # 少带宽,但是会增加服务器CPU的开销哦,Nginx默认只对text/html进行压缩 ,
    # 如果要对html之外的内容进行压缩传输,我们需要手动来设置。
    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_types text/plain application/x-javascript text/css application/xml;

}

2.3 日志格式

http {

    #日志格式定义
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"'
                          '$upstream_addr $upstream_status $upstream_response_time $request_time';

    #格式引用
    access_log /var/logs/nginx-access.log main;

    #指定日志的缓存大小为32k,日志写入前启用gzip进行压缩,压缩比使用默认值1,缓存数据有效时间为1分钟
    #access_log /var/logs/nginx-access.log main buffer=32k gzip flush=1m

}

2.4 代理设置

http {

    #代理参数设置
    proxy_intercept_errors on;
    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;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_set_header origin $http_origin;
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;

    server {

        listen 8128;
        server_name _;

        location / {
            proxy_pass  https://www.test.com/;
        }
    }
}

2.5 负载均衡

#
http {

    #负载均衡算法
    #rr: 默认,轮流转发
    #least_conn: 最小连接,保持的连接数最少的优先转发
    #ip_hash: ip哈希,按照客户端ip的hash来作为用户的标识转发
    upstream api {
       server 10.0.0.1:20202 weight=1 fail_timeout=200s max_fails=3;
       server 10.0.0.3:20202 weight=1 fail_timeout=200s max_fails=3 down; #down表示关闭,下线节点
       server 10.0.0.5:20202 weight=1 fail_timeout=200s max_fails=3;
       server 10.0.0.2:20202 weight=1 fail_timeout=200s max_fails=3 backup; #backup备份,全挂了我才上
    }
}

2.6 并发限制

http {

    #基于客户端ip地址定义一个tcp连接池,内存大小为20m
    limit_conn_zone  $http_x_forwarded_for zone=test_conn:20m;

    #基于客户端ip地址定义一个http连接池,内存大小为20m,限制一秒中内只允许同一个ip发起300个http请求
    limit_req_zone $http_x_forwarded_for zone=test_req:20m rate=300r/s;

    #基于客户端ip地址、uri、、token_id、token定义一个连接池,大小为10m,限制一分钟内只允许发起5个请求
    limit_req_zone $binary_remote_addr$uri$http_token_open_id$http_accesstoken zone=apiLimit:10m rate=5r/m;

    #超过限制的http连接返回599状态码
    limit_req_status 599;

    #错误日志级别改为warn
    limit_req_log_level warn;

    server {
        location / {
            limit_req zone=test_req burst=50 nodelay; #每秒300个请求,超过则加入队列等候,等候大于50返回错误状态码
            limit_conn test_conn 30;  #单个ip发起连接数
        }
    }
}

2.7 四层代理

# 代理后端测试数据库,位于http层以外
stream {

    upstream mysql_proxy {
       #hash $remote_addr consistent;
       server 172.16.0.5:15603; # Mysql需要授权代理服务器访问
    }

    server {
       listen 15613; # 注意:不能使用默认端口连接
       proxy_connect_timeout 5s; # 连接超时时间
       proxy_timeout 300s; # 空闲超时时间
       proxy_pass mysql_proxy; # 需要放行代理访问策略
    }

}

2.8 下载站点

server {

    listen 15900;
    server_name _;

    location / {
        allow 172.16.0.16;    #uat节点
        deny all;
        limit_rate_after 3m;  #3分钟后限制下载速率,避免多线程下载工具,可以配置limit使用
        limit_rate 500k;  #限制速率为500kb
        alias /sftp_home/packages;  #展示目录
        autoindex on; #开启整个目录浏览下载,默认off禁止
        autoindex_localtime on;      #显示的时间为文件服务器时间
        autoindex_exact_size off; #显示文件的粗略大小
    }
}

2.9 配置生成

一个自动生成nginx配置的网站,访问 https://www.digitalocean.com/community/tools/nginx?global.app.lang=zhCN