Amazon S3 改變 403 的收費方式

這算是一連串的故事,首先是四月底的時候「How an empty S3 bucket can make your AWS bill explode」這篇,提到了他一個晚上收到了 US$1,300 的帳單,因為有人 (沒有權限的人) 對他的 S3 bucket 狂打了 100M requests (一億筆),雖然都是 403 的 access denied,但還是得付 request 與頻寬的費用。

對於想要搞的人來說,us-east-1 的 Amazon S3 費用是 $0.005/1K requests (PUT, COPY, POST, LIST requests),換算大一點的單位是 $5/1M requests,拿個 ab 之類的工具超級簡單就可以打出破千 reqs/sec,如果是 k6 之類的工具,其實一台電腦就蠻容易打爆?

作者聯絡 AWS 客服後,客服回答你需要付這筆費用 (「這不是 bug,是 feature」):

Yes, S3 charges for unauthorized requests (4xx) as well[1]. That’s expected behavior.

然後這件事情就在社群傳開了,傳到 Jeff Barr 後直接公開提到他認為客戶不應該付 unauthorized request 的 cost (應該是先跟內部其他高層討論過了),等於是宣佈了會改掉:

不過這件事情之前應該就有人提過了,結果 Colin Percival 直接戳,他在 2006 年 Amazon S3 剛出來的時候就提過了:

Anyway,兩個禮拜過去後,剛剛看到宣佈收費方式修改:「Amazon S3 will no longer charge for several HTTP error codes」。

針對從不屬於自己帳號所產生的 403 不收費 (包括 request 與頻寬費用):

With this change, bucket owners will never incur request or bandwidth charges for requests that return an HTTP 403 (Access Denied) error response if initiated from outside their individual AWS account or AWS Organization.

然後多了一頁「Billing for Amazon S3 error responses」專門說明這件事情,這邊列的比較完整,除了 403 以外也包含了其他的 HTTP response code 是不收費的:

The current page shows a full list of HTTP 3XX and 4XX status codes that won't be billed.

補了一個 18 年的洞...

Route 53 Resolver DNS Firewall 的 chain 處理

在「Stop the CNAME chain struggle: Simplified management with Route 53 Resolver DNS Firewall」這邊看到的新功能。

說實話... 我早就忘記 Route 53 Resolver DNS Firewall 這個產品了,我查資料才發現我在 2021 年的時候寫過:「AWS 推出 Amazon Route 53 Resolver DNS Firewall」。

這個產品的用途是避免透過 DNS 將敏感資訊打出去,不過先前的產品的條件很死,遇到 CNAME 或是 DNAME 的情況,你必須事先把可能後續的 record 也放進白名單才行,所以如果遇到類似於 X (Twitter) 用的 的情況就很麻煩了:

;; ANSWER SECTION:          300     IN      CNAME 3409 IN      CNAME 110 IN CNAME 110  IN      CNAME 725   IN      A

理想上是你放行 就好,但因為 CNAME 的關係,你可能會需要多放行 * 以及 *

可是這是第三方的服務,你無法控制對方怎麼切換 (沒有 API contract 的概念),像是有時候他會跳到 Fastly

;; ANSWER SECTION:          290     IN      CNAME 290 IN A

如果之後又跑出 Akamai 或是 CloudFront 的話就沒完沒了。

另外一種常見的情況是第三方的 API endpoint,對方有可能有多個不同的點做 DR 切換,有可能 CNAME 到 AWSELB 或是 GCPCloud Load balancing 上。

