07 . Nginx常用模块及案例

时间:2022-07-25
本文章向大家介绍07 . Nginx常用模块及案例,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

访问控制

用户访问控制

ngx_http_auth_basic_module

有时我们会有这么一种需求,就是你的网站并不想提供一个公共的访问或者某些页面不希望公开,我们希望的是某些特定的客户端可以访问。那么我们可以在访问时要求进行身份认证,就如给你自己的家门加一把锁,以拒绝那些不速之客。我们在服务课程中学习过apache的访问控制,对于Nginx来说同样可以实现,并且整个过程和Apache 非常的相似。

#1.建立口令文件
htpasswd -c /etc/nginx/passwd.db user1
New password:
Re-type new password:
Adding password for user user1
#2.实现认证
vim default.conf
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        auth_basic "hello";                                # 这一行是你登录窗口写的提示文字
        auth_basic_user_file /etc/nginx/passwd.db;         # 密码存放的目录
    }
    
# htpasswd -c选项只有第一次没有密码文件的时候需要添加,第二再添加账户的时候,不需要跟-c
systemctl reload nginx

# 用户认证局限性
# 1. 用户信息依赖文件方式
# 2. 用户管理文件过多,无法联动
# 3. 操作管理机械,效率低下

# 解决办法
# 1. Nginx结合LUA实现高效验证
# 2. Nginx结合LDAP利用nginx-auth-ldap模块

访问测试 重新加载配置文件后如果用elinks,curl访问会报错401,需要授权,需要用浏览器访问.

主机访问控制

ngx_http_access_module

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        # auth_basic "hello";
        # auth_basic_user_file /etc/nginx/passwd.db;
        allow 39.108.140.0;  #只允许此IP访问
        deny all;	     	 #拒绝所有
    }
elinks --dump 49.233.69.195
                                 403 Forbidden

状态访问

ngx_http_stub_status_module

使用第三方的软件监控nginx时,需要保证其本身能显示状态信息,然后利用这些数据显示一些监控数据和生成图表,使用该模块需要在编译nginx时启用该模块.

# 在server中加入以下几行
    location ~ /status {
        stub_status on;
        access_log off;            # 状态模块的访问不记录日志
        allow 39.108.140.0;        # 只允许管理员访问
        deny all;                 
    }
curl 49.233.69.195/status
Active connections: 1             # Nginx当前活跃连接数
server accepts handled requests
14 14 14      
Reading: 0 Writing: 1 Waiting: 0
            
#第一个14:	为一共处理的多少个连接请求
#第二个14:	为创建多少次握手
#第三个14:	为总处理了多少请求    

# Active connections        对后端发起的当前活动连接数
# server accepts handled requests:
# server:    Nginx总共处理了14个连接, 表示Nginx处理接收握手总次数

#    成功创建了14次握手,也就是成功的连接数connection     失败连接=(总连接数-成功连接数) (相等表示中间没有失败的)
#    总共处理了14个请求数requests (server和client建立一条连接之后开始请求数据,每有一个请求此数字会+1)

# request:                   http请求,GET/POST/DELETE/UPLOAD(指的是请求资源),默认情况下下一个请求需要一个连接,但是如果开启了长连接,那么一个连接可以对应多个请求.

# Reading:                   nginx读取到客户端的Header信息数,请求头,Nginx读取数据
# Waiting:                    nginx返回给客户端的Header信息数,响应头,如果这个值飙升,说明后面的节点挂掉了,例如数据库等. Nginx写的情况
# Waiting:                   开启keep-alive的情况下,这个值等于active - (reading + writing),意思就是Nginx说已经处理完正在等候下一次请求指令的驻留连接.处理完等待下次请求的数量, 通俗点就是即没有读也没有写,建立连接情况.
# 一般监控都是通过此模块监控状态比如蓝鲸,zabbix;如果需要监控进程和端口需要

网站过滤

替换网站响应内容: ngx_http_sub_module

server里面加入下面两行代码.
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        sub_filter nginx 'flying';        # 默认只替换第一个nginx为flying,如果有多的nginx是不会替换的.
    }

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        sub_filter nginx 'flying';
        sub_filter_once off;             # 替换全部nginx为flying
    }

实用用法

如果我们用模板生成网站的时候,因为疏漏或者别的原因造成代码不如意,但是此时因为文件数量巨大,不方便全部重新生成,那么这个时候我们就可以用此模块来暂时实现纠错,另一方面,我们也可以利用这个实现服务器端文字过滤的效果.

Nginx流量控制(连接和请求)

http协议的连接与请求

HTTP是建立在TCP, 在完成HTTP请求需要先建立TCP三次握手(称为TCP连接),在连接的基础上再HTTP请求 HTTP请求建立在一次TCP连接基础上,一次TCP请求至少产生一次HTTP请求

连接频率限制限制模块

ngx_http_limit_conn_module (nginx的连接频率限制模块可以根据定义的key来限制每个键值的连接数.)

# Syntax: limit_req_zone key zone=name:size rate=rate;(设置速率每秒多少个请求)
# Default: —
# Context: http

# Syntax: limit_req zone=name [burst=number] [nodelay];(burst可以设置前多少个请求不限制,也可以设置是否延迟访问)
# Default: —
# Context: http, server, location

# Example:
yum -y install httpd-tools

vim /etc/nginx/nginx.conf
http {
limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s;

vim /etc/nginx/conf.d/default.conf
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        limit_req zone=req_zone;
       #limit_req zone=req_zone burst=5;            #5个请求时不限制的,但有延迟
       #limit_req zone=req_zone burst=5 nodelay;    #无延迟,只要拿到令牌就可以处理
    }

