Linux

NGINX 網頁伺服器防禦 DDoS 阻斷服務攻擊設定教學與範例

介紹如何設定 NGINX 網頁伺服器組態,防範 DDoS 阻斷服務攻擊。

DDoS 阻斷服務攻擊是一種網路攻擊手法,透過大量的網路連線與請求,使伺服器的網路或系統資源耗盡,讓服務暫時中斷或停止,導致正常使用者無法正常存取伺服器上的服務。

應用層 DDoS 攻擊特徵

OSI 第七層應用層的 DDoS 攻擊通常都是由特別設計過的程式,對特定的系統所發動的,例如讓程式同時建立大量的連線,讓伺服器的連線數量達到上限,無法接受後來正常的連線。

這類 DDoS 攻擊的連線通常會有以下幾種特徵,了解這些特徵對於 DDoS 的防禦工作會有幫助:

  • 大量的連線來自於少量固定的 IP 位址(也就是攻擊者的機器)。
  • 由於攻擊的連線是由程式所製造的,目的在於癱瘓伺服器,所以其連線的頻率會遠高於正常連線的頻率。
  • HTTP 的 User-Agent 標頭內容可能會是非標準的值。
  • HTTP 的 Referer 標頭內容可能會非常可疑。

限制請求頻率

NGINX 伺服器可以限制特定網址的請求發送頻率,例如對於每個 IP 位址在存取 /login.html 的時候,限制每分鐘只能送出 30 個請求,也就是說每個請求之間至少間隔 2 秒:

# 定義一個名稱為 one 的 zone,儲存使用者 IP 位址,限制請求頻率為每分鐘 30 次
limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;

server {
  location /login.html {
    # 以 zone 限制請求頻率
    limit_req zone=one;
  }
}

在這段設定中,limit_req_zone 建立一個名稱為 one 的共享記憶體空間(zone),用來儲存指定的鍵值(key),在這個例子中鍵值就是使用者的 IP 位址($binary_remote_addr),而在 /login.html 的設定中則使用 limit_req 引用這個 zone 來限制請求頻率。

限制連線數

NGINX 伺服器也可以限制每個 IP 位址可建立連線數量的上限值,避免攻擊程式占用大量的網路連線,例如限制每個 IP 位址在存取 /store/ 之下的資料時,最多只能建立 10 條連線:

# 定義一個名稱為 addr 的 zone,儲存使用者 IP 位址
limit_conn_zone $binary_remote_addr zone=addr:10m;

server {
  location /store/ {
    # 限制同時連線數上限值為 10
    limit_conn addr 10;
  }
}

這裡的 limit_conn_zone 會建立一個名稱為 addr 的 zone,儲存使用者的 IP 位址,而 limit_conn 則會依據 addr 中的 IP 位址資料,限制每個 IP 位址最多只能同時建立 10 連線。

關閉太慢的連線

有些正常連線在主要資料傳輸完畢之後,還是依然繼續保持連線狀態,攻擊者可以利用這種方式保持大量閒置的連線,讓伺服器滿載。

client_body_timeoutclient_header_timeout 可以用來設定 NGINX 伺服器寫入網頁資料與標頭的最長間隔時間,這兩個設定的預設值都是 60 秒,以下設定可以將此兩個值改為 10 秒,也就是當等待 10 秒沒有寫入資料時,讓 NGINX 伺服器中斷該連線:

server {
  # 設定網頁內容寫入間隔上限值
  client_body_timeout 10s;

  # 設定網頁標頭寫入間隔上限值
  client_header_timeout 10s;
}

IP 位址黑名單

如果我們可以確認出攻擊者的 IP 位址,可以直接透過 NGINX 的 IP 位址黑名單功能,阻擋這些來源的 IP 位址。例如阻擋 123.123.123.1123.123.123.16 這段區間的 IP 位址:

location / {
  # 阻擋指定 IP 網段
  deny 123.123.123.0/28;
}

也可以個別指定每一個要阻擋的來源 IP 位址:

location / {
  # 個別指定 IP 位址黑名單
  deny 123.123.123.3;
  deny 123.123.123.5;
  deny 123.123.123.7;
}

IP 位址白名單

如果我們的 NGINX 伺服器只開放給特定 IP 網段的使用者存取,可以先以 allow 設定允許存取的來源 IP 位址,再加上 deny all 封鎖其他不在白名單內的 IP 位址:

location / {
  # 設定允許連線的來源 IP 位址
  allow 192.168.1.0/24;

  # 阻擋其他不在白名單內的 IP 位址
  deny all;
}

Proxy 設定

若有使用 ngx_http_proxy_module,可以考慮將 proxy_cache_use_stale 設定為 updating,可讓資料在更新的時候,不要重複送出更新的請求。

另外亦可注意在設定 proxy_cache_key 的時候,不要將 $query_string 納入其中,以免攻擊者送出亂數的 $query_string 導致快取塞爆快取空間。

阻擋特定的請求

如果攻擊者對特定的網頁發動攻擊,我們可以暫時阻擋特定網頁的請求:

# 阻擋特定網頁的所有請求
location /foo.php {
  deny all;
}

如果發現攻擊的請求中,User-Agent 都呈現奇怪的內容,也可以依據 User-Agent 將含有特定字眼的請求阻擋掉:

location / {
  # 阻擋 User-Agent 含有 foo 或 bar 的請求
  if ($http_user_agent ~* foo|bar) {
    return 403;
  }
}

在 NGINX 設定檔中,我們可以透過 http_ 加上 HTTP 的標頭名稱來取用對應的 HTTP 標頭資訊,例如 $http_user_agent 就是 User-Agent 的資訊,透過這樣的方式,我們可以使用任意的 HTTP 標頭資訊來篩選請求。

參考資料

Share
Published by
Office Guide
Tags: 資訊安全

Recent Posts

Python 使用 PyAutoGUI 自動操作滑鼠與鍵盤

本篇介紹如何在 Python ...

1 年 ago

Ubuntu Linux 以 WireGuard 架設 VPN 伺服器教學與範例

本篇介紹如何在 Ubuntu ...

1 年 ago

Linux 網路設定 ip 指令用法教學與範例

本篇介紹如何在 Linux 系...

1 年 ago

Linux 以 Cryptsetup、LUKS 加密 USB 隨身碟教學與範例

介紹如何在 Linux 系統中...

1 年 ago