幫你的 S3 Bucket 掛上 Cloudflare CDN
前幾天看到有大大在臉書上分享了一個慘烈的案例。內容是說他的客戶在 GCP (Google Cloud Platform) 上的公開儲存空間被 DDoS 攻擊,上面的某個檔案在兩天內被下載了數億次。因為訪問雲端儲存空間的流量是要計費的,所以即使只有短短兩天,還是產生了高達 1 萬美金的鉅額費用。😳
這樣的案例其實並不是第一次發生,之前 AWS 也發生過類似的事情。基本上所有公有雲的儲存服務都會對訪問的流量計價。也就是說,如果你有一個公開的雲端儲存空間,而且裡面有存放檔案,那麼只要有人想,他就可以讓你的帳單直接爆炸。
AWS 有一個非常離奇的案例。有一位用戶的 S3 Bucket 名稱,恰巧與某款熱門免費工具預設的資料備份 S3 Bucket 名稱相同,結果導致許多使用該工具的人,在未修改預設設定的情況下,會嘗試將資料寫入這位用戶的 S3 Bucket,雖然寫入會因為沒有權限而失敗,但大流量還是讓這位用戶因此收到了高達 1300 美金的帳單。
這件事情最離奇的點,是嘗試對沒有權限的 Bucket 寫入資料是會計價的!目前這個問題已經被 AWS 修復。
那麼有什麼方法可以避免自己的公開儲存空間被 DDoS 呢?案例分享下方的留言,就有不少人提到可以藉由掛上 CDN (Content Delivery Network) 來避免產生巨額費用。不過這個解決辦法可能只適用於佛心廠商 Cloudflare,Cloudflare 的 CDN 服務除了是免費的,還提供對 DDoS 一定的保護,對小網站來說非常夠用。
然而大部分廠商提供的 CDN 服務,例如 AWS Cloudfront 或是 Azure CDN,這些服務也還是要根據流量收費的。所以說如果想要完全避免 DDos 所造成的負面影響,最好的辦法還是課金,除了掛上 CDN,還要搭配 WAF (Application Firewall) 來過濾掉異常的流量。
WAF 對小網站來說,有點殺雞用牛刀了 (還有就是太貴)。如剛剛所說,小網站簡單的掛上 Cloudflare 就行。下面就來簡單的分享如何幫 S3 Bucket 掛上 Cloudflare 的 CDN。
幫你的 S3 Bucket 掛上 Cloudflare CDN
如果想要將你的 S3 Bucket 掛上 CDN,首先你必須要有一個自己的網域,並將這個網域交由 Cloudflare 託管。
以我擁有的 docfunc.com
網域為例,假設我想建立一個 S3 Bucket 用來存放我個人的檔案,可以怎麼做?
首先先到 S3 上面建立一個 Bucket,地區我選在 us-west-2
,名稱我設定為 files.docfunc.com
。
Bucket 的設定記得關閉 Block Public Access settings for this bucket
,讓Bucket 是可以被公開訪問的。
調整完設定後,就可以開始建立 Bucket。需要注意的是,Bucket 建立好之後還不是公開的狀態。我們需要設定 Bucket Policy 來允許所有人訪問。
前往 Bucket 的頁面,找到 Permissions 下的 Bucket Policy 設定,將其修改為以下內容,就可以開放 Bucket 的訪問權限。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAccessFromEveryone",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::files.docfunc.com/*"
}
]
}
修改完 Bucket Policy 後,可以嘗試上傳一個圖片上去,看看能否透過 S3 的網址來訪問剛剛上傳的圖片,此時可以注意一下圖片的 S3 網址長什麼樣子。如果你之前有建立過 Bucket,你應該會注意到這個 S3 網址格式似乎有點特別。
如果你的 Bucket 名稱並不是網域的格式,那麼圖片的 S3 網址應該會長這樣:
https://<BUCKET_NAME>.s3.<AWS_REGION>.amazonaws.com/...
我們剛剛建立的 Bucket 名稱是網域的格式,所以圖片的 S3 網址會長這樣:
https://s3.<AWS_REGION>.amazonaws.com/<BUCKET_NAME>/...
發現差別了嗎?😁
接下來到 Cloudflare 的主控台幫這個 Bucket 掛上 CDN。在 docfunc.com
這個網域底下新增一個名稱為 files.docfunc.com
的 CNAME 記錄,並將其指向 s3.<AWS_REGION>.amazonaws.com
網域。
CNAME 記錄全稱為真實名稱記錄 (Canonical Name Record),用來用於將一個域名映射到另外一個域名 (真實名稱)。
如果你想讓多個域名對應到同一個 IP,CNAME 紀錄會非常方便。
假設你想讓
blog.example.com
與www.example.com
都指向example.com
背後對應的 IP,那麼就可以在blog.example.com
與www.example.com
上面新增一個 CNAME 紀錄指向example.com
。如果 IP 需要更動,那麼只需要修改example.com
的 A 紀錄即可。
注意 CNAME 紀錄的網址必須要與 Bucket 名稱完全相同。
設定好 CNAME 紀錄之後,嘗試用 files.docfunc.com
這個網域訪問剛剛的圖片。如果你成功看到圖片,就代表你已經成功的幫 S3 Bucket 掛上 Cloudflare 的 CDN了!
等一下!還沒結束!
原本 S3 的網址,此時還是可以訪問的。如果 DDoS 攻擊還是走你原本 S3 的網址,那麼掛上 CDN 也沒用。因此我們要修改 Bucket Policy,只允許 Cloudflare 的 IP 能夠訪問你的 Bucket。
修改一下 Bucket Policy,使用 Condition
來限制來源 IP。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAccessFromCloudflare",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::files.docfunc.com/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"2400:cb00::/32",
"2606:4700::/32",
"2803:f800::/32",
"...以下省略其他 IPv6 CIDR",
"173.245.48.0/20",
"103.21.244.0/22",
"103.22.200.0/22",
"...以下省略其他 IPv4 CIDR"
]
}
}
}
]
}
修改完 Bucket Policy 後再次訪問原本 S3 的網址,就會看到訪問被阻擋了。
除了掛上 Cloudflare CDN,同時也建議開啟預算告警 (Budget Alert)。當費用超過預先設定的預算上限時,可以讓雲端廠商寄信通知我們,好讓我們在第一時間反應。