系統設計面試:如何設計基於 MASQUE 的 CONNECT-UDP 代理?
題干與適用場景
行動客戶端只能穩定存取 HTTPS,但語音、遊戲和即時探測依賴 UDP。請設計一個代理,讓客戶端透過 HTTP 建立到目標 UDP 主機的通道,並涵蓋連線生命週期、資料轉送、鑑權、限流、DNS、故障切換與回退。
RFC 9298 定義 CONNECT-UDP 方法與代理範本;RFC 9297 定義 HTTP Datagrams 與 Capsule Protocol,分別承載不可靠資料與可靠控制資訊。高品質回答要把協定語意、代理資源與安全策略分層,不能把「加了 TLS」當成完整濫用防護。
面試官考察點
- 能否區分 CONNECT-UDP 的通道建立、資料轉送與關閉。
- 是否說明 HTTP/3 Datagram 與 Capsule 的適用邊界及無 Datagram 時的回退。
- 是否設計目標位址白名單、連接埠策略、使用者鑑權與租戶配額。
- 是否處理 DNS 解析、逾時、重試、半開連線與故障切換。
- 是否給出頻寬、並發、丟包、延遲、濫用與成本指標。
- 是否知道代理不能保證 UDP 的可靠性、順序或端到端加密語意。
回答前需要澄清的問題
- 客戶端與代理是否都支援 HTTP/3 Datagrams,還是必須相容 HTTP/2?
- 目標是企業內網存取、即時媒體,還是開放網際網路代理?目標決定白名單與濫用風險。
- 客戶端是否提供目標主機名稱,代理是否代做 DNS?解析結果的生命週期與隱私要求是什麼?
- 單一使用者允許多少通道、頻寬與並發 UDP 流?是否需要按區域就近接入?
- 允許的最大閒置時間、單包大小與總工作階段時長是多少?
30 秒回答框架
我會先把代理限定為已鑑權的目標集合,再用 CONNECT-UDP 建立工作階段。控制訊息走 Capsule,支援時用 HTTP/3 Datagram 承載 UDP 資料;不支援時回退到可靠封裝或拒絕,不假裝提供相同延遲。資料面按租戶做令牌桶、並發與閒置逾時,DNS 在受控解析器完成並繫結工作階段。節點異常時只重建可重播的工作階段,避免複製不可重播資料。驗收同時看 p99 延遲、丟包、建連成功率、資源占用、拒絕率與濫用告警。
分步驟深入解答
1. 建立工作階段與狀態機
客戶端向代理發送 CONNECT-UDP,請求目標主機與連接埠。代理先驗證身分、策略與配額,再解析目標並建立工作階段。狀態至少包括待鑑權、已連線、排空與關閉;每個狀態都設定逾時與原因碼,防止半開工作階段長期占用資源。
CONNECT / .well-known/masque/udp/example.test/443 HTTP/3
Host: proxy.example實作應遵循 RFC 9298 的請求範本與編碼規則,示例只表達意圖,不取代完整協定欄位。
2. 劃分控制面與資料面
Capsule Protocol 適合可靠的工作階段控制、錯誤與關閉通知;HTTP/3 Datagram 適合不要求重傳的 UDP 資料。代理把每個 Datagram 映射到對應的 UDP socket,並限制單包大小、佇列深度與突發量。若路徑不支援 Datagram,應明確回退到可靠封裝或回傳不支援,避免把可靠傳輸引入即時路徑卻不計成本。
3. 設計鑑權與目標策略
代理先驗證短期令牌、租戶狀態與裝置繫結,再依目標網域、IP 區段、連接埠及用途做 allowlist。禁止客戶端任意指定內網、迴路、雲端中繼資料位址或高風險連接埠。DNS 解析應在受控解析器完成,記錄解析版本與 TTL,避免重新解析把同一工作階段悄悄切到不同租戶邊界。
4. 限流、配額與成本控制
按租戶同時限制通道數、每秒封包數、位元組速率、單一工作階段時長與閒置時間。入口與出口都使用令牌桶,超過配額回傳可觀測的拒絕原因;節點還要保留全域保護閾值。統計代理 CPU、核心 socket、佇列、出口頻寬與每工作階段成本,避免只限制 HTTP 請求數而放過長時間 UDP 流。
5. 處理故障與回退
對建立連線失敗、目標不可達、DNS 逾時與代理過載分別記錄原因。新工作階段可在健康節點重試;已發送的 UDP 資料通常不可安全重播,因此故障切換應只恢復控制狀態或讓上層重新建立工作階段。客戶端不支援 Datagram 時,服務端應依業務選擇可靠封裝或明確失敗,並在指標中區分兩種路徑。
6. 觀測與安全營運
每個工作階段記錄租戶、代理節點、目標策略版本、建立與關閉原因、位元組數、封包數、丟包估計、p50/p95/p99 延遲及限流事件。日誌不得記錄完整令牌或敏感載荷。偵測連接埠掃描、異常目標集中度、突發放大與跨租戶資源爭搶,並準備按租戶、目標與區域快速撤銷策略。
7. 灰度與驗收
先在固定區域與 allowlist 目標灰度,使用對照組比較直連、Datagram 路徑與回退路徑。壓力測試涵蓋丟包、亂序、代理重啟、DNS 變更、半開連線與超額流量。發布門檻應包含建連成功率、即時請求 p99、丟包率、每工作階段資源、拒絕誤報與濫用告警延遲;任一安全閾值超限就收緊策略或關閉新路徑。
高品質示範回答
我會把它做成只服務已鑑權租戶和明確目標集合的代理。客戶端發起 CONNECT-UDP 後,代理驗證令牌、目標與配額,受控 DNS 解析並建立工作階段。控制訊息使用 Capsule;支援 HTTP/3 Datagram 時承載不要求重傳的 UDP 資料,並為每個工作階段設定封包大小、佇列、速率、閒置與總時長上限。
出口策略阻斷內網、迴路、中繼資料與高風險連接埠,入口出口都做租戶令牌桶。故障時新工作階段可切換健康節點,已發送 UDP 資料不自動重播。觀測建連成功率、p99 延遲、丟包、資源與成本,同時監控掃描與放大行為。灰度比較 Datagram、回退與直連,安全或資源閾值超限就關閉新路徑。
常見錯誤
- 只說「用 HTTPS 包住 UDP」 → 沒有定義通道語意和資料承載 → 分開 CONNECT-UDP、Capsule 與 Datagram。
- 把代理當成可靠傳輸 → UDP 的丟包和順序語意仍由上層負責 → 明確能力邊界與指標。
- 允許任意目標位址 → 形成內網探測或反射放大器 → 使用目標和連接埠 allowlist,阻斷特殊位址。
- 只按 HTTP 請求限流 → 長連線仍可耗盡 socket 與頻寬 → 同時限制通道、封包、位元組、時長與閒置。
- 故障時重播全部 UDP 資料 → 可能重複交易或破壞即時協定 → 只恢復可重播控制狀態,讓上層重建資料工作階段。
- 只測平均延遲 → 尾延遲和濫用會被隱藏 → 同時看 p99、丟包、拒絕和安全告警。
追問及應對
HTTP/2 不能傳送 HTTP/3 Datagram 時怎麼辦?
依業務選擇可靠封裝、長輪詢式傳輸或明確拒絕,並分開計量延遲、CPU 與頻寬成本;不要聲稱它與不可靠 Datagram 等價。
代理如何避免 SSRF?
在解析後和連線前都檢查目標 IP,阻斷迴路、鏈路本地、私有、雲端中繼資料與策略外網段,並處理 DNS 重新繫結;策略版本要繫結工作階段並可撤銷。
UDP 丟包應由誰重試?
代理只回報可觀測的傳輸結果,不擅自重播業務封包。由具備冪等與序列語意的上層協定決定重試,即時媒體通常選擇丟棄或錯誤修正。
代理重啟如何恢復工作階段?
優先讓客戶端重新鑑權並建立新工作階段;若必須保留控制狀態,只恢復短期、可驗證且不包含不可重播資料的狀態,舊 socket 立即排空。
如何證明限流沒有誤傷?
按租戶、區域、目標與客戶端版本比較拒絕率與成功率,設定錯誤拒絕預算,並用回放流量驗證突發、長連線與節點故障下的配額行為。