亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Nginx流量控制及白名單實(shí)現(xiàn)

 更新時(shí)間:2024年08月06日 11:28:51   作者:ZZDICT  
本文主要介紹了Nginx流量控制實(shí)現(xiàn),還包括了針對(duì)客戶端IP地址的白名單和黑名單應(yīng)用不同“流量限制”的高級(jí)配置,具有一定的參考價(jià)值,感興趣的可以了解一下

流量限制 (rate-limiting),是Nginx中一個(gè)非常實(shí)用,卻經(jīng)常被錯(cuò)誤理解和錯(cuò)誤配置的功能。我們可以用來(lái)限制用戶在給定時(shí)間內(nèi)HTTP請(qǐng)求的數(shù)量。請(qǐng)求,可以是一個(gè)簡(jiǎn)單網(wǎng)站首頁(yè)的GET請(qǐng)求,也可以是登錄表單的 POST 請(qǐng)求。流量限制可以用作安全目的,比如可以減慢暴力密碼破解的速率。通過(guò)將傳入請(qǐng)求的速率限制為真實(shí)用戶的典型值,并標(biāo)識(shí)目標(biāo)URL地址(通過(guò)日志),還可以用來(lái)抵御 DDOS 攻擊。更常見(jiàn)的情況,該功能被用來(lái)保護(hù)上游應(yīng)用服務(wù)器不被同時(shí)太多用戶請(qǐng)求所壓垮。

以下將會(huì)介紹Nginx的 流量限制 的基礎(chǔ)知識(shí)和高級(jí)配置,”流量限制”在Nginx Plus中也適用。

1、Nginx如何限流

Nginx的”流量限制”使用漏桶算法(leaky bucket algorithm),該算法在通訊和分組交換計(jì)算機(jī)網(wǎng)絡(luò)中廣泛使用,用以處理帶寬有限時(shí)的突發(fā)情況。就好比,一個(gè)桶口在倒水,桶底在漏水的水桶。如果桶口倒水的速率大于桶底的漏水速率,桶里面的水將會(huì)溢出;同樣,在請(qǐng)求處理方面,水代表來(lái)自客戶端的請(qǐng)求,水桶代表根據(jù)”先進(jìn)先出調(diào)度算法”(FIFO)等待被處理的請(qǐng)求隊(duì)列,桶底漏出的水代表離開(kāi)緩沖區(qū)被服務(wù)器處理的請(qǐng)求,桶口溢出的水代表被丟棄和不被處理的請(qǐng)求。

2、配置基本的限流

準(zhǔn)備兩臺(tái)機(jī)器,關(guān)閉防火墻和selinux

localhostRoucky_linux9.4192.168.226.20
localhostRoucky_linux9.4192.168.226.21

都使用nginx官方源下載nginx并啟動(dòng)

sudo tee /etc/yum.repos.d/nginx.repo << 'EOF'
[nginx-stable]
name=nginx stable repo
baseurl=https://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
 
[nginx-mainline]
name=nginx mainline repo
baseurl=https://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
EOF
yum install -y nginx
systemctl enable --now nginx

 這里還準(zhǔn)備了訪問(wèn)自動(dòng)測(cè)試的代碼,使用go語(yǔ)言編寫(xiě)

package main

import (
	"fmt"
	"io"
	"net/http"
	"time"
)

// ANSI color codes
const (
	RedColor    = "\033[31m"
	GreenColor  = "\033[32m"
	YellowColor = "\033[33m"
	ResetColor  = "\033[0m"
)

// 記錄成功、失敗、無(wú)法響應(yīng)以及服務(wù)暫時(shí)不可用(503)的請(qǐng)求數(shù)量
var successCount int
var failureCount int
var unresponsiveCount int
var tempUnavailableCount int // 新增變量來(lái)跟蹤503 Service Unavailable狀態(tài)的請(qǐng)求數(shù)量

// makeRequest 向給定的 URL 發(fā)送一個(gè) GET 請(qǐng)求,并根據(jù)響應(yīng)的成功與否以不同顏色打印出響應(yīng)狀態(tài)和所花費(fèi)的時(shí)間。
func makeRequest(url string, attempt int) {
	startTime := time.Now()
	resp, err := http.Get(url)
	elapsedTime := time.Since(startTime)

	if err != nil {
		// 如果因?yàn)榫W(wǎng)絡(luò)問(wèn)題或服務(wù)器問(wèn)題導(dǎo)致請(qǐng)求失敗,我們將其計(jì)為“無(wú)法響應(yīng)”
		fmt.Printf("[%d] %sRequest unresponsive: %s %.4f seconds%s\n", attempt, RedColor, err, elapsedTime.Seconds(), ResetColor)
		unresponsiveCount++
		return
	}
	defer func(Body io.ReadCloser) {
		err := Body.Close()
		if err != nil {
			fmt.Printf("Error closing response body: %s\n", err)
		}
	}(resp.Body)

	color := GreenColor
	if resp.StatusCode == 503 {
		color = YellowColor
		tempUnavailableCount++ // 對(duì)返回503狀態(tài)碼的請(qǐng)求進(jìn)行統(tǒng)計(jì)
	} else if resp.StatusCode != 200 {
		color = RedColor
		failureCount++
	} else {
		successCount++
	}

	// 根據(jù)狀態(tài)碼,以對(duì)應(yīng)的顏色打印響應(yīng)狀態(tài)碼和耗時(shí)
	fmt.Printf("[%d] %s%d %.4f seconds%s\n", attempt, color, resp.StatusCode, elapsedTime.Seconds(), ResetColor)
}

