亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

首頁 慕課教程 Nginx 入門教程 Nginx 入門教程 11 Nginx 的 Http 模塊介紹(中)

Nginx 的 Http 模塊介紹(中)

在前面介紹完 post-read、server-rewrite、find-config、rewrite 和 post-rewrite 階段后,我們將繼續學習 preaccess 和 access 兩個階段,中間會涉及部分模塊,一同進行說明。

1. preaccess 階段

在 preaccess 階段在 access 階段之前,主要是限制用戶的請求,比如并發連接數(limit_conn模塊)和每秒請求數(limit_req 模塊)等。這兩個模塊對于預防一些攻擊請求是很有效的。

1.1 limit_conn 模塊

ngx_http_limit_conn_module 模塊限制單個 ip 的建立連接的個數,該模塊內有 6 個指令。分別如下:

  • limit_conn_zone: 該指令主要的作用就是分配共享內存。 下面的指令格式中 key 定義鍵,這個 key 往往取客戶端的真實 ip,zone=name 定義區域名稱,后面的 limit_conn 指令會用到的。size 定義各個鍵共享內存空間大小;
Syntax: limit_conn_zone key zone=name:size;
Default:Context: http
  • limit_conn_status: 對于連接拒絕的請求,返回設置的狀態碼,默認是 503;
Syntax: limit_conn_status code;
Default: limit_conn_status 503;
Context: http, server, location
  • limit_conn: 該指令實際限制請求的并發連接數。指令指定每個給定鍵值的最大同時連接數,當超過這個數字時被返回 503 (默認,可以由指令 limit_conn_status 設置)錯誤;
Syntax: limit_conn zone number;
Default:Context: http, server, location
  • limit_conn_log_level: 當達到最大限制連接數后,記錄日志的等級;
Syntax: limit_conn_log_level info | notice | warn | error;
Default: limit_conn_log_level error;
Context: http, server, location
  • limit_conn_dry_run: 這個指令是 1.17.6 版本中才出現的,用于設置演習模式。在這個模式中,連接數不受限制。但是在共享內存的區域中,過多的連接數也會照常處理。
Syntax:	limit_conn_dry_run on | off;
Default: limit_conn_dry_run off;
Context: http, server, location
  • limit_zone: 該指令已棄用,由 limit_conn_zone 代替,不再進行說明。

實例

http {
    ...
    limit_conn_zone $binary_remote_addr zone=addr:10m

    server {
        ...
        location / {
            limit_conn_status 500;
            limit_conn_log_level warn;
            # 限制向用戶返回的速度,每秒50個字節
            limit_rate 50;
            limit_conn addr 10;
        }
    }

}

1.2 limit_req 模塊

ngx_http_limit_req_module 模塊主要用于處理突發流量,它基于漏斗算法將突發的流量限定為恒定的流量。如果請求容量沒有超出設定的極限,后續的突發請求的響應會變慢,而對于超過容量的請求,則會立即返回 503(默認)錯誤。

該模塊模塊中比較重要的指令有:

  • limit_req_zone 指令,定義共享內存, key 關鍵字以及限制速率
Syntax:	limit_req_zone key zone=name:size rate=rate [sync];
Default:Context: http
  • limit_req 指令,限制并發連接數
Syntax:	limit_req zone=name [burst=number] [nodelay | delay=number];
Default:Context: http, server, location
  • limit_req_log_level 指令,設置服務拒絕請求發生時打印的日志級別
Syntax:	limit_req_log_level info | notice | warn | error;
Default:
limit_req_log_level error;
Context:	http, server, location
  • limit_req_status 指令, 設置服務拒絕請求發生時返回狀態碼
Syntax: limit_req_status code;
Default: limit_req_status 503;
Context: http, server, location

2. access 階段

2.1 限制某些 ip 地址的訪問權限

在 access 階段,我們可以通 allow 和 deny 指令來允許和拒絕某些 ip 的訪問權限,指令的用法如下:

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

實例

allow 和 deny 指令后面可以跟具體 ip 地址,也可以跟一個 ip 段, 或者所有(all)。

location / {
    deny  192.168.1.1;
    allow 192.168.1.0/24;
    allow 10.1.1.0/16;
    allow 2001:0db8::/32;
    deny  all;
}

2.2 auth_basic 模塊

auth_basic 模塊是基于 HTTP Basic Authentication 協議進行用戶名和密碼的認證,它默認是編譯進 Nginx 中的,可以在源碼編譯階段通過 --without-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

對于使用文件保存用戶名和密碼,二者之間需用冒號隔開,如下所示。

# comment
name1:password1
name2:password2:comment
name3:password3

