請求限制
限制主要有兩種類型:
- 連接頻率限制: limit_conn_module
- 請求頻率限制: limit_req_module
HTTP協議的連接與請求
HTTP協議是基於TCP的,如果要完成一次HTTP請求的時候,首先進行TCP的三次握手。當建立連接的時候就可以進行請求和響應。
可以得到結論:
HTTP請求建立在一次TCP連接基礎上,一次TCP請求至少產生一次HTTP請求(可以有多個)
對於 limit_conn_module模塊
該ngix_http_limit_conn_module模塊用於限制每個定義的密鑰的連接數量,特別是來自單個IP地址的連接數量。
並非所有連接都被計算在內 只有在服務器處理請求並且已經讀取了整個請求頭時才計算連接。
對於連接限制的配置:
Syntax: limit_conn_zone key zone=name:size;
Default: —
Context: http
Syntax: limit_conn zone number;
Default: — Context: http, server, location
對於第一部分可以理解在內存中開辟一個區域對於指定的nginx變量(key,例如:binary_remote_addr)進行限制。name表示申請的空間的名字,size表示申請空間的大小。
對於第二部分zone就是第一部分設置的名字name,number表示進行並發的限制。例如設置為1,表示一個時間段只能有一個。
對於ngx_http_limit_req_module模塊:
用於限制每一個定義的密鑰的請求的處理速率,特別是從一個單一的IP地址的請求的處理速率。限制是使用“泄漏桶”方法完成的
對於請求限制的配置:
Syntax: limit_req_zone key zone=name:size rate=rate;
Default: —
Context: http
Syntax: limit_req zone=name [burst=number] [nodelay];
Default: —
Context: http, server, location
對於第一部分配置和連接配置相似,rate表示速率,以秒s為單位(rate=1r/s)
對於第二部分zone就是第一部分設置的名字name,[]內為可配置選項。
實例:
首先編寫配置文件 default.conf
limit_conn_zone $binary_remote_addr zone=conn_zone:1m; limit_req_zone $binary_remote_addr zone=req_zone:1m rate=1r/s; server { listen 80; server_name localhost; #charset koi8-r; #access_log /var/log/nginx/log/host.access.log main; location / { root /opt/app/code; #limit_conn conn_zone 1; #limit_req zone=req_zone burst=3 nodelay; #limit_req zone=req_zone burst=3; #limit_req zone=req_zone; index index.html index.htm; }
我們看到上面為定義zone,第二行是請求定義,表示對遠程請求進行每秒一次的請求限制。這里的binary_remote_addr和remote_addr代表的含義是一樣的(遠程主機的IP)只是使用binary_remote_addr存儲一個IP會比remote_addr省10個字節。burst 參數往后延遲3個請求 nodelay 立即返回
保存重新加載
使用 ab 進行壓力測試
ab -n 40 -c 20 http://192.168.1.112/
可以看到40 個都連接成功
請求限制打開,1s同一個客戶端只允許連接一次
再次進行測試
ab -n 40 -c 20 http://192.168.1.112/
可以發現只成功了一次
訪問控制
nginx的訪問控制主要分為兩類:
- 基於IP的訪問控制 http_access_module
- 基於用戶的信任登錄 http_auth_basic_module
對於http_access_module模塊:
模塊允許限制訪問某些客戶端地址。訪問也可以通過密碼子請求結果或JWT來限制滿足控制地址和密碼的同時訪問限制。
配置語法:
Syntax: allow address | CIDR | unix: | all;
Default: —
Context: http, server, location, limit_except
Syntax: deny address | CIDR | unix: | all;
Default: —
Context: http, server, location, limit_except
語法中address表示地址,CIDR表示網段。unix:指定了特殊值,則允許訪問所有UNIX域套接字。all表示所有的。
實例:配置訪問控制
首先我們查看沒有限制的時候進行的輸出
編輯配置文件
location ~ ^/admin.html { root /opt/app/code; deny 192.168.1.6; allow all; index index.html index.htm; }
其中 ~ 表示對請求路徑URL模式匹配,表示跟目下以1.html開頭的家目錄設置在/opt/app/code。
然后檢查配置重啟
nginx -tc /etc/nginx/nginx.conf systemctl reload nginx
重新訪問我們的頁面
現在配置只有本機可以訪問
location ~ ^/admin.html { root /opt/app/code; allow 192.168.1.0/24; deny all; index index.html index.htm; }
然后檢查配置重啟
nginx -tc /etc/nginx/nginx.conf systemctl reload nginx
重新訪問我們的頁面
http_access_module模塊的局限性:
nginx的訪問控制限制是針對客戶端的IP來進行限制的,但是nginx並不確定真正的客戶端是哪個,凡是和nginx進行交互的都被當做是客戶端。(remote_addr是直接和nginx通信的IP)如果我們訪問不是直接訪問到服務端而是由中間代理進行(如上圖),訪問控制這時就會失效。
局限性解決方法總結:
方法一: 采用http頭信息控制訪問,如HTTP_X_FORWARD_FOR
方法二: 結合geo模塊
方法三: 通過HTTP自定義變量傳遞
http_x_forwarded_for頭信息控制訪問 會更好的解決該問題,它要求訪問時必須帶上所有用到的ip的地址信息
我們看一下http_x_forwarded_for記錄過程:
http_x_forwarded_for = Client IP, Proxy(1)IP, Proxy(2)IP,...

http_auth_basic_module模塊
配置語法
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
語法講解:
auth_basic 默認關閉,開啟的話輸入一段字符串即可。
auth_basic_user_file 該文件存儲用戶賬號密碼。
我們看一下官網的文件格式
# comment name1:password1 name2:password2:comment name3:password3
密碼加密方式有多中這里我們使用htpasswd
can be generated using the “htpasswd” utility from the Apache HTTP Server distribution or the “openssl passwd” command
想要使用該方式,首先要裝對應的包
yum -y install httpd-tools
接下來創建對應的use_file文件
htpasswd -c ./auth_conf zhangbiao
location ~ ^/admin.html { root /opt/app/code; auth_basic "Auth access test! input your password!"; auth_basic_user_file /etc/nginx/auth_conf; index index.html index.htm; }
進行語法檢查
nginx -tc /etc/nginx/nginx.conf systemctl reload nginx
現在我們再次訪問頁面的時候就需要輸入用戶名密碼
輸入剛才的賬號密碼就可以正常訪問了。
局限性:
一: 用戶信息依賴文件
二: 操作管理機械,效率低
解決方式:
一: nginx結合LUA實現高效驗證
二: nginx配合LDAP打通,利用nginx-auth-ldap模塊