分布式拒絕服務攻擊(DDoS)指的是通過多台機器向一個服務或者網站發送大量看似合法的資料包使其網絡阻塞、資源耗盡進而不能為正常使用者提供正常服務的攻擊手段。随着網際網路帶寬的增加和相關工具的不斷釋出,這種攻擊的實施難度越來越低,有大量IDC托管機房、商業站點、遊戲服務商一直飽受DDoS攻擊的困擾,那麼如何緩解甚至解決DDoS呢?

分布式拒絕服務攻擊(DDoS)指的是通過多台機器向一個服務或者網站發送大量看似合法的資料包使其網絡阻塞、資源耗盡進而不能為正常使用者提供正常服務的攻擊手段。随着網際網路帶寬的增加和相關工具的不斷釋出,這種攻擊的實施難度越來越低,有大量IDC托管機房、商業站點、遊戲服務商一直飽受DDoS攻擊的困擾,那麼如何緩解甚至解決DDoS呢?最近Rick Nelson在Nginx的官方部落格上發表了一篇文章,介紹了如何通過Nginx和Nginx Plus緩和DDoS攻擊。
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還提到了如何處理基于範圍的攻擊和如何處理高負載的問題,以及如何使用Nginx Plus Status子產品發現異常的流量模式,定位DDoS攻擊。