關於Laravel 與 Nginx 限流策略防止惡意請求

1、問題背景

最近公司最近的幾臺線上服務器常常出現CPU覆蓋太高,影響部分應用響應超時,產生了大量的短信和郵件報警,通過排查數據庫日誌和access.log,發現是API接口被刷,被惡意瘋狂請求,最大一次大概120次/s。php

以前沒有過太多這方面經驗,處理起來不是很順暢,此次的問題恰好提了醒,通過此次的問題暴露,來記錄一下解決方案和策略。nginx

線上的部署方案是:nginx + laravel。laravel

首先咱們嘗試從nginx層面入手,將佔用更少的內存消耗,無需再轉發到php-fpm上處理。算法

2、(惡意)請求特徵

想好很好的特徵,就必須捕捉必定的特徵,經過這個特徵來有效的控制到惡意請求。數據庫

  1. 短期內,IP對某接口產生大量請求
  2. user_agent,非正常信息或爲空
  3. 請求量比平時要高漲不少。

3、限流策略(nginx)

限制請求數

首先的話.就是控制單IP時間上的請求次數和IP鏈接數,配置以下:api

http {
    limit_req_zone $binary_remote_addr zone=one:1m rate=1r/s;

    server {
        location /api/ {
            limit_req zone=one burst=5;
        }
    }
}

limit_req_zone主要控制單個IP的請求速率,使用漏桶算法來完成限制,limit_req_zone size,主要用於儲存統計IP的請求信息,1M能夠儲存16000個IP,當每秒的請求超過了16000個的時候,其他訪問都會被訪問503 服務暫不可用。服務器

上面的模板設置了,每秒最大不超過1個請求,最大延遲請求不超過5個。併發

若是咱們的服務器每次接口的響應時間是在200ms-300ms,那咱們對應的每秒的限制就應該設置成 1000ms / 接口響應耗時curl

限制併發鏈接數

限制完用戶請求頻率後,若是仍然仍是存在很大的惡意請求,咱們還能夠進行併發數的限制。php-fpm

http {
    limit_conn_zone $binary_remote_addr zone=one:1m;

    server {
        location /api/ {
           limit_conn one 10;
        }
    }
}

limit_conn_zone:主要是用於控制請求併發數,頻率不能太快。

limit_conn_zone size跟limit_req_zone意思一致,可根據須要動態調控,上面的案例中,表示限制每一個客戶端IP最大併發鏈接數爲10。

設定IP黑名單

當某個IP請求過於頻繁或者須要徹底杜絕該IP的訪問時,能夠經過nginx的deny配置來禁止黑名單中的IP訪問。

http {
    include blockip.conf; 
}

黑名單配置

deny 195.91.112.66;
deny 192.168.2.100;

被添加黑名單後,再次訪問就會出現403禁止訪問.
image

限制UA(user-agent)信息

http {
    server {
        if ($http_user_agent ~* "curl") {
          return 403;
        }
    }
}

上面就禁止了ua信息爲curl的客戶端,直接返回403。

禁止多個ua,經過|來隔斷。

if ($http_user_agent ~* "curl|wget") {
    return 403;
}

(四)、限流策略(laravel)

在咱們的laravel項目中,存在一個Throttle中間件,該策略,能夠在應用層上面,有效抑制用戶能夠惡意請求,配置以下:

Route::group(['middleware' => 'throttle:30:1'],function(){
    Route::any('/login', 'LoginController@login');
});

在throttle配置中,第一個參數控制了請求數,第二個參數用於控制請求頻率,上面的配置代表,每一個客戶端IP每分鐘最大請求30次 login路由。

當客戶端ip超出請求限制後,服務端就會返回429 Too Many Attempts.響應

相關文章
相關標籤/搜索