在 centos 系統上,想要生成這樣的密碼文件,我們可以使用 httpd-tools 工具完成,直接使用 yum install安裝即可。

$ sudo yum install httpd-tools
# 生成密碼文件user_file,帳號為user,密碼為pass
$ htpasswd -bc user_file user pass

接下來,我們只需要配置好 auth_basic 指令,即可對相應的 http 請求做好認證工作。

2.3 第三方訪問控制

第三方的訪問控制是用到了auth_request模塊,該模塊的功能是向上游服務轉發請求,如果上游服務返回的相應碼是 2xx,則通過認證,繼續向后執行;若返回的 401 或者 403,則將響應返回給客戶端。

auth_request 模塊默認是未編譯進 Nginx 中的,因此我們需要使用 --with-http_auth_reques_module
將該模塊編譯進 Nginx 中,然后我們才能使用該模塊。

Syntax: auth_request uri | off;
Default: auth_request off;
Context: http, server, location

Syntax: auth_request_set $variable value;
Default:Context: http, server, location

官方示例:

location /private/ {
    auth_request /auth;
    ...
}

location = /auth {
    # 上游認證服務地址
    proxy_pass ...
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_set_header X-Original-URI $request_uri;
}

3. 實驗

3.1 limit_conn 模塊實驗

本次案例將使用 limit_conn 模塊中的指令完成限速功能實驗。實驗配置塊如下:

...
http {
    ...
    # 沒有這個會報錯,必須要定義共享內存
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    ...
    server {
        server_name localhost;
        listen 8010;

        location / {
           limit_rate 50;
           limit_conn addr 1;
        }

    }
    ...
}
...

使用 limit_rate 指令用于限制 Nginx 相應速度,每秒返回 50 個字節,然后是限制并發數為 2,這樣方便展示效果。當我們打開一個瀏覽器請求該端口下的根路徑時,由于相應會比較慢,迅速打開另一個窗口請求同樣的地址,會發現再次請求時,正好達到了同時并發數為 2,啟動限制功能,第二個窗口返回 503 錯誤(默認)。

訪問第一次

圖片描述

快速訪問第二次
圖片描述

3.2 access 模塊實驗

我們做一個簡單的示例,配置如下。在 /root/test/web 下有 web1.html 和 web2.html 兩個靜態文件。訪問/web1.html 時,使用 allow all指令將所有來源的 ip 請求全部放過(當然也可以不寫);使用 deny all 會拒絕所有,所以訪問 /web2.htm l時,會出現 403 的報錯頁面。

server {
   server_name access.test.com;
   listen 8011;

   root /root/test/web;

   location /web1.html {
      default_type text/html;
      allow all;
      # return 200 'access';
   }

   location /web2.html {
      default_type text/html;
      deny all;
      # return 200 'deny';
   }
}

訪問允許的 web1.html 頁面
圖片描述

訪問禁止的 web2.html
圖片描述

大家可以思考下,如果使用的是 return 指令呢,會有怎樣的結果?打開注釋,重新加載 Nginx 后,可以看到無論是訪問 /web1.html 還是 /web2.html,我們都可以看到想要的 return 指令中的結果。這是因為 return 指令所在的 rewrite 模塊先于 access 模塊執行,所以不會執行到 allow 和 deny 指令就直接返回了。但是對于訪問靜態頁面資源,則是在 content 階段執行的,所以會在經過 allow 和 deny 指令處理后才獲取靜態資源頁面的內容,并返回給用戶。

3.3 auth_basic 模塊實驗

   $ htpasswd -bc /root/user.pass store @store.123!
   $ cat /root/user.pass
   store:$apr1$36xHOQGz$yk4O3roiW3SIJrkXFJ0pS1

在 Nginx 加入如下 server 塊的配置,監聽 8012 端口,并在 / 路徑中加入認證模塊。

server {
   server_name auth_basic.test.com;
   listen 8012;

   location / {
       auth_basic           "my site";
       auth_basic_user_file /root/user.pass;
   }
}

重新加載 Nginx 后,訪問主機的 8012 端口的根路徑時,就會發現需要輸入賬號和密碼了。成功輸入賬號和密碼后,就可以看到 Nginx 的歡迎頁了。

使用 auth_basic 模塊認證

圖片描述
認證成功后的頁面

圖片描述

4. 小結

本篇文章中,我們介紹了 Http 請求的 11 個階段中的中間階段,分別為 preaccess 和 access 階段。在這兩個階段中,主要生效的指令有limit_conn、limit_req、allow、deny 等,這些指令幾乎都是用來做訪問控制的,用來限制 Nginx 的并發連接、訪問限速、設置訪問白名單以及認證訪問等。這些安全限制在線上環境是十分必要的,必須要限制惡意的請求以及添加白名單操作。