func main() {
	url := "http://192.168.226.21"
	totalAttempts := 1000
	startTime := time.Now()

	for attempt := 1; attempt <= totalAttempts; attempt++ {
		makeRequest(url, attempt)
	}

	totalElapsedTime := time.Since(startTime)
	successRate := (float64(successCount) / float64(totalAttempts)) * 100
	failureRate := (float64(failureCount) / float64(totalAttempts)) * 100
	unresponsiveRate := (float64(unresponsiveCount) / float64(totalAttempts)) * 100
	tempUnavailableRate := (float64(tempUnavailableCount) / float64(totalAttempts)) * 100 // 計(jì)算503狀態(tài)碼比率

	fmt.Printf("%sTotal elapsed time: %.4f seconds%s\n", ResetColor, totalElapsedTime.Seconds(), ResetColor)
	fmt.Printf("成功率: %.2f%%, 失敗率: %.2f%%, 無(wú)法響應(yīng)的請(qǐng)求比: %.2f%%, 服務(wù)暫時(shí)不可用請(qǐng)求比率(503): %.2f%%\n", successRate, failureRate, unresponsiveRate, tempUnavailableRate)
}

實(shí)驗(yàn)開(kāi)始前進(jìn)行訪問(wèn)1000次測(cè)試耗時(shí)和成功率

 在192.168.226.20主機(jī)操作

“流量限制”配置兩個(gè)主要的指令,limit_req_zonelimit_req,如下所示:  

在http模塊里配置

    # 定義一個(gè)限流區(qū)域
    # $binary_remote_addr 使用二進(jìn)制格式的客戶端IP地址作為鍵
    # zone=mylimit:10m 創(chuàng)建一個(gè)名為'mylimit'的共享內(nèi)存區(qū)域,大小為10MB
    # rate=10r/s 每秒最多允許1個(gè)請(qǐng)求
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
    upstream myweb {
        server 192.168.226.21:80 weight=1 max_fails=1 fail_timeout=1;
    }

在server模塊里配置

server {
    listen       80;  # 定義服務(wù)器監(jiān)聽(tīng)的端口為 80,這是 HTTP 協(xié)議的默認(rèn)端口。
    server_name  localhost;  # 設(shè)置服務(wù)器名稱為 localhost,這意味著它將響應(yīng)發(fā)送到 localhost 的請(qǐng)求。
    
    location /{  # 定義對(duì)根路徑("/")的請(qǐng)求的處理規(guī)則。
        root   /usr/share/nginx/html;  # 設(shè)置文檔根目錄,這是 Nginx 在響應(yīng)請(qǐng)求時(shí)查找文件的地方。
        index  index.html index.htm;  # 設(shè)置當(dāng)請(qǐng)求是一個(gè)目錄時(shí),默認(rèn)會(huì)返回的文件。在這里,如果訪問(wèn)根目錄("/"),會(huì)首先嘗試返回 index.html 文件,如果沒(méi)有找到,再嘗試 index.htm。
        limit_req zone=mylimit;  # 為根路徑的請(qǐng)求應(yīng)用請(qǐng)求限制,使用名為 mylimit 的限流規(guī)則。
        limit_req_dry_run off;  # 設(shè)置為on以在日志中查看限制的影響,而不會(huì)實(shí)際限制流量
        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;
    }
}
#修改默認(rèn)打開(kāi)頁(yè)面,用來(lái)區(qū)分兩個(gè)主機(jī)
#修改192.168.226.20主機(jī)
echo "webserver1" > /usr/share/nginx/html/index.html

#修改192.168.226.21主機(jī)
echo "webserver2" > /usr/share/nginx/html/index.html
#兩個(gè)主機(jī)都重啟nginx
systemctl restart nginx

 瀏覽器訪問(wèn)192.168.226.20實(shí)際上會(huì)看到webserver2的字樣頁(yè)面,然后刷新看,有失敗和成功頁(yè)面,就完成了基本的限流設(shè)置。跑完go代碼看結(jié)果如果(比率是有一點(diǎn)波動(dòng)的是正常的):