ab  -n 100 -c 10 http://39.108.140.0/
Time taken for tests:   0.940 seconds                     # 请求花费的总时间
Complete requests:      100
Failed requests:        99                                # 请求了100,失败了99
   (Connect: 0, Receive: 0, Length: 99, Exceptions: 0)    
Write errors:           0
Non-2xx responses:      99                                # 非200请求99个

连接限制没有请求限制有效?

我们前面说过, 多个请求可以建立在一次的TCP连接之上, 那么我们对请求的精度限制,当然比对一个连接的限制会更加的有效。 因为同一时刻只允许一个连接请求进入。 但是同一时刻多个请求可以通过一个连接进入。 所以请求限制才是比较优的解决方案。

防盗链

图片防盗链

防止网站资源被盗用 ngx_http_referer_module

# 盗链是本网站的url显示其他网站图片,而直接用它的URL是转发,宣传的也是人家的URL.
# 主机proxy准备一张图片放到根目录
mv 1.png  /usr/share/nginx/html/

# 主机rearend修改index.html
cat /usr/share/nginx/html/index.html
<html>
<head>
    <meta charset="utf-8">
    <title>hello everyone</title>
</head>
<body style="background-color:red;">
    <img src="http://39.108.140.0/1.png"/>
</body>
</html>

此时用windows10谷歌浏览器访问rearend主机,但是日志在proxy主机上,消耗资源也是proxy主机

tail -1 /var/log/nginx/access.log 114.242.249.222 - - [03/Nov/2019:17:00:31 +0800] "GET /1.png HTTP/1.1" 304 0 "http://49.233.69.195/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36" "-"

修改proxy主机配置文件

vim /etc/nginx/conf.d/default.conf
    location ~ .(img|png|gif)$ {
        root /usr/share/nginx/html/images;
        index index.html;
    valid_referers none blocked *.youmen.cn server_names ~youmen  ~.google
. ~baidu;
    if ($invalid_referer) {
        return 403;
    }
}
systemctl reload nginx

此时再用浏览器访问rearend主机就会显示一张破碎的图片标志,图片资源也加载不出来

如何区分哪些是不正常的用户?

http referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上referer,告诉服务器我是从那个页面链接过来的,服务器借此可以获得一些信息用于处理,例如防止未经允许的网站盗链图片、文件等,因此Http Referer头信息是可以通过程序伪装生成的,所以通过Referer信息防盗链并非100%可靠,但是他能限制大部分盗链情况。

Nginx下载站点

Nginx默认不允许整个目录浏览下载

如果需要开启,修改一下配置文件即可

autoindex常用参数

autoindex_exact_size off;
# 默认为on, 显示出文件的确切大小,单位是bytes。
# 修改为off,显示出文件的大概大小,单位是kB或者MB或者GB。
autoindex_localtime on;
# 默认为off,显示的文件时间为GMT时间。
# 修改为on, 显示的文件时间为文件的服务器时间。
charset utf-8,gbk;
# 默认中文目录乱码,添加上解决乱码。
开启全站目录浏览器功能(http下面添加如下内容)
autoindex on;  # 开启目录文件列表
autoindex_exact_size on;  # 显示出文件的确切大小,单位是bytes
autoindex_localtime on;  # 显示的文件时间为文件的服务器时间
charset utf-8,gbk,gb2312;  # 避免中文乱码

add_header Content-Disposition attachment;  # 文件下载(可以不开启该功能)
开启网站部分目录浏览器功能
# 编辑nginx.conf,在Server{}模块或者localtion模块加入以下内容:
autoindex on;  # 开启目录文件列表
autoindex_exact_size on;  # 显示出文件的确切大小,单位是bytes
autoindex_localtime on;  # 显示的文件时间为文件的服务器时间
charset utf-8,gbk,gb2312;  # 避免中文乱码

Nginx配置HTTPS

在之前步骤我们下载完证书后会得到一个文件,解压后会有两个文件

# 以.pem为后缀或文件类型的是证书文件
# 以.key位后缀或文件类型的是密钥文件

# 将这两个文件上传到我们nginx服务器
# 此处我的Nginx是yum装的,目录是/etc/nginx/

# 我们在这个目录创建一个cert目录
mkdir /etc/nginx/cert
# 并将我们上传的文件重命名为domain.name前缀
mv 3913414_www.zcj.net.cn.key domain.name.key
mv 3913414_www.zcj.net.cn.pem domain.name.pem

server {
    listen       80;
    server_name  zcj.net.cn zcj.net.cn;
    return 301 https://www.zcj.net.cn$request_uri;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

server {
    listen 443 ssl;
    ssl on;
    # 更换证书时候把此处文件替换掉重启服务就行了
    ssl_certificate  /etc/nginx/cert/domain.name.pem;
    ssl_certificate_key /etc/nginx/cert/domain.name.key;
    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
    }
}

systemctl reload nginx
ss -antp |grep nginx
LISTEN     0      128          *:80                       *:*                   users:(("nginx",pid=21376,fd=6),("nginx",pid=21375,fd=6))
LISTEN     0      128          *:443                      *:*                   users:(("nginx",pid=21376,fd=7),("nginx",pid=21375,fd=7))

# 打开浏览器再次访问即可看到用户和我们网站是https链接了   
[root@blog cert]# curl www.zcj.net.cn -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.16.1
Date: Thu, 14 May 2020 06:41:36 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://www.zcj.net.cn/