1、nginx平滑升级

平滑升级:升级过程中用户的访问不断开

简单粗暴的方法:
1、备份现有的ngx命令
2、用新的版本的ngx命令替换原有的命令
3、重启nginx

需求:不重启nginx且升级nginx

平滑升级:

平滑更新步骤说明
1、准备好新的nginx命令(已经测试的可用的)
2、检查旧版本的ngx是否运行,如果没有则运行
3、把当前环境的nginx命令备份,使用新的命令替换把当前运行nginx的pid文件改个名
4、通过kill命令向当前运行的nginx发出信息,准备被替代-USR2 pid使用新的nginx命令启动nginx进程
5、测试调试,关闭旧的nginx进程即可(kill即可)

1.1 环境准备

web01中操作
1、准备nginx1.24.0
2、准备新版本的nginx,比如放在/tmp/目录,比如使用tengine2.3.3
3、备份原有的ngx命令

1.2 具体操作

第一步:准备新版的nginx命令

假设,lb01的nginx命令是最新版的,把lb01的 nginx命令发送到web01的/tmp目录中

[root@lb01 ~]#scp /sbin/nginx 192.168.10.7:/tmp

第二步:备份原有的nginx命令

web01中,备份原有的nginx命令

[root@web01 ~]#mv /sbin/nginx /sbin/nginx-1.24.0

第三步:用新的nginx命令替换

新的nginx命令已经放在/tmp目录中,将它复制到/sbin/目录中即可

[root@web01 ~]#cp /tmp/nginx /sbin/

第四步:使用kill命令启动新的ngx

注意不能使用systemctl restart重启nginx

查看旧版本的ngx运行的pid

[root@web01 ~]#cat /var/run/nginx.pid*
22786
[root@web01 ~]#ps -ef | grep 22786
root      22786      1  0 20:48 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
www       22787  22786  0 20:48 ?        00:00:02 nginx: worker process
root      24103   1726  9 21:12 pts/0    00:00:00 grep --color=auto 22786
[root@web01 ~]#

使用kill -USR2 pid号结束进程:

[root@web01 ~]#kill -USR2 `cat /var/run/nginx.pid`

查看nginx的pid

[root@web01 ~]#ll /var/run/nginx.pid*
-rw-r--r-- 1 root root 6 Jul  1 21:15 /var/run/nginx.pid
-rw-r--r-- 1 root root 6 Jul  1 20:48 /var/run/nginx.pid.oldbin
[root@web01 ~]#

此时有2个pid,一个是正在运行的,一个是旧的

第五步:结束旧的进程

[root@web01 ~]#kill `cat /var/run/nginx.pid.oldbin`

2、rewrite功能

2.1 nginx重定向概述

重定向:也叫URL重定向,也叫URL改写

通过模块指令实现对url、uri改变

未来的需求:

1、网站是http(80)--->https(443)URL重定向
  例如:用户访问:http://www.baidu.com --->https://www.baidu.com
2、根据客户端访问类型进行跳转
  希望根据用户客户端类型进行判断,例如:
    使用手机访问,则访问m.baidu.com
    否则默认访问www.baidu.com
3、新老域名跳转,例如:www.360buy.com  ---> jd.com
4、需要我们调整URL格式:伪静态(搜索引擎收入),例如:
    https://doc.qq.com/desklg/Rfklvv1124gg11

2.2 模块与指令

rewrite模块

相关指令说明
return实现对url的改写,一般与nginx变量一起使用 返回指定的状态码
rewrite实现对url的改写,使用正则匹配uri,进行改写,还有各种标记
set创建或修改nginx变量
if判断,一般与nginx变量一起使用
1)return指令
格式说明
格式1return code URL;返回状态码+新的url地址
格式2return code;返回状态码
放哪server,location,if

案例01:如果用户访问/admin/页面,返回403

[root@web01 ~]#vim /etc/nginx/conf.d/rewrite.test.conf
server {
  listen 80;
  server_name rewrite.test.com;
  root /app/code/rewrite;
  location / {
    index index.html;
  }
  location /admin/ {
    return 403;
  }

案例02:域名跳转

用户访问rewrite.test.com 跳转到:www.badu.com

server {
  listen 80;
  server_name rewrite.test.com;
  root /app/code/rewrite;
  return 302 https://www.baidu.com;
}

302:临时跳转

301:永久跳转

本地做hosts解析,浏览器打开即可看到跳转效果

谷歌浏览器安装Redirect-Path_v2.2.2插件,可以看到跳转的过程信息:

命令行访问:

[root@web01 ~]#curl -Lv -H Host:rewrite.test.com  http://192.168.10.7/

-L:–location,跟踪跳转,响应是301、302跳转的时候使用

案例03:http跳转到https

server {
  listen 80;
  server_name rewrite.test.com;
  return 302 https://rewrite.test.com$request_uri;
}
server {
  listen 443 ssl;
  server_name rewrite.test.com;
  root /app/code/rewrite;
  私钥;
  公钥(证书);
  location / {
     index index.html;
  }
}

这里只演示格式写法,由于没有公钥、私钥,所以,无法正式运行

2)if判断

if指令可以在server、location中使用,if在nginx中不能嵌套使用

