美文网首页Nginx
8. Nginx高级配置

8. Nginx高级配置

作者: 随便写写咯 | 来源:发表于2021-03-18 01:21 被阅读0次

    3 Nginx高级配置

    3.1 Nginx状态页

    • 基于ngx_http_stubs_module模式实现, 在编译安装时, 需要添加编译参数, --with-http_stub_status_module, 否则配置完成之后监测会提示语法错误

    • 状态页显示的是整个服务器的状态, 而非虚拟主机的状态

    # 在任意一个虚拟主机配置即可
            location  /nginx_status {
                    stub_status;
                    auth_basic "auth log";
                    auth_basic_user_file /apps/nginx/conf/.htpasswd;
                    allow 120.78.154.82;
                    deny all;
            }
    
    
    • 状态页用于输出nginx的基本状态信息
    Active connections: 2 
    server accepts handled requests
     4(accepts) 4(handled) 3(requests) 
    Reading: 0 Writing: 1 Waiting: 1 
    
    • 状态页参数
    Active connections: # 当前处于活动状态的客户端连接数, 包括连接等待, 空闲连接数 = reading+writing+waiting
    accepts: # 统计总值, Nginx自启动后, 已经接受的客户端请求的总数
    handled: # 统计总值, Nginx自启动后, 已经处理完成的客户端请求总数, 通常等于accepts, 除非有因worker_connections限制等被拒绝的连接
    requests: # 统计总值, Nginx自启动后客户端发来的总的请求数
    Reading: # 当前状态, 正在读取客户端请求报文首部的连接的连接数, 数值越大, 说明排队现象越严重, 性能不足
    Writing: # 当前状态, 正在向客户端发送响应报文过程中的连接数, 数值越大, 说明访问量越大
    Waiting: # 当前状态, 正在等待客户端发出请求的空闲连接数, 开启 keep-alive的情况下, 这个值等于active - (reading+writing)
    

    3.2 Nginx 第三方模块

    第三方模块是对nginx的功能扩展, 第三方模块需要在编译安装nginx的时候使用参数--add-module=PATH指定路径添加, 有的模块是由公司的开发人员针对业务需求定制开发的, 有的模块是开源爱好者开发好之后上传到github进行开源的模块, nginx支持第三方模块, 需要从源码重新编译, 比如:开源的echo模块: https://github.com/openresty/echo-nginx-module

    [17:12:39 root@nginx ~]#systemctl stop nginx
    [17:47:15 root@nginx ~]#cp -a /apps/nginx/sbin/nginx{,.bak}
    
    [17:48:00 root@nginx ~]#vim /apps/nginx/conf.d/pc.conf
    server {                                                                                                                                                                            
        listen 80;
        server_name pc.wang.org;
        error_page 404  /index.html;
        error_log /data/nginx/logs/pc_wang_org_error.log;
    
        location  / {                                                                                                                                                        
            root /data/nginx/html/pc;
        }
        location /main {
        
            index index.html;
            default_type text/html; # 必须指定默认类型为文件, 否则会认为是不识别的默认模式, 浏览器会把main文件下载下来
            echo "hello world,main-->"; # 访问/main时, 会打印hello world,main--> remote_addr(远程连接客户端地址)
            echo $remote_addr; # 远程连接客户端地址, 公网ip
            echo_reset_timer; # 将计时器开始时间重置为现在
            echo_location /sub1; # 调用/sub1 location里的指令
            echo_location /sub2; # 调用/sub2 location里的指令
            echo "took $echo_timer_elapsed sec for total."; # 打印访问/main, 总共花费的时间
        
        }
        location /sub1 {
        
            echo_sleep 1;
            echo sub1;
        }
        location /sub2 {
        
            echo_sleep 1;
            echo sub2;
        }
    }
    
    # 此时, 因为nginx编译时没有把echo模块编译进去, 因此, 重新加载服务会报错
    [17:52:12 root@nginx ~]#nginx -s reload
    nginx: [emerg] unknown directive "echo" in /apps/nginx/conf.d/pc.conf:14
    
    • 下面准备重新编译nginx, 把echo模块编译进去
    [17:12:39 root@nginx ~]#systemctl stop nginx # 停止nginx服务
    [17:47:15 root@nginx ~]#cp -a /apps/nginx/sbin/nginx{,.bak} # 将现有的二进制文件做备份
    
    cd /usr/local/src
    yum -y install git
    git clone https://github.com/openresty/echo-nginx-module.git
    
    [18:13:01 root@nginx /usr/local/src]#ls
    echo-nginx-module-master.zip  nginx-1.18.0  nginx-1.18.0.tar.gz
    
    [18:18:22 root@nginx /usr/local/src]#unzip echo-nginx-module-master.zip 
    
    [18:19:05 root@nginx /usr/local/src]#ls
    echo-nginx-module-master  echo-nginx-module-master.zip  nginx-1.18.0  nginx-1.18.0.tar.gz
    
    
    [18:13:04 root@nginx /usr/local/src]#cd nginx-1.18.0/
    
    ./configure --prefix=/apps/nginx \
    --user=nginx \
    --group=nginx \
    --with-http_ssl_module \
    --with-http_v2_module \
    --with-http_realip_module \
    --with-http_stub_status_module \
    --with-http_gzip_static_module \
    --with-pcre \
    --with-stream \
    --with-stream_ssl_module \
    --with-stream_realip_module \
    --add-module=/usr/local/src/echo-nginx-module-master
    
    
    make && make install
    
    # 编译成功
    [18:21:07 root@nginx /usr/local/src/nginx-1.18.0]#ll /apps/nginx/sbin/nginx
    -rwxr-xr-x 1 root root 8126344 Mar 17 18:21 /apps/nginx/sbin/nginx
    
    [18:21:17 root@nginx /usr/local/src/nginx-1.18.0]#ll /apps/nginx/sbin/
    total 22768
    -rwxr-xr-x 1 root  root  8126344 Mar 17 18:21 nginx # 新的二进制程序
    -rwxr-xr-x 1 nginx nginx 7591104 Mar 15 15:22 nginx.bak # 手动的备份
    -rwxr-xr-x 1 nginx nginx 7591104 Mar 15 15:22 nginx.old # 编译后会自动备份
    
    
    [18:21:37 root@nginx /usr/local/src/nginx-1.18.0]#nginx -t
    nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
    nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
    [18:22:26 root@nginx /usr/local/src/nginx-1.18.0]#systemctl start nginx
    
    图片.png

    3.3 Nginx变量使用

    nginx的变量可以在配置文件中引用, 作为功能判断或者日志等场景使用
    变量可以分为内置变量和自定义变量
    内置变量是由nginx模块自带, 通过变量可以获取到众多的与客户端访问相关的值
    

    3.3.1 内置变量

    • 官方文档:
    http://nginx.org/en/docs/varindex.html
    
    • 常用内置变量
    $remote_addr;
    # 显示客户端地址, 一般是用户的公网出口ip, 请求通告DNS解析到企业的防护墙入口, 通告DNAT发送到四层负载(HA), 再由HA转发给七层的Nginx, 由于HA工作在四层时并不会修改请求报文的源ip, 防火墙的DNAT也不会修改源ip, 因此请求报文到达Nginx后, 源ip还是用户公网出口ip, 也就会被记录到$remote_addr;
    
    $http_name;
    #所有请求报文的字段, 都可以用$http_name变量来获取, name就是请求报文字段的名字
    
    $proxy_add_x_forwarded_for;
    # 此变量表示将客户端ip追加到请求报文中X-Forwarded-For首部字段, 多个ip之间用逗号分隔, 如果请求报文中没有X-Forwarded-For, 就使用$remore_addr;
    the “X-Forwarded-For” client request header field with the $remote_addr variable appended to it, separated by a comma. If the “X-Forwarded-For” field is not present in the client request header, the $proxy_add_x_forwarded_for variable is equal to the $remote_addr variable.
    
    $args;
    # 变量中存放了URL中的参数, 例如访问: http://pc.wang.org/main/index.do?id=202020202&partner=search
    # 返回结果为, id=202020202&partner=search
    
    $document_root;
    # 保存了针对当前资源的请求的系统根目录, 例如:/apps/nginx/html
    
    $document_uri;
    # 保存了当前请求中, 不包含参数的URI, 注意是不包含请求的指令, 比如 http://pc.wang.org/main/index.do?id=202020202&partner=search 会被定义为/main/index.do
    # 返回结果为: /main/index.do
    
    $host;
    # 存放了请求的host名称
    
    limit_rate 10240
    echo $limit_rate;
    # 如果nignx服务器使用了limit_rate配置了限制下载速度, 则会显示具体速度, 否则显示0
    
    $remote_port;
    # 客户端请求nginx服务器随机打开的端口号, 这里是每个客户端自己的端口
    
    $remote_user;
    # 已经经过auth basic module验证的用户名
    
    $request_body_file;
    # 做反向代理时发给后端服务器的本地资源的名称
    
    $request_method;
    # 请求资源的方式, GET/PUT/DELETE等
    
    $request_filename;
    # 当前请求的资源文件的磁盘路径, 由/root或alias指令与URI请求生成的文件组成的绝对路径
    如: /apps/nginx/html/main/index.html
    # 当请求的资源总是找不到时, 可以在对应的location下, 添加$request_filename来查看具体是找的磁盘上哪个文件
    
    $request_uri; 除了FQND剩下的链接内容
    # 包含请求参数的原始URI, 不包含主机名, 相当于: $document_uri?$args, 例如: /main/index.do?id=20200221&partner=search
    
    $scheme;
    # 请求的协议, 例如: http, https, ftp等
    # 通过$scheme可以实现, 当用户用http访问时, 自动跳转的https
    
    $server_protocol;
    # 保存了客户端请求资源使用的协议的版本, 例如: HTTP/1.0, HTTP/1.1, HTTP/2.0等
    
    $server_addr;
    # 保存了服务器的ip地址
    
    $server_name;
    # 请求的服务器的主机名
    
    $server_port;
    # 请求的服务器的端口号
    
    $http_name;
    # name为任意请求报文首部字段, 表示记录请求报文的首部字段
    
    $http_user_agent;
    # 客户端浏览器的详细信息
    
    $http_cookie;
    # 客户端的cookie信息
    
    $cookie_name;
    # name为任意请求报文首部字段cookie的key名
    
    • 范例: $args
    [18:53:45 root@nginx /apps/nginx/conf.d]#vim pc.conf 
    
    
    server {
        listen 80;
        server_name pc.wang.org;
        error_page 404  /index.html;
        error_log /data/nginx/logs/pc_wang_org_error.log;
    
        location  / {
            root /data/nginx/html/pc;
        }
        location /main {
    
            index index.html;
            default_type text/html;
            echo "hello world,main-->";
            echo $remote_addr;
            echo $args;                                                                                                                                                                  
            echo_reset_timer;
            echo_location /sub1;
            echo_location /sub2;
            echo "took $echo_timer_elapsed sec for total.";
    
        }
        location /sub1 {
    
            echo_sleep 1;
            echo sub1;
        }
        location /sub2 {
    
            echo_sleep 1;
            echo sub2;
        }
    }
    [18:55:03 root@nginx /apps/nginx/conf.d]#nginx -s reload
    
    图片.png
    • 范例: $document_root
    server {
        listen 80;
        server_name pc.wang.org;
        error_page 404  /index.html;
        error_log /data/nginx/logs/pc_wang_org_error.log;
    
        location  / {
            root /data/nginx/html/pc;
        }
        location /main {
    
            index index.html;
            default_type text/html;
            echo "hello world,main-->";
            echo $remote_addr;
            echo $document_root;
       }                                                                                                                                                                                
    }
    
    
    [19:11:22 root@nginx /apps/nginx/conf.d]#nginx -s reload
    [19:11:23 root@nginx /apps/nginx/conf.d]#curl http://pc.wang.org/main/
    hello world,main-->
    10.0.0.86
    /apps/nginx/html # 因为location /main中没有定义document_root, 而且访问/main不会匹配/, 因此会用编译安装时定义的编译路径+html, 和server中的设置无关
    
    • 范例: $document_uri
    • 范例: $host
    server {
        listen 80;
        server_name pc.wang.org;
        error_page 404  /index.html;
        error_log /data/nginx/logs/pc_wang_org_error.log;
    
        location  / {
            root /data/nginx/html/pc;
        }
        location /main {
    
            index index.html;
            default_type text/html;
            echo "hello world,main-->";
            echo $remote_addr;
            echo $document_root; 
            echo $document_uri;
            echo $host;                                                                                                                                                                 
       }
    }
    
    
    nginx -s reload
    
    [19:17:57 root@nginx /apps/nginx/conf.d]#curl 'http://pc.wang.org/main/index.do?id=202020202&partner=search'
    hello world,main-->
    10.0.0.86
    /apps/nginx/html
    /main/index.do # $document_uri的返回结果, 不带域名, 不带参数
    pc.wang.org # 请求的主机头
    
    • 范例: $scheme
    • 范例: $http_user_agent
    • 范例: $http_cookie
    • 范例: $cookie_name
    • 范例:
    $scheme://$host$document_uri?$args # 可以显示用户访问的完整路径
    
    server {
        listen 80;
        server_name pc.wang.org;
        error_page 404  /index.html;
        error_log /data/nginx/logs/pc_wang_org_error.log;
    
        location  / {
            root /data/nginx/html/pc;
        }
        location /main {
    
            index index.html;
            default_type text/html;
            echo "hello world,main-->";
            echo $remote_addr;
            echo $document_root;
            echo $scheme;
            echo $host;
            echo $document_uri;
            echo $args;
            echo $scheme://$host$document_uri?$args;                                                                                                                                    
       }
    }
    
    nginx -s reload
    
    # curl -b "cookie_key=cookie_name;key=name;key=name", curl -b可以模拟浏览器携带cookie访问
    [19:28:36 root@nginx /apps/nginx/conf.d]#curl -b name=admin 'http://pc.wang.org/main/index.do?id=202020202&partner=search'
    hello world,main-->
    10.0.0.86
    /apps/nginx/html
    http # $scheme返回值
    pc.wang.org $host返回值, FQDN
    /main/index.do $request_uri返回值, 除了FQDN和参数, 剩下的部分
    id=202020202&partner=search # $args, 返回URL中的参数
    http://pc.wang.org/main/index.do?id=202020202&partner=search # 访问的整个URL路径
    

    3.3.2 自定义变量

    假如需要自定义变量名称和值, 可以使用指令set $variable value; 另外自定义变量也可引用内置变量的值

    语法格式:

    set $variable value;
    可以用在 server, location, if中
    

    范例: 自定义变量的使用

        location /main {
            index index.html;
            default_type text/html;
            echo "hello world,main-->";
            set $name admin;                                                                                                                                                            
            echo $name; 
            set $client_ip $remote_addr;
            echo $client_ip;
       }
    
    [19:42:57 root@nginx /apps/nginx/conf.d]#curl pc.wang.org/main
    hello world,main-->
    admin # echo $name
    10.0.0.86 # 把$remote_addr的值, 赋值给$client_ip, 然后打印
    

    3.4 Nginx自定义访问日志

    访问日志是记录客户端即用户的具体请求内容信息, 全局配置模块中的error_log是记录nignx服务器运行时的错误日志, 错误日志一般只有一个, 但是访问日志可以在不同的虚拟主机中定义多个
    定义一个日志需要使用access_log指定的日志保存路径, 使用log_format指定日志的格式, 格式中定义要保存的具体日志内容

    访问日志由ngx_http_log_module模块实现

    注意: log_format只支持在http语句块中定义, 因此, 如果想实现不同虚拟主机使用不同的日志, 那么需要在http语句块中定义多个日志格式, 之后在server语句块中利用access_log去调用不同的格式, access_log支持在不同的语句块设置

    3.4.1 自定义默认格式日志

    定义日志格式    #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  logs/access.log  main;
    
    10.0.0.86 - - [17/Mar/2021:19:43:21 +0800] "GET /main HTTP/1.1" 200 57 "-" "curl/7.61.1"
    

    如果想要保留日志的原始格式, 只是添加相应的日志内容, 则配置如下:

    范例: 给pc和mobile两个站点, 定制不同的默认格式access日志

    # 先在主配置文件的http语句块定义两个不同的日志格式
    
    http {
        include       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  logs/access.log  main;
    
        log_format pc_log '$remote_addr [$time_local] "$request" $status ' '"$http_user_agent"';
        log_format mobile_log '$remote_addr [$time_local] "$request" ' '$status $body_bytes_sent';
    
    # 在pc和mobile的子配置文件中, 定义访问日志存放路径, 并且调用响应的格式
    
    server {
        listen 80;
        server_name pc.wang.org;
        error_page 404  /index.html;
        error_log /data/nginx/logs/pc_wang_org_error.log;
        access_log /data/nginx/logs/pc_access.log pc_log;                                                                                                                               
        location  / {                                                                                                                                                        
            root /data/nginx/html/pc;
        }
        location /main {
        
            index index.html;
            default_type text/html;
            echo "hello world,main-->";
            set $name admin;
            echo $name;
            set $client_ip $remote_addr;
            echo $client_ip;
       }
    }
    
    
    server {
      
        listen 80;
        server_name m.wang.org;
        root /data/nginx/html/mobile;
        index index index.html;
        access_log /data/nginx/logs/mobile_access.log mobile_log;                                                                                                                       
    }
    
    
    # 重新加载nginx验证
    nginx -s reload
    
    [20:19:35 root@nginx ~]#ll /data/nginx/logs/
    total 8
    -rw-r--r-- 1 root root   0 Mar 17 20:18 mobile_access.log
    -rw-r--r-- 1 root root  73 Mar 17 20:18 pc_access.log
    
    
    图片.png 图片.png

    3.4.2 自定义JSON格式日志

    Nginx的默认访问日志记录内容相对比较单一, 默认的格式也不方便后期做日志统计分析, 生成环境中通常将Nginx日志转换为JSON日志, 然后配置使用ELK做日志收集-统计和分析

    • 范例: 将访问日志定义为JSON格式, 利用Python脚本提取信息
    key:value
    
    #定义JSON格式访问日志
    
        log_format access_json '{"@timestamp":"$time_iso8601",'
            '"host":"$server_addr",'
            '"clientip":"$remote_addr",'
            '"size":$body_bytes_sent,'
            '"responsetime":$request_time,' # 总的处理时间
            '"upstreamtime":"$upstream_response_time",' # 后端应用服务器处理时间
            '"upstreamhost":"$upstream_addr",'
            '"http_host":"$host",'
            '"uri":"$uri",'
            '"xff":"$http_x_forwarded_for",'
            '"referer":"$http_referer",'
            '"tcp_xff":"$proxy_protocol_addr",'
            '"http_user_agent":"$http_user_agent",'
            '"status":"$status"}';
    
    
    # 虚拟主机中调用JSON格式日志
    access_log logs/access_json.log access_json;
    
    [21:16:14 root@naruto ~]#tail /apps/nginx/logs/access_json.log  -f
    
    
    
    
    {"@timestamp":"2021-03-17T21:16:41+08:00","host":"172.18.152.251","clientip":"120.78.154.82","size":0,"responsetime":0.000,"upstreamtime":"0.000","upstreamhost":"127.0.0.1:9000","http_host":"120.78.154.82","uri":"/wp-cron.php","xff":"-","referer":"-","tcp_xff":"-","http_user_agent":"WordPress/5.3.2; http://120.78.154.82","status":"499"}
    {"@timestamp":"2021-03-17T21:16:41+08:00","host":"172.18.152.251","clientip":"113.228.11.154","size":22702,"responsetime":0.069,"upstreamtime":"0.069","upstreamhost":"127.0.0.1:9000","http_host":"120.78.154.82","uri":"/index.php","xff":"-","referer":"-","tcp_xff":"-","http_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0","status":"200"}
    
    • 利用python脚本提取返回状态码和所有的ip地址
    [21:34:16 root@nginx ~]#vim log.py
    
    #!/usr/bin/python3
    status_200 = []
    status_404 = []
    with open("/apps/nginx/logs/access_json.log") as f:
        for line in f.readlines():
            line = eval(line)
            if line.get("status") == "200":
                status_200.append(line.get)
            elif line.get("status") == "404":                                                                                                                                           
                status_404.append(line.get)
            else:
                print("状态码 ERROR")
            print(line.get("clientip"))
    f.close()
    print("状态码200的有--:",len(status_200))
    print("状态码404的有--:",len(status_404))
    
    
    [21:34:15 root@nginx ~]#python3 log.py 
    10.0.0.86
    10.0.0.1
    10.0.0.1
    状态码200的有--: 1
    状态码404的有--: 2
    
    
    • 补充: python2代码转换成python3代码工具
    2to3
    
    [21:34:38 root@nginx ~]#pip3 install 2to3
    
    
    # 查看需要改动的代码
    [21:35:19 root@nginx ~]#2to3 log.py 
    
    # 直接让工具修改
    [21:35:19 root@nginx ~]#2to3 -w log.py 
    

    3.5 Nginx压缩功能

    Nginx支持对指定类型的文件进行压缩, 然后再传输给客户端, 而且压缩还可以设置压缩比例, 压缩后的文件大小将比源文件显著变小, 这样有助于降低出口带宽的利用率, 降低企业的IT支出, 不会占用相应的CPU资源

    Nginx对文件的压缩功能依赖于模块: ngx_http_gzip_module

    • 配置指令
    # 启用或禁用gzip压缩, 默认关闭
    gzip on | off;
    
    # 压缩比由低到高从1到9, 默认为1
    gzip_comp_level level;
    
    # 禁用IE6 gzip功能
    gzip_disable "MSIE [1-6]\.";
    
    # gzip压缩的最小文件, 小于设置值的文件将不会压缩
    gzim_min_length 1k;
    
    # 启用压缩功能时, 协议的最小版本, 默认为HTTP/1.1
    gzip_http_version 1.0 | 1.1;
    
    # 指定Nginx服务需要向服务器申请的缓存空间的个数和大小, 平台不同, 默认, 32 4k 或者 16 8k
    gzip_buffers number size;
    
    # 指明仅对哪些类型的资源执行压缩操作, 默认为gzip_types text/html, 不用显示指定, 否则出错
    gzip_types mime-type ...;
    
    # 如果启用压缩, 是否在响应报文头部插入"Vary: Accept-Encoding", 一般建议打开
    gzip_vary on | off;
    
    • 范例:
    [22:41:19 root@nginx ~]#ll /var/log/messages  -h
    -rw-------. 1 root root 2.1M Mar 17 22:06 /var/log/messages
    [22:42:34 root@nginx ~]#cp /var/log/messages /data/nginx/html/pc/messages
    [22:47:21 root@nginx ~]#chmod +r /data/nginx/html/pc/messages # 日志文件默认只有root能读, 需要修改权限
    mv /data/nginx/html/pc/messages /data/nginx/html/pc/m.txt # 修改成压缩支持的mime格式
    # 把日志文件拷贝到pc.wang.org站点的家目录下, 测试对其压缩
    
    # 压缩前
    
    图片.png
    # 修改pc.wang.org站点的配置文件
    # gzip可以配置在server语句块
        gzip on;
        gzip_comp_level 5;
        gzip_min_length 1k;                                                                                                                                                             
        gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/gif image/png;
        gzip_vary on;
    
    nginx -s reload
    
    # 压缩后
    
    图片.png
    10.0.0.86 [17/Mar/2021:22:59:36 +0800] "GET /m.txt HTTP/1.1" 200 297417
    

    3.6 Nginx实现https

    Nginx的https功能基于模块ngx_http_ssl_module实现, 因此编译安装时, 需要添加参数,ngx_http_ssl_module, 开启ssl功能, --with-http_ssl_module

    3.6.1 https配置参数

    配置参数:

    ssl on | off;
    listen 443 ssl;
    
    # 指向包含当前虚拟主机的证书和CA的两个证书信息的文件, 一般是crt文件(nginx证书一个有两个文件, 一个是服务器私钥, 一个是服务器的证书和CA的证书)
    ssl_certificate /path/to/file;
    
    # 当前虚拟主机使用的私钥文件, 一般是key文件
    ssl_certificate_key /path/to/file;
    
    # 支持ssl协议版本, 早期为ssl, 现在是tls, 默认为后三个
    ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2]
    
    # 配置ssl缓存: 
          off 关闭缓存
          none 通知客户端支持ssl session cache, 但是实际不支持
          builtin[:size] 使用OpenSSL内建缓存, 是每个worker进程私有的
          [shared:name:size] 在各woker之间使用一个共享的缓存, 需要定义一个缓存名称和缓存空间大小, 一兆可以存储4000个会话信息, 多个虚拟主机可以使用相同的缓存名称
    
    # 客户端连接可以复用ssl session cache中缓存的有效时长, 默认5m
    ssl_session_timeout time;
    

    3.6.2 自签名证书

    [23:15:17 root@nginx ~]#cd /apps/nginx/
    [23:24:54 root@nginx /apps/nginx]#mkdir certs
    [23:24:56 root@nginx /apps/nginx]#cd certs
    # 生成CA的自签名证书
    [23:38:56 root@nginx /apps/nginx/certs]#openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 3650 -out ca.crt
    Generating a RSA private key
    .............................................................................................++++
    ...........................................................................................++++
    writing new private key to 'ca.key'
    -----
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    # CA信息
    Country Name (2 letter code) [XX]:CN # 所属国家 
    State or Province Name (full name) []:LN # 所属省份
    Locality Name (eg, city) [Default City]:AS # 所属城市
    Organization Name (eg, company) [Default Company Ltd]:wang.org # CA公司名称
    Organizational Unit Name (eg, section) []:IT # 所属部门
    Common Name (eg, your name or your server's hostname) []:ca.wang.org # CA域名
    Email Address []:anshan88@qq.com # 邮箱
    
    
    
    [23:39:21 root@nginx /apps/nginx/certs]#ll
    total 8
    -rw-r--r-- 1 root root 2090 Mar 17 23:39 ca.crt
    -rw------- 1 root root 3272 Mar 17 23:38 ca.key
    
    

    3.6.3 CA制作服务器私钥和证书申请文件

    [23:41:01 root@nginx /apps/nginx/certs]#openssl req -newkey rsa:4096 -nodes -sha256 -keyout pc.wang.org.key -out pc.wang.org.csr
    Generating a RSA private key
    ........++++
    .......................++++
    writing new private key to 'pc.wang.org.key'
    -----
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    # 网站信息
    -----
    Country Name (2 letter code) [XX]:CN # 网站所属国家
    State or Province Name (full name) []:LN # 网站所属省份
    Locality Name (eg, city) [Default City]:AS # 网站所属城市
    Organization Name (eg, company) [Default Company Ltd]:wang.org # 网站所属公司
    Organizational Unit Name (eg, section) []:IT # 部门
    Common Name (eg, your name or your server's hostname) []:pc.wang.org # 网站域名
    Email Address []:anshan88@qq.com # 邮箱
    
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:
    
    

    3.6.4 CA签发证书

    [23:42:46 root@nginx /apps/nginx/certs]#openssl x509 -req -days 3650 -in pc.wang.org.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out pc.wang.org.crt
    Signature ok
    subject=C = CN, ST = LN, L = AS, O = wang.org, OU = IT, CN = pc.wang.org, emailAddress = anshan88@qq.com
    Getting CA Private Key
    
    
    
    [23:43:05 root@nginx /apps/nginx/certs]#ll
    total 24
    -rw-r--r-- 1 root root 2090 Mar 17 23:39 ca.crt
    -rw------- 1 root root 3272 Mar 17 23:38 ca.key
    -rw-r--r-- 1 root root 1968 Mar 17 23:42 pc.wang.org.crt
    -rw-r--r-- 1 root root 1728 Mar 17 23:41 pc.wang.org.csr
    -rw------- 1 root root 3272 Mar 17 23:41 pc.wang.org.key
    
    

    3.6.5 验证证书内容

    [23:43:05 root@nginx /apps/nginx/certs]#openssl x509 -in pc.wang.org.crt -noout -text
    Certificate:
        Data:
            Version: 1 (0x0)
            Serial Number:
                09:95:d7:63:66:c8:bd:70:6a:2b:a0:36:ad:61:33:c7:82:21:25:40
            Signature Algorithm: sha256WithRSAEncryption
       #证书发布者     Issuer: C = CN, ST = LN, L = AS, O = wang.org, OU = IT, CN = ca.wang.org, emailAddress = anshan88@qq.com
            Validity
                Not Before: Mar 17 15:42:54 2021 GMT
                Not After : Mar 15 15:42:54 2031 GMT
       #证书接收者        Subject: C = CN, ST = LN, L = AS, O = wang.org, OU = IT, CN = pc.wang.org, emailAddress = anshan88@qq.com
    
    

    3.6.6 将ca的自签名证书和颁发给pc.wang.org的证书合并

    apache的ssl证书有三个文件:
    apache私钥
    apache的证书
    chain证书链, 指向上级ca信息
    
    nginx的ssl证书有两个文件:
    nginx私钥
    nginx和ca的证书, 放在一个文件pem文件中
    
    [00:16:09 root@nginx /apps/nginx/certs]#cat pc.wang.org.crt ca.crt > pc.wang.org.pem # 需要先cat服务器证书, 再cat上级CA证书, 否则会报错
    
    

    3.6.7 配置nginx支持https

    
    
    server {
        listen 80;
        listen 443 ssl;
        server_name pc.wang.org;
        ssl_certificate /apps/nginx/certs/pc_wang.org.pem;
        ssl_certificate_key /apps/nginx/certs/pc.wang.org.key;                                                                                                                          
        ssl_session_cache shared:sslcache:20m;
        ssl_session_timeout 10m;
        
        error_page 404  /index.html;
        error_log /data/nginx/logs/pc_wang_org_error.log;
        access_log /data/nginx/logs/pc_access.log mobile_log;
            
    
        location  / {
            root /data/nginx/html/pc;
        }
    }
    ~    
    
    [23:47:37 root@nginx /apps/nginx/certs]#nginx -t
    nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
    nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
    [23:47:38 root@nginx /apps/nginx/certs]#nginx -s reload
    
    
    图片.png 图片.png 图片.png

    3.6.8 实现多域名https

    Nginx支持基于多个IP实现多域名的功能, 并且还支持单个IP多域名的基础之上实现HTTPS, 其功能是基于Nginx的SNI(Server Name Indicatioin)功能实现, SNI是为了解决一个Nginx服务器内使用一个IP绑定多个域名和证书的功能, 其具体功能是客户端在连接到服务器建立SSL连接之前先发送要访问站点的域名(Hostname), 这样服务器再根据这个域名返回给客户端一个合适的证书

    • 范例: SNI功能
    [00:00:04 root@nginx /apps/nginx/certs]#nginx -V
    nginx version: nginx/1.18.0
    built by gcc 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC) 
    built with OpenSSL 1.1.1g FIPS  21 Apr 2020
    TLS SNI support enabled # SNI功能启用
    configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/usr/local/src/echo-nginx-module-master
    
    
    # 给m.wang.org站点制作证书
    
    [00:00:10 root@nginx /apps/nginx/certs]#openssl req -newkey rsa:4096 -nodes -sha256 -keyout m.wang.org.key -out m.wang.org.csr
    Generating a RSA private key
    ...............................................................................................................................................................................++++
    ..........++++
    writing new private key to 'm.wang.org.key'
    -----
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [XX]:CN
    State or Province Name (full name) []:LN
    Locality Name (eg, city) [Default City]:AS
    Organization Name (eg, company) [Default Company Ltd]:wang.org
    Organizational Unit Name (eg, section) []:IT
    Common Name (eg, your name or your server's hostname) []:m.wang.org
    Email Address []:anshan88@qq.com       
    
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:
    
    
    [00:02:15 root@nginx /apps/nginx/certs]#openssl x509 -req -days 3650 -in m.wang.org.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out m.wang.org.crt
    Signature ok
    subject=C = CN, ST = LN, L = AS, O = wang.org, OU = IT, CN = m.wang.org, emailAddress = anshan88@qq.com
    Getting CA Private Key
    
    [00:23:53 root@nginx /apps/nginx/certs]#ll
    total 40
    -rw-r--r-- 1 root root 2090 Mar 17 23:39 ca.crt
    -rw------- 1 root root 3272 Mar 17 23:38 ca.key
    -rw-r--r-- 1 root root 2090 Mar 18 00:13 m.wang.org.crt
    -rw-r--r-- 1 root root 1724 Mar 18 00:02 m.wang.org.csr
    -rw------- 1 root root 3272 Mar 18 00:01 m.wang.org.key
    -rw-r--r-- 1 root root 1968 Mar 17 23:42 pc.wang.org.crt
    -rw-r--r-- 1 root root 1728 Mar 17 23:41 pc.wang.org.csr
    -rw------- 1 root root 3272 Mar 17 23:41 pc.wang.org.key
    -rw-r--r-- 1 root root 4058 Mar 18 00:21 pc.wang.org.pem
    
    
    [00:23:55 root@nginx /apps/nginx/certs]#cat m.wang.org.crt  ca.crt > m.wang.org.pem
    [00:24:25 root@nginx /apps/nginx/certs]#ll
    total 48
    -rw-r--r-- 1 root root 2090 Mar 17 23:39 ca.crt
    -rw------- 1 root root 3272 Mar 17 23:38 ca.key
    -rw-r--r-- 1 root root 2090 Mar 18 00:13 m.wang.org.crt
    -rw-r--r-- 1 root root 1724 Mar 18 00:02 m.wang.org.csr
    -rw------- 1 root root 3272 Mar 18 00:01 m.wang.org.key
    -rw-r--r-- 1 root root 4180 Mar 18 00:24 m.wang.org.pem
    -rw-r--r-- 1 root root 1968 Mar 17 23:42 pc.wang.org.crt
    -rw-r--r-- 1 root root 1728 Mar 17 23:41 pc.wang.org.csr
    -rw------- 1 root root 3272 Mar 17 23:41 pc.wang.org.key
    -rw-r--r-- 1 root root 4058 Mar 18 00:21 pc.wang.org.pem
    
    
    # 配置mobile站点
    
    server {
      
        listen 80;
        server_name m.wang.org;
        listen 443 ssl;
        ssl_certificate /apps/nginx/certs/m.wang.org.pem;
        ssl_certificate_key /apps/nginx/certs/m.wang.org.key;                                                                                                                           
        ssl_session_cache shared:sslcache:20m;
        ssl_session_timeout 10m;
    
        root /data/nginx/html/mobile;
        index index index.html;
        access_log /data/nginx/logs/mobile_access.log mobile_log;
    }
    
    [00:39:29 root@nginx ~]#nginx -t
    nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
    nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
    [00:39:31 root@nginx ~]#nginx -s reload
    
    
    
    图片.png 图片.png

    注意: 使用了SSL证书后, 需要全站的连接都是HTTPS, 否则证书会无效, 浏览器访问网站时仍然会显示不安全

    3.6.9 实现HSTS

    • 配置文件
    server {
      listen 443 ssl;
      server_name pc.wang.org
      add_header Strict-Transport-Security "max-age=3153600; includeSubDomains" always;
      localtion / {
        ....
      }
    }
    
    • 范例: 在pc.wang.org站点开启HSTS
    [01:01:42 root@nginx /data/nginx/html/pc/images]#vim /apps/nginx/conf.d/pc.conf
    # 添加在server语句块
        add_header Strict-Transport-Security "max-age=3153600; includeSubDomains" always;  
    
    [01:01:42 root@nginx /data/nginx/html/pc/images]#vim /apps/nginx/conf.d/pc.conf
    [01:05:08 root@nginx /data/nginx/html/pc/images]#nginx -s reload
    
    
    • 验证
    [01:05:35 root@nginx /data/nginx/html/pc/images]#curl -ikL https://pc.wang.org
    HTTP/1.1 200 OK
    Server: nginx/1.18.0
    Date: Wed, 17 Mar 2021 17:05:55 GMT
    Content-Type: text/html
    Content-Length: 11
    Last-Modified: Mon, 15 Mar 2021 12:57:27 GMT
    Connection: keep-alive
    ETag: "604f59b7-b"
    Strict-Transport-Security: max-age=3153600; includeSubDomains
    Accept-Ranges: bytes
    
    pc website
    

    3.7 关于favicon.so

    favicon.so文件是浏览器打开网站时, 显示的小图标, 当客户端使用浏览器访问页面时, 浏览器会自动主动发起请求获取页面的favicon.ico文件, 但是当浏览器请求的favicon.ico文件不存在时, 服务器会记录404日志, 而且浏览器也会显示404报错

    方法1: 服务器不记录访问日志

    lcation = /favicon.ico {
      log_not_found off;
      access_log off;
    }
    

    方法2: 将图标保存到指定目录访问

        location = /favicon.ico {
            root /data/nginx/html/pc/images;
            expires 365d;                                                                                                                                                               
        }
    
    [00:58:18 root@nginx /data/nginx/html/pc]#mkdir images
    [00:58:22 root@nginx /data/nginx/html/pc]#cd images/
    [00:58:54 root@nginx /data/nginx/html/pc/images]#ls
    favicon.ico
    
    
    10.0.0.86 - - [17/Mar/2021:20:18:44 +0800] "GET / HTTP/1.1" 200 612 "-" "curl/7.61.1"
    

    3.8 升级OpenSSL版本

    # 当前OpenSSL版本
    built with OpenSSL 1.1.1g FIPS  21 Apr 2020
    # 准备升级到1.1.1h
    
    # 当前的nginx二进制文件
    
    [01:08:18 root@nginx ~]#ll /apps/nginx/sbin/
    total 22768
    -rwxr-xr-x 1 root  root  8126344 Mar 17 18:21 nginx
    -rwxr-xr-x 1 nginx nginx 7591104 Mar 15 15:22 nginx.bak
    -rwxr-xr-x 1 nginx nginx 7591104 Mar 15 15:22 nginx.old
    
    
    # 下载最新版本OpenSSL源码包
    
    [01:08:22 root@nginx ~]#cd /usr/local/src
    [01:09:19 root@nginx /usr/local/src]#wget https://www.openssl.org/source/openssl-1.1.1h.tar.gz
    [01:10:57 root@nginx /usr/local/src]#tar xvf openssl-1.1.1h.tar.gz
    
    
    [01:14:54 root@nginx /usr/local/src/nginx-1.18.0]#cd nginx-1.18.0/
    [01:14:54 root@nginx /usr/local/src/nginx-1.18.0]#./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/usr/local/src/echo-nginx-module-master --with-openssl=/usr/local/src/openssl-1.1.1h
    
    [01:15:40 root@nginx /usr/local/src/nginx-1.18.0]#make && make install
    
    
    # 编译后
    [01:20:13 root@nginx /apps/nginx/sbin]#ll
    total 26672
    -rwxr-xr-x 1 root  root  11587608 Mar 18 01:19 nginx # 新的二进制文件
    -rwxr-xr-x 1 nginx nginx  7591104 Mar 15 15:22 nginx.bak
    -rwxr-xr-x 1 root  root   8126344 Mar 17 18:21 nginx.old
    
    
    # 无需重启nginx, 即可生效
    [01:20:13 root@nginx /apps/nginx/sbin]#nginx -V
    nginx version: nginx/1.18.0
    built by gcc 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC) 
    built with OpenSSL 1.1.1h  22 Sep 2020
    TLS SNI support enabled
    configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/usr/local/src/echo-nginx-module-master --with-openssl=/usr/local/src/openssl-1.1.1h
    

    相关文章

      网友评论

        本文标题:8. Nginx高级配置

        本文链接:https://www.haomeiwen.com/subject/ptekcltx.html