這裡介紹如何設定 NGINX 網頁伺服器,加上密碼認證與限制可存取的 IP 位址,並控制頻寬與連線數。
在 NGINX 伺服器中若要限制只有特定的使用者可以瀏覽網頁的話,可以使用帳號與密碼認證的方式,或是設定可存取網頁的來源 IP 位址,以下是設定的步驟教學。
NGINX 帳號與密碼認證
auth_basic 可以啟用 HTTP Basic Authentication,讓使用者透過帳號與密碼進行認證,而儲存帳號與密碼的檔案則是使用 auth_basic_user_file 來指定:
location / {
auth_basic "closed site";
auth_basic_user_file conf/htpasswd;
}
auth_basic_user_file 所指定的帳號與密碼檔案格式如下:
# 這是註解
name1:password1
name2:password2:這是註解
name3:password3
而密碼的部分要先經過編碼,可以使用 Apache 所提供的 htpasswd 指令來產生,或是使用 openssl:
openssl passwd
執行這行指令之後,再輸入兩次要設定的密碼,就會產生經過編碼的密碼,例如 12345 經過編碼後會像這樣:
A5F0pZqTMG1ks
再把這個經過編碼的密碼放進帳號與密碼的檔案中,
gtwang:A5F0pZqTMG1ks
這樣就新增了一個 gtwang 帳號,而密碼為 12345。
如果要整個網站都受到帳號與密碼的保護,但開放一些特定目錄可以不需要帳號與密碼,則可以在不需要帳號與密碼的路徑中把 auth_basic 設定為 off:
server {
auth_basic "closed website";
auth_basic_user_file conf/htpasswd;
location /public/ {
auth_basic off;
}
}
這樣使用者在瀏覽所有 /public/ 之下的網頁都不需要輸入帳號與密碼。
NGINX 限制可存取的 IP 位址
allow 與 deny 可以設定允許與禁止存取網頁的來源 IP 位址,設定的方式跟 Apache 一樣,列在上方的規則會優先執行:
location / {
deny 192.168.1.2;
allow 192.168.1.1/24;
allow 127.0.0.1;
deny all;
}
這樣的設定會禁止 192.168.1.2 這個來源 IP 位址存取網頁,並允許其它所有 192.168.1.1/24 網段的 IP 位址的存取,另外也允許本機(127.0.0.1)存取,除了上述的來源之外,一律禁止存取。
除了 IPv4 之外,也可以使用 IPv6,用法皆相同:
location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
allow 2001:0db8::/32;
deny all;
}
接下來要介紹 NGINX 的頻寬與連線數控制,請繼續閱讀下一頁。
NGINX 頻寬與連線數控制
對於負載量比較高的伺服器,可以設定每一位使用者可使用的資源上限,例如同時間最大連線數、連線頻率(每秒或每分鐘連線次數)以及下載速度。
同時間最大連線數
若要限制同時間最大連線數,首先要使用 limit_conn_zone 定義一個 key 與 zone 參數:
limit_conn_zone $binary_remote_addr zone=addr:10m;
這裡定義一個名為 addr 的 zone,空間大小是 10MB,worker 行程會使用這個 zone 所配置的共享記憶體空間來儲存 key 的計數值。這裡的我們使用 $binary_remote_addr 來作為判斷來源 IP 的依據(key),會使用這個二進位的變數來作為 key 是因為它跟一般的字串比起來,會比較省空間,如果 zone 所配置的共享記憶體空間用完了,那伺服器就會回傳 503(Service Temporarily Unavailable)的錯誤訊息。
接著再使用 limit_conn 指定一個 IP 同時間可以允許的最大連線數:
location /download/ {
limit_conn addr 1;
}
以上的設定只有對於來源 IP 做限制,如果要設定整台伺服器所有連線的上限值,可以這樣設定:
http {
limit_conn_zone $server_name zone=server:10m;
server {
limit_conn server 1000;
}
}
這樣就可以把伺服器同時能夠接受的連線數上限設定為 1000。
由於在 NAT 之內的所有設備會共享一個對外 IP 位址,若以 IP 位址限制使用資源的方式,會造成 NAT 之下的所有設備共享單一 IP 位址的資源限制,這一點在制定規則時需要納入考慮。
連線頻率
若要限制連線頻率,首先也是一樣要用 limit_req_zone 定義 key 與 zone 參數:
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
這裡除了定義 zone 的名稱與大小之外,還加上了一個 rate 指定連線頻率的上限,單位可以使用每秒的連線次數(r/s)或是每分鐘的連線次數(r/m),例如若要指定每分鐘不可超過 30 次連線,則設定為 30r/m。
然後在需要限制連線頻率的地方加上 limit_req 的設定:
location /search/ {
limit_req zone=one burst=5;
}
這裡的 zone 就指定成剛剛上面定義的 zone 名稱,如果使用者所發出的連線頻率超過上限時,多出來的連線會先被放在伺服器的佇列中,等候一小段時間之後再處理,維持整體的連線頻率不會超過設定的上限,而 burst 參數是設定這個佇列的長度,如果連線數多到連佇列都放不下時,就會產生 503 的錯誤。
如果不想讓放在佇列中的請求延遲處理,可以加上 nodelay:
limit_req zone=one burst=5 nodelay;
下載速度
若要限制每個連線的頻寬,可以使用 limit_rate:
location /download/ {
limit_rate 50k;
}
在這樣的設定之下,每一個連線的下載速度最高不可超過每秒 50KB,但一個使用者可以同時開啟多條連線,如果需要限制連線數,可再加上 limit_conn 的限制條件:
location /download/ {
limit_conn addr 1;
limit_rate 50k;
}
如果要讓使用者可以先下載一部份的資料,再進行連線頻寬的限制,可以使用 limit_rate_after:
limit_rate_after 500k;
limit_rate 20k;
這樣的設定可以讓使用者先下載 500KB 的資料之後,再進行限速,這通常會用在線上影音串流的網站,先讓使用者快速下載影音檔的表頭,然後再以正常的速度傳送串流資料,確認使用者是以串流的形式觀看,而不是直接下載。
以下是一個實際應用的範例,這個設定可讓一般的網頁同時可以接受 5 條連線(一般的瀏覽器通常最多使用 3 條),而在下載 /download/ 之下的檔案時,一次只能下載一個檔案,1MB 以下的檔案不限速,超過 1MB 的檔案則限速每秒 50KB。
http {
limit_conn_zone $binary_remote_address zone=addr:10m
server {
root /www/data;
limit_conn addr 5;
location / {
}
location /download/ {
limit_conn addr 1;
limit_rate_after 1m;
limit_rate 50k;
}
}
}
