六、高级配置:
1.网页的状态页:
基于nginx 模块 ngx_http_stub_status_module 实现,在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module,否则配置完成之后监测会是提示语法错误注意: 状态页显示的是整个服务器的状态,而非虚拟主机的状态。
状态页用于输出 nginx 的基本状态信息:
Active connections:
#当前处于活动状态的客户端连接数,包括连接等待空闲连接数=reading+writing+waiting
accepts:
#统计总值,Nginx自启动后已经接受的客户端请求的总数。
handled:
#统计总值,Nginx自启动后已经处理完成的客户端请求总数,通常等于accepts,除非有因worker_connections限制等被拒绝的连接
requests:
#统计总值,Nginx自启动后客户端发来的总的请求数。
Reading:
#当前状态,正在读取客户端请求报文首部的连接的连接数,数值越大,说明排队现象严重,性能不足
Writing:
#当前状态,正在向客户端发送响应报文过程中的连接数,数值越大,说明访问量很大
Waiting:
#当前状态,正在等待客户端发出请求的空闲连接数,开启 keep-alive的情况下,这个值等于active – (reading+writing)
可以只提取里面的基本状态的数字
[root@localhost conf.d]#curl 192.168.91.3/status 2>/dev/null|awk '/Reading/{print $2,$4,$6}'
为了安全考虑,可以搭配验证模块一起使用
server {
listen 80;
server_name www.lucky.com;
root /data/html;
location /status {
stub_status;
auth_basic "welcome future";
auth_basic_user_file /mnt/.nginxuser;
}
}
只允许自己,拒绝所有
server {
listen 80;
server_name www.lucky.com;
root /data/html;
location /status {
stub_status;
auth_basic "welcome future";
auth_basic_user_file /mnt/.nginxuser;
allow 192.168.91.3;
deny all;
}
}
2.nginx 第三方模块:
2.1 echo模块:
更改子配置文件:
编译之前,先关闭 nginx,导入压缩包,并解压
[root@localhost opt]# unzip echo-nginx-module-master.zip
[root@localhost opt]# cd nginx-1.18.0/
[root@localhost nginx-1.18.0]# systemctl stop nginx
[root@localhost nginx-1.18.0]# ./configure --help | grep add
--with-http_addition_module enable ngx_http_addition_module
--add-module=PATH enable external module
[root@localhost 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=/opt/echo-nginx-module-master
[root@localhost nginx-1.18.0]# make && make install
[root@localhost nginx-1.18.0]# systemctl start nginx
测试:
3.变量:
官方文档 http://nginx.org/en/docs/varindex.html
3.1 内置变量:
$remote_addr | 存放了客户端的地址,注意是客户端的公网IP |
$args | 变量中存放了URL中的参数 |
$document_uri | 保存了当前请求中不包含参数的URI,注意是不包含请求的指令 |
$host | 存放了请求的host名称 服务端的地址 |
$request_filename | 当前请求的资源文件的磁盘路径,由root或alias指令与URI请求生成的文件绝对路径 |
$scheme | 请求的协议,例如:http,https,ftp等 |
$http_user_agent | 客户端浏览器的详细信息 |
$http_cookie | 客户端的cookie信息 |
$document_root | 保存了针对当前资源的请求的系统根目录 |
$remote_addr;
#存放了客户端的地址,注意是客户端的公网IP
$proxy_add_x_forwarded_for
#此变量表示将客户端IP追加请求报文中X-Forwarded-For首部字段,多个IP之间用逗号分隔,如果请求中没有X-Forwarded-For,就使用$remote_addrthe “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.
客户机 代理1 代理2 nginx服务器
$proxy_add_x_forwarded_for: 在代理1 上存的是 客户机的ip
$proxy_add_x_forwarded_for: 在代理2 上存的是 客户机的ip,代理1的ip 用逗号隔开
$proxy_add_x_forwarded_for: nginx 上存的是 客户机的ip,代理1的ip,代理2的ip
$args;
#变量中存放了URL中的参数,例如:http://www.kgc.org/main/index.do?id=20190221&partner=search
#返回结果为: id=20190221&partner=search 存放的就是这个
select * from table where id=20190221
$document_root;
#保存了针对当前资源的请求的系统根目录,例如:/apps/nginx/html
$document_uri;
#保存了当前请求中不包含参数的URI,注意是不包含请求的指令,比
如:http://www.kgc.org/main/index.do?id=20190221&partner=search会被定义为/main/index.do
#返回结果为:/main/index.do
$host;
#存放了请求的host名称
服务端的地址
limit_rate 10240;
echo $limit_rate;
#如果nginx服务器使用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
$request_uri; https:// www.baidu.com/main/index.do?id=20190221&partner=search
#包含请求参数的原始URI,不包含主机名,相当于:$document_uri?$args,例如:/main/index.do?id=20190221&partner=search
$scheme;
#请求的协议,例如:http,https,ftp等
$server_protocol;
#保存了客户端请求资源使用的协议的版本,例如:HTTP/1.0,HTTP/1.1,HTTP/2.0等
$server_addr;
#保存了服务器的IP地址
$server_name;
#请求的服务器的主机名
$server_port; 443 https
#请求的服务器的端口号
$http_<name>
#name为任意请求报文首部字段,表示记录请求报文的首部字段
arbitrary request header field; the last part of a variable name is the field name converted to lower case with dashes replaced by underscores
#用下划线代替横线
#示例: echo $http_User_Agent;
$http_user_agent;
#客户端浏览器的详细信息
$http_cookie;
#客户端的cookie信息
$cookie_<name>
#name为任意请求报文首部字部cookie的key名
$http_<name>
#name为任意请求报文首部字段,表示记录请求报文的首部字段,ame的对应的首部字段名需要为小写,如果有
横线需要替换为下划线
arbitrary request header field; the last part of a variable name is the field
name converted to lower case with dashes replaced by underscores #用下划线代替横线
#示例:
echo $http_user_agent;
echo $http_host;
$sent_http_<name>
#name为响应报文的首部字段,name的对应的首部字段名需要为小写,如果有横线需要替换为下划线,此变量有问题
echo $sent_http_server;
$arg_<name>
#此变量存放了URL中的指定参数,name为请求url中指定的参数
#对比 变量 $arg 是全部, 如果 要id 如下
echo $arg_id;
3.2 自定义变量:
假如需要自定义变量名称和值,使用指令 set $variable value;
4.自定义访问日志:
4.1 日志的格式可以指定:
访问日志是记录客户端即用户的具体请求内容信息,而在全局配置模块中的 error log 是记录 nginx服务器运行时的日志保存路径和记录日志的 level,因此两者是不同的,而且Nginx的错误日志一般只有一个,但是访问日志可以在不同 server 中定义多个,定义一个日志需要使用 access_log 指定日志的保存路径,使用 log_format 指定日志的格式,格式中定义要保存的具体日志内容。
访问日志由 ngx_http_log_module 模块实现
Syntax: access_log path [format [buffer=size] [gzip[=level]] (flush=time] [if=condition]];access_log off;
Defau1t:
access_log 1ogs/access.1og combined;
Context: http,server, location,if in location,limit_except
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'
'$server_name:$server_port';
log_format test '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'
'$server_name:$server_port';
格式可以定义多个
###注意如果开启 include 注意定义自配置文件与 日志格式的上下关系 , 日志格式一定要在 include 之前 否则会不生效。
测试:
查看:
4.2 自定义 json 格式日志:
可以配置它以输出自定义的JSON格式日志。这种格式对于日志记录和后续分析非常有用,因为JSON格式易于解析并且适合于许多日志分析工具,如方便ELK收集日志。
修改主配置文件:
[root@localhost ~]# vim /apps/nginx/conf/nginx.conf
30 log_format access_json '{"@timestamp":"$time_iso8601",'
31 '"host":"$server_addr",'
32 '"clientip":"$remote_addr",'
33 '"size":$body_bytes_sent,'
34 '"responsetime":$request_time,'
35 '"upstreamtime":"$upstream_response_time",'
36 '"upstreamhost":"$upstream_addr",'
37 '"http_host":"$host",'
38 '"uri":"$uri",'
39 '"xff":"$http_x_forwarded_for",'
40 '"referer":"$http_referer",'
41 '"tcp_xff":"$proxy_protocol_addr",'
42 '"http_user_agent":"$http_user_agent",'
43 '"status":"$status"}';
44 access_log logs/access.log access_json;
查看json格式日志:
{"@timestamp":"2024-02-25T21:54:30+08:00", '"host":"192.168.190.102",' '"clientip":"192.168.190.100",' '"size":612,' '"responsetime":0.000,' '"upstreamtime":"-",' '"upstreamhost":"-",' '"http_host":"192.168.190.102",' '"uri":"/index.html",' '"xff":"-",' '"referer":"-",' '"tcp_xff":"-",' '"http_user_agent":"curl/7.29.0",' '"status":"200"}'
4.3 日志分割:
----------------日志切割-------------------
vim /opt/fenge.sh
#!/bin/bash
# Filename: fenge.sh
day=$(date -d "-1 day" "+%Y%m%d") #显示前一天的时间
logs_path="/var/log/nginx"
pid_path="/usr/local/nginx/logs/nginx.pid"
[ -d $logs_path ] || mkdir -p $logs_path #创建日志文件目录
mv /usr/local/nginx/logs/access.log ${logs_path}/kgc.com-access.log-$day #移动并重命名日志文件
kill -USR1 $(cat $pid_path) #重建新日志文件
find $logs_path -mtime +30 -exec rm -rf {} \; #删除30天之前的日志文件
#find $logs_path -mtime +30 | xargs rm -rf
chmod +x /opt/fenge.sh
/opt/fenge.sh
ls /var/log/nginx
ls /usr/local/nginx/logs/access.log
#设置周期计划任务
crontab -e
0 1 * * * /opt/fenge.sh
5. 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压缩的最小文件,小于设置值的文件将不会压缩
gzip_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;
#预压缩,先压缩好,不用临时压缩,消耗cpu
gzip_static on | off;
5.1 实际操作:
太小的文件没必要压缩,压缩说不定变大了
测试:
如果不是 200,按ctrl强制刷新:
5..2 预压缩:
gzip_static on | off 预压缩,先压缩好,不用临时压缩,消耗cpu
更改配置文件:
更改子配置文件:
压缩文件:
[root@localhost data]# gzip index.html
[root@localhost data]# ls
index.html.gz
[root@localhost data]# mv index.html.gz m.html.gz
测试:
6.https 功能:
Web网站的登录页面都是使用https加密传输的,加密数据以保障数据的安全,HTTPS能够加密信息,以免敏感信息被第三方获取,所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议,HTTPS其实是有两部分组成:HTTP + SSL / TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。
过程:
1.客户端发起HTTPS请求
用户在浏览器里输入一个 https 网址,然后连接到服务器的 443 端口
2.服务端的配置
采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请,区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面。这套证书其实就是一对公钥和私钥
3.传送服务器的证书给客户端
证书里其实就是公钥,并且还包含了很多信息,如证书的颁发机构,过期时间等等
4.客户端解析验证服务器证书
这部分工作是由客户端的TLS来完成的,首先会验证公钥是否有效,比如:颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框提示证书存在问题。如果证书没有问题,那么就生成一个随机值,然后用证书中公钥对该随机值进行非对称加密
5.客户端将加密信息传送服务器
这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加感解密了
6. 服务端解密信息
服务端将客户端发送过来的加密信息用服务器私钥解密后,得到了客户端传过来的随机值
7.服务器加密信息并发送信息
服务器将数据利用随机值进行对称加密,再发送给客户端
8.客户端接收并解密信息
客户端用之前生成的随机值解密服务段传过来的数据,于是获取了解密后的内容
nginx 的 https 功能基于模块 ngx_http_ssl_module 实现,因此如果是编译安装的nginx要使用参数 ngx_http_ssl_module 开启 ssl 功能,但是作为 nginx 的核心功能,yum安装的 nginx 默认就是开启的,编译安装的nginx需要指定编译参数 --with-http_ssl_module 开启
ssl on | off;
#为指定的虚拟主机配置是否启用ssl功能,此功能在1.15.0废弃,使用listen [ssl]替代
listen 443 ssl;
ssl_certificate /path/to/file;
#指向包含当前虚拟主机和CA的两个证书信息的文件,一般是crt文件
ssl_certificate_key /path/to/file;
#当前虚拟主机使用的私钥文件,一般是key文件
ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];
#支持ssl协议版本,早期为ssl现在是TLS,默认为后三个
ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
#配置ssl缓存
off: #关闭缓存
none: #通知客户端支持ssl session cache,但实际不支持
builtin[:size]:#使用OpenSSL内建缓存,为每worker进程私有
[shared:name:size]:#在各worker之间使用一个共享的缓存,需要定义一个缓存名称和缓存空间大小,一兆可以存储4000个会话信息,多个虚拟主机可以使用相同的缓存名称
ssl_session_timeout time;
#客户端连接可以复用ssl session cache中缓存的有效时长,默认5m
编译安装的nginx需要指定编译参数 --with-http_ssl_module 开启
6.1.自签名证书:
#所有的证书需要放在一起不能移开
bash certificate.sh
cat kgc.com.crt ca.crt > www.kgc.com.crt
#kgc.com.crt(购买者)
#ca.crt(颁发者)
mv kgc.com.key www.kgc.com.key
#www.kgc.com.key(验证钥匙)
[root@localhost ~]# cd /data
[root@localhost data]# ls
[root@localhost data]# mkdir ssl
[root@localhost data]# cd ssl/
[root@localhost ssl]# rz -E
rz waiting to receive.
[root@localhost ssl]# ls
certificate.sh
[root@localhost ssl]# bash certificate.sh
[root@localhost ssl]# ls
ca.crt ca.key certificate.sh kgc.com.crt kgc.com.csr kgc.com.key
[root@localhost ssl]# cat kgc.com.crt ca.crt > www.kgc.com.crt
[root@localhost ssl]# mv kgc.com.key www.kgc.com.key
[root@localhost ssl]# ll www*
-rw-r--r--. 1 root root 2201 2月 26 10:25 www.kgc.com.crt
-rw-------. 1 root root 1704 2月 26 10:23 www.kgc.com.key
生成私钥工具:
更改子配置文件:
测试:
7.自定义图标:
favicon.ico 文件是浏览器收藏网址时显示的图标,当客户端使用浏览器问页面时,浏览器会自己主动发起请求获取页面的favicon.ico文件,但是当浏览器请求的 favicon.ico 文件不存在时,服务器会记录404日志,而且浏览器也会显示404报错。
下载百度图标:
复制到主站点:
测试:
七:重写功能 rewrite:
Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求,此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库,rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能,比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为自动访问,另外还可以在一定程度上提高网站的安全性。
1.ngx_http_rewrite_module模块指令:
官方文档: Module ngx_http_rewrite_module
Module ngx_http_rewrite_module
1.1 if指令:
用于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进行配置,Nginx的if语法仅能使用if做单次判断,不支持使用if else或者if elif这样的多重判断,用法如下:
格式:
if (条件匹配) {
action
}
使用正则表达式对变量进行匹配,匹配成功时if指令认为条件为true,否则认为false,变量与表达式之间使用以下符号链接:
=
#比较变量和字符串是否相等,相等时if指令认为该条件为true,反之为false
!=
#比较变量和字符串是否不相等,不相等时if指令认为条件为true,反之为false
~
#区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~
#区分大小写字符,判断是否匹配,不满足匹配条件为真,满足匹配条件为假
~*
#不区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~*
#不区分大小字符,判断是否匹配,满足匹配条件为假,不满足匹配条件为真
-f 和 !-f #判断请求的文件是否存在和是否不存在
-d 和 !-d #判断请求的目录是否存在和是否不存在
-x 和 !-x #判断文件是否可执行和是否不可执行
-e 和 !-e #判断请求的文件或目录是否存在和是否不存在(包括文件,目录,软链接)
location /main {
index index.html;
default_type text/html;
if ( $scheme = http ){
echo "if-----> $scheme";
}
if ( $scheme = https ){
echo "if ----> $scheme";
}
#if (-f $request_filename) {
# echo "$request_filename is exist";
#}
if (!-e $request_filename) {
echo "$request_filename is not exist";
#return ;
}
}
示例:
1.2 return 指令:
return用于完成对请求的处理,并直接向客户端返回响应状态码,比如:可以指定重定向URL(对于特殊重定向状态码,301/302等) 或者是指定提示文本内容(对于特殊状态码403/500等),处于此指令后的所有配置都将不被执行,return可以在server、if 和 location块进行配置。
语法格式:
www.pc.com/test/
404
return code; #返回给客户端指定的HTTP状态码
return code [text]; #返回给客户端的状态码及响应报文的实体内容,可以调用变量,其中text如果有空格,需要用单或双引号
return code url; #返回给客户端的URL地址
location /main {
index index.html;
default_type text/html;
if ( $scheme = http ){
return 666 "if-----> $scheme"; #如果是http的 打印http
}
if (!-e $request_filename){
return 302 /index.html; #如果用户不存在,返回302,直接跳转到主页面
}
跳转
任意跳转:
location / {
root /data;
if (!-e $request_filename){
return 302 http://www.baidu.com;
}
}
如果访问不存在就跳转到百度
测试:
301 和 302区别:
301 永久重定向 读取过一次,就会将此条配置缓存在我们的客户端,即使 nginx 服务器宕机,在缓存时间内,还是可以跳转。
302 临时重定向 不会有缓存在客户端,每次跳转需要 nginx 服务器解析,一旦服务器宕机就无法跳转
自定义内容:
只可以文字浏览器访问:
1.3 set 指令:
指定key并给其定义一个变量,变量可以调用Nginx内置变量赋值给key,另外set定义格式为set $key value,value可以是text, variables和两者的组合。
location /main {
root /data/nginx/html/pc;
index index.html;
default_type text/html;
set $name kgc;
echo $name;
set $my_port $server_port(nginx 自带的变量 服务端口 一般80);
echo $my_port;
}
实例:
1.4 break:
用于中断当前相同作用域(location)中的其他Nginx配置,与该指令处于同一作用域的Nginx配置中,位于它前面的配置生效,位于后面的 ngx_http_rewrite_module 模块中指令就不再执行,Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,该指令可以在server块和locationif块中使用。
注意: 如果break指令在location块中后续指令还会继续执行,只是不执行 ngx_http_rewrite_module 模块的指令,其它指令还会执行
location /main {
root /data/nginx/html/pc;
index index.html;
default_type text/html;
set $name kgc;
echo $name;
break; #location块中break后面指令还会执行
set $my_port $server_port;
echo $my_port;
}
示例:
注意: 如果break指令在location块中后续指令还会继续执行,只是不执行 ngx_http_rewrite_module 模块的指令,其它指令还会执行。
2.rewrite :
通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配,rewrite主要是针对用户请求的URL或者是URI做具体处理.
语法格式:
rewrite可以配置在 server、location、if
语法格式 :
rewrite regex replacement(www.baidu.com) [flag];
正则匹配原始访问url 替代你想让客户访问的 标志 ()premanent301
redirect302 break last
rewrite 将用户请求的URI基于regex所描述的模式进行检查,匹配到时将其替换为表达式指定的新的URI
正则表达式格式:
. #匹配除换行符以外的任意字符
\w #匹配字母或数字或下划线或汉字
\s #匹配任意的空白符
\d #匹配数字 [0-9] 。。
\b #匹配单词的开始或结束
^ #匹配字付串的开始
$ #匹配字符串的结束
* #匹配重复零次或更多次
+ #匹配重复一次或更多次
? #匹配重复零次或一次
{n} #匹配重复n次
{n,} #匹配重复n次或更多次
{n,m} #匹配重复n到m次
*? #匹配重复任意次,但尽可能少重复
+? #匹配重复1次或更多次,但尽可能少重复
?? #匹配重复0次或1次,但尽可能少重复
{n,m}? #匹配重复n到m次,但尽可能少重复
{n,}? #匹配重复n次以上,但尽可能少重复
\W #匹配任意不是字母,数字,下划线,汉字的字符
\S #匹配任意不是空白符的字符
\D #匹配任意非数字的字符
\B #匹配不是单词开头或结束的位置
[^g] #匹配除了g以外的任意字符
[^gg] #匹配除了gg 这几个字母以外的任意字符
rewrite flag 使用介绍
利用nginx的rewrite的指令,可以实现url的重新跳转,rewrtie有四种不同的flag,分别是 redirect(临时重定向302)、permanent(永久重定向301)、break和last。其中前两种是跳转型的flag,后两种是代理型。
- 跳转型指由客户端浏览器重新对新地址进行请求
- 代理型是在WEB服务器内部实现跳转
redirect;302
#临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302
permanent;301
#重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求,状态码:301
break;
#重写完成后,停止对当前URL在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块之后的其它配置;结束循环,建议在location中使用
#适用于一个URL一次重写
#一次匹配
last;
#重写完成后,停止对当前URI在当前location中后续的其它重写操作,而后对新的URL启动新一轮重写检查,不建议在location中使用
#适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户301
#多次匹配
实例:
更改子配置文件:
创建所需文件夹:
测试:
案例:http 转https :
针对全站跳转:
location / { #针对全站跳转
if ( $scheme = http ) { #如果不加条件判断,会导致死循环
rewrite /(.*) https://$host/$1 permanent;
}
}
last 与 break:
location /break { #访问break
rewrite .* /test break; #重写到test
}
location /last { #访问break
rewrite .* /test last; #重写到test
}
location /test {
rewrite 403; #last返回403,因为last会多次匹配
}
说明:
redirect;302:临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302
permanent;301:重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求,状态码:301
break:重写完成后,停止对当前URL在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块之后的其它配置;结束循环,建议在location中使用,适用于一个URL一次重写
last:重写完成后,停止对当前URI在当前location中后续的其它重写操作,而后对新的URL启动新一轮重写检查,不建议在location中使用。适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户301。
案例1:更换目录访问方式,目录转化为对象存储形式:
要求:
/20200106/static->/static?id=20200106
/20200123/image ->/image?id=20200123
方法:
rewrite ^/(\d+)/(.+)/ /$2?id=$1 break;
\d+:一个以上数字;.+:一个以上的字符
案例2:多目录转换访问方式:
要求:
www.lucky.com/images/20200106/1.jpg => www.lucky.com/index.do?name=images&dir=20200106=&fi1e=1.jpg
规则配置:
if($host ~* (.*)\.lucky\.com) {
rewrite ^/(.*)/(\d+)/(.*)$ /index.do?name=$1&dir=$2&file=$3 last;}
示例:
3. 防盗链:
防盗链基于客户端携带的 referer 实现,referer 是记录打开一个页面之前记录是从哪个页面跳转过来的标记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗链,referer 就是之前的那个网站域名,正常的 referer 信息有以下几种:
none: #请求报文首部没有 referer 首部,
比如用户直接在浏览器输入域名访问web网站,就没有referer信息。
blocked: #请求报文有 referer 首部,但无有效值,
比如为空。
server_names: #referer首部中包含本主机名及即nginx 监听的server_name。
arbitrary_string: #自定义指定字符串,但可使用*作通配符。
示例: *.kgc.org www.kgc.*
regular expression:#被指定的正则表达式模式匹配到的字符串,要使用~开头
示例: ~.*\.kgc\.com
1.被盗端添加文件a.jpg:
[root@localhost data]# ls
a.jpg beijing favicon.ico index.html ssl
2. 盗取端开启httpd服务,添加web前端配置:
第二台
[root@localhost ~]# cd /var/www/html/
<html>
<body>
<h1>ni hao </h1>
<img src="http://192.168.91.3/a.jpg"/> #这里如果写域名,需要修改hosts配置添加域名解析
</body>
</html>
[root@localhost html]# systemctl restart httpd
实验:
第一台:
清空子配置文件:
添加图片:
第二台机器:
添加httpd子配置文件:
本机:
去真机上添加dns解析
C:\Windows\System32\drivers\etc hosts 文件
测试:
3.访问盗取端地址,可以直接获得被盗端图片。
实现防盗链 :
server{
listen 80;
server_name www.lucky.com;
root /data/html;
location ~* \.(jpg|gif|swf)$ {
root /data/html;
valid_referers none blocked *.lucky.com lucky.com;
if ( $invalid_referer ) {
rewrite ^/ http://www.lucky.com/error.png;
}
}
}
实验:
更改配置文件:
访问:
自定义返回图片:
更改配置文件:
测试:
八、反向代理:
正向代理:代理的是客户端去访问服务端
反向代理:代理的是服务端
1. 定义
反向代理:reverse proxy,指的是代理外网用户的请求到内部的指定的服务器,并将数据返回给用户的一种方式,这是用的比较多的一种方式。
Nginx 除了可以在企业提供高性能的web服务之外,另外还可以将 nginx 本身不具备的请求通过某种预定义的协议转发至其它服务器处理,不同的协议就是Nginx服务器与其他服务器进行通信的一种规范,主要在不同的场景使用以下模块实现不同的功能。
2.模块:
ngx_http_proxy_module: #将客户端的请求以http协议转发至指定服务器进行处理
ngx_http_upstream_module #用于定义为proxy_pass,fastcgi_pass,uwsgi_pass等指令引用的后端服务器分组 负载均衡
ngx_stream_proxy_module:#将客户端的请求以tcp协议转发至指定服务器处理 四层代理
ngx_http_fastcgi_module:#将客户端对php的请求以fastcgi协议转发至指定服务器助理
ngx_http_uwsgi_module: #将客户端对Python的请求以uwsgi协议转发至指定服务器处理
同构协议:代理服务器两边请求一样
异构协议:代理服务器两边请求不一样
主配置里面,PHP语言的程序模板已经写好:
3. 实现 http 反向代理:
1.反向代理配置参数:
proxy_pass;
#用来设置将客户端请求转发给的后端服务器的主机,可以是主机名(将转发至后端服务做为主机头首部)、IP
地址:端口的方式
#也可以代理到预先设置的主机群组,需要模块 ngx_http_upstream_module 支持
示例:
10.0.0.8/web
location /web {
index index.html;
proxy_pass http://10.0.0.18:8080;
#如果你访问10.0.0.8/web 就相当于访问10.0.0.18:8080
##8080后面无uri,即无 / 符号,需要将location后面url 附加到proxy_pass指定的url后面,此行为类似于root
重点:
如果location定义其uri时使用了正则表达式模式(包括~,~*,但不包括^~),则proxy_pass之后必须不能使用uri; 即不能有/ ,用户请求时传递的uri将直接附加至后端服务器之后
server {
...
server_name HOSTNAME;
location ~|~* /uri/ {
proxy_pass http://host:port; # proxy_pass 后面的 url 不能加/
}
...
}
proxy_hide_header field;
#用于 nginx 作为反向代理的时候,在返回给客户端 http 响应时,隐藏后端服务器相应头部的信息,可以设置
在http,server或location块
#示例: 隐藏后端服务器ETag首部字段
location /web {
index index.html;
proxy_pass http://10.0.0.18:8080/;
proxy_hide_header ETag;
}
proxy_pass_header field;
#默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel等参数,如果
要传递的话则要使用 proxy_pass_header field 声明将后端服务器返回的值传递给客户端
#field 首部字段大小不敏感
#示例:透传后端服务器的 Server 和 Date 首部给客户端,同时不再响应报中显示前端服务器的Server字段
proxy_pass_header Server;
proxy_pass_header Date;
proxy_pass_request_body on | off;
#是否向后端服务器发送HTTP实体部分,可以设置在http,server或location块,默认即为开启
proxy_pass_request_headers on | off;
#是否将客户端的请求头部转发给后端服务器,可以设置在http,server或location块,默认即为开启
2.实战:反向代理单台web服务器:
2.1 proxy_pass :
客户端:192.168.91.5,服务器:192.168.91.4;代理服务器:192.168.91.3
代理服务器配置文件:
客户端开启httpd服务:
客户端访问代理服务器:
2.2其他操作:
在真实服务器上做防火墙规则:
丢弃:
服务端添加防火墙规则:
iptables -A INPUT -s 192.168.91.3 -j DROP
#客户端再次访问会出现504网关超时(有可能只是处理时间久,服务器不一定挂了),时间较长1分钟,没有定义代理超时时间
拒绝:
服务器修改防火墙规则:
[root@localhost html]# iptables -R INPUT 1 -s 192.168.91.3 -j REJECT
#客户端再次访问,会出现502,一般出现502代表后端真实服务器挂了
504 和 502 区别:
502 一般出现502,代表后端真实服务器挂了
504 网关超时 (有可能只是单纯处理时间久,服务器不一定挂了)
加 / 与不加 /:
不加 是追加
加 / 是替换
总结:
加 / 是替换 显示 welcome to my world 是将 location 上的url 替换后 proxy 配置里的连接
不加 / 是追加 显示 api 是将 location 上的url 追加在后面
针对某个uri 进行访问:
要求:将用户对域www.pc.com的请求转发给后端服务器处理
代理端配置文件:
server{
listen 80;
server_name www.lucky.com;
root /data/html;
location ~* /api { #只要包含api的都替换成192.168.190.100
proxy_pass http://192.168.91.3;
}
}
http://192.168.91.3 不加/ 是将location上的url追加在后面
http://192.168.91.3/ 加上/ 是将1ocation上的url替换后proxy配置里的连接
3.指定location实现反向代理动静分离
代理服务器配置文件:
server {
listen 80;
server_name www.lucky.com;
root /data/html;
location ~* /api {
proxy_pass http://192.168.91.4;
#访问代理的api的url就跳转到http://192.168.91.4/api/index.html
}
location ~* \.(jpg|jpeg|png|gif|bmp)$ {
proxy_pass http://192.168.91.5;
#访问以这些结尾的文件,那么就去http://192.168.91.5/var/www/html/index.html
}
}
访问的是7-3的内容
4. 反向代理示例:缓存功能:
缓存功能默认关闭,需要开启
proxy_cache zone_name | off; 默认off
#指明调用的缓存,或关闭缓存机制;Context:http, server, location
#zone_name 表示缓存的名称.需要由proxy_cache_path事先定义
proxy_cache_key string;
#缓存中用于“键”的内容,默认值:proxy_cache_key $scheme$proxy_host$request_uri;
proxy_cache_valid [code ...] time;
#定义对特定响应码的响应内容的缓存时长,定义在http{...}中
示例:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_path;
#定义可用于proxy功能的缓存;Context:http 必须放在http语句中
proxy_cache_path path [levels=levels] [use_temp_path=on|off]
keys_zone=zone_name:size [inactive=time] [max_size=size] [manager_files=number]
[manager_sleep=time] [manager_threshold=time] [loader_files=number]
[loader_sleep=time] [loader_threshold=time] [purger=on|off]
[purger_files=number] [purger_sleep=time] [purger_threshold=time];
#示例:在http配置定义缓存信息
proxy_cache_path /var/cache/nginx/proxy_cache #定义缓存保存路径,proxy_cache会自动创建
levels=1:2:2 #定义缓存目录结构层次,1:2:2可以生成2^4x2^8x2^8=2^20=1048576个目录
keys_zone=proxycache:20m #指内存中缓存的大小,主要用于存放key和metadata(如:使用次数),一般1M可存放8000个左右的key
inactive=120s #缓存有效时间
max_size=10g; #最大磁盘占用空间,磁盘存入文件内容的缓存空间最大值
#调用缓存功能,需要定义在相应的配置段,如server{...};或者location等
proxy_cache proxycache;
proxy_cache_key $request_uri; #对指定的数据进行MD5的运算做为缓存的key
proxy_cache_valid 200 302 301 10m; #指定的状态码返回的数据缓存多长时间
proxy_cache_valid any 1m; #除指定的状态码返回的数据以外的缓存多长时间,必须设置,否则不会缓存
proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ; #默认是off
#在被代理的后端服务器出现哪种情况下,可直接使用过期的缓存响应客户端
#示例
proxy_cache_use_stale error http_502 http_503;
proxy_cache_methods GET | HEAD | POST ...;
#对哪些客户端请求方法对应的响应进行缓存,GET和HEAD方法总是被缓存
清理缓存:
方法1: rm -rf 缓存目录
方法2: 第三方扩展模块ngx_cache_purge
在主配置文件中添加:
查看缓存目录:
此时为空:
访问:
查看:
添加首部字段:
nginx基于模块 ngx_http_headers_module 可以实现对后端服务器响应给客户端的报文中添加指定的响应首部字段
Syntax: add_header name value [always];
Default;
Context: http,server,location,if in location
#添加响应报文的自定义首部:
add_header name value [always];
#示例:
add_header X-Via $server_addr; #当前nginx主机的IP
add_header X-Cache $upstream_cache_status; #是否缓存命中
add_header X-Accel $server_name; #客户访问的FQDN
add_header X-Via
add_header X-Cache
add_header X-Accel
add_header X-Via $server_addr; #当前nginx主机的ip
add_header X-Cache $upstream_cache_status; #是否命中缓存
add_header X-Accel $server_name;#客户访问的FQDN
命中的缓存不代表从真实服务器中来,而是从缓存中来
5.实现反向代理客户端IP透传:
在Nginx中,代理客户端IP透传是指将客户端的真实IP地址(也称为远程IP地址)传递给后端服务器。这在一些情况下非常有用,例如,当Nginx作为反向代理服务器时,我们希望后端服务器能够获取到客户端的真实IP地址,而不是Nginx服务器的IP地址。
反向代理的概念:
反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
反向代理是为服务端服务的,反向代理可以帮助服务器接收来自客户端的请求,帮助服务器做请求转发,负载均衡等。
反向代理对服务端是透明的,对我们是非透明的,即我们并不知道自己访问的是代理服务器,而服务器知道反向代理在为他服务。
反向代理的优势:
隐藏真实服务器;
负载均衡便于横向扩充后端动态服务;
动静分离,提升系统健壮性;
5.1一级代理:
客户端服务器:7-2 192.168.91.4(nginx)——》代理服务器:7-1 192.168.91.3(nginx)——》后端服务器:7-3 192.168.91.5(httpd)
7-1:
[root@localhost ~]# vim /apps/nginx/conf.d/pc.conf
server {
listen 80;
server_name www.lucky.com;
root /data/html;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#添加客户端IP和反向代理服务器IP到请求报文头部
location / {
proxy_pass http://192.168.91.5;
}
}
[root@localhost ~]# nginx -t
[root@localhost ~]# nginx -s reload
7-3:
[root@localhost html]# vim /etc/httpd/conf/httpd.conf
196 LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{X-Forwarded-For}i\"" combined
#添加变量X-Forwarded-For
[root@localhost html]# systemctl restart httpd
配置:
7-3查看日志:
之前
改之后:
5.2 多级代理:
1.给代理服务器7-22子配置文件添加内容:
vim /apps/nginx/conf.d/pc.conf
2.给代理服务器7-2主配置文件添加内容:
vim /etc/nginx/nginx.conf
3.给代理服务器7-3添加内容
4.客户端访问代理服务器7-1
5.查看:
[root@localhost ~]# tail -f /var/log/nginx/access.log
6.http反向代理负载均衡:
6.1 概述:
Nginx 可以将客户端的请求转发至单台后端服务器,但是无法转发至特定的一组的服务器,而且不能对后端服务器提供相应的服务器状态监测,Nginx 可以基于 ngx_http_upstream_module 模块提供服务器分组转发、权重分配、状态监测、调度算法等高级功能。
配置方式:
server address [parameters];
#配置一个后端web服务器,配置在 upstream 内,至少要有一个 server 服务器配置。
#server 支持的 parameters 如下:
weight=number #设置权重,默认为1,实现类似于LVS中的WRR,WLC等
max_conns=number #给当前后端server设置最大活动链接数,默认为0表示没有限制
max_fails=number #后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非周期性的探测
fail_timeout=time #后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒
backup #设置为备份服务器,当所有后端服务器不可用时,才会启用此备用服务器 sorry server 自己不能转自己
down #标记为 down 状态
resolve #当 server 定义的是主机名的时候,当A记录发生变化会自动应用新IP而不用重启Nginx
配置格式:
http {
upstream web {
server 192.168.91.3 weight=5;
server 192.168.91.4;
server 192.168.91.5;
least_conn;
ip_hash;
keepalive 32;
fair;
}
}
server {
listen 80;
server_name www.lucky.com;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
root /data/html;
location / {
proxy_pass http://web/
}
}
上面的配置中,upstream块定义了后端服务器的列表和负载均衡算法。server块定义了反向代理服务器的监听端口和域名,以及请求转发的配置。具体说明如下:
upstream块:定义了一个名为web的负载均衡服务器组,其中包含了三个后端服务器,分别是192.168.91.3、192.168.91.4、192.168.91.5。
weight=5表示将第一个后端服务器的权重设置为5,即分配更多的请求给它。ip_hash表示使用IP哈希算法进行负载均衡。keepalive 32表示使用长连接并保持32个连接。
server块:定义了一个监听80端口的虚拟主机,它的域名是www.pc.com。location /表示将所有请求转发给upstream块中定义的服务器组web。proxy_set_header指令可以设置请求头,以便后端服务器能够获取客户端的真实IP地址等信息。
由于使用了least_conn;算法,Nginx会动态地将请求发送到当前连接数最少的后端服务器上,以达到负载均衡的目的。
upstream块中使用了ip_hash算法,表示会根据客户端的IP地址,将该客户端的所有请求都发送到同一个后端服务器上。
由于使用了fair算法,请求会被发送到响应时间最短的服务器上,从而实现负载均衡。
6.2调度算法:
调度算法:
1. 轮询 一人一次
2. 加权轮询
3. ip hash
4. url hash
5. cookie hash
6.最少连接数
7.fair 根据响应时间
6.2.1 轮询算法:
默认算法是轮询算法即反向代理服务器处理用户请求时,每个后端服务器都轮流提供响应。
http {
upstream web {
server 192.168.91.3:80;
server 192.168.91.4:80;
}
6.2.2 加权轮询算法:
在默认轮询的基础上增加权重,weight=number。如果后端有2个服务器其中一个配置权重为weight=5另外一个不配置默认是1,则有用户访问时分配给给有权重的服务器和不配置权重的服务器的比例为5:1。
http {
upstream web {
server 192.168.91.2 weight=5;
server 192.168.91.3;
}
6.2.3 最小连接数算法:
最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器,相当于LVS中的WLC。按照nginx反向代理服务器和后端服务器的连接数分配请求,连接越少的分配处理请求优先级越高。例如最小连接数(least_conn;)是设置是3,1号后端服务器有2个请求在处理,而后2号后端服务器只有1个请求在处理,则新请求交给后端服务器2。
6.2.4 ip_hash算法:
基于客户端IP地址的负载均衡算法。它会根据客户端的IP地址,将该客户端的所有请求都发送到同一个后端服务器上。这样可以保证同一个客户端的所有请求都被发送到同一个后端服务器,从而保证了会话的一致性。
http {
upstream web {
ip_hash;
server 192.168.190.100:80;
server 192.168.190.101:80;
}
6.2.5 fair算法:
基于后端服务器的负载均衡算法。它会根据后端服务器的响应时间,将请求发送到响应时间最短的服务器上。这样可以保证请求被发送到处理能力最强的服务器上,从而提高系统的性能。
http {
upstream web {fair;
server 192.168.91.3:80;
server 192.168.91.4:80;
}
6.3 实验:
6.3.1轮询:
7-1:
主配置文件下:
7-2:
7-3:
本机7-4测试:
当其中一台挂掉,就不去访问他了,直接跳过
那是因为 nginx 有检测机制 健康性检测 就不去这台机了
6.3.2 加权轮询:
更改7-1主配置文件:
测试:
三比一的概率
6.3.3 最大链接数、连续检测和延迟上线:
20 upstream web {
21 server 192.168.91.4;
22 server 192.168.91.5; max_conns=10 max_fails=3 fail_timeout=30s;
23 }
#max_conns=number #给当前后端server设置最大活动链接数,默认为0表示没有限制
#max_fails=number 后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非周期性的探测
#fail_timeout=time 后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒。这样避免服务器刚上线不稳定再次导致业务失败
6.3.4备份服务器:
当所有后端服务器不可用时,才会启用此备用服务器sorry server,自己不能转自己
更改:
只有7-2可以访问了
关掉7-2:
备用服务器上线:
6.3.5 hash调度操作:
根据客户端ip:
修改代理服务器配置
20 upstream web {
21 hash $remote_addr; #hash客户端ip
22 server 192.168.91.4;
23 server 192.168.91.5;
24 }
第一次匹配到那就一直匹配:
注:hash/总权重得到正确的值,该值会受权重影响,至于访问到那台与谁会话保持存在几率
根据请求地址:
20 upstream web {
21 hash $request_uri; #发送请求的地址,一旦确定不会轻易改变
22 server 192.168.91.4;
23 server 192.168.91.5;
24 }
修改代理服务器7-2配置
20 upstream web {
21 hash $cookie_hello; #提取cookie中hello关键字
22 server 192.168.91.4;
23 server 192.168.91.5;
24 }
最少连接数:
least_conn
fair :
此种算法可以依据页面大小和加载时间长短智能的进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。
7.stream 服务模块:
用的四层,只能控制tcp、udp(实现反向代理功能,包括TCP协议代理)
redis 是一个数据库
配置文件: vim /etc/redis.conf
8.四层代理和七层代理的区别:
4层是指传输层的 TCP/UDP 协议
7层是指应用层的 HTTP 协议
代理原理:
4层代理:使用 NAT(Network Address Translation)技术,即网络地址转换。即请求进来的时候,nginx 只修改数据包里面的目标IP、源IP、端口,然后就直接把数据包发给目标服务器(即nginx不知道请求的具体内容),目标服务器处理完成后,发给 nginx,nginx 数据包再做一次类似的修改,就返回给请求的客户端了。
7层代理:nginx 读取并解析 Http 请求内容,然后将具体内容(请求行、请求头、空行、请求数据)转发到相应的服务器,转发的过程是:建立和目标机器的连接,然后转发请求,收到响应数据再转发给请求客户端。