1、一般与nginx内置变量或自定义变量一起使用
2、与location使用的符号类似,如:
  ~、~*、!~、!~*、=、!=、
3、常用\*、!
4、nginx中取反、排除,只能用if

案例04:前面的rewrite.test.com网站只准许GET、POST、HEAD 3种请求方法,其他的访问禁止

[root@web01 ~]#cat /etc/nginx/conf.d/rewrite.test.conf
server {
  listen 80;
  server_name rewrite.test.com;
  root /app/code/rewrite;
  if ($request_method !~ "GET|POST|HEAD") {
     return 403;
  }
  location / {
    index index.html;
  }
}

可以使用405状态码,405表示使用的请求方法不被网站允许或支持。

重启nginx,测试

[root@web01 ~]#nginx -s reload
#GET
[root@web01 ~]#curl -v -H Host:rewrite.test.com  http://192.168.10.7/
#HEAD
[root@web01 ~]#curl -I -v -H Host:rewrite.test.com  http://192.168.10.7/
#POST
[root@web01 ~]#curl -X POST -v -H Host:rewrite.test.com  http://192.168.10.7/
3)set指令

set:用于创建或修改nginx变量

# shell中的写法
变量名=值
例如:name=zhangsan
echo $name
# nginx中的写法
set  $变量  值;
例如:set  $name zhangsan;

例如:

[root@web01 ~]#vim  /etc/nginx/conf.d/rewrite.test.conf
server {
  listen 80;
  server_name rewrite.test.com;
  set $url $http_host$request_uri;
  return 200 $url;
}

重启nginx,测试:

[root@web01 ~]#nginx -s reload
[root@web01 ~]#curl -H Host:rewrite.test.com  http://192.168.10.7/
rewrite.test.com/

案例05:设置网站是否为维护状态,如果是:返回503,否则,访问正常

流程:设置标记$flag,默认是0

判断如果$flag的值是1,则返回503

[root@web01 ~]#vim /etc/nginx/conf.d/rewrite.test.conf
server {
  listen 80;
  server_name rewrite.test.com;
  root /app/code/rewrite;
  set $flag 1;
 
  if ( $flag = 1 ) {
     return 503;
  }
  error_page 503 /503.html;
  location / {
    index index.html;
  }
}
[root@web01 ~]#echo "503 error" > /app/code/rewrite/503.html

error_page:遇到指定的错误的时候显示指定的页面,需要nginx遇到对应的错误才会生效

把变量独立放在一个文件:

#变量单独在一个文件中定义
[root@web01 ~]#vim /app/code/rewrite/flag.txt
set $flag 1;

[root@web01 ~]#vim /etc/nginx/conf.d/rewrite.test.conf
server {
  listen 80;
  server_name rewrite.test.com;
  root /app/code/rewrite;
  include /app/code/rewrite/flag.txt;
  if ( $flag = 1 ) {
     return 503;
  }
  error_page 503 /503.html;
  location / {
    index index.html;
  }
}
4)rewrite指令

rewrite正则用于匹配用户请求的uri

命令格式:与sed ‘s###g’类似,实现替换功能,rewrite替换url内容(改写)

rewrite指令说明
格式rewrite 找什么(具体内容、正则、保护分组) 替换成什么(具体内容、后向引用)[标记];标记可以省略,默认使用302
放在哪server、location、if
rewrite匹配的内容,匹配uri

rewrite的301、302标记

301:permanent
302:redirect

案例06:域名跳转

[root@web01 ~]#vim /etc/nginx/conf.d/rewrite.test.conf
server {
  listen 80;
  server_name rewrite.test.com;
  #return 301 http://www.baidu.com$request_uri;
  rewrite ^(.*)$ https://www.baidu.com/$1  redirect;
}

^:匹配的是域名(rewrite.test.com)的末尾

$1:第一个分组

redirect:表示302,可以不写,默认是302

案例07:配置phpshe(shop)电商的伪静态规则

假设伪静态之后的url地址(静态):http://192.168.10.7:83/product/1
伪静态之前的url地址(动态):http://192.168.10.7:83/index.php?mod=product&act=1

书写的rewrite目标,把用户访问的静态url地址还原成动态地址,地址通过php处理

rewrite  匹配伪静态请求url   还原成动态url;
rewrite  ^/([0-9a-zA-Z]+)/(\d+)   http://192.168.10.7:83/index.php?mod=$1&act=$2; 
或:rewrite  ^/(\w+)/(\d+)   http://192.168.10.7:83/index.php?mod=$1&act=$2;  
\w:[a-zA-Z0-9_]
\d:数字

直接访问:http://192.168.10.7:83/product/1

则报错:

下面进行rewrite改写:

修改shop的config.php文件,把url_mode改成pathinfo,表示开启伪静态

[root@web01 ~]#vim /app/code/shop/config.php
$pe['url_model'] = 'pathinfo'; //url模式,可选项(pathinfo/pathinfo_safe/php)

书写伪静态欢迎规则

修改站点配置文件

