Linux架构09 nginx访问认证模块, 状态模块, 连接限制, 请求限制, location匹配
# string写了代表开启认证 (string为注释, 没什么用,但要写,不然为off不开) Syntax: auth_basic string | off; # string写任意字符串,除360浏览器提示,其他浏览器看不到 Default: auth_basic off; Context: http, server, location, limit_except # 指定认证的文件 Syntax: auth_basic_user_file file; Default: — Context: http, server, location, limit_except
# 创建密码文件需要htpasswd (手写是不识别的) [root@web01 conf.d]# htpasswd -c /etc/nginx/conf.d/auth_basic linux # linux为账号 New password: # 输入密码,这里输入linux Re-type new password: Adding password for user linux # 可以命令里直接输入密码,通过-b参数,把密码写在后面(不推荐,暴露密码) [root@web01 conf.d]# htpasswd -c -b /etc/nginx/conf.d/auth_basic linux linux # 密码文件内容 [root@web01 conf.d]# cat auth_basic linux:$apr1$/x0ZVRwr$ufOhtdQWYR1tGVvMqABOw/ # 注意:生成多对密码时,不使用-c参数 [root@web01 conf.d]# htpasswd -c /etc/nginx/conf.d/auth_basic lhd [root@web01 conf.d]# cat auth_basic linux:$apr1$/x0ZVRwr$ufOhtdQWYR1tGVvMqABOw/ lhd:$apr1$...
server { listen 80; server_name localhost; access_log /var/log/nginx/www.chess.com.log main; location / { root /code; index index.html; } location /download { root /code; autoindex on; autoindex_exact_size off; autoindex_localtime on; allow 10.0.0.0/24; deny all; # 不配不行 auth_basic "please input password!"; auth_basic_user_file /etc/nginx/conf.d/auth_basic; } }
Syntax: stub_status;
Default: —
Context: server, location
server { listen 80; server_name localhost; access_log /var/log/nginx/www.chess.com.log main; location / { root /code; index index.html; } location /download { root /code; autoindex on; autoindex_exact_size off; autoindex_localtime on; allow 10.0.0.0/24; deny all; auth_basic "please input password!"; auth_basic_user_file /etc/nginx/conf.d/auth_basic; } location /status { stub_status; # 配置状态模块(如果配置的location中有index页面,会直接显示页面) } }
Active connections: 2 server accepts handled requests 2 2 10 Reading: 0 Writing: 1 Waiting: 1 Active connections: # 活跃的连接数 accepts # TCP连接总数(一个TCP可以有多个请求,长连接) handled # 成功的TCP连接 requests # 请求数(所有通过nginx的请求都算) Reading # 读取请求头部 Writing # 返回给客户端的头部 Waiting # 等待的请求数(开启长连接才会有) # 取消长连接 # vim nginx.conf keepalive_timeout 0; # 类似关闭长连接 keepalive_timeout 65; # 最长65秒没有活动则断开连接 # 获取请求数量 [root@web01 nginx]# curl -qs 10.0.0.7/status | awk 'NR==3 {print $3}' 32
长连接配置 keepalive_timeout timeout [header_timeout]; #TCP握手建立连接后,会话可以保持多长时间, #在此时间内,可以继续传送数据,而不用再次握手 #默认值 keepalive_timeout 75s #header_timeout 用作响应头中显示,可以与前一个值不一样 #作用域 http, server, location keepalive_requests number; #一次请求不断开连接的情况下最多可以传送多少个资源 #默认值 keepalive_requests 1000; #作用域 http, server, location #在请求过程中以上两项达到一项阀值,连接就会断开 server{ listen 80; server_name www.m99-magedu.com; root /var/www/html/www.m99-magedu.com; keepalive_timeout 15 30; #在当前server 中修改配置,服务端真实时长是15S,响应头中显示30S } server{ listen 80; server_name www.m99-magedu.com; root /var/www/html/www.m99-magedu.com; keepalive_requests 2; #一个连接中可以获取两个资源 }
# 设置限制的空间(请求进来先存入空间,再访问。不断开,内容就在空间中。如果空间已满,拒绝请求) #调用模块 空间的内容 空间=空间名字:空间大小 Syntax: limit_conn_zone key zone=name:size; Default: — Context: http # 指要配置在http层 # 调用上面的空间(只配置上面的没用,还得调用才能生效) Syntax: limit_conn zone number; # number:同一秒支持多少个连接 Default: — Context: http, server, location # 指要配置在http/server/location层
http { ... ... # 定义空间conn_zone,存的内容为$remote_addr,空间大小为10m limit_conn_zone $remote_addr zone=conn_zone:10m;#用户访问满了,新请求就连接不了。等有人不连接了,空间里对应变量会释放,就能进行连接了 ... ... }
# 调用空间,空间名称,最大连接数(同一秒) server { ... ... #设置共享内存区域和设置最大允许连接数。当超过此限制时,服务器将返回 错误 以恢复请求。 limit_conn conn_zone l; # 这里为1秒能只能有一个新请求进行连接 } # 如果每秒进来一个,一直等空间到10m,也会拒绝访问
连接限制模块只能限制连接,但是有可能一次连接多次请求,一个连接里很次请求进行攻击。
#设置限制请求的空间 #模块 空间里保存的内容 空间=空间名称:大小 速率 1r/s(1秒1次请求) Syntax: limit_req_zone key zone=name:size rate=rate [sync]; # key 定义用于限速的关键字, 表示以什么为依据来限速 Default: — Context: http #调用上面的空间 速率增加(5,即速率每s加5请求) (追加请求)不延迟 (追加请求)延迟时间 Syntax: limit_req zone=name [burst=number] [nodelay | delay=number]; Default: — Context: http, server, location
# 写在conf.d下的conf文件里开头和写在nginx.conf中的http层效果相同,都属于http层 limit_req_zone $remote_addr zone=req_zone:1m rate=1r/s; #定义一个limit_req_zone,以 $remote_addr 值来标记客户端,zone 名称为req_zone,存储空间为 1m
#同一客户端每秒能同时建立1个连接,1r/s 完整写法是 1requests/secends
#但是 nginx 是毫秒级别的控制粒度,1r/s 意味着对同一客户端在 1000ms 只能处理一个请求
server { listen 81; server_name localhost; access_log /var/log/nginx/www.snake.com.log main; location / { root /code/snake; index index.html; limit_req zone=req_zone; # 调用 # limit_req zone=req_zone burst=5 nodelay; # 调用, 相当于处理6r/s(追加的请求不延迟) } }
# 当前配置,如果服务端在500ms内收到同一个客户端2个以上的请求,除了第一个请求会被处理之外,其它请求都返回503 # 并发是程序的天然属性,可能存在这个500ms 内有大量的请求,后续时间内没有任何请求的情况, # 我们应该尽量 均匀平滑 的处理所有请求而不是直接拒绝 limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s; server{ listen 80; server_name www.m99-magedu.com; root /var/www/html/www.m99-magedu.com; limit_req zone=mylimit burst=3; #把3个请求放在队列里,等待处理(其他超出的直接拒绝) # 定义了客户端可以超过rate 速率的请求数,在当前配置中,如果500ms 内同一客户端有5个请 求,则首先处理第1个, # 后续第2个到第4个请求放到队列中,在随后的时间内,每陋500ms 处理一个 # 第5个请求直接返回503 } limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s; server{ listen 80; server_name www.m99-magedu.com; root /var/www/html/www.m99-magedu.com; limit_req zone=mylimit burst=3 nodelay; } # burst=3 虽然使得客户端的请求变得 均匀平滑,但增加了响应时间,排在队列越后面的请求等待时间越 久,如果请求数过多,可能会等到超时也不会被处理 # nodelay 表示无延时队列 # 当服务端在500ms 内收到同一客户端 5个请求的时候,第1个到第4个请求会被直接处理,同时标记队列中 己占满,第5个返回503 # 后续每过500ms 释放出一个队列中的空间让新的请求进来
可以配置限制请求返回的状态码
limit_req_zone $remote_addr zone=req_zone:1m rate=1r/s; server { listen 81; server_name localhost; access_log /var/log/nginx/www.snake.com.log main; location / { root /code/snake; index index.html; limit_req zone=req_zone; limit_req_status 412; # 配置返回的状态码(可以是自己定义的) } }
# ab工具 [root@web01 ~]# ab -n 20 -c 2 http://10.0.0.7:81/ # -n多少个请求 -c并发量 Server Software: nginx/1.24.0 Server Hostname: 10.0.0.7 Server Port: 81 Document Path: / Document Length: 1216 bytes Concurrency Level: 2 Time taken for tests: 0.003 seconds Complete requests: 20 Failed requests: 19 (Connect: 0, Receive: 0, Length: 19, Exceptions: 0) Write errors: 0 Non-2xx responses: 19 Total transferred: 8761 bytes HTML transferred: 4959 bytes Requests per second: 7598.78 [#/sec] (mean) Time per request: 0.263 [ms] (mean) Time per request: 0.132 [ms] (mean, across all concurrent requests) Transfer rate: 3250.63 [Kbytes/sec] received
限制单一连接下载速度
limit_rate rate; #对单个客户端连接限速,默认单位为字节,其它单位需要显式指定,表示每秒的下载速度 #限速只对单一连接而言,同一客户端两个连接,总速率为限速2倍,默认值0,表示不限制 limit_rate_after size; #在传输了多少数据之后开始限速,默认值0,表示一开始就限速 #作用域 http, server, location, if in location server{ listen 80; server_name www.m99-magedu.com; root /var/www/html/www.m99-magedu.com; limit_rate 10k; #每秒下载速度为10K limit_rate_after 1m; #前1M不开启限速 } # 测试 # wget http://www.m99-magedu.com/100M.img
使用Nginx Location可以控制访问网站的路径,但一个server可以有多个location配置,多个location的优先级该如何区分
Syntax: location [ = | ~ | ~* | ^~ | / ] uri { ... }
location @name { ... }
Default: —
Context: server, location
匹配符 | 优先级 | |
---|---|---|
= | 精确匹配 | 1 |
^~ | 以某个字符串开头 | 2 |
~ | 区分大小写的正则匹配 | 3 |
~* | 不区分大小写的正则匹配 | 4 |
/ | 通用匹配,任何请求都会匹配到 | 5 |
[root@web01 conf.d]# vim testlocation.conf server { listen 80; server_name www.linux.com; #location / { # default_type text/html; # return 200 "location /"; #} location =/ { default_type text/html; # 返回类型为text格式 return 200 "location =/"; # 页面显示location =/ } location ~ / { default_type text/html; return 200 "location ~/"; } location ^~ / { default_type text/html; return 200 "location ^~"; } }
[root@web01 conf.d]# cat testserver.conf server { listen 80; server_name localhost; location / { root /code; } location ~ \.php$ { # \为转义,如果不加转义,.就代表任意字符(因为这里是正则匹配) root /php; } location ~ \.jsp$ { root /jsp; } location ~* \.(jpg|gif|png|js|css)$ { root /pic; } location ~* \.(sql|bak|tgz|tar.gz|git)$ { root /package; } } 1.PHP 2.JPG 3.jsp 4.tGz 5.Gif
location 配置 @
@name #定义
范例:@location 重定向 server{ listen 80; server_name www.m99-magedu.com; root /var/www/html/www.m99-magedu.com; error_page 404 @error; location @error { default_type text/html; return 200 "page not found"; } }