Nginx訪問控制
阿新 • • 發佈:2020-11-22
一 Nginx 連線限制
1.1 HTTP協議的連線與請求
HTTP是建立在TCP, 一次HTTP請求需要先建立TCP三次握手(稱為TCP連線),在連線的基礎上再進行HTTP請求。 HTTP請求建立在一次TCP連線基礎上,對於HTTP會話,一次TCP連線可以建立多次HTTP請求。HTTP協議版本 | 連線關係 |
HTTP1.0 | TCP不能複用 |
HTTP1.1 | 順序性TCP複用 |
HTTP2.0 | 多路複用TCP複用 |
1.2 相關模組
Nginx自帶的limit_conn_module模組(TCP連線頻率限制模組)和limit_req_mudule模組(HTTP請求頻率限制模組)支援對連線頻率以及請求頻率、來源進行限制,通常可可以用來防止DDOS攻擊。 配置語法:語法 | 範圍 | 說明 |
limit_conn_zone 標識 zone=空間名:空間大小; | http | 用於宣告一個儲存空間 |
limit_conn 空間名 併發限制數; | http、server、location | 用於限制某個儲存空間的併發數量 |
limit_conn_log_level 日誌等級; | http、server、location | 當達到最大限制連線數後, 記錄日誌的等級 |
limit_conn_status 狀態碼; | http、server、location | 當超過限制後,返回的響應狀態碼,預設是503 |
limit_req_zone key zone=空間名:空間大小 rate=每秒請求數; | http | 用於宣告一個儲存空間 |
limit_req zone=空間名 [burst=佇列數] [nodelay]; | http、server、location | 用於限制某個儲存空間的併發數量 |
1.3 配置方式
limit_conn_zone和limit_req_zone會宣告一個zone空間來記錄連線狀態, 才能限制數量。 zone是儲存連線狀態的空間, 以鍵值對儲存, 通常以客戶端地址$binary_remote_addr作為key來標識每一個連線。 當zone空間被耗盡,伺服器將會對後續所有的請求返回503(Service Temporarily Unavailable) 錯誤。1.4 常見策略
1 http { 2 limit_req_zone $binary_remote_addr zone=req_zone:1m rate=10r/s; 3 }釋義:定義一個req_zone的zone,設定1m空間大小,每秒10個請求數。 提示:burst和nodelay對併發請求設定了一個緩衝區和是否延遲處理的策略。 場景一:limit_req zone=req_zone;(即連線數等於請求數)
- 若第1秒傳送10個請求, 正常響應。
- 若第1秒傳送13個請求, 前10個請求正常響應, 後3個請求返回503(Service Temporarily Unavailable)。
- 第1秒傳送10個請求, 正常響應。
- 第1秒傳送13個請求, 前10個請求正常響應, 後3個請求放入brust等待響應。
- 第1秒傳送20個請求, 前10個請求正常響應, 後5個請求放入brust等待響應, 最後5個請求返回503(Service Temporarily Unavailable), 第2秒執行brust中的5個請求。
- 第1秒傳送20個請求, 前10個請求正常響應, 後5個請求放入brust等待響應, 最後5個請求返回503(Service Temporarily Unavailable), 第2秒傳送6個請求, 執行brust中的5個請求, 將5個請求放入brust等待響應, 剩下的1個請求返回503(Service Temporarily Unavailable)。
- 第1秒傳送10個請求, 正常響應。
- 第1秒傳送13個請求, 13個請求正常響應。
- 第1秒傳送20個請求, 前15個請求正常響應, 後5個請求返回503(Service Temporarily Unavailable)。
- 第1秒傳送20個請求, 前15個請求正常響應, 後5個請求返回503(Service Temporarily Unavailable), 第2秒傳送6個請求, 正常響應。
1.5 連線限制配置
[root@master ~]# mkdir /usr/share/nginx/limit/ [root@master ~]# echo '<h1>Limit</h1>' > /usr/share/nginx/limit/index.html [root@master ~]# vi /etc/nginx/nginx.conf user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; limit_conn_zone $binary_remote_addr zone=conn_zone:10m; limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s;
提示:$binary_remote_addr和$remote_addr代表的含義是一樣的(遠端主機的IP),只是使用$binary_remote_addr儲存一個IP會比remote_addr省10個位元組。
[root@master ~]# vi /etc/nginx/conf.d/limit.conf server { server_name limit.linuxds.com; location / { root /usr/share/nginx/limit; index index.html; limit_conn conn_zone 1; #引用全域性中的連線限制zone,並設定同一時刻只允許一個客戶端連線 limit_req zone=req_zone; #引用全域性中的請求限制zone #limit_req zone=req_zone burst=3 nodelay; #參考場景三,此處註釋 } }
[root@master ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置檔案 nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@master ~]# nginx -s reload #過載配置檔案釋義: limit_conn_zone $binary_remote_addr zone=conn_zone:10m:http段定義一個連線限制zone; limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s:http段定義一個請求限制zone, rate為限制速率,限制一秒鐘最多一個請求; 注意:多個請求可以建立在一次的TCP連線之上,因此通過對請求的限制,可以實現更精細的控制,粒度更細。因此請求限制相對比連線限制更優。
1.6 測試驗證
[root@master ~]# yum -y install httpd-tools [root@master ~]# ab -n 50 -c 10 http://limit.linuxds.com/index.html This is ApacheBench, Version 2.3 <$Revision: 1430300 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking limit.linuxds.com (be patient).....done Server Software: nginx/1.18.0 Server Hostname: limit.linuxds.com Server Port: 80 Document Path: /index.html Document Length: 15 bytes Concurrency Level: 10 Time taken for tests: 0.017 seconds Complete requests: 50 Failed requests: 49 (Connect: 0, Receive: 0, Length: 49, Exceptions: 0) Write errors: 0 Non-2xx responses: 49 Total transferred: 18326 bytes HTML transferred: 9668 bytes Requests per second: 2898.55 [#/sec] (mean) Time per request: 3.450 [ms] (mean) Time per request: 0.345 [ms] (mean, across all concurrent requests) Transfer rate: 1037.48 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 1 0.6 0 3 Processing: 1 2 1.0 2 5 Waiting: 1 1 0.8 1 3 Total: 1 3 1.5 2 6 WARNING: The median and mean for the initial connection time are not within a normal deviation These results are probably not that reliable. Percentage of the requests served within a certain time (ms) 50% 2 66% 3 75% 3 80% 4 90% 5 95% 5 98% 6 99% 6 100% 6 (longest request) [root@master ~]#
二 Nginx IP限制
2.1 相關模組
http_access_module:該模組可實現基於IP的訪問控制,但通過代理可以繞過限制。語法 | 範圍 | 說明 |
allow IP地址 | CIDR網段 | unix: | all; | http、server、location、limit_except | 允許IP地址、CIDR格式的網段、unix套接字或所有來源訪問 |
deny IP地址 | CIDR網段 | unix: | all; | http、server、location、limit_except | 禁止IP地址、CIDR格式的網段、unix套接字或所有來源訪問 |
2.2 IP訪問控制配置
[root@master ~]# mkdir /usr/share/nginx/ipaccess/ [root@master ~]# echo '<h1>Ipaccess</h1>' > /usr/share/nginx/ipaccess/index.html [root@master ~]# vi /etc/nginx/conf.d/ipaccess.conf server { server_name 192.168.1.220; location / { root /usr/share/nginx/ipaccess; index index.html; deny 192.168.1.7; #拒絕特定IP allow all; #允許其他所有 } }
[root@master ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置檔案 nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@master ~]# nginx -s reload #過載配置檔案
2.3 測試驗證
使用IP地址時需要把/usr/share/nginx/html/index.html改下名。
[root@master html]# curl 192.168.1.220
<h1>Ipaccess</h1>
注意:nginx的訪問控制限制是針對客戶端的IP來進行限制的,但是nginx並不確定真正的客戶端是哪個,凡是和nginx進行互動的都被當做是客戶端。即remote_addr是直接和nginx通訊的IP,若不是直接訪問到服務端而是由中間代理進行,訪問控制這時就會失效。
優化方法: 方法一:採用http頭資訊控制訪問,如HTTP_X_FORWARD_FOR 方法二:結合geo模組 方法三:通過HTTP自定義變數傳遞 http_x_forwarded_for頭資訊控制訪問會更好的解決該問題,它要求訪問時必須帶上所有用到的ip的地址資訊,如下圖所示:
三 Nginx 賬號限制
3.1 相關模組
http_auth_basic_module:基於檔案匹配使用者密碼的登入。語法 | 範圍 | 說明 |
auth_basic 請輸入你的帳號密碼 | off; (預設關閉) | http、server、location、limit_except | 顯示使用者登入提示 (有些瀏覽器不顯示提示) |
auth_basic_user_file 儲存帳號密碼的檔案路徑; | http、server、location、limit_except | 從檔案中匹配帳號密碼 |
3.2 賬號訪問控制設定
[root@master ~]# mkdir /usr/share/nginx/account/ [root@master ~]# mkdir /etc/nginx/passwd/ [root@master ~]# echo '<h1>Account</h1>' > /usr/share/nginx/account/index.html
[root@master html]# vi /etc/nginx/conf.d/account.conf server { server_name 192.168.1.220; location / { root /usr/share/nginx/account; index index.html; auth_basic "Auth access test! input your password!"; auth_basic_user_file /etc/nginx/passwd/auth_conf; } }
[root@master html]# yum -y install httpd-tools [root@master html]# htpasswd -c /etc/nginx/passwd/auth_conf xhy New password: Re-type new password: Adding password for user xhy
[root@master ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置檔案 nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@master ~]# nginx -s reload #過載配置檔案
提示:htpasswd -c 建立新檔案, -b可在引數中直接輸入密碼。
3.3 測試驗證
提示: 通過賬戶控制存在如下侷限性:
- 使用者資訊依賴檔案;
- 操作管理機械,配置效率低。
四 Nginx 流量限制
4.1 相關模組
http_core_moduleblock:設定除了指定的http methods外其他method將被限制,允許GET就自動允許HEAD方法。語法 | 範圍 | 說明 |
limit_rate rate; 預設值為0,即關閉限速。 | http、server、location | 限制向客戶端傳送響應的速率限制。 |
limit_rate_after size; 預設值為0,即關閉限速。 | http、server、location | 設定不限速傳輸的響應大小。 |
4.2 限速設定
server {
……
limit_rate_after 3m;
limit_rate 20k;
}
}
[root@master ~]# nginx -t -c /etc/nginx/nginx.conf #檢查配置檔案 nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@master ~]# nginx -s reload #過載配置檔案
4.3 測試驗證
可以測試下載。
參考: https://www.cnblogs.com/cheyunhua/p/9640281.html https://www.cnblogs.com/crazymagic/p/11012991.html