[root@web01 ~]#vim /etc/nginx/conf.d/shop.conf
server {
  listen 83;
  server_name shop.com;
  error_log /var/log/nginx/shop-error.log notice;
  access_log /var/log/nginx/shop-access.log main;
  rewrite ^/(\w+)/(\d+)  http://192.168.10.7:83/index.php?mod=$1&act=$2;
  root /app/code/shop;
  location / {
     index index.php;
  }
  location ~* \.php$ {
     fastcgi_pass 127.0.0.1:9000;
     fastcgi_index index.php;
     fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
     include fastcgi_params;
  }
}
5)rewrite标记
标记说明补充
redirect(默认)302,临时。用户访问的时候,收到302提示及新的位置Location(响应头),用户根据Location新的位置进行访问(让用户重新发出http请求)新、旧的地址都可以用
permanent301,永久。用户访问的时候,收到301提示及新的位置Location(响应头),用户根据Location新的位置进行访问(让用户重新发出http请求)旧的地址取消了,用不了。只能用新的网站
break用户的请求匹配到包含break指令或rewrite规则后,即使后面还有location规则,不会继续运行,终止运行
last用户请求匹配到包含last标记的rewrite规则后,停止继续执行,nginx会重新发出内部请求,请求与location规则进行匹配开启nginx rewrite_log才能看到

案例:

[root@web01 ~]#vim /etc/nginx/conf.d/flag.test.conf
server {
  listen 80;
  server_name flag.test.com;
  root /app/code/flag;
  error_log /var/log/nginx/flag-error.log notice;
  rewrite_log on; #需要错误日志debug...notice
  location / {
    rewrite /1.html /2.html;
    rewrite /2.heml /3.html;
  }
  location /2.html {
    rewrite /2.html /b.html;
  }
  location /3.html {
    rewrite /3.html /a.html;
  }
}
#站点目录及测试文件
[root@web01 ~]#mkdir -p /app/code/flag
[root@web01 ~]#echo 1.html url > /app/code/flag/1.html
[root@web01 ~]#echo 2.html url > /app/code/flag/2.html
[root@web01 ~]#echo 3.html url > /app/code/flag/3.html
[root@web01 ~]#echo a.html url > /app/code/flag/a.html
[root@web01 ~]#echo b.html url > /app/code/flag/b.html
#重启nginx
[root@web01 ~]#systemctl restart nginx

1、访问/1.html显示a.html内容

[root@web01 ~]#curl -H Host:flag.test.com http://192.168.10.7/1.html
a.html url

2、访问/2.html显示b.html内容

[root@web01 ~]#curl -H Host:flag.test.com http://192.168.10.7/2.html
b.html url

3、在rewrite /1.html /2.html加上break标记,即:

server {
  listen 80;
  server_name flag.test.com;
  root /app/code/flag;
  error_log /var/log/nginx/flag-error.log notice;
  rewrite_log on; #需要错误日志debug...notice
  location / {
    rewrite /1.html /2.html break;
    rewrite /2.heml /3.html;
  }
  location /2.html {
    rewrite /2.html /b.html;
  }
  location /3.html {
    rewrite /3.html /a.html;
  }
}

执行完rewrite后直接结束。

此时,访问/1.html显示b.html内容:

[root@web01 ~]#curl -H Host:flag.test.com http://192.168.10.7/1.html
b.html url

4、在rewrite /1.html /2.html加上last标记,即:

server {
  listen 80;
  server_name flag.test.com;
  root /app/code/flag;
  error_log /var/log/nginx/flag-error.log notice;
  rewrite_log on; #需要错误日志debug...notice
  location / {
    rewrite /1.html /2.html last;
    rewrite /2.heml /3.html;
  }
  location /2.html {
    rewrite /2.html /b.html;
  }
  location /3.html {
    rewrite /3.html /a.html;
  }
}

访问/1.html显示b.html内容:

[root@web01 ~]#curl -H Host:flag.test.com http://192.168.10.7/1.html
b.html url

查看日志可以看到跳转情况:

[root@web01 ~]#tail /var/log/nginx/flag-error.log 

3、nginx优化

3.1 nginx配置详解

nginx完整配置示例:

user    www;
pid    /run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile  65535;