limit_req_zone指令定義了流量限制相關(guān)的參數(shù),而limit_req指令在出現(xiàn)的上下文中啟用流量限制(示例中,對(duì)于”/login/”的所有請(qǐng)求)。

limit_req_zone指令通常在HTTP塊中定義,使其可在多個(gè)上下文中使用,它需要以下三個(gè)參數(shù):

  • Key - 定義應(yīng)用限制的請(qǐng)求特性。示例中的 Nginx 變量$binary_remote_addr,保存客戶端IP地址的二進(jìn)制形式。這意味著,我們可以將每個(gè)不同的IP地址限制到,通過(guò)第三個(gè)參數(shù)設(shè)置的請(qǐng)求速率。(使用該變量是因?yàn)楸茸址问降目蛻舳薎P地址$remote_addr,占用更少的空間)

  • Zone - 定義用于存儲(chǔ)每個(gè)IP地址狀態(tài)以及被限制請(qǐng)求URL訪問(wèn)頻率的共享內(nèi)存區(qū)域。保存在內(nèi)存共享區(qū)域的信息,意味著可以在Nginx的worker進(jìn)程之間共享。定義分為兩個(gè)部分:通過(guò)zone=keyword標(biāo)識(shí)區(qū)域的名字,以及冒號(hào)后面跟區(qū)域大小。16000個(gè)IP地址的狀態(tài)信息,大約需要1MB,所以示例中區(qū)域可以存儲(chǔ)160000個(gè)IP地址。

  • Rate - 定義最大請(qǐng)求速率。在示例中,速率不能超過(guò)每秒10個(gè)請(qǐng)求。Nginx實(shí)際上以毫秒的粒度來(lái)跟蹤請(qǐng)求,所以速率限制相當(dāng)于每100毫秒1個(gè)請(qǐng)求。因?yàn)椴辉试S”突發(fā)情況”(見(jiàn)下一章節(jié)),這意味著在前一個(gè)請(qǐng)求100毫秒內(nèi)到達(dá)的請(qǐng)求將被拒絕。

當(dāng)Nginx需要添加新條目時(shí)存儲(chǔ)空間不足,將會(huì)刪除舊條目。如果釋放的空間仍不夠容納新記錄,Nginx將會(huì)返回 503狀態(tài)碼(Service Temporarily Unavailable)。另外,為了防止內(nèi)存被耗盡,Nginx每次創(chuàng)建新條目時(shí),最多刪除兩條60秒內(nèi)未使用的條目。

limit_req_zone指令設(shè)置流量限制和共享內(nèi)存區(qū)域的參數(shù),但實(shí)際上并不限制請(qǐng)求速率。所以需要通過(guò)添加

limit_req指令,將流量限制應(yīng)用在特定的location或者server塊。在上面示例中,我們對(duì)/login/請(qǐng)求進(jìn)行流量限制。

現(xiàn)在每個(gè)IP地址被限制為每秒只能請(qǐng)求10次/login/,更準(zhǔn)確地說(shuō),在前一個(gè)請(qǐng)求的100毫秒內(nèi)不能請(qǐng)求該URL。

3、處理突發(fā)

如果我們?cè)?00毫秒內(nèi)接收到2個(gè)請(qǐng)求,怎么辦?對(duì)于第二個(gè)請(qǐng)求,Nginx將給客戶端返回狀態(tài)碼503。這可能并不是我們想要的結(jié)果,因?yàn)閼?yīng)用本質(zhì)上趨向于突發(fā)性。相反地,我們希望緩沖任何超額的請(qǐng)求,然后及時(shí)地處理它們。我們更新下配置,limit_req中使用burst參數(shù)

重啟nginx然后運(yùn)行g(shù)o代碼請(qǐng)求測(cè)試

burst參數(shù)定義了當(dāng)請(qǐng)求速率超過(guò)rate參數(shù)所設(shè)定的限制時(shí),允許額外處理的請(qǐng)求數(shù)量。這些額外的請(qǐng)求將被暫時(shí)放入一個(gè)隊(duì)列中等待處理,而不是立即返回錯(cuò)誤。但是訪問(wèn)量大的話后面的排隊(duì)時(shí)間就會(huì)太慢,并不是最優(yōu)的選擇。 

burst參數(shù)定義了超出zone指定速率的情況下(示例中的mylimit區(qū)域,速率限制在每秒10個(gè)請(qǐng)求,或每100毫秒一個(gè)請(qǐng)求),客戶端還能發(fā)起多少請(qǐng)求。上一個(gè)請(qǐng)求100毫秒內(nèi)到達(dá)的請(qǐng)求將會(huì)被放入隊(duì)列,我們將隊(duì)列大小設(shè)置為20。

