流量限制 (rate-limiting),是Nginx中一個非常實用,卻經常被錯誤理解和錯誤配置的功能。我們可以用來限制用戶在給定時間內HTTP請求的數量。請求,可以是一個簡單網站首頁的GET請求,也可以是登錄表單的 POST 請求。流量限制可以用作安全目的,比如可以減慢暴力密碼破解的速率。通過將傳入請求的速率限制為真實用戶的典型值,并標識目標URL地址(通過日志),還可以用來抵御 DDOS 攻擊。更常見的情況,該功能被用來保護上游應用服務器不被同時太多用戶請求所壓垮。
以下將會介紹Nginx的 流量限制 的基礎知識和高級配置,”流量限制”在Nginx Plus中也適用。
1、Nginx如何限流
Nginx的”流量限制”使用漏桶算法(leaky bucket algorithm),該算法在通訊和分組交換計算機網絡中廣泛使用,用以處理帶寬有限時的突發情況。就好比,一個桶口在倒水,桶底在漏水的水桶。如果桶口倒水的速率大于桶底的漏水速率,桶里面的水將會溢出;同樣,在請求處理方面,水代表來自客戶端的請求,水桶代表根據”先進先出調度算法”(FIFO)等待被處理的請求隊列,桶底漏出的水代表離開緩沖區被服務器處理的請求,桶口溢出的水代表被丟棄和不被處理的請求。
2、配置基本的限流
“流量限制”配置兩個主要的指令,limit_req_zone
和limit_req
,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
192.168.62.155配置: limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r /s ; upstream myweb { server 192.168.62.157:80 weight=1 max_fails=1 fail_timeout=1; } server { listen 80; server_name localhost; location /login { limit_req zone=mylimit; proxy_pass http: //myweb ; proxy_set_header Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } |
1
2
3
4
5
6
7
8
9
|
192.168.62.157配置: server { listen 80; server_name localhost; location /login { root /usr/share/nginx/html ; index index.html index.html; } } |
連點兩次后
limit_req_zone
指令定義了流量限制相關的參數,而limit_req
指令在出現的上下文中啟用流量限制(示例中,對于”/login/”的所有請求)。
limit_req_zone
指令通常在HTTP塊中定義,使其可在多個上下文中使用,它需要以下三個參數:
-
Key - 定義應用限制的請求特性。示例中的 Nginx 變量
$binary_remote_addr
,保存客戶端IP地址的二進制形式。這意味著,我們可以將每個不同的IP地址限制到,通過第三個參數設置的請求速率。(使用該變量是因為比字符串形式的客戶端IP地址$remote_addr
,占用更少的空間) -
Zone - 定義用于存儲每個IP地址狀態以及被限制請求URL訪問頻率的共享內存區域。保存在內存共享區域的信息,意味著可以在Nginx的worker進程之間共享。定義分為兩個部分:通過
zone=keyword
標識區域的名字,以及冒號后面跟區域大小。16000個IP地址的狀態信息,大約需要1MB,所以示例中區域可以存儲160000個IP地址。 - Rate - 定義最大請求速率。在示例中,速率不能超過每秒1個請求。Nginx實際上以毫秒的粒度來跟蹤請求,所以速率限制相當于每1000毫秒1個請求。因為不允許”突發情況”(見下一章節),這意味著在前一個請求1000毫秒內到達的請求將被拒絕。
limit_req_zone
指令設置流量限制和共享內存區域的參數,但實際上并不限制請求速率。所以需要通過添加
limit_req
指令,將流量限制應用在特定的location
或者server
塊。在上面示例中,我們對/login/
請求進行流量限制。
現在每個IP地址被限制為每秒只能請求1次/login/
,更準確地說,在前一個請求的1000毫秒內不能請求該URL。
3、處理突發
如果我們在1000毫秒內接收到2個請求,怎么辦?對于第二個請求,Nginx將給客戶端返回錯誤。這可能并不是我們想要的結果,因為應用本質上趨向于突發性。相反地,我們希望緩沖任何超額的請求,然后及時地處理它們。我們更新下配置,在limit_req
中使用burst
參數:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r /s ; upstream myweb { server 192.168.62.157:80 weight=1 max_fails=1 fail_timeout=1; } server { listen 80; server_name localhost; location /login { limit_req zone=mylimit burst=20; proxy_pass http: //myweb ; proxy_set_header Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } |
burst
參數定義了超出zone指定速率的情況下(示例中的mylimit
區域,速率限制在每秒10個請求,或每100毫秒一個請求),客戶端還能發起多少請求。上一個請求100毫秒內到達的請求將會被放入隊列,我們將隊列大小設置為20。
這意味著,如果從一個給定IP地址發送21個請求,Nginx會立即將第一個請求發送到上游服務器群,然后將余下20個請求放在隊列中。然后每100毫秒轉發一個排隊的請求,只有當傳入請求使隊列中排隊的請求數超過20時,Nginx才會向客戶端返回錯誤。
4、配置流量控制相關功能
1、配置日志記錄
默認情況下,Nginx會在日志中記錄由于流量限制而延遲或丟棄的請求,如下所示:
2019/02/13 04:20:00 [error] 120315#0: *32086 limiting requests, excess: 1.000 by zone "mylimit", client: 192.168.1.2, server: nginx.com, request: "GET / HTTP/1.0", host: "nginx.com"
日志條目中包含的字段:
- limiting requests - 表明日志條目記錄的是被“流量限制”請求
- excess - 每毫秒超過對應“流量限制”配置的請求數量
- zone - 定義實施“流量限制”的區域
- client - 發起請求的客戶端IP地址
- server - 服務器IP地址或主機名
- request - 客戶端發起的實際HTTP請求
- host - HTTP報頭中host的值
默認情況下,Nginx以error
級別來記錄被拒絕的請求,如上面示例中的[error]
所示(Nginx以較低級別記錄延時請求,一般是info
級別)。如要更改Nginx的日志記錄級別,需要使用limit_req_log_level
指令。這里,我們將被拒絕請求的日志記錄級別設置為warn
:
一定要定義日志位置和級別才可以:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r /s ; upstream myweb { server 192.168.62.157:80 weight=1 max_fails=1 fail_timeout=1; } server { listen 80; server_name localhost; location /login { limit_req zone=mylimit burst=20; limit_req_log_level warn; proxy_pass http: //myweb ; proxy_set_header Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } |
繼續訪問測試,看error.log日志
2、發送到客戶端的錯誤代碼
一般情況下,客戶端超過配置的流量限制時,Nginx響應狀態碼為503(Service Temporarily Unavailable)。可以使用limit_req_status
指令來設置為其它狀態碼(例如下面的404狀態碼):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r /s ; upstream myweb { server 192.168.62.157:80 weight=1 max_fails=1 fail_timeout=1; } server { listen 80; server_name localhost; location /login { limit_req zone=mylimit; limit_req_log_level warn; limit_req_status 404; proxy_pass http: //myweb ; proxy_set_header Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } |
5、nginx 流量控制總結
以上已經涵蓋了Nginx和Nginx Plus提供的“流量限制”的很多功能,包括為HTTP請求的不同location設置請求速率,給“流量限制”配置burst
參數。
nginx 訪問控制
1、nginx 訪問控制模塊
(1)基于IP的訪問控制:http_access_module
(2)基于用戶的信任登錄:http_auth_basic_module
2、基于IP的訪問控制
1、配置語法
1
2
3
4
5
6
7
|
Syntax:allow address | CIDR | unix: | all; default:默認無 Context:http,server,location Syntax:deny address | CIDR | unix: | all; default:默認無 Context:http,server,location |
2、修改/etc/nginx/conf.d/access_mod.conf
內容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
server { listen 80; server_name localhost; location ~ ^ /admin { root /home/www/html ; index index.html index.hml; deny 192.168.1.8; allow all; #deny 192.168.1.8; } } #需要注意: 如果先允許訪問,在定義拒絕訪問。那么拒絕訪問不生效。 |
虛擬機宿主機IP為192.168.1.8
,虛擬機IP為192.168.1.11
,故這里禁止宿主機訪問,允許其他所有IP訪問。
宿主機訪問http://192.168.1.11/admin
,顯示403 Forbidden
。
當然也可以反向配置,同時也可以使用IP網段的配置方式,如allow 192.168.1.0/24;
,表示滿足此網段的IP都可以訪問。
3、指定location拒絕所有請求
如果你想拒絕某個指定URL地址的所有請求,而不是僅僅對其限速,只需要在location
塊中配置deny
all指令:
1
2
3
4
5
6
7
8
|
server { listen 80; server_name localhost; location /foo .html { root /home/www/html ; deny all; } } |
3、基于用戶的信任登錄
1、配置語法
1
2
3
4
5
6
7
8
|
Syntax:auth_basic string | off; default:auth_basic off; Context:http,server,location,limit_except Syntax:auth_basic_user_file file; default:默認無 Context:http,server,location,limit_except file:存儲用戶名密碼信息的文件。 |
2、配置示例
改名access_mod.conf
為auth_mod.conf
,內容如下:
1
2
3
4
5
6
7
8
9
10
|
server { listen 80; server_name localhost; location ~ ^ /admin { root /home/www/html ; index index.html index.hml; auth_basic "Auth access test!" ; auth_basic_user_file /etc/nginx/auth_conf ; } } |
auth_basic
不為off
,開啟登錄驗證功能,auth_basic_user_file
加載賬號密碼文件。
3、建立口令文件
1
2
3
4
5
6
7
8
9
|
[root@192 ~] # mkdir /home/www/html/admin -p [root@192 ~] # vim /home/www/html/admin hello qf [root@192 ~] # yum install -y httpd-tools #htpasswd 是開源 http 服務器 apache httpd 的一個命令工具,用于生成 http 基本認證的密碼文件 [root@192 ~] # htpasswd -cm /etc/nginx/auth_conf user10 //第一次新建用戶 [root@192 ~] # htpasswd -m /etc/nginx/auth_conf user20 //第二次添加用戶 [root@192 ~] # cat /etc/nginx/auth_conf user10:$apr1$MOa9UVqF$RlYRMk7eprViEpNtDV0n40 user20:$apr1$biHJhW03$xboNUJgHME6yDd17gkQNb0 |
4、訪問測試
5、局限性
(1)用戶信息依賴文件方式
(2)操作管理機械,效率低下
到此這篇關于nginx 流量控制以及訪問控制的實現的文章就介紹到這了,更多相關nginx 流量控制及訪問控制內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/qq_44273583/article/details/105438060