nginx高级应用
1、nginx的https功能应用
HTTP + SSL / TLS,编译时需指定编译ssL模块
[root@centos8 nginx-1.20.2]#./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
1.1、实现HSTS
访问http自动跳转到https
在第一次访问网站时使用的http访问,服务器返回携带有hsts报文头的响应报文指向访问https,hsts报文头中有带有一定期限,在期限内再次访问该网站均会跳转以https的方式访问,减少安全风险
[root@centos8 ~]#vim /apps/nginx/conf.d/pc.conf
server {
listen 443 ssl;
server_name www.magedu.org;
root /data/nginx/html;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; #添加报文头,期限31536000秒
location / {
if ( $scheme = http ) { #如果以http访问则跳转到https
rewrite ^/(.*)$ https://www.magedu.org/$1 redirect;
}
root /data/nginx/html;
}
}
1.2、多域名https
需各自建立各自的配置文件,指定配置证书文件即可,注意证书和域名相匹配
[root@centos8 nginx]#openssl req -newkey rsa:4096 -nodes -sha256 -keyout www.key -x509 -days 3650 -out www.crt
[root@centos8 nginx]#openssl req -newkey rsa:4096 -nodes -sha256 -keyout m.key -x509 -days 3650 -out m.crt
[root@centos8 nginx]#vim /conf/pc/www.conf
server {
listen 80; #不加密访问端口
listen 443 ssl; #加密访问端口
ssl_certificate /apps/nginx/www.crt;
ssl_certificate_key /apps/nginx/www.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
root /data/nginx/html;
server_name www.magedu.org;
}
[root@centos8 nginx]#vim /conf/pc/m.conf
server {
listen 80; #不加密访问端口
listen 443 ssl; #加密访问端口
ssl_certificate /apps/nginx/m.crt;
ssl_certificate_key /apps/nginx/m.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
root /data/nginx/html;
server_name m.magedu.org;
}
1.3、Rewrite相关功能
利用 ngx_http_rewrite_module 模块,将URL访问请求跳转,重定向,默认编译有该功能
举例:
实现网页跳转到https,且不会出现死循环跳转
#方法一,分开两个端口
[root@centos8 nginx]#vim /conf/pc/m.conf
server {
listen 80;
root /data/nginx/html;
server_name m.magedu.org;
return https://www.baidu.com/;
}
server {
listen 443 ssl;
ssl_certificate /apps/nginx/m.crt;
ssl_certificate_key /apps/nginx/m.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
root /data/nginx/html;
server_name m.magedu.org;
location = /nginx_status {
stub_status;
}
}
#方法二,加个条件判断if,内置变量$scheme的值不是http就是https固定范围
[root@centos8 nginx]#vim /conf/pc/m.conf
server {
listen 80;
listen 443 ssl;
ssl_certificate /apps/nginx/m.crt;
ssl_certificate_key /apps/nginx/m.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
root /data/nginx/html;
server_name m.magedu.org;
if ($scheme = http) { #通过内置变量$scheme判断是否是http,是就跳转
return https://www.baidu.com/;
}
location = /nginx_status {
stub_status;
}
}
1.4、总结
注意浏览器缓存,curl命令没有缓存
[root@centos8 ~]#vim /apps/nginx/conf.d/pc.conf
server {
listen 80; #访问端口
server_name www.magedu.org; #指定域名
root /data/nginx/html/pc; #指定根、默认页面文件
location / { #针对全站跳转https
if ( ! -e $request_filename ) { #if判断,! -e所访问文件或目录是否不存在,$request_filename请求的资源
return 301 /index.heml; #意为如果请求的资源不存在,则跳转到根页面下,如xxx
}
if ( $http_user_agent ~ MSIE){ #判断浏览器版本$http_user_agent,包含~,MSIE字符,
rewrite ^(.*)$ /msie/$1 break; #跳转
}
rewrite ^(.*)$ https://$host/$1 redirect; #匹配跳转,$host变量:请求头,域名
}
}
server {
listen 443 ssl; #指定加密端口443
ssl_certificate /apps/nginx/certs/www.magedu.org.crt; #指定证书文件
ssl_certificate_key /apps/nginx/certs/www.magedu.org.key; #指定私钥文件
ssl_session_cache shared:sslcache:20m; #开启共享缓存,指定大小
ssl_session_timeout 10m; #连接可以重复使用共享缓存的时间
server_name www.magedu.org; #指定域名
}
location /login { #针对特定的URL进行跳转https
if ($scheme = http ){ #如果没有加条件判断,会导致死循环
rewrite / https://$host/login redirect;
}
}
#/20200106/static ->/static?id=20200106
#/20200123/image ->/image?id=20200123
rewrite ^/(\d+)/(.+)/ /$2?id=$l last; #后向引用
#(\d+)一个数字+以上,(.+)一个字符以上
www.magedu.com/images/20200106/1.jpg => www.magedu.com/index.do?name=images&dir=20200106=&file=1.jpg
#规则配置:
if ($host ~* (.*)\.magedu\.com) {
rewrite ^/(.*)/(\d+)/(.*)$ /index.do?name=$1&dir=$2&file=$3 last;
}
1.5、Nginx防盗链
用别人网站的资源来为自己提供服务
可通过日志查看
#编译安装指定路径/apps/nginx/,所以日志文件在
/apps/nginx/logs/access.log
#也可自定义日志,针对多域名情况使用
access_log /apps/nginx/logs/access-www.log testlog;
#显示访问请求GET /images/logo.png HTTP/1.1,通过http://www.mageedu.org/调用,从这个网站跳转到本机网站来访问资源
[root@centos8 ~]#tail /apps/nginx/logs/access-www.log
10.0.0.1 - - [10/Jun/2023:16:12:35 +0800] "GET /images/logo.png HTTP/1.1" 200 5934 "http://www.mageedu.org/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36 Edg/86.0.622.38" "-"
1.5.1、实现防盗链
基于模块ngx_http_referer_module,相当于建立黑白名单
server {
valid_referers none blocked server_names #定义仅这些形式访问有效
*.example.com example.* www.example.org/galleries/ ~\.google\.;
valid_referers none blocked server_names
*.magedu.com *.magedu.org ~\.google\. ~\.baidu\. ~\.bing\. ~\.so\. ;
if ($invalid_referer) { #不在上面定义了的其他形式无法访问
return 403;
}
}
none:#请求报文首部没有referer首部,比如用户直接在浏览器输入域名访问web网站,就没有referer信息。
blocked:#请求报文有referer首部,但无有效值,比如为空。
server_names:#referer首部中包含本主机名及即nginx 监听的server_name。
arbitrary_string:#自定义指定字符串,但可使用*作通配符。示例: *.magedu.org www.magedu.*
regular expression:#被指定的正则表达式模式匹配到的字符串,要使用~开头,例如:~.*\.magedu\.com
2、Nginx反向代理功能
- 正向代理主要是为客户端提供服务,指定让代理取访问哪个服务,服务器端看不到客户端来源,仅能看到代理服务器
- 反向代理是为服务器端提供服务,客户端连接访问,先连接到反向代理服务器、nginx负载均衡,再由反向代理服务器分发给后端服务器,后端服务器能看到客户端地址,客户端看不到服务器端地址,仅能看到反向代理服务器
- 反向代理:reverse proxy,指的是代理外网用户的请求到内部的指定的服务器,并将数据返回给用户的一种方式,这是用的比较多的一种方式。
- 同构代理:前后协议相同,http/http
- 异构代理:前后协议不相同,http/https
2.1、nginx和LVS的区别:
LVS仅作为转发,不参与连接,而nginx反向代理是客户端连接访问发送到的是代理服务器,参与连接,服务器解开检查解析再封装发送到后端web服务器,并发连接数要x2,多一倍,七层负载,
- 工作层:LVS四层,nginx七层
- 监听端口:LVS不监听,nginx监听端口
- 后端服务器是否能看到客户端地址:LVS可以,nginx不可用
- 连接(三次握手):LVs不参与连接,只负责转发;nginx代理后端服务器和客户端建立连接
- 缓存:LVS不支持缓存,没有意义;nginx支持缓存
- 监听端口:LVS不会打开监听端口,nginx必须打开,因为是应用层软件
2.2、具体实现
#单机连接,整个网站都代理,当后端服务器宕机时会无法连接
[root@centos8 ~]#vim /apps/nginx/conf.d/pc.conf
server {
listen 80;
server_name www.magedu.org;
root /data/nginx/html/pc;
location / {
proxy_pass http://10.0.0.18:8080; #当访问网站www.magedu.org是转发访问请求到后端服务器http://10.0.0.8上
proxy_connect_timeout 10s; #nginx代理服务器与后端服务器尝试建立连接的超时时间,默认为60秒
}
}
#指定访问特定资源的的请求进行调度,注意访问的是根下的文件,动静分离
[root@centos8 ~]#vim /apps/nginx/conf.d/pc.conf
server {
listen 80;
server_name www.magedu.org;
root /data/nginx/html/pc;
location ~ \.(jpg|png|gif)$ { #访问特定资源才跳转到后端服务器,静态资源文件,jpg|png|gif
proxy_pass http://10.0.0.18:8080;
#注意地址后面是否加/,没加/的是访问的该地址下的URL,如果加了/,实际访问的是该地址的首页、根,且不允许正则多对一模糊匹配
proxy_connect_timeout 10s;
}
location /api { #动态资源文件api
proxy_pass http://10.0.0.28:8080;
proxy_connect_timeout 10s;
}
}
2.2.1、502和504的区别
-
504:访问连接超时,网关连接超时,或者后端服务器无回应报文
- 有后端服务器arp缓存的关机或者iptables的DROP规则,没有回应
-
502:代理服务器从后端服务器收到了一条伪响应,如无法连接到网关;Bad Gateway,比如后端服务端口没有打开
- stop停止服务器或者iptables的REJECT规则,有回应
-
根本区别在于是否能收到服务器端的回应
2.2.2、添加响应报文的头部信息
基于模块ngx_http_headers_module
1、更改的是反向代理服务器发往客户端的报文,响应报文的首部字段
add_header class m48; #可指定内容,首部字段class,值m48
add_header X-Cache $upstream_cache_status; #是否缓存命中,访问数据是否从缓存而来,变量$upstream_cache_status的值是HIT/MISS,是或不是
2、更改的是反向代理服务器发往后端服务器的报文,让后端服务器可以记录客户端的地址
单一代理
proxy_set_header clientip $remote_addr #变量$remote_addr表示客户端地址,clientip自定义的首部字段名称
#更改日志格式
[root@centos8 ~]# vim /apps/nginx/conf/nginx.conf
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" $http_clientip'; #添加指定$http_clientip
多级代理,即中间多个代理服务器
使用变量KaTeX parse error: Double subscript at position 12: proxy_add_x_̲forwarded_for,不…remote_addr,后续第二个代理服务器会追加第一个代理服务器的地址到x_forwarded_for中,直到后端服务器
#在第一个代理服务器上
[root@centos8 ~]# vim /apps/nginx/conf/nginx.conf
"$http_x_forwarded_for" #添加日志格式,默认带有,可自行查看
[root@centos8 ~]#vim /apps/nginx/conf/conf.d/pc.conf
server {
location / {
proxy_pass http://10.0.0.18;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #添加固定首部字段X-Forwarded-For,引用变量
}
.......
}
#在第二个代理服务器上
[root@centos8 ~]# vim /apps/nginx/conf/nginx.conf
"$http_x_forwarded_for" #添加日志格式,默认带有,可自行查看
[root@centos8 ~]#vim /etc/nginx/nginx.conf
server {
location / {
proxy_pass http://10.0.0.28;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #添加固定首部字段X-Forwarded-For,引用变量
}
.......
}
#查看日志
[root@centos8 ~]#tail /apps/nginx/logs/access.log -f
2.3、反向代理负载均衡
基于模块ngx_http_upstream_module
- 负载均衡、
- 被动健康性检查,有访问请求才检查
- 可以理解为将后端服务器放在一个集群中进行管理调度
2.3.1、upstream配置参数
#自定义一组服务器,配置在http块内
#当代理服务器收到请求报文是发往www.magedu.org的80端口时,将请求跳转到webserver,轮询访问webserver里的主机
[root@centos8 ~]# vim /apps/nginx/conf/nginx.conf
upstream webserver { #webserver后端服务器集群的名称
server 10.0.0.18 weight=5; #将后端主机10.0.0.18加入集群,也可写成域名
server 10.0.0.28 weight=3; #weight=3,权重,优先级,默认是1
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server backup1.example.com backup; #提供备份服务器功能
server unix:/tmp/backend3;
hash $remote_addr; #客户端地址固定时,会调度往固定后端服务器,
weight=number #设置权重,默认为1,实现类似于LVS中的WRR,WLC等
max_conns=number #给当前后端server设置最大活动链接数,默认为0表示没有限制
max_fails=number #后端服务器的下线条件,探测后端服务器是否健康的次数,都没回应则认为已下线,默认为1,利用TCP协议
fail_timeout=time #后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒
backup #设置为备份服务器,当所有后端服务器不可用时,才会启用此备用服务器
down #标记为down状态,可以平滑下线后端服务器,新用户不再调度到此主机,旧用户不受影响
server {
listen 80;
server_name www.magedu.org;
root /data/nginx/html/pc;
location / {
proxy_pass http://webserver; #跳转指向
}
2.3.2、调度算法
hash KEY [consistent];
#基于指定请求报文中首部字段或者URI等key做hash计算,使用consistent参数,将使用ketama一致性hash算法,适用于后端是Cache服务器(如varnish)时使用,consistent定义使用一致性hash运算,一致性hash基于取模运算
ip_hash;
#源地址hash调度方法,基于的客户端的remote_addr(源地址IPv4的前24位或整个IPv6地址)做hash计算,以实现会话保持
#等价于hash $remote_addr;但hash $remote_addr是对全部32bit的IPv4进行hash计算
least_conn;
#最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器,相当于LVS中的WLC
#根据数据报文中的某一内容进行哈希运算,根据计算所得摘要进行调度,不利于增加或删除节点
#会话保持
hash $remote_addr; #根据原地址来调度,客户端地址固定时,会调度往固定后端服务器
hash $http_name; #首部字段固定,调度往固定后端服务器
hash $request_uri consistent; #基于用户请求的uri做hash
hash $cookie_sessionid #基于cookie中的sessionid这个key进行hash调度,实现会话绑定
2.3.3、一致性hash算法
当后端服务器主机数量或权重发生变化时,会尽可能保持就连接访问调度,尽可能不变,只影响较少用户的调度
#在算法规则后面加上consistent即可实现
hash $remote_addr; #根据原地址来调度,客户端地址固定时,会调度往固定后端服务器
hash $http_name consistent; #首部字段固定,调度往固定后端服务器
hash $request_uri consistent; #基于用户请求的uri做hash
hash $cookie_sessionid #基于cookie中的sessionid这个key进行hash调度,实现会话绑定
2.3.4、四层反向代理复制均衡
基于ngx_stream_proxy_module模块实现tcp负载,另外基于模块ngx_stream_upstream_module实现后端服务器分组转发、权重分配、状态监测、调度算法等高级功能。
如果编译安装,需要指定 --with-stream 选项才能支持ngx_stream_proxy_module模块,后端服务器需安装的支持四层TCP/UDP协议
注意配置时候只能在主配置文件中进行配置,因为其作用在main语句块中,和http语句块平级
stream { #定义stream相关的服务;Context:main #标明stream,用于四层代理
upstream backend { #定义后端服务器 #自定义后端服务器集群名称为backend
hash $remote_addr consistent; #定义调度算法
server backend1.example.com:12345 weight=5; #定义具体server信息
server 127.0.0.1:12345 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
#server 10.0.0.18:6379; #需写上端口
#server 10.0.0.28:6379;
#server10.0.0.7:53; #UDP使用
}
upstream mysql-server{
server 10.0.0.18:3306;
server 10.0.0.28:3306;
}
server { #定义server #用于接收用户请求
listen 12345; #监听反向代理服务器的端口请求
listen 53 udp; #使用UDP协议,需指定udp,默认是TCP
proxy_connect_timeout 1s; #连接超时时间
proxy_timeout 3s; #转发超时时间
proxy_pass backend; #转发到具体服务器组
}
}
2.4、利用LNMP实现可道云私有云
#部署规划:
10.0.0.100:CentOS8,Nginx,php-fpm,kodbox
10.0.0.8:CentOS8,MySQL8.0,Redis5.0
10.0.0.7:DNS
具体实现
2.4.1、在后端服务器上
[root@10.0.0.8 ~]#yum -y install redis mysql-server;systemctl enable --now mysqld redis
[root@10.0.0.8 ~]#mysql
create database kodbox;
create user kodbox@'10.0.0.%' identified by '123456';
grant all on kodbox.* to kodbox@'10.0.0.%';
[root@10.0.0.8 ~]#sed -i '/^bind.*/c bind 0.0.0.0' /etc/redis.conf
[root@10.0.0.8 ~]#systemctl restart redis
2.4.2、在LNP上
子配置文件: include conf.d/*.conf,需要在主配置文件中用include的值指定文件,
如放在http语句块中,则指定文件中的内容必须要支持http语句块
php扩展源码包https://pecl.php.net/package/redis,选择下载即可
#nginx编译安装,在此仅为提醒需安装软件
[root@10.0.0.100 ~]#yum -y install php-fpm php-mbstring php-json php-xml php-gd php-mysqlnd php-cli php-devel
[root@10.0.0.100 ~]#systemctl enable --now nginx php-fpm
[root@10.0.0.100 ~]#vim /apps/nginx/conf/nginx.conf
incluse /apps/nginx/conf.d/*.conf; #在最后一个花括号前面加上指定文件路径。以.conf结尾
}
[root@10.0.0.100 ~]#mkdir -p /data/kodbox/ #页面存放目录
[root@10.0.0.100 ~]#mkdir -p /apps/nginx/conf.d/ #只配置文件存放目录
[root@10.0.0.100 ~]#vim /apps/nginx/conf.d/kodbox.conf
server {
listen 80;
server_name kodbox.magedu.org;
root /data/kodbox/;
index index.php;
client_max_body_size 200M;
location ~ \.php$ {
root /data/kodbox/;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ ^/(ping|fpm_status)$ { #配置转发
fastcgi_pass 127.0.0.1:9000;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
[root@10.0.0.100 ~]#nginx -s reload
#更改php设置
[root@10.0.0.100 ~]#sed -Ein -e 's/(^post_max_size =).*/\1 200M/g' -e 's/(^upload_max_filesize =).*/\1 200M/g' /etc/php.ini
[root@10.0.0.100 ~]#sed -Ein -e 's/(^user =).*/\1 nginx/' -e 's/(^group =).*/\1 nginx/' -e 's/(^;listen =).*/\1 127.0.0.1:9000' -e 's#(^;pm.status_path =)#\1 /fpm_status#' -e 's/(^;ping.response =)/\1 pong/' /etc/php-fpm.d/www.conf
[root@10.0.0.100 ~]#systemctl restart php-fpm
##php页面
[root@10.0.0.100 ~]#wget https://static.kodcloud.com/update/download/kodbox.1.41.zip #php页面源码
[root@10.0.0.100 ~]#unzip kodbox.1.41.zip -d /data/kodbox/
[root@10.0.0.100 ~]#chown -R nginx. /data/kodbox/
[root@10.0.0.100 ~]#wget https://pecl.php.net/get/redis-5.3.7.tgz #php-redis扩展包
[root@10.0.0.100 ~]#tar xf redis-5.3.7.tgz -c /usr/local/src
[root@10.0.0.100 ~]#cd redis-5.3.7/
[root@10.0.0.100 redis-5.3.7]#phpize
[root@10.0.0.100 redis-5.3.7]#.configure
[root@10.0.0.100 redis-5.3.7]#make && make install
[root@10.0.0.100 redis-5.3.7]#vim /etc/php.d/31-redis.ini #31是文件排序,不重要,主要是告诉php添加了新模块
extension=redis
[root@10.0.0.100 ~]#systemctl restart php-fpm
在DNS上
[root@10.0.0.7 ~]#yum -y install bind bind-utils
[root@10.0.0.7 ~]#cd /var/named/
[root@10.0.0.7 ~]#touch magedu.org.zone
[root@10.0.0.7 ~]#chmod 640 magedu.org.zone
[root@10.0.0.7 ~]#chown named. magedu.org.zone
[root@10.0.0.7 ~]#vim /etc/named.rfc1912.zones
zone "magedu.org" {
type master;
file "magedu.org.zone";
};
[root@10.0.0.7 ~]#vim /var/named/magedu.org.zone
$TTL 1D
@ IN SOA master admin.qq.com. ( 20230503 3H 10M 1D 6H )
NS master
#sz NS ns1 #主从复制用,在此为单一实验
master A 10.0.0.8
#ns1 A 10.0.0.18
kodbox A 10.0.0.100
[root@10.0.0.7 ~]#rndc reload