這意味著,如果從一個(gè)給定IP地址發(fā)送21個(gè)請(qǐng)求,Nginx會(huì)立即將第一個(gè)請(qǐng)求發(fā)送到上游服務(wù)器群,然后將余下20個(gè)請(qǐng)求放在隊(duì)列中。然后每100毫秒轉(zhuǎn)發(fā)一個(gè)排隊(duì)的請(qǐng)求,只有當(dāng)傳入請(qǐng)求使隊(duì)列中排隊(duì)的請(qǐng)求數(shù)超過(guò)20時(shí),Nginx才會(huì)向客戶端返回503。

4、無(wú)延遲的排隊(duì)

配置burst參數(shù)將會(huì)使通訊更流暢,但是可能會(huì)不太實(shí)用,因?yàn)樵撆渲脮?huì)使站點(diǎn)看起來(lái)很慢。在上面的示例中,隊(duì)列中的第20個(gè)包需要等待2秒才能被轉(zhuǎn)發(fā),此時(shí)返回給客戶端的響應(yīng)可能不再有用。要解決這個(gè)情況,可以在burst參數(shù)后添加nodelay參數(shù):

重啟nginx運(yùn)行g(shù)o測(cè)試代碼 

使用nodelay參數(shù),Nginx仍將根據(jù)burst參數(shù)分配隊(duì)列中的位置,并應(yīng)用已配置的速率限制,而不是清理隊(duì)列中等待轉(zhuǎn)發(fā)的請(qǐng)求。相反地,當(dāng)一個(gè)請(qǐng)求到達(dá)“太早”時(shí),只要在隊(duì)列中能分配位置,Nginx將立即轉(zhuǎn)發(fā)這個(gè)請(qǐng)求。將隊(duì)列中的該位置標(biāo)記為”taken”(占據(jù)),并且不會(huì)被釋放以供另一個(gè)請(qǐng)求使用,直到一段時(shí)間后才會(huì)被釋放(在這個(gè)示例中是,100毫秒后)。

假設(shè)如前所述,隊(duì)列中有20個(gè)空位,從給定的IP地址發(fā)出的21個(gè)請(qǐng)求同時(shí)到達(dá)。Nginx會(huì)立即轉(zhuǎn)發(fā)這個(gè)21個(gè)請(qǐng)求,并且標(biāo)記隊(duì)列中占據(jù)的20個(gè)位置,然后每100毫秒釋放一個(gè)位置。如果是25個(gè)請(qǐng)求同時(shí)到達(dá),Nginx將會(huì)立即轉(zhuǎn)發(fā)其中的21個(gè)請(qǐng)求,標(biāo)記隊(duì)列中占據(jù)的20個(gè)位置,并且返回503狀態(tài)碼來(lái)拒絕剩下的4個(gè)請(qǐng)求。

現(xiàn)在假設(shè),第一組請(qǐng)求被轉(zhuǎn)發(fā)后101毫秒,另20個(gè)請(qǐng)求同時(shí)到達(dá)。隊(duì)列中只會(huì)有一個(gè)位置被釋放,所以Nginx轉(zhuǎn)發(fā)一個(gè)請(qǐng)求并返回503狀態(tài)碼來(lái)拒絕其他19個(gè)請(qǐng)求。如果在20個(gè)新請(qǐng)求到達(dá)之前已經(jīng)過(guò)去了501毫秒,5個(gè)位置被釋放,所以Nginx立即轉(zhuǎn)發(fā)5個(gè)請(qǐng)求并拒絕另外15個(gè)。

效果相當(dāng)于每秒10個(gè)請(qǐng)求的“流量限制”。如果希望不限制兩個(gè)請(qǐng)求間允許間隔的情況下實(shí)施“流量限制”,nodelay參數(shù)是很實(shí)用的。

注意: 對(duì)于大部分部署,我們建議使用burstnodelay參數(shù)來(lái)配置limit_req指令。

5、高級(jí)配置示例

通過(guò)將基本的“流量限制”與其他Nginx功能配合使用,我們可以實(shí)現(xiàn)更細(xì)粒度的流量限制。

1、白名單

下面這個(gè)例子需要將上面做過(guò)的刪除,然后重新配置

#排除上面實(shí)驗(yàn)的干擾,重新安裝配置nginx
yum remove -y nginx
yum install -y nginx
systemctl enable --now nginx

下面這個(gè)例子將展示,如何對(duì)任何不在白名單內(nèi)的請(qǐng)求強(qiáng)制執(zhí)行“流量限制”: 

vim /etc/nginx/nginx.conf

將下面的http塊替換nginx配置文件的里的http塊代碼,其他不用動(dòng)