所以為了「保險」,這個方式通常都是開整個 CDN 的服務,但這麼一來攻擊者可以透過租用這些服務 (像是 *,搭配一些其他比較鬆的 rule 鑽出來。

這次的這個功能有點 stateful firewall 的概念,第一個啟動的 record 是被放行的,那 CNAME 或是 DNAME 延伸出來的 record 也跟著放行,這樣算是補強了這個問題...


看到 AWS KMS 的公告:「AWS KMS announces more flexible automatic key rotation」。

第一個是增加了 rotation 的彈性,可以設定日期,不過 7 years (2560 days) 是怎麼算出來的?(某種風險公式?):

You can now customize the frequency of rotation period between 90 days to 7 years (2560 days) as well as invoke key rotation on demand for customer managed KMS keys.

另外一個是降價,看起來是 rotate 第三次以後就不收費?對於有在 rotation 的單位來說是個降價... (如果沒在 rotate 的就 XDDD)

We’re also introducing new pricing for KMS automatic key rotation. Previously, each rotation of a KMS key added $1/month per rotation to a KMS customer managed key. Now, for KMS keys that you rotate automatically or on demand, the first and second rotation of the key adds $1/month (prorated hourly) in cost, but this price increase is capped at the second rotation, and all rotations after your second rotation are not billed. For customers that have keys with 3 or more rotations, all of these keys will see a price reduction to $3/month (prorated) starting the first week of May 2024.

這也算是鼓勵拉高 rotation 的次數吧?

AWS Lambda 的 cache 架構

Lobsters 上看到的老文章:「[Cache Architecture for] Container Loading in AWS Lambda」,原文從 url 看起來是去年五月發表的資訊了:「Container Loading in AWS Lambda」。

主要是在講 container 怎麼 load 才會儘快執行,首先是提到了大家常用的 layer cache,在 AWS Lambda 上則是改用了 block level cache:

Most of the existing systems do this at the layer or file level, but we chose to do it at the block level.

然後每一塊 512KB:

We unpack a snapshot (deterministically, which turns out to be tricky) into a single flat filesystem, then break that filesystem up into 512KiB chunks.

接著是提到 lazy load 的方式:「Slacker: Fast Distribution with Lazy Docker Containers」:

Our analysis shows that pulling packages accounts for 76% of container start time, but only 6.4% of that data is read.

Slacker speeds up the median container development cycle by 20x and deployment cycle by 5x.

而這個技巧也被用在 AWS Lambda 上,而且是透過 FUSE 實作:

In Lambda, we did this by taking advantage of the layer of abstraction that Firecracker provides us. Linux has a useful feature called FUSE provides an interface that allows writing filesystems in userspace (instead of kernel space, which is harder to work in).

另外一個 AWS Lambda 有實作的是 tiered caching,分成三層,包括了 worker 的 local cache (L1)、同一個 AZ 上的 cache (L2) 以及 S3 上的資料 (L3):

Despite our local on-worker (L1) cache being several orders of magnitude smaller than the AZ-level cache (L2) and that being much smaller than the full data set in S3 (L3), we still get 67% of chunks from the local cache, 32% from the AZ level, and less than 0.1% from S3.

也因為 L3 cache 是 S3 的關係,他們在 L1 與 L2 上就不用擔心 durability 的問題 (反正不見了就往後面找):

The whole set of chunks are stored in S3, meaning the cache doesn’t need to provide durability, just low latency.

但還是用了 Erasure code,儘量維持每個 cache tier 在自己 tier 裡面就可以找到資料的機率,這樣可以盡量降低 peak latency (於是造成 99.9%/99.95%/99.99% 的 SLO 不好看?):

Think about what happens in a classic consistent hashed cache with 20 nodes when a node failure happens. Five percent of the data is lost. The hit rate drops to a maximum of 95%, which is a more than 5x increase in misses given that our normal hit rate is over 99%. At large scale machines fail all the time, and we don’t want big changes in behavior when that happens.

So we use a technique called erasure coding to completely avoid the impact. In erasure coding, we break each chunk up into M parts in a way that it can be recreated from any k. As long as M - k >= 1 we can survive the failure of any node with zero hit rate impact (because the other k nodes will pick up the slack).

大概是本來比較簡單的三層架構在 benchmark 後發現無法達成對應的 SLO,所以就「補上」erasure code 拉高 SLO,從這邊就可以感覺到老闆的要求對於架構設計上的影響...


CloudFront 端出 Embedded Points of Presence

看到 CloudFront 的產品新聞稿:「Amazon CloudFront announces availability of Embedded Points of Presence」,AWS 在 CloudFront 上端出了 Embedded Points of Presence 服務,看名字就是更彈性的 CDN PoP,不過想知道更細節的東西得去看 FAQs 的部分...

從這段可以看到應該是 AWS 的 appliance,然後放到實體機房裡面提供服務:

These embedded POPs are owned and operated by Amazon and deployed in the last mile of the ISP/MNO networks to avoid capacity bottlenecks in congested networks that connect end viewers to content sources, improving performance.


Q. Is there a separate charge for using embedded POPs?
No, there is no additional charge for using CloudFront embedded POPs.

另外這個服務會是 opt-in 選擇加入,但不需要額外設定 distribution,而且 CloudFront 會針對有 opt-in 的 distribution 自動混搭:

Embedded POPs are an opt-in capability intended for the delivery of large scale cacheable traffic. Please contact your AWS sales representative to evaluate if embedded POPs are suitable for your workloads.

No, you do not need to create a new distribution specifically for embedded POPs. If your workload is eligible, CloudFront will enable embedded POPs for your existing distribution upon request.

You don't have to choose between CloudFront embedded POPs or CloudFront POPs for content delivery. Once your CloudFront distribution is enabled for embedded POPs, CloudFront's routing system dynamically utilizes both CloudFront POPs and embedded POPs to deliver content, ensuring optimal performance for end users.

下一章「Compliance」的部分有提到 embedded POPs 是不包括在 PCI DSSHIPAA 以及 SOC 這些 compliance 的,所以也可以回頭看到在提到推薦掛上來的內容,有避開掉敏感服務,主要是以大家都會看到一樣的內容的東西為主:

Embedded POPs are custom built to deliver large scale live-streaming events, video-on-demand (VOD), and game downloads.

看起來有點像是 NetflixOpen Connect 或是 GoogleGGC,讓 ISP 或是 MNO 可以放 cache service 降低對外消耗的流量。

這應該會回到老問題,ISP/MNO 當然是希望 CloudFront 花錢放機器進來,不會是 ISP/MNO 自己申請放,這不是技術問題而是商業問題...


在「Cloud Egress Costs (」這邊看到的文章,原文在「Cloud Egress Costs」這邊,主要是整理了表格出來可以快速了解不同雲端的流量費用差異,裡面不是單純 VPS 比較,而是各類的服務都拿出來比,像是 storage 類的以及 CDN 類的都有放進來...

Backblaze 的頻寬費用算法頗有趣,每個月給資料量的三倍大小當作免費頻寬,沒記錯的話因為 Cloudflare 是 Backblaze 的 partner,兩邊的傳輸費用不計費,如果資料是可以公開的,可以透過這個方式接出來;如果真的得走一般的流量輸出,收費是 US$0.01/GB (所以換算後是 US$10/TB)。

三家常被擺在一起的 VPS (LinodeDigitalOceanVultr) 的頻寬也都是 US$10/TB。

以前沒注意到的是 OVH CloudScaleway 的頻寬費用居然是免費的?另外 Hetzner 雖然要收費但也很低?有機會好像該玩看看,看一下品質如何?

停止使用 Spamhaus DNSBL

剛剛看到「If you query Spamhaus Projects’ legacy DNSBLs via DigitalOcean move to the free Data Query Service」這篇,覺得愈來愈詭異了,研究了目前的情況後決定停用 Spamhaus

現在已經愈來愈少自己架設 mail server 了,不過我自己還是留了幾個 domain 跑在自己架設的 Postfix 上面,最主要是 command line 下面用 Mutt 讀信還是蠻方便的,另外一方面是確保一個信箱是不受到大企業的管制。

如果不是拿套裝軟體直接架設的話,自己架設 mail server 會有不少東西要設定:在 MTA 這端通常會使用 DNSBL 擋掉已知會發 spam 的 IP address。

DNSBL 的原理不難,就是拿 IPv4 address 組合一個 hostname,透過 DNS 查詢就會知道這個 IPv4 address 是否在清單;換句話說,就是拿 DNS protocol 當作 API,當作資料庫查詢。

舉個例子來說,假設我要查 這個位置的情況 (從「Worst /24 blocks based on total spam count」這邊翻出來的),這邊使用 SpamCop 的清單,我先把 IPv4 address 反過來變成,然後再加上 SpamCop 所指定的,變成,接下來查詢就可以查到: has address

如果是 的話,同樣方法組合成 可以看到沒有在 SpamCop 清單內:

Host not found: 3(NXDOMAIN)

這邊選擇用 DNS 的好處包括了 DNS resolver 及 DNS library 自然的 cache,不需要 Postfix 這類 MTA 再自己實作 cache 層,對於有大量信件 (無論是正常的或是 spam) 進來的時候也不會造成提供清單的服務大量的負載。

回頭來說 Spamhaus 的情況,他們公告要擋 DigitalOcean 的理由很奇怪,因為 DigitalOcean 架設了自己的 mirror 所以他們不知道使用的量,要使用者去 Spamhaus 上註冊申請後拿到一個自己的 使用。

有了 unique key 在 query,這樣就給了 Spamhaus 很清晰追蹤資料,加上 Privacy Policy 裡面的資訊:

We may have to share your personal data with the parties set out below for the purposes set out in the table in paragraph 4.
– Third parties to whom we may choose to sell, transfer, or merge parts of our business or our assets. Alternatively, we may seek to acquire other businesses or merge with them. If a change happens to our business, then the new owners may use your personal data in the same way as set out in this privacy notice.


另外一方面,查資料的時候發現他們已經擋掉 Google Public DNS 以及 Cloudflare DNS

這是我自己架設 Unbound 的查詢:

gslin@home [~] [05:09/W4] host has address has address has address

這是 Google Public DNS (

gslin@home [~] [05:09/W4] host
Using domain server:

Host not found: 3(NXDOMAIN)

這是 Cloudflare DNS (

gslin@home [~] [05:09/W4] host
Using domain server:
Aliases: has address

在 Spamhaus 的「Frequently Asked Questions (FAQ)」這篇裡面有提到 的回應是「Query via public/open resolver」:	Any	Typing error in DNSBL name	Any	Query via public/open resolver	Any	Excessive number of queries


換成 t4g.small 後的一些整理

昨天在這邊提到因為 Amazon EC2t4g.small 提供了 free tier 方案 (到今年年底),blog 主機剛好從 t4g.micro 改成用 t4g.small,到年底前可以看看有沒有 t5g 或是類似的主機出來:「往上升級或是用 Unlimited mode 撐」。

除了換完後 CPU credit 給的量上升減緩了情況以外,我在檢查時才發現 PHPopcache 的 cache 使用量也超過預設值 128MB 了,改成 192MB 後看起來 CPU usage 也有下降一些:

這點算是先前沒注意到的,上面 PHP 跑兩個 WordPress 以及一個 MediaWiki (都掛了各式各樣的 plugin & extension),還有一個自己寫的小東西,這樣會超過 opcache 的 cache 大小...

現在換到 t4g.small 後總算又開始養的起 CPU credit 了:

另外也補上幾個 CloudWatch Alarms (看起來 free tier 是十個) 監控主機的 CPUCreditBalance,然後透過 AWS Chatbot 接到自己的 Slack 上,至少之後有狀況的時候會主動通知。

往上升級或是用 Unlimited mode 撐

這個 blog 跑在 Amazon EC2t4g.micro 上面,以往跑起來 baseline 是 10% CPU credit 也還算夠用,但最近的 loading 特別的大,發現是有 bot 在砍站砍的比較兇 (參考「t4g 的 CPU credit 被吃完了」這邊),雖然擋掉後有降不少,但看起來還是比之前高不少:(這邊是一天的平均,拉三個月資料來看)

以往這種一陣一陣的可以靠 CPU credit 頂過去,但因為先前 CPU credit 被 bot 砍完後沒了,就常常撞到底,只好先開 Unlimited mode 擋著了。

另外一方面,當初買的三年 RI 時間也快到了 (居然),這幾天差不多要處理了:

February 9, 2021, 17:43 (UTC+8:00)

February 9, 2024, 17:43 (UTC+8:00)

升級到 t4g.small 剛好會符合 AWS 的免費方案,看起來可以先掙扎一陣子:

Until December 31, 2024, all AWS customers will be enrolled automatically in the T4g free trial as detailed in the AWS Free Tier. During the free-trial period, customers who run a t4g.small instance will automatically get 750 free hours per month deducted from their bill during each month.

我記得我算過但沒找到文章,所以這邊還是算一下... 如果 t4g.small 要錢的話,與 Unlimited mode 的消費差異大概是多少。

us-east-1t4g.small 是 $0.0168/hr,用 720 小時換算是 $12.096/mo。

假設 CPU 使用率平均在 15%,那用 t4g.micro 的 $0.0084/hr 會是 $6.408/mo,另外加上 5% * 2vCPU = 10% 的 Unlimited mode 費用 ($0.04/hr/vCPU),會是 $2.88/mo。

假設 CPU 使用率平均在 20% (剛好跟 t4g.small 的 baseline 相同的話),會是 $5.76/mo,所以如果用不到對應的記憶體的話,跑 Unlimited mode 會比較划算。