banner
r3n

r3n

Nothing Nowhere
twitter
discord user

Nohit.cc / DDoS防護的實踐錄

介紹#

Minecraft 伺服器始終面臨 DDoS 攻擊的威脅。本文將基於 2025 年 6 月底結束服務的 DDoS 保護服務「Nohit.cc」約四年的運營經驗,分享我們面臨的挑戰以及為克服這些挑戰所採用的技術變遷。

我本人有大型 Minecraft 伺服器的運營經驗,並以此知識為基礎,與三位學生共同創立了 Nohit.cc。希望這份記錄能對面臨類似挑戰的伺服器管理者和技術人員有所幫助。

保護方式的變遷#

初期構成: HAProxy 和摸索的免費服務 (2021 年)#

服務開始之初,我們在 Oracle Cloud 的免費配額及我們的多餘 VPS 上運行 HAProxy。利用docker kill -s HUP在保持現有連接的情況下重新加載配置,這是一個由高中生自製的驚險系統,通過 PHP 製作的 API 動態地修改設置。用戶從面板中隨機分配端口,並使用 gdnsd 進行圓形輪詢的負載均衡。

然而,由於用戶的急劇增加,這個臨時系統無法穩定運行,加上主要成員之一的離開,導致我們在約半年後暫時休止服務。

技術刷新:轉向 infrared (2021 年 8 月~)#

在服務重新啟動時,我們轉變了方針,從免費提供轉為「用戶共同分擔費用,構建更強大的保護」。系統也進行了更新,將代理軟件從 HAProxy 切換到基於 Go 語言的infrared(的分支)。這使得所有用戶都能使用 25565 端口,並通過域名進行通信分流,實現了更精緻的配置。

引入 Cloudflare Spectrum 與 L7 攻擊的鬥爭 (2022 年~2023 年初)#

由於對infrared的整合使得大量端口變得不必要,我們開始使用 Cloudflare Spectrum。雖然能以低價引入強大的 L4 保護,但如果源伺服器的 IP 被惡意用戶曝光,將會直接受到攻擊,這是一個致命的缺陷。由於國內缺乏便宜且可靠的上游防火牆 VPS,我們暫時採用了這一配置。

此時,攻擊的主流趨勢從簡單的 L4 洪水轉向更巧妙的 L7 攻擊。特別是對於不留痕跡的攻擊類型,我們面臨了很大的挑戰。

最終,我們發現不穩定行為的原因在於 Cloudflare Spectrum 獨特的速率限制和規範。無法處理大量新連接,導致玩家的連接不定期斷開。在 Spectrum 與 infrared 之間使用 proxy-protocol 的配置使得 L3/L4 級別的訪問控制變得困難,應用層的實時處理也存在極限。

向真正的 DDoS 保護過渡:採用 GSL 和 Path.net (2023 年~2024 年)#

我們認為繼續使用 Spectrum 不切實際,因此在 2023 年 2 月轉向使用 GSL 的自定義防火牆環境。隨後,為了應對針對 CPU 資源的新 L7 攻擊,我們也暫時引入了 Web Captcha 認證等措施。

在 2023 年 5 月,我們評估了成本效益後再次轉向 Path.net。隨之而來的是價格的調整。由於固定費用的裸金屬伺服器缺乏擴展靈活性,最終我們使用 Linode、Datapacket 等,輕鬆擴展基礎設施。

2024 年進入後,為了滿足新加坡、台灣和香港等亞洲地區的需求,我們正式新增了海外位置。同時,考慮到 GeyserMC 的更新跟進困難及競爭服務的興起,我們在 2024 年 3 月停止了對 UDP 的支持,並優化了規模。

最終保護配置的詳細信息 (2023 年以後)#

      +--------------+                +---------------+
      |   玩家       |                | Vercel (面板) |
      +--------------+                +---------------+
             |                              |
 (1. DNS查詢) |                              | (A. 面板操作)
             v                              v
      +--------------+                +---------------+
      |    gdnsd     |                |      API      |
      +--------------+                +---------------+
             |                              |
 (2. 返回IP)   |                              | (B. 設置反映)
             |                              |
             |                              v
             |                    +------------------+
             |                    |  infrared(分支)  |
             |                    +------------------+
             |                          ^      |
             +--------------------------+      | (C. 指標)
               (3. 連接獲取的IP)           v
                                        +----------+
                                        | Grafana  |
                                        +----------+