#load modules
include /etc/nginx/modules-enabled/*.conf;

events {
  multi_accept   on; #性能优化
  worker_connections  65535;
}

http {
  charset     utf-8;
  sendfile    on;
  tcp_nopush  on;
  tcp_nodelay on;
  types_hash_max_size  2048;
  types_hash_bucket_size  64;
  client_max_body_size    16M;

  #MTME
  include       mime.types;
  default_type  application/octet-stream;

  #logging
  access_log    /var/log/nginx/access.log;
  error_log    /var/log/nginx/error.log  warn;

  #limits 安全优化
  limit_req_log_devel   warn;
  limit_req_zone  $binary_remote_addr  zone=login:10m rate=10r/m;

  #ssl 配置https 开始 
  ssl_session_timeout  1d;
  ssl_session_cache    shared:SSL:10m;
  ssl_session_tickets  off;
 
  #diffie-hellman  parameter for DHE ciphersuites
  ssl_dhparam    /etc/nginx/dhparam.pem;

  #mozilla intermediate configuration
  ssl_protocols  TLSv1.2  TLSv1.3;
  ssl_ciphers   ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

  #OCSP Stapling
  ssl_stapling   on;
  ssl_stapling_verify  on;
  resolver  1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
  resolver_timeout  2s;
  #配置HTTPS 结束

  #load configs
  include  /etc/nginx/conf.d/*.conf;

  #server部分配置
  server {
     listen   443 ssl http2;
     listen   [::]:443 ssl http2;
     server_name blog.test.com;
     set    $base  /app/code/;
     root   $base/blog/;

     #SSL
     ssl_certificate  /etc/letsencrypt/live/blog.test.com/fullchain.pem;
     ssl_certificate  /etc/letsencrypt/live/blog.test.com/privkey.pem;
     ssl_trusted_certificate /etc/letsencrypt/live/blog.test.com/chain.pem;

     #security headers
     add_header X-XSS-Protection  "1;mode=block" always;
     add_header X-Content-Type-Options  "nosniff" always;
     add_header Referrer-Policy  "no-referrer-when-downgrade" always;
     add_header Content-Security-Policy "default-src 'self' http:https:ws:wss:data:blob:'unsafe-inline';frame-ancestors 'self';"  always;
     add_header Permissions-Policy "interest-cohort=()" always;
     add_header Strict-Transport-Security "max-age=31536000;includeSubDomains" always;

     # .files 禁止访问 
     location ~ /\.(?!well-known) {
          deny all;
     }
     # security.txt
     location /security.txt {
         return 301 /.well-known/security.txt;
     }
     location = /.well-known/security.txt {
         alias ~/security.txt;
     }
     # index.php
     index index.php;
     # index.php fallback
     location / {
       try_files $uri $uri/ /index.php?$query_string;
       #测试指定的uri是否存在
       #如果不存在,则设置个默认的(最后的那个)
     }
     
     # favicon.ico  站点的图标文件
     location = /favicon.ico {
       log_not_found off;
       access_log  off;
     }

     #robots.txt 安全优化
     location = /robots.txt {
       log_not_found  off;
       access_log  off;
     }

     # assets,media 性能优化
     location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|mp4|ogg|midi?|wav|m4a|acc|mov|webm|mpe?g|avi|flv|ogv|wmv)$ {
         expires 7d;
         access_log on;
     }
    
     # svg,fonts  性能优化
     location ~* \.(?:scgz?|ttf|ttc|otf|eot|woff2?)$ {
       add_header Access-Control-Allow-Origin "*";
       exprise 7d;
       access_log off;
     }
     
     # gzip 性能优化
     gzip         on;
     gzip_vary    on;
     gzip_proxied any;
     gzip_comp_level 6;
     gzip_types   text/plain  text/css  text/xml  application/json  application/javascript  application/rss+xml  application/atom+xml  image/svg+xml;

     #brotli 性能优化 
     brotli   on;
     brotli_comp_level 6;
     brotli_types   text/plain  text/css  text/xml  application/json  application/javascript  application/rss+xml  application/atom+xml  image/svg+xml;

     # handle .php
     location ~ \.php$ {
      # fastcgi_pass  unix:/var/run/php/php-fpm.sock;
        fastcgi_pass  127.0.0.1:9000;

       #404
       try_files  $fastcgi_script_name =404;
       
       # default fastcgi_params
       include  fastcgi_params;
     
       # fastcgi  settings
       fastcgi_index    index.php;
       fastcgi_buffers  8  16k;
       fastcgi_buffer_size  32k;

       #fastcgi params
       fastcgi_param DOCUMENT_ROOT  $realpath_root;
       fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
       fastcgi_param PHP_ADMIN_VALUE "open_basedir=$base/:/usr/lib/php/:/tmp/";
     }
  }
   # http  redirect
 server {
    listen 80;
    listen [::]:80;
    server_name blog.test.com;

    # ACME-challenge
    location ^~ /.well-know/acme-challenge/ {
       root /var/www/_letsencrypt;
    }
    location / {
       return 301 https://blog.test.com$request_uri;
    }
 } 
}

生成环境的配置示例:

#user  root;
worker_processes  4;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

pid        logs/nginx.pid;

worker_rlimit_nofile 65535;
events {
    worker_connections  65535;
    use epoll;
    }


http {
    include       mime.types;
    default_type  application/octet-stream;
    #ssi on;
    #ssi_silent_errors on
    underscores_in_headers on;
    log_format  main  '[$remote_addr] [$remote_port] [$remote_user] [$http_cookie] [$time_local] [$request] [$http_host]'
                  '[$request_method] [$http_x_forwarded_for] [$status] [$upstream_status] [$body_bytes_sent] [$http_referer]'
                  '[$http_user_agent] [$ssl_protocol] [$ssl_cipher] [$upstream_addr] [$request_time] [$upstream_response_time]'; 

 ##如果需要打印用户真实IP,使用$http_x_forwarded_for代替$remote_addr,
 #    log_format access '{"appname":"nginx",'
 #                       '"logtime": "$time_local", '
 #                        '"client_ip": "$remote_addr", '
 #                        '"remote_user": "$remote_user", '
 #                        '"http_referer": "$http_referer", '
 #                        '"resp_len": "$body_bytes_sent", '
 #                        '"waster_time": "$request_time", '
 #                        '"status": "$status", '
 #                        '"request_path": "$request", '
 #                        '"request_method": "$request_method", '
 #                        '"request_url": "$http_referer", '
 #                        '"body_bytes_sent":"$body_bytes_sent", '
 #                        '"http_forwarded": "$http_x_forwarded_for", '
 #                        '"user_agent": "$http_user_agent" ,'
 #                        '"upstream":  "$upstream_addr",'
 #                        '"upstream_status": "$upstream_status"}';

    access_log  logs/access.log  main;

    sendfile  on;
    tcp_nopush  on;
    server_tag  off; 
    server_info  off; 
    server_tokens  off;
    fastcgi_intercept_errors on;
    keepalive_requests 3000;
    keepalive_timeout  120;    
    check_shm_size  50m;
    proxy_ssl_server_name on;
    proxy_ssl_verify off;
    proxy_intercept_errors on;
    gzip  on;  

#WAF
#    lua_shared_dict limit 10m;
#    lua_package_path "/servyou/tengine/conf/ngx_lua_waf/?.lua";
#    init_by_lua_file "/servyou/tengine/conf/ngx_lua_waf/init.lua";
#    access_by_lua_file "/servyou/tengine/conf/ngx_lua_waf/waf.lua";


    upstream account-core-web {
        server 10.0.0.111:8001;
        check interval=5000 rise=2 fall=5 timeout=3000 type=http;
        check_http_send "HEAD /account-core-web-service/version HTTP/1.0\r\n\r\n";
        check_http_expect_alive http_2xx http_3xx;
        }

    upstream bszm-web {
        server 10.0.0.111:8002;
        check interval=5000 rise=2 fall=5 timeout=3000 type=http;
        check_http_send "HEAD /bszm-web/RemoteCallServlet?health=test  HTTP/1.0\r\n\r\n";
        check_http_expect_alive http_2xx http_3xx;
        }

    upstream wszx-web {
        server 10.0.0.111:8003;
        check interval=5000 rise=2 fall=5 timeout=3000 type=http;
        check_http_send "HEAD /wszx-web/RemoteCallServlet?health=test  HTTP/1.0\r\n\r\n";
        check_http_expect_alive http_2xx http_3xx;
        }

    upstream zmpt-web {
        server 10.0.0.111:8004;
        check interval=5000 rise=2 fall=5 timeout=3000 type=http;
        check_http_send "HEAD /zmpt-web/RemoteCallServlet?health=test  HTTP/1.0\r\n\r\n";
        check_http_expect_alive http_2xx http_3xx;
        }

    upstream wlx-svc {
        server 10.0.0.111:8005;
        check interval=5000 rise=2 fall=5 timeout=3000 type=http;
        check_http_send "HEAD /wlzx-svc/RemoteCallServlet?health=test  HTTP/1.0\r\n\r\n";
        check_http_expect_alive http_2xx http_3xx;
        }

    upstream dzzlk {
        server 10.0.0.111:8006;
        check interval=5000 rise=2 fall=5 timeout=3000 type=http;
        check_http_send "HEAD /dzzlk/RemoteCallServlet?health=test  HTTP/1.0\r\n\r\n";
        check_http_expect_alive http_2xx http_3xx;
        }

    upstream zmpt-gld {
        server 10.0.0.111:8007;
        check interval=5000 rise=2 fall=5 timeout=3000 type=http;
        check_http_send "HEAD /zmpt-gld/RemoteCallServlet?health=test  HTTP/1.0\r\n\r\n";
        check_http_expect_alive http_2xx http_3xx;
        }

    # web 层代理
    server {
        listen       8081;
        #server_name  localhost;

        #charset utf-8;
        port_in_redirect off;
        proxy_buffer_size 128k;
        proxy_buffers   4 128k; 
        proxy_busy_buffers_size 256k; 
        proxy_temp_file_write_size 1024k;
        proxy_max_temp_file_size 100M;
        large_client_header_buffers 4 128k;
        client_max_body_size 100m;
        client_body_buffer_size 128k;

        proxy_read_timeout 300;
        proxy_send_timeout 300;
        proxy_connect_timeout 60;
        proxy_next_upstream off;

        #拦截除以下方式的请求(DELETE PUT)
        if ($request_method !~ ^(GET|HEAD|POST)$ ){
            return 403;
            }

        #deny ip;
        #nginx访问黑名单
        #if ($remote_addr ~* 'ip01|ip02'){
        #    return 307  https://oldboyedu.com/error;
        #    }


        # 访问根自动跳转至首页
        #location = / {
        #    rewrite ^(.*)$ http://10.0.0.7:8081/wszx-web/bszm/apps/views/beforeLogin/indexBefore/pageIndex.html#/ ;
        #    }

    #前端静态资源
    location /nsrymh {
        alias /servyou/tengine/nsrymh;
        autoindex off;
        }

    #前端静态资源
    location /nsryh5mh {
        alias /servyou/tengine/nsryh5mh;
        autoindex off;
        }

    #前端静态资源
    location /hndzswj {
        alias /servyou/tengine/hndzswj;
        autoindex off;
        }

    #行为日志记录代理
    location /burial {
        alias /servyou/tengine/burial;
        autoindex off;
        }

    #bszm-web 依赖 login-web下面的字体
    location /login-web {
        alias /servyou/tengine/login-web;
        autoindex off;
        }

    #纳税人下载的文件
    location /download {
        alias /servyou/tengine/download;
        autoindex off;
        }


    location  /account {
        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        #add_header Access-Control-Allow-Origin http://1.1.1.1;  #允许跨域
        #add_header X-Frame-Options SAMEORIGIN;
        proxy_pass http://account-core-web/account-core-web-service$request_uri;
        }
        
    location  /yhzx-web {
        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_pass http://yhzx-web$request_uri;
        }

    location  /wszx-web {
        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_pass http://wszx-web$request_uri;
        }
        
    location  /zmpt-web {
        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_pass http://zmpt-web$request_uri;
        }

    location  /zmpt-gld {
        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_pass http://zmpt-gld$request_uri;
        }

    location  /wlzx-svc {
        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_pass http://wszx-svc$request_uri;
        }
 
    location  /dzzlk {
        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_pass http://dzzlk$request_uri;
        }
        
    location  /bszm-web {
        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_pass http://bszm-web$request_uri;
        }
        

 
#   location /download {
#       alias /filepath1;
#       autoindex off;
#       }

    location ~ /druid {
        deny  all;
        }
    #weblogic漏洞挡板
    location ~ ^/wls-wsat {
        deny  all;
        }
    location ~ ^/uddiexplorer {
        deny all;
        }
    location ~ ^/bea_wls_internal {
        deny all;
        }
    location ~ ^/console {
        deny all;
        }
    location ~ ^/_async {
        deny all;
        }
    location ~ ^/bea_wls_deployment_internal {
        deny all;
        }

    location ~ ^/status{
        allow 192.168.0.0/16;
        allow 10.0.0.0/8;
        deny all;
        check_status;
        access_log off;
        }
    
    location ~ ^/nginx_status {
        allow 192.168.0.0/16;
        allow 10.0.0.0/8;
        deny all;
        stub_status on;
        access_log off;
        }

#    set $a 0;
#    if ($request_uri ~ hessian){
#        set $a 1;
#        }
#    if ($request_uri ~ RemoteCallServlet){
#        set $a 1;
#        }
#    if  ($remote_addr  ~* '192.168.2') {
#        set $a 0;
#        }
#    if  ($remote_addr  ~* '82.17.64') {
#        set $a 0;
#        }
#    if ($a = 1){
#        return 403;
#        }       

    location /error {
        root html;
        }
    error_page 501 502 503 504  /51x.html;
        location = /51x.html {
        root html;
        }
    error_page 400 401 402 403 404 405 406 407 408 409 410 412 413 414 415  /40x.html;
        location = /40x.html {
        root html;
        }
    }
include test.conf;
}

3.2 优化一览表

优化类型优化说明优化方法
安全优化1、隐藏nginx版本信息修改nginx配置文件,设置:server_tokens off;
安全优化2、修改nginx名称信息修改nginx源码配置文件
nginx-xxx/src/core/nginx.h
nginx-xxx/src/http/ngx_http_header_filter_module.c
nginx-xxx/src/http/nginx_special_response.c
安全优化3、修改nginx软件work_processes进程用户信息修改nginx默认用户,利用配置文件参数,例如: user www www;
编译安装采用编译参数实现
安全优化4、优化nginx服务上传文件大小限制client_max_body_size,设置客户端请求报文主体最大尺寸,默认是1M,用户上传文件大小。可以在http、server、location中设置。超过限制的大小,报413错误
安全优化5、配置nginx相关日志操作防止日志过大,进行日志文件轮询切割:
1、yum安装nginx,自动切割(logrotate)
2、编译安装手动切割
部分日志内容不进行记录,节省磁盘空间。
对日志文件进行授权
logrotate 日志切割工具+系统定时任务
kill -USR1 cat /var/run/nginx.pid
安全优化6、nginx站点目录及文件uri访问控制在动态解析配置前面,设置限制特定目录下扩展名文件、限制指定目录uri信息访问,利用禁止策略和返回错误信息限制用户访问,利用黑名单白名单方式,禁止非域名访问网站等
安全优化7、图片及目录防盗链根据HTTP referer实现防盗链。用户从哪里跳转过来的(通过域名) refer 控制
例如:if ( $http_referer !~ “空或www.baidu.com“) { return 403;}
安全优化8、错误页面的优雅显示对错误代码实行本地页面跳转。优雅显示错误页面放到本地单独目录下。
安全优化9、nginx站点目录文件及目录权限优化只将用户上传数据的目录设为755,用户和组使用nginx。其余目录和文件为755/644,用户和组用root。
网站相当于www用户,因此:
1、站点目录,整体文件和目录,文件644,目录755,用户和组均为root
2、用户上传数据的目录和文件,目录755,文件644,用户和组为www
安全优化10、nginx限制请求访问HTTP用户请求方法:GET、POST、PUT、HEAD、DELETE、TRACE、OPTIONS等等 例如:
if ($http_mothod !~ “GET|POST|HEAD”) { return 403; #deny all; }
安全优化11、nginx防爬虫优化利用robots.txt机器人协议防止爬虫。在网站目录下面放robots.txt文件,利用$http_user_agent变量来阻止爬虫代理访问。
安全优化12、监牢模式(keep in jail)利用nginx -c参数启动nginx多实例。普通用户无法使用1-1024端口。80–转发iptables–>8080
安全优化13、限速limit_ratelimit_rate 速度,如:limit_rate 100k
安全优化14、控制客户端请求nginx的频率访问频率、nginx处理的频率:
limit_conn_module:连接频率限制(服务端) limit_req_module:请求频率限制(限制客户端)
性能优化15、修改nginx软件work process进程数量woker_processes 8;
一般和CPU的核心数一致,高并发可以设为 核心数的2倍。
查看cpu核心数:lscpu、nproc 、/proc/cpuinfo、top命令按1
1个核心处理1件事情。Intel超线程技术,1个核心出来2件事情
性能优化16、优化nginx服务进程均匀分配到不同CPU处理,即CPU亲和力(工具人进程平均使用cpu核心)利用worker_cpu_affinity进行优化(CPU亲和力),让CPU的每个核心平均
4颗cpu优化配置参数为0001 0010 0100 1000
2颗CPU优化配置参数:0101 1010 worker_cpu_affinity 0101 1010;
worker_affinity auto;
Linux系统设置CPU亲和力为:taskset (15k)
Bin 1111 15 0x00000f
Taskset -p oxf pid #把进程绑定到对应的cpu核心上
性能优化17、优化nginx事件处理模型利用use epoll 参数修改事件模型为epoll。事件模型指定配置参数放置在event区块中。Nginx epoll:处理数据异步;Apache select:处理数据同步
性能优化18、优化nginx单进程客户端连接数利用worker_connections连接参数进行调整。用户最大并发连接数=worker进程数*worker连接数
性能优化19、优化nginx服务进程打开文件数利用worker_rlimit_nofile参数进行调整(65535)
性能优化20、优化nginx服务数据高效传输模式利用sendfile on打开高效传输模式。
tcp_nopush on表示将数据积攒到一定的量再进行传输
tcp_nodelay on表示将数据信息进行快速传输
性能优化21、优化nginx服务超时信息keepalive_timeout优化客户端访问nginx服务端超时时间。Http协议特点:连接断开后会给你保留一段时间
client_header_timeout优化服务端读请求头的超时时间
client_body_timeout优化两个请求主体发动间隔超时时间
send_timeout优化两个响应信息的间隔超时时间
性能优化22、优化nginx服务与连接缓存与缓冲信息Fastcgi与php连接缓存、缓冲信息。适用于nginx的各种buffer和cache
性能优化23、配置nginx gzip压缩实现性能优化利用gzip命令进行对数据信息压缩优化
性能优化24、brotli压缩(第三方模块)与gzip类似,用于https环境
性能优化25、expires缓存利用location匹配相应要缓存的信息,利用expires把数据缓存到浏览器中

1、修改server_tokens为off,隐藏版本

2、修改web服务名称,比如:nginx改成Tomcat,tengine改成apache

需要修改源码的3个文件:

nginx-xxx/src/core/nginx.h
nginx-xxx/src/http/ngx_http_header_filter_module.c
nginx-xxx/src/http/nginx_special_response.c

修改如下:

#修改一下参数
[root@web03 ~/tengine-2.3.3]#egrep -n "NGINX_(VERSION|VAR)" src/core/nginx.h
13:#define NGINX_VERSION      "1.18.0"
14:#define NGINX_VER          "nginx/" NGINX_VERSION
29:#define NGINX_VAR          "NGINX"
[root@web03 ~/tengine-2.3.3]#

#修改/src/http/ngx_http_header_filter_module.c的参数:
static u_char ngx_http_server_string[] =

#修改src/http/ngx_http_special_response.c的参数:
"<hr><center>nginx</center>" CRLF

3、限制用户上传文件大小

#在http{}中修改client_max_body_size参数
client_max_body_size  50m;

还要修改php

#修改/etc/opt/remi/php74/php.ini文件
post_max_size=50M
upload_max_filesize=50M

4、日志切割

日志切割使用的命令:
logrotate -f /etc/logrotate.d/nginx
默认是系统定时任务调用,可以自定义书写crontab  -e
#日志切割的配置格式:
[root@web01 ~]#cat /etc/logrotate.d/nginx
#指定要切割的文件
/var/log/nginx/*.log {
        daily       #每天切割
        missingok   #文件不存在不报错
        rotate 52   #循环52次,从第53次开始,删除旧的切割
        compress    #对日志进行压缩
        delaycompress  #隔天压缩
        notifempty  #文件为空不切割
        create 640 nginx adm  #切割后文件的权限、用户、用组
        #切割后运行指定的命令,一般是重启的命令
        sharedscripts
        postrotate
                if [ -f /var/run/nginx.pid ]; then
                        kill -USR1 `cat /var/run/nginx.pid`  #相当于reload
                fi
        endscript
}

查看被压缩的日志文件:zcat 日志文件

5、访问控制

例如:

location /admin/ {
   return 403;
   #deny all;
}

6、防盗链

什么是盗链:网站中盗取其他人网站的资源连接。

防盗链:1、加水印;2、通过referer头判断,用户间接访问就会有这个头部信息;3、配置认证,登录后才能用

if ( $http_referer ~ "img.com") {
   return 403;
}

7、错误页面

配置如下:

error_page 501 502 503 504 /50x.html;
location = /50x.html {
  root /app/code/error;
}
error_page 400 401 402 403 404 405 406 407 408 409 410 412 413 414 415 /40x.html;
location = /40x.html {
 root /app/code/error;
}
#在return如何指定错误提示的页面
set $flage 1;
if ($flage = 1) {
  return 503 http://xxx/50x.html;
}

8、nginx站点目录文件及目录权限优化

权限推荐设置:
1、整个网站目录,文件644,目录755,用户和组均为root
2、涉及用户上传数据的目录,文件644,目录755,用户和组为www(中间件运行的用户,比如:nginx、www)
3、时刻盯紧临时目录
4、给网站设置md5sum校验,对于缓存不需要做校验,例如:
  [root@web01 ~]#find /app/code/blog/ -type f | xargs md5sum > blog_file.md5 #没有排除缓存文件
  校验:
  [root@web01 ~]#md5sum -c --quiet blog_file.md5

定时任务定期执行:md5sum -c –quiet blog_file.md5 2>/dev/null | wc -l

然后把结果保存下来传输到备份服务器

检查是否有新增的文件:find /app/code/blog/ -type f | wc -l

研究aide命令

9、利用nginx限制请求访问

HTTP用户请求方法:GET、POST、PUT、HEAD、DELETE、TRACE、OPTIONS等等
例如:
if ($http_mothod !~ "GET|POST|HEAD") {
   return 403;
   #deny all;
}

10、防爬虫

什么是爬虫?通过命令或软件下载网站的指定的信息。

如何防爬虫?

1、君子协议。robots.txt,文件格式:
User-agent: Baiduspider
Disallow: /baidu
Disallow: /s?
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh
2、在nginx中通过ua变量进行判断,手动屏蔽爬虫,在server中设置,例如:
server {
   #这种屏蔽容易误杀一些搜索引擎的爬虫
  if ($http_user_agent ~* "spider|bot") {
       return 403;
  }
}
可以精确写出具体不想要的爬虫,排除法,比如:
if ($http_user_agent !~* "baidu|google|android|ios|windows") 
但是,也可能误杀
3、增加登录,认证功能

11、nginx监牢模式

监牢模式:通过普通用户(非虚拟用户)运行与管理指定的服务。

比如,nginx进程运行使用www(虚拟用户),而启动重启操作使用root用户。可不可以统一一个普通用户?

一般是编译安装的软件(可以安装到指定目录,如:–prefix=/app/tools/nginx/)

还可以是二进制软件。

如果是nginx有个坑,1-1024范围的端口是特权端口,只能是root管理。

12、限速(速度,请求频率)

限制下载速度
例如:limit_rate  100k

13、访问频率

访问频率、nginx处理的频率:
limit_conn_module:连接频率限制(服务端)
limit_req_module:请求频率限制(限制客户端)

#木桶原理
测试limit_conn
limit_conn_zone
limit_conn  zone  number
例如:
http {
  #limit_conn_zone 创建木桶
  #$binary_remote_addr  根据客户端ip进行限制
  #zone=木桶的名字
  #10m 木桶的大小为10m
  limit_conn_zone $binary_remote_addr zone=conn_zone:10m;  #10m大小
  server {
    limit_conn conn_zone 1; #1个ip地址连接并发数是1
  }
}

测试:ab -n 10 -c 2 -H Host:tes.com http://192.168.10.5/

limit_req:

http {
  # rate=1r/s,每秒处理1个
  limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s;
  server {
    limit_req zone=req_zone burst=5;#burst,并发数
  }
}

14、优化nginx服务进程打开文件数

Linux文件描述符,用于控制每个进程最多可以打开多少个文件。
这个值分为2个部分:
1、系统的设置
  1)修改/etc/security/limits.conf文件:
   *  soft  nofile 65535
   *  hard  nofile 65535
  2)命令行:ulimit -n 65535 (临时生效)
2、服务软件的设置,例如:nginx
  worker_rlimit_nofile 65535

15、优化nginx服务与连接缓存与缓冲信息

cache缓存区读服务:

fastcgi_cache  my_nginx
fastcgi_cache_valid 200  302 1h;
fastcgi_cache_valid 301  1d;
fastcgi_cache_valid any 1m;

buffer缓冲区写服务:

fastcgi_read_timeout
fastcgi_buffer_size  8k;
fastcgi_buffers  8  8k;
fastcgi_busy_buffers_sizes  16k;

16、配置nginx gzip压缩实现性能优化

gzip on;
gzip_min_length 1k; #设置大于1k的才压缩
gzip_buffers 4 16k; #设置压缩缓存
#gzip_http_version 1.0;
gzip_comp_level 2; #压缩级别,数字越大,压缩率(占用空间)越小,占用cpu越多
gzip_types text/plain application/x-javascript  text/css  application/xml  text/javascript  application/x-http-php; #哪些类型的文件需要压缩,这些类型需用mime  types媒体类型(/etc/nginx/mime.types)

16、expires缓存

location ~* \.(css|jpeg|html|js|bmp|png)$ {
  expires 1d;
}