7. DoS 拒絕服務攻擊
7-1 什麽是 DoS 拒絕服務攻擊
想像你今天開一間書店,惡意的對手找了跑腿100人在你的店門口只看不買,這一種攻擊就叫做 DoS 拒絕服務攻擊。不像前幾章,駭客的目的是竊取資料或是修改資料,DoS 攻擊的目的是讓你做不成生意,讓你的網站無法服務正常用戶。
攻擊的手法就是暴力,只要不斷地發送 HTTP 請求讓伺服器忙不過來即可。用瀏覽器不斷重新整理太慢了,讓我們安裝一個 wrk,這是一個量測 HTTP 伺服器效能的壓力測試工具:
執行 brew install wrk
執行 wrk -t12 -c400 -d30s http://localhost:3000/products
這會在 30 秒內,同時平行發送 12 個 HTTP 請求,並保持 400 個 HTTP 連線不中斷的速度,進行 http://localhost:3000/products
的壓力測試。
Running 30s test @ http://localhost:3000/products
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 468.83ms 168.30ms 888.55ms 63.89%
Req/Sec 3.12 3.07 10.00 65.31%
50 requests in 30.06s, 1.30MB read
Socket errors: connect 0, read 319, write 0, timeout 14
Non-2xx or 3xx responses: 4
Requests/sec: 1.66
Transfer/sec: 44.25KB
本機跑的 rails server
超不耐打的,這個網站基本上是廢了,你用瀏覽器已經無法正常瀏覽 http://localhost:3000
了。
強烈警告,對自己的網站打叫做”壓力測試”,對別人的網站打可是”干擾他人網路正常功能”,是犯法的行為。請不要以身試法。
7-2 如何防禦?
DoS 其實是不太好防禦的攻擊,因為並不是因為網站有什麽漏洞造成的。大方向只能想辦法去辨識攻擊方的樣態,然後進行封鎖。實務上需要臨場反應,碰到了見招拆招。
封鎖攻擊方的 IP 網路地址是最基本的手法,問題就出在樣態可能很多種,例如 DDoS (分佈式DoS)就是利用很多臺中毒的電腦,同時進行攻擊,那麽來源 IP 就很多,防禦方就不容易判斷哪一些是正常用戶流量、哪一些是惡意的。
在 Rails 中,可以安裝 rack-attack gem,這可以設定當特定 IP 位址就某一段時間記憶體取太多次的話,自動進行封鎖:
不過困難點在於太多次是多少次,設太低會阻擋到正常用戶,例如有些公司組織很可能是很多人共享同一個 IP 位址來上網的,透過 VPN 科學上網的話,來源 IP 也是很多人共享的。但是設太高又沒效果。
編輯 Gemfile
+ gem 'rack-attack'
執行 bundle
編輯 config/application.rb
+ config.middleware.use Rack::Attack
新增 config/initializers/rack-attack.rb
class Rack::Attack
throttle('req/ip', :limit => 180, :period => 1.minutes) do |req|
req.ip
end
### Prevent Brute-Force Login Attacks ###
# The most common brute-force login attack is a brute-force password
# attack where an attacker simply tries a large number of emails and
# passwords to see if any credentials match.
#
# Another common method of attack is to use a swarm of computers with
# different IPs to try brute-forcing a password for a specific account.
# Throttle POST requests to /login by IP address
#
# Key: "rack::attack:#{Time.now.to_i/:period}:logins/ip:#{req.ip}"
throttle('logins/ip', :limit => 5, :period => 20.seconds) do |req|
if req.path == '/users/sign_in' && req.post?
req.ip
end
end
# Throttle POST requests to /login by email param
#
# Key: "rack::attack:#{Time.now.to_i/:period}:logins/email:#{req.email}"
#
# Note: This creates a problem where a malicious user could intentionally
# throttle logins for another user and force their login requests to be
# denied, but that's not very common and shouldn't happen to you. (Knock
# on wood!)
throttle("logins/email", :limit => 5, :period => 20.seconds) do |req|
if req.path == '/users/sign_in' && req.post?
# return the email if present, nil otherwise
req.params['email'].presence
end
end
end
重啟伺服器。以上設定包括:
- 一分鐘內,一個 IP 位址只能存取 180 次
- 針對
/users/sign_in
這個登入網址,20 秒內只能嘗試登入 5 次 - 針對
/users/sign_in
這個網址,同一 email 在 20 秒內只能嘗試登入 5 次
另外可以做的事情就是,改進網站效能:假如你有一個頁面效能很爛,需要跑好幾秒,這麽這就是網站 DoS 的弱點,因為駭客只要去打這個頁面就有最好的攻擊效果。
如果真的面臨大量的 DDoS 攻擊,就不是 Rails 應用層級可以處理得了,必須購買專門的網路防火牆,例如 Cloudflare、Google Cloud Armor、AWS Shield、百度安全、雲盾DDoS高防IP等等雲服務商的產品。