#將下面的http塊替換nginx配置文件的里的http塊代碼,其他不用動(dòng)
http {
    include       /etc/nginx/mime.types;  # 包括MIME類型定義,讓Nginx能根據(jù)文件擴(kuò)展名設(shè)置正確的Content-Type頭。
    default_type  application/octet-stream;  # 設(shè)置默認(rèn)的MIME類型,當(dāng)文件類型未定義時(shí)使用。

    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;  # 定義access日志的存儲(chǔ)位置和使用的格式。

    # 以下部分定義了基于IP地址的訪問(wèn)限制。
    geo $limit {
        default 		1;  # 默認(rèn)情況下,所有IP地址的$limit值設(shè)為1。
        10.0.0.0/24 	0;  # 對(duì)于這兩個(gè)子網(wǎng)中的IP地址,將$limit設(shè)為0。
        192.168.0.0/24 	0;
    }
    
    # 根據(jù)$limit的值,動(dòng)態(tài)地設(shè)置$limit_key變量。
    map $limit $limit_key {
        0 "";  # 如果$limit為0,$limit_key為空。
        1 $binary_remote_addr;  # 如果$limit為1,$limit_key使用二進(jìn)制格式的客戶端IP地址。
    }
    
    # 定義請(qǐng)求限制區(qū)域req_zone,按$limit_key對(duì)請(qǐng)求進(jìn)行分組,每個(gè)組最多每秒處理5個(gè)請(qǐng)求。
    limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;

    server {  # 定義一個(gè)服務(wù)器監(jiān)聽(tīng)在80端口。
        listen 80;  # 監(jiān)聽(tīng)80端口。
        server_name localhost;  # 服務(wù)器名稱設(shè)置為localhost。
        
        location / {  # 對(duì)于根路徑的請(qǐng)求。
            limit_req zone=req_zone burst=10 nodelay;  # 應(yīng)用請(qǐng)求限制,允許突發(fā)請(qǐng)求高達(dá)10個(gè)。
            root /usr/share/nginx/html;  # 網(wǎng)站根目錄。
            index index.html index.hml;  # 定義默認(rèn)首頁(yè)。
        }
    }
    
    include /etc/nginx/conf.d/*.conf;  # 導(dǎo)入/etc/nginx/conf.d/目錄下的所有.conf配置文件。
}

這個(gè)例子同時(shí)使用了geomap指令。geo塊將給在白名單中的IP地址對(duì)應(yīng)的$limit變量分配一個(gè)值0,給其它不在白名單中的分配一個(gè)值1。然后我們使用一個(gè)映射將這些值轉(zhuǎn)為key,如下:

  • 如果$limit變量的值是0,$limit_key變量將被賦值為空字符串

  • 如果$limit變量的值是1,$limit_key變量將被賦值為客戶端二進(jìn)制形式的IP地址

兩個(gè)指令配合使用,白名單內(nèi)IP地址的$limit_key變量被賦值為空字符串,不在白名單內(nèi)的被賦值為客戶端的IP地址。當(dāng)limit_req_zone后的第一個(gè)參數(shù)是空字符串時(shí),不會(huì)應(yīng)用“流量限制”,所以白名單內(nèi)的IP地址(10.0.0.0/24和192.168.0.0/24 網(wǎng)段內(nèi))不會(huì)被限制。其它所有IP地址都會(huì)被限制到每秒5個(gè)請(qǐng)求。

limit_req指令將限制應(yīng)用到/的location塊,允許在配置的限制上最多超過(guò)10個(gè)數(shù)據(jù)包的突發(fā),并且不會(huì)延遲轉(zhuǎn)發(fā)。

2、location 包含多l(xiāng)imit_req指令

我們可以在一個(gè)location塊中配置多個(gè)limit_req指令。符合給定請(qǐng)求的所有限制都被應(yīng)用時(shí),意味著將采用最嚴(yán)格的那個(gè)限制。例如,多個(gè)指令都制定了延遲,將采用最長(zhǎng)的那個(gè)延遲。同樣,請(qǐng)求受部分指令影響被拒絕,即使其他指令允許通過(guò)也無(wú)濟(jì)于事。

擴(kuò)展前面將“流量限制”應(yīng)用到白名單內(nèi)IP地址的例子:

http {
	# ...

	limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;
	limit_req_zone $binary_remote_addr zone=req_zone_wl:10m rate=15r/s;

	server {
		# ...
		location / {
			limit_req zone=req_zone burst=10 nodelay;
			limit_req zone=req_zone_wl burst=20 nodelay;
			# ...
		}
	}
}

白名單內(nèi)的IP地址不會(huì)匹配到第一個(gè)“流量限制”,而是會(huì)匹配到第二個(gè)`req_zone_wl`,并且被限制到每秒15個(gè)請(qǐng)求。
不在白名單內(nèi)的IP地址兩個(gè)限制能匹配到,所以應(yīng)用限制更強(qiáng)的那個(gè):每秒5個(gè)請(qǐng)求。

因此理解了原理,修改上面的http塊里的代碼進(jìn)行測(cè)試:

#將下面的http塊替換nginx配置文件的里的http塊代碼,其他不用動(dòng)
http {
    include       /etc/nginx/mime.types;  # 包括MIME類型定義,讓Nginx能根據(jù)文件擴(kuò)展名設(shè)置正確的Content-Type頭。
    default_type  application/octet-stream;  # 設(shè)置默認(rèn)的MIME類型,當(dāng)文件類型未定義時(shí)使用。

    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;  # 定義access日志的存儲(chǔ)位置和使用的格式。

    # 以下部分定義了基于IP地址的訪問(wèn)限制。
    geo $limit {
        default 		1;
        10.0.0.0/24 	0;
        192.168.0.0/24 	0;
    }
    
    # 根據(jù)$limit的值,動(dòng)態(tài)地設(shè)置$limit_key變量。
    map $limit $limit_key {
        0 "";  # 如果$limit為0,$limit_key為空。
        1 $binary_remote_addr;  # 如果$limit為1,$limit_key使用二進(jìn)制格式的客戶端IP地址。
    }
    
    # 定義請(qǐng)求限制區(qū)域req_zone,按$limit_key對(duì)請(qǐng)求進(jìn)行分組,每個(gè)組最多每秒處理5個(gè)請(qǐng)求。
    limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;
	limit_req_zone $binary_remote_addr zone=req_zone_wl:10m rate=15r/s;
    server {  # 定義一個(gè)服務(wù)器監(jiān)聽(tīng)在80端口。
        listen 80;  # 監(jiān)聽(tīng)80端口。
        server_name localhost;  # 服務(wù)器名稱設(shè)置為localhost。
        
        location / {  # 對(duì)于根路徑的請(qǐng)求。
            limit_req zone=req_zone burst=10 nodelay;
			limit_req zone=req_zone_wl burst=20 nodelay;
            root /usr/share/nginx/html;  # 網(wǎng)站根目錄。
            index index.html index.hml;  # 定義默認(rèn)首頁(yè)。
        }
    }
    
    include /etc/nginx/conf.d/*.conf;  # 導(dǎo)入/etc/nginx/conf.d/目錄下的所有.conf配置文件。
}

重啟nginx測(cè)試:

接下來(lái)將白名單和黑名單調(diào)換

重啟nginx并測(cè)試

因此:白名單內(nèi)的IP地址不會(huì)匹配到第一個(gè)“流量限制”,而是會(huì)匹配到第二個(gè)req_zone_wl,并且被限制到每秒15個(gè)請(qǐng)求。不在白名單內(nèi)的IP地址兩個(gè)限制能匹配到,所以應(yīng)用限制更強(qiáng)的那個(gè):每秒5個(gè)請(qǐng)求是正確的。

6、配置流量控制相關(guān)功能

1、配置日志記錄

默認(rèn)情況下,Nginx會(huì)在日志中記錄由于流量限制而延遲或丟棄的請(qǐng)求,如下所示:

2024/06/20 20:20:00 [error] 120315#0: *32086 limiting requests, excess: 1.000 by zone "mylimit", client: 192.168.226.20, server: nginx.com, request: "GET / HTTP/1.0", host: "nginx.com"

日志條目中包含的字段:

  • limiting requests - 表明日志條目記錄的是被“流量限制”請(qǐng)求

  • excess - 每毫秒超過(guò)對(duì)應(yīng)“流量限制”配置的請(qǐng)求數(shù)量

  • zone - 定義實(shí)施“流量限制”的區(qū)域

  • client - 發(fā)起請(qǐng)求的客戶端IP地址

  • server - 服務(wù)器IP地址或主機(jī)名

  • request - 客戶端發(fā)起的實(shí)際HTTP請(qǐng)求

  • host - HTTP報(bào)頭中host的值

Nginx 的 limit_req_log_level 指令用于定義當(dāng)請(qǐng)求速率超出 limit_req 指定的速率限制時(shí),日志記錄的級(jí)別。這允許你對(duì)因超出請(qǐng)求速率限制而被延遲或拒絕的請(qǐng)求進(jìn)行特定級(jí)別的日志記錄,從而能夠更靈活地處理這些日志信息,而不必改變?nèi)值腻e(cuò)誤日志級(jí)別。

limit_req_log_level 指令支持的日志級(jí)別包括:

  • info: 記錄基礎(chǔ)信息,這是默認(rèn)設(shè)置。
  • notice: 記錄正常但重要的情況。
  • warn: 記錄更嚴(yán)重的警告信息。
  • error: 記錄錯(cuò)誤信息,這個(gè)設(shè)置通常用于希望對(duì)超限請(qǐng)求進(jìn)行更加突出顯示的場(chǎng)景。

默認(rèn)情況下,Nginx以error級(jí)別來(lái)記錄被拒絕的請(qǐng)求,如上面示例中的[error]所示(Ngin以較低級(jí)別記錄延時(shí)請(qǐng)求,一般是info級(jí)別)。如要更改Nginx的日志記錄級(jí)別,需要使用limit_req_log_level指令。這里,我將被拒絕請(qǐng)求的日志記錄級(jí)別設(shè)置為warn

limit_req_zone $binary_remote_addr zone=myzone:10m rate=1r/s;

server {
    location / {
        limit_req zone=myzone burst=5 nodelay;
        limit_req_log_level warn;
        ...
    }
}

在上面的例子中,limit_req_zone 指令定義了一個(gè)名為 myzone 的速率限制區(qū)域,限制速率為每秒1個(gè)請(qǐng)求。在 server 塊的 location 部分,通過(guò) limit_req 應(yīng)用了這個(gè)速率限制,并且設(shè)置了 burst 參數(shù)為5,表示允許短時(shí)間內(nèi)超出速率限制的請(qǐng)求在不被立即拒絕的情況下排隊(duì)等待處理。更重要的是,通過(guò) limit_req_log_level warn 指令,指定了當(dāng)請(qǐng)求被延遲或拒絕時(shí),這些事件將以 warn 級(jí)別記錄在日志中。這意味著只有當(dāng)請(qǐng)求因?yàn)槌鏊俾氏拗贫谎舆t或拒絕時(shí),才會(huì)在日志中以警告級(jí)別記錄,從而使這類事件在日志文件中更加突出,便于管理員進(jìn)行分析和監(jiān)控。

擴(kuò)展日志記錄級(jí)別:

注意區(qū)別這兩個(gè)日志對(duì)應(yīng)的層級(jí)關(guān)系和定義

Nginx 的日志記錄級(jí)別用于控制日志中記錄信息的詳細(xì)程度。在 Nginx 中,你可以為錯(cuò)誤日志(error_log 指令)設(shè)置不同的日志級(jí)別,這些級(jí)別從最低到最高包括:

  • debug: 提供最詳盡的日志信息,包括調(diào)試信息。這個(gè)級(jí)別記錄所有的詳細(xì)操作,對(duì)于開(kāi)發(fā)或調(diào)試非常有用,但在生產(chǎn)環(huán)境中會(huì)生成大量日志信息。

  • info: 記錄基礎(chǔ)的信息性消息,除了 debug 級(jí)別的信息。

  • notice: 記錄正常但重要的條件。默認(rèn)級(jí)別,標(biāo)準(zhǔn)的錯(cuò)誤和重要信息都會(huì)被記錄。

  • warn: 記錄警告信息,例如使用了非標(biāo)準(zhǔn)的配置指令或者有潛在的錯(cuò)誤。

  • error: 記錄處理請(qǐng)求時(shí)發(fā)生的錯(cuò)誤,但不會(huì)阻止服務(wù)運(yùn)行的錯(cuò)誤信息。

  • crit: 記錄臨界條件錯(cuò)誤,比如嚴(yán)重的硬件或軟件錯(cuò)誤。

  • alert: 要求立即采取行動(dòng)的情況,如系統(tǒng)運(yùn)行環(huán)境出現(xiàn)了非常嚴(yán)重的問(wèn)題。

  • emerg: 記錄緊急情況,如系統(tǒng)不可用的情況。

配置錯(cuò)誤日志級(jí)別的語(yǔ)法如下:

error_log  /path/to/your/error.log  level;

這里,/path/to/your/error.log 是想要保存錯(cuò)誤日志的文件路徑,level 是上面提到的日志級(jí)別之一。如果不指定級(jí)別,error 級(jí)別會(huì)被使用。

在配置日志時(shí),選擇適當(dāng)?shù)娜罩炯?jí)別對(duì)于優(yōu)化性能和管理日志文件大小很重要。例如,在開(kāi)發(fā)環(huán)境中,可能會(huì)使用 debug 級(jí)別以便獲取盡可能多的信息來(lái)調(diào)試應(yīng)用。然而,在生產(chǎn)環(huán)境中,可能會(huì)選擇 notice 或 warn 級(jí)別,來(lái)減少日志文件的大小并關(guān)注更重要的系統(tǒng)消息。

2、發(fā)送到客戶端的錯(cuò)誤代碼

一般情況下,客戶端超過(guò)配置的流量限制時(shí),Nginx響應(yīng)狀態(tài)碼為503(Service Temporarily Unavailable)??梢允褂?code>limit_req_status指令來(lái)設(shè)置為其它狀態(tài)碼(例如下面的412狀態(tài)碼):

可選擇范圍大約在400-599之間,并盡量避免與已存在的狀態(tài)碼產(chǎn)生沖突,造成歧義。 

續(xù)接上面的配置,只需要在server模塊中的location模塊中加入一個(gè)參數(shù)為

limit_req_status 412;

添加的位置如圖說(shuō)式:

重啟nginx

systemctl restart nginx

測(cè)試查看:

這里是因?yàn)槲业膅o代碼的bug顯示黃色,因?yàn)閾Q了裝填嗎顯示成失敗對(duì)應(yīng)的紅色,但其實(shí)已經(jīng)從默認(rèn)的503狀態(tài)碼切換到指定的412狀態(tài)碼了。

7、nginx 流量控制總結(jié)

以上已經(jīng)涵蓋了Nginx和Nginx Plus提供的“流量限制”的很多功能,包括為HTTP請(qǐng)求的不同loation設(shè)置請(qǐng)求速率,給“流量限制”配置burstnodelay參數(shù)。還涵蓋了針對(duì)客戶端IP地址的白名單和黑名單應(yīng)用不同“流量限制”的高級(jí)配置,闡述了如何去日志記錄被拒絕和延時(shí)的請(qǐng)求。

到此這篇關(guān)于Nginx流量控制實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Nginx流量控制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • nginx刷新頁(yè)面出現(xiàn)404解決方案(親測(cè)有效)

    nginx刷新頁(yè)面出現(xiàn)404解決方案(親測(cè)有效)

    本文主要介紹了nginx刷新頁(yè)面出現(xiàn)404解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 使用Nginx、Nginx Plus抵御DDOS攻擊的方法

    使用Nginx、Nginx Plus抵御DDOS攻擊的方法

    DDOS 是一種通過(guò)大流量的請(qǐng)求對(duì)目標(biāo)進(jìn)行轟炸式訪問(wèn),導(dǎo)致提供服務(wù)的服務(wù)器資源耗盡進(jìn)而無(wú)法繼續(xù)提供服務(wù)的攻擊手段。這篇文章主要介紹了使用Nginx、Nginx Plus抵御DDOS攻擊的方法,感興趣的小伙伴們可以參考一下
    2018-06-06
  • linux下Nginx 0.8.40的安裝方法

    linux下Nginx 0.8.40的安裝方法

    這篇文章主要介紹了linux下Nginx 0.8.40的安裝方法,需要的朋友可以參考下
    2014-11-11
  • 詳解Nginx如何處理WebSocket連接

    詳解Nginx如何處理WebSocket連接

    在當(dāng)今互聯(lián)網(wǎng)的世界中,實(shí)時(shí)通信變得越來(lái)越重要,WebSocket 作為一種實(shí)現(xiàn)實(shí)時(shí)雙向通信的技術(shù),正被廣泛應(yīng)用于各種場(chǎng)景,而 Nginx 作為一款高性能的 Web 服務(wù)器和反向代理服務(wù)器,在處理 WebSocket 連接方面也有著出色的表現(xiàn),本文介紹了Nginx如何處理WebSocket連接
    2024-07-07
  • Nginx使用Gzip算法對(duì)報(bào)文進(jìn)行壓縮詳解

    Nginx使用Gzip算法對(duì)報(bào)文進(jìn)行壓縮詳解

    這篇文章主要給大家介紹了關(guān)于Nginx的Gzip功能的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Nginx具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • 詳解Nginx中的Rewrite的重定向配置與實(shí)踐

    詳解Nginx中的Rewrite的重定向配置與實(shí)踐

    這篇文章主要介紹了詳解Nginx中的Rewrite的重定向配置與實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • nginx啟動(dòng)、關(guān)閉及重啟等簡(jiǎn)單命令小結(jié)

    nginx啟動(dòng)、關(guān)閉及重啟等簡(jiǎn)單命令小結(jié)

    這篇文章主要介紹了使用命令行重啟Nginx的方法,包括修改配置文件后重啟以使更改生效,查看端口占用情況,以及如何關(guān)閉Nginx,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-03-03
  • nginx修改server信息的方法詳解

    nginx修改server信息的方法詳解

    請(qǐng)求響應(yīng)信息會(huì)暴露nginx版本信息,若攻擊者獲知服務(wù)器組件等信息及版本信息,會(huì)使下一步的攻擊和漏洞測(cè)試提供便利,所以本文給大家介紹了nginx修改server信息的方法,需要的朋友可以參考下
    2025-02-02
  • 基于Nginx禁止指定IP、國(guó)外IP訪問(wèn)我的網(wǎng)站

    基于Nginx禁止指定IP、國(guó)外IP訪問(wèn)我的網(wǎng)站

    這篇文章主要介紹了用Nginx禁止指定IP、國(guó)外IP訪問(wèn)我的網(wǎng)站,想要實(shí)現(xiàn)這個(gè)功能方法有很多種,這里基于 Nginx 的 ngx_http_geoip2 模塊來(lái)禁止國(guó)外 IP 訪問(wèn)網(wǎng)站,需要的朋友可以參考下
    2022-05-05
  • Nginx解決history模式下頁(yè)面刷新404問(wèn)題示例

    Nginx解決history模式下頁(yè)面刷新404問(wèn)題示例

    這篇文章主要為大家介紹了Nginx解決history模式下頁(yè)面刷新404問(wèn)題示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10

最新評(píng)論