經過配置nginx 抵禦不合法請求

##ngx_http_limit_conn_module模塊 使用此模塊主要用來限制每秒請求數量,至於依據什麼條件限制是由咱們來自定義的。 官方文檔 Module ngx_http_limit_req_module 中文翻譯的 nginx限制請求數ngx_http_limit_req_module模塊html

文檔講的很詳細了,大體說下: limit_req_zone $variable zone=name:size rate=rate; 命令的意思是,以$variable變量爲條件,起名爲name,設置的存儲空間大小爲size,設置限定頻率爲rate;node

咱們能夠設置多個,不一樣條件,不一樣名稱,不一樣大小的限制。 這個定義咱們是須要寫在**http配置段中**。 在匹配的location中寫上limit_req zone=name [burst=number] [nodelay];這裏burst就是容許的漏桶數,當請求頻率大於rate可是超出的數量不大於burst設置的數量,則nginx會將超出的請求延遲後面返回。若是請求數量超出burst了,則將超出部分直接返回錯誤碼,默認503。至於nodelay就是設置是否要延遲,有它不超過burst的請求才延遲。 網上大多條件都是$binary_remote_addr,其實咱們能夠根據本身的需求,來定義自身的相應條件,活學活用嘛,下面會有實例。nginx


##ngx_http_limit_conn_module模塊 這個模塊主要限制單獨ip同一時間的鏈接數 官方文檔 Module ngx_http_limit_conn_module。 中文翻譯的 nginx限制鏈接數ngx_http_limit_conn_module模塊服務器

各位看文檔吧,個人實戰中沒有使用此模塊。dom


##實戰階段翻譯

好了,下面進入實戰階段: 首先咱們的初始配置文件時是(不完整):code

http {
    server {
        listen  8080 default_server;
        server_name  localhost:8080;
        
    location ~ .* {
		proxy_pass http://127.0.0.1:8080;
		proxy_set_header X-Real-IP $remote_addr;
	    }
    }
}

咱們的需求是,有一批接口被頻繁的不合法訪問,咱們要作限制。 初版:限制爲1s一次請求,漏桶數爲5。server

http {

    limit_req_zone  $binary_remote_addr  zone=one:10m rate=1r/s;
    server {
        listen  8080 default_server;
        server_name  localhost:8080;
        
    location ~ .* {
		proxy_pass http://127.0.0.1:8080;
		proxy_set_header X-Real-IP $remote_addr;
	    }
	    
	location ^~ /interface {
		limit_req zone=one burst=5 nodelay;
		proxy_pass http://127.0.0.1:8080;
	    }
    }
}

這裏加了proxy_pass http://127.0.0.1:8080;這裏配置了轉發,不然匹配以後會找不到服務器的。htm

可是這樣會有個問題,目前咱們是以ip作的限制,可是有可能網吧或者校內出口就是一個或幾個ip,咱們這樣限制的話會把正經常使用戶也限制到了,得不償失。其實咱們能夠換一種思路來定位到單一用戶,正常一個請求過來,咱們都會設置攜帶一個關於用戶的`token`信息。至於這個`token`是如何生成的,只有服務器知道,那咱們加入咱們的每次請求中,`header`中帶有這個信息,`token`值,若是一個非法的請求可能沒有這個值,即便有這個值咱們也能夠以`token`爲條件來限制,這樣更合理些。

第二版blog

http {

    limit_req_zone  $http_token  zone=two:10m rate=1r/s;
    server {
        listen  8080 default_server;
        server_name  localhost:8080;
        
    location ~ .* {
		proxy_pass http://127.0.0.1:8080;
		proxy_set_header X-Real-IP $remote_addr;
	    }
	    
	location ^~ /interface {
	    if($http_token=""){
	        return 403;
	    }
		limit_req zone=two burst=5 nodelay;
		proxy_pass http://127.0.0.1:8080;
	    }
    }
}

nginx中,使用$http_變量名,取的就是header中相應的變量。

前方預警:我特地在這個配置中留了個坑,若是你像我這樣配置的話,重啓會報一個異常nginx: [emerg] unknown directive "if($http_token" ,很奇怪是不,這個異常我花了很長時間才解決,緣由是if(中間須要個空格,沒錯,就是這個空格花了我好幾個小時,血淚的教訓啊,但願各位不要再重蹈覆轍。 這個問題的解決的文章:Nginx unknown directive 「if($domain」

此次的配置,多少能夠限制住的,對我一個nginx的小白來講,調研一點用一點,也是不錯的。


參考文章: 經過nginx配置文件抵禦攻擊 Nginx配置proxy_pass轉發的/路徑問題 nginx限制請求數ngx_http_limit_req_module模塊 在Nginx中記錄自定義Header

相關文章
相關標籤/搜索