整體結構#

最終的配置使得管理者流程和玩家的通信流程集中於中央的 infrared 代理。考慮到用戶數量的變化和成本的增減,最終達成了靈活的擴展能力。

DNS / 負載均衡#

為了有效運營包括海外 PoP 在內的多個據點,高度的 DNS 控制是必不可少的,這包括 GeoDNS(基於位置的連接目的地變更)、Failover(故障時自動切換)、RoundRobin(負載均衡)的組合。由於 AWS Route53 / Constellix 等商業服務成本高昂,我們選擇了可以自建的 gdnsd。

特別是,利用 GeoDNS 進行流量分散在避免單一據點的負載集中方面發揮了重要作用。我們將用戶的伺服器連接限制為僅通過域名,並拒絕所有直接連接到各 PoP 的 IP 地址。這樣,除非 L7 機器人網絡故意繞過 DNS 等,攻擊流量也會像玩家一樣分散到全球基礎設施中。這種架構在防止特定據點受到攻擊方面發揮了巨大效果。

以下是針對日本用戶的實際設置示例的一部分。

# 定義數據中心和權重
jpgeo => {
    map => map_japan
    up_thresh = 0.00000001
    service_types => mc
    plugin => weighted
    dcmap => {
        DC-JP => {
            JP01 => [1.1.1.1,1], #nht-tyo-1
            JP02 => [1.1.1.2,1], #nht-tyo-2
            JP03 => [1.1.1.3,1], #nht-tyo-3
            JP04 => [1.1.1.4,1], #nht-tyo-4
        },
        DC-SG => [1.1.1.5,1] #nht-sgp-1
        DC-UK => [1.1.1.6,1] #nht-lon-1
        DC-CN => [1.1.1.7,1] #Softbank
    }
}
# 根據GeoIP數據庫,根據訪問來源大陸/國家分配最佳數據中心
map_japan => {
    geoip2_db => GeoLite2.mmdb,
    datacenters => [DC-JP,DC-SG,DC-UK,DC-CN],
    map => {
        AF => [DC-UK],
        AN => [DC-JP],
        NA => [DC-JP],
        SA => [DC-JP],
        AS => {
            default => [DC-JP],
            SG => [DC-SG],
            MY => [DC-SG],
            ID => [DC-SG],
            CN => [DC-CN],
        }
        OC => [DC-JP],
        EU => [DC-UK],
    }
}

健康檢查#

為了提高 Failover 的準確性,我們使用mcping進行健康檢查。僅僅進行 TCP 端口的通訊確認,在 L7 攻擊下伺服器可能無法正常響應的情況下也會被誤判為「正常」。通過 mcping,我們基於實際能否作為 Minecraft 響應,實現了更準確的存活監控。

service_types = {
    mc = {
        plugin = extmon
        cmd = ["/etc/gdnsd/mcping/mcping", "%%ITEM%%", "25565"]
        interval = 8
        timeout = 5
        up_thresh = 3
        ok_thresh = 3
        down_thresh = 2
    }
}

各保護伺服器的對策#

在各 PoP 中,根據需要使用 nftables。根據攻擊情況動態應用速率限制。

Nohit.cc 的運營所獲得的教訓#

在運營 Nohit.cc 的四年間,我們獲得的最大教訓是,自行補充那些現成產品無法觸及的領域的重要性。

其象徵性例子是 Minecraft (Java) 採用 TCP 的事實。TCP 的狀態性質使其能夠忽略像 UDP 洪水這樣的簡單攻擊,但對於巧妙設計的攻擊卻產生了特有的脆弱性。理解這些並準確應對,僅依賴通用的 DDoS 保護服務是不夠的。

不僅是技術挑戰,作為運營者所獲得的經驗也非常珍貴。在需求和供應都有限的利基領域,我們開發的服務能夠被社區接受並實際發揮作用,這種感覺是無法用任何東西來替代的喜悅。有時甚至會收到公安的情報提供請求,這是個人追求技術所無法經歷的事件,讓我同時感受到作為社會基礎設施提供服務的責任與趣味。

希望本文分享的四年記錄能對未來從事 DDoS 對策的人們有所幫助。

在下一篇文章中,我們將深入探討此次提到的 GSL 和 Path.net 等各個託管服務提供商的 DDoS 保護的具體「特性」及其有效選擇的方法。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。