分布式拒絕服務攻擊(DDoS)指的是通過多臺機器向一個服務或者網站發送大量看似合法的數據包使其網絡阻塞、資源耗盡從而不能為正常用戶提供正常服務的攻擊手段。隨著互聯網帶寬的增加和相關工具的不斷發布,這種攻擊的實施難度越來越低,有大量IDC托管機房、商業站點、游戲服務商一直飽受DDoS攻擊的困擾,那么如何緩解甚至解決DDoS呢?最近https://www.Nginx.com/blog/author/rick/在Nginx的官方博客上發表了一篇文章,介紹了https://www.nginx.com/blog/mitigating-ddos-attacks-with-nginx-and-nginx-plus/。
Rick Nelson首先介紹了DDoS攻擊的一些特點,例如攻擊的流量通常來源于一些固定的IP地址,每一個IP地址會創建比真實用戶多得多的連接和請求;同時由于流量全部是由機器產生的,其速率要比人類用戶高的多。此外,進行攻擊的機器其User-Agent頭也不是標準的值,Referer頭有時也會被設置成能夠與攻擊關聯起來的值。針對這些特點,Rick Nelson認為Nginx和Nginx Plus有很多能夠通過調節或控制流量來應對或者減輕DDoS攻擊的特性。
限制請求率將Nginx和Nginx Plus可接受的入站請求率限制為某個適合真實用戶的值。例如,通過下面的配置讓一個真正的用戶每兩秒鐘才能訪問一次登錄頁面:
limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m; server { ... location /login.html { limit_req zone=one; ... } }
在該配置中, limit_req_zone指令配置了一個名為 one的共享內存 zone用來存儲$binary_remote_addr的請求狀態,location塊中/login.html的 limit_req指令引用了共享內存zone。
限制連接的數量將某個客戶端IP地址所能打開的連接數限制為真實用戶的合理值。例如,限制每一個IP對網站/store部分打開的連接數不超過10個:
limit_conn_zone $binary_remote_addr zone=addr:10m; server { ... location /store/ { limit_conn addr 10; ... } }
該配置中, limit_conn_zone指令配置了一個名為 addr的共享內存 zone用來存儲 $binary_remote_addr的請求,location塊中/store/的 limit_conn指令引用了共享內存zone,并將最大連接數設置為10.
關閉慢連接關閉那些一直保持打開同時寫數據又特別頻繁的連接,因為它們會降低服務器接受新連接的能力。Slowloris就是這種類型的攻擊。對此,可以通過 client_body_timeout和client_header_timeout指令控制請求體或者請求頭的超時時間,例如,通過下面的配置將等待時間控制在5s之內:
server { client_body_timeout 5s; client_header_timeout 5s; ... }
設置IP黑名單如果能識別攻擊者所使用的客戶端IP地址,那么通過 deny指令將其屏蔽,讓Nginx和Nginx Plus拒絕來自這些地址的連接或請求。例如,通過下面的指令拒絕來自123.123.123.3、123.123.123.5和123.123.123.7的請求:
location / { deny 123.123.123.3; deny 123.123.123.5; deny 123.123.123.7; ... }
設置IP白名單如果允許訪問的IP地址比較固定,那么通過 allow和 deny指令讓網站或者應用程序只接受來自于某個IP地址或者某個IP地址段的請求。例如,通過下面的指令將訪問限制為本地網絡的一個IP段:
location / { allow 192.168.1.0/24; deny all; ... }
通過緩存削減流量峰值通過啟用緩存并設置某些緩存參數讓Nginx和Nginx Plus吸收攻擊所產生的大部分流量峰值。例如,通過 proxy_cache_use_stale指令的 updating參數告訴Nginx何時需要更新過期的緩存對象,避免因重復發送更新請求對后端服務器產生壓力。另外, proxy_cache_key指令定義的鍵通常會包含嵌入的變量,例如默認的鍵 $scheme$proxy_host$request_uri包含了三個變量,如果它包含 $query_string變量,那么攻擊者可以通過發送隨機的 query_string值來耗盡緩存,因此,如果沒有特別原因,不要在該鍵中使用 $query_string變量。
阻塞請求配置Nginx和Nginx Plus阻塞以下類型的請求:
- 以某個特定URL為目標的請求
- User-Agent頭中的值不在正常客戶端范圍之內的請求
- Referer頭中的值能夠與攻擊關聯起來的請求
- 其他頭中存在能夠與攻擊關聯在一起的值的請求
例如,通過下面的配置阻塞以/foo.php為目標的攻擊:
location /foo.php { deny all; }
或者通過下面的配置阻塞已識別出的User-Agent頭的值是foo或者bar的DDoS攻擊:
location / { if ($http_user_agent ~* foo|bar) { return 403; } ... }
限制對后端服務器的連接數通常Nginx和Nginx Plus實例能夠處理比后端服務器多得多的連接數,因此可以通過Nginx Plus限制到每一個后端服務器的連接數。例如,通過下面的配置限制Nginx Plus和每一臺后端服務器之間建立的連接數不多于200個:
upstream website { server 192.168.100.1:80 max_conns=200; server 192.168.100.2:80 max_conns=200; queue 10 timeout=30s; }
另外,Rick Nelson還提到了如何http://nginx.com/blog/nginx-protect-cve-2015-1635/?_ga=1.144784956.967276342.1451228467和http://nginx.com/blog/tuning-nginx/?_ga=1.87178896.967276342.1451228467,以及http://nginx.org/en/docs/http/ngx_http_status_module.html?_ga=1.187642144.967276342.1451228467發現異常的流量模式,定位DDoS攻擊。