運作原理
dae 透過 eBPF 將程式載入 Linux 核心中的 tc(traffic control)掛載點運作。此程式會在流量進入 TCP/IP 網路堆疊前執行流量分流。下圖顯示 tc 在 Linux 網路協定堆疊中的位置(圖中為接收路徑,傳送路徑方向相反),其中 netfilter 代表 iptables/nftables 的位置。


流量分流原理
分流依據
dae 支援依網域名稱、來源 IP、目的地 IP、來源連接埠、目的地連接埠、TCP/UDP、IPv4/IPv6、處理程序名稱、MAC 位址及其他因素進行流量分流。
其中,來源 IP、目的地 IP、來源連接埠、目的地連接埠、TCP/UDP、IPv4/IPv6 與 MAC 位址可藉由解析 MACv2 訊框取得。
處理程序名稱是藉由監控 cgroupv2 掛載點中本機處理程序的 socket、connect 與 sendmsg 系統呼叫取得。接著會從處理程序控制區塊讀取並解析命令列。相較於 Clash 這類掃描整個 procfs 以取得處理程序資訊的使用者空間程式,此方法快得多(後者甚至可能耗時數十毫秒)。
網域名稱是藉由攔截 DNS 請求,並將請求的網域名稱與對應 IP 位址關聯取得。不過,此方法有一些潛在問題:
- 可能造成誤判。例如,若短時間內同時存取共用同一 IP 位址的國內與國外網站,或瀏覽器使用 DNS 快取。
- 使用者的 DNS 請求必須經過 dae。可將 dae 設為 DNS 伺服器,或在 dae 作為閘道時使用公開 DNS,以達成此條件。
儘管存在這些挑戰,與其他方法相比,這個方法已是最佳解法。例如,Fake IP 方法無法依 IP 分流,且有嚴重的快取污染問題。同樣地,網域嗅探僅能攔截 TLS/HTTP 等流量。雖然以 SNI 嗅探進行流量分流有效,但 eBPF 對程式複雜度的限制及其不支援迴圈,使我們無法在核心空間實作網域嗅探。
因此,若 DNS 請求無法通過 dae,基於網域的分流就不會成功。
為減輕 DNS 污染並提升 CDN 連線速度,dae 在使用者空間採用網域嗅探。當
dial_mode設為 "domain" 或其變體,且需要處理代理流量時,dae 會將嗅探到的網域傳送至代理伺服器,而非傳送 IP 位址。因此,代理伺服器會重新解析網域,並使用最佳 IP 連線。此方法可解決 DNS 污染並提升 CDN 連線速度。此外,已使用其他分流方案且不想讓 DNS 請求通過 dae,但仍希望特定流量依網域分流的進階使用者(例如依目標網域分流 Netflix 節點與下載節點的流量,部分流量透過核心直接連線),可透過設定
dial_mode: domain++強制使用嗅探到的網域進行分流。
dae 會使用 tc 掛載點中的程式重新導向流量,以實現流量分流。重新導向依分流結果而定:流量會被重新導向至 dae 的 tproxy 連接埠,或繞過 dae 直接通行。
代理機制
dae 的代理機制與其他程式相似。不過,在繫結 LAN 介面時,dae 會運用 eBPF,直接在 tc 掛載點將待代理流量的 socket buffer 與 dae 的 tproxy 監聽連接埠 socket 關聯。繫結 WAN 介面時,dae 會將待代理流量的 socket buffer 從網卡的輸出佇列移至輸入佇列;同時停用校驗和,並將目的地位址修改為 tproxy 監聽連接埠。
從效能測試來看,dae 的代理效能略優於其他代理程式,但差異不大。
自 PR:implement stack bypass 起,劫持資料路徑已改為繞過堆疊,以獲得更佳效能並減少堆疊影響(例如 netfilter、systemd-sysctl)。請參閱 PR 說明以進一步理解。
直接連線機制
一般而言,流量分流會讓流量通過代理程式、經過分流模組,然後決定使用代理還是建立直接連線。此過程需要透過網路堆疊解析、處理並複製流量,將流量交給代理程式,然後再透過網路堆疊複製、處理及封裝後送出。這會消耗大量資源。尤其在 BitTorrent 下載等情境中,即使設為直接連線,仍會消耗大量連線、連接埠、記憶體與 CPU 資源。代理程式處理不當甚至可能影響遊戲情境中的 NAT 類型,造成連線錯誤。
dae 在更早的核心階段執行流量分流,並透過第 3 層路由轉送直接連線流量。此方法減少核心與使用者空間之間的切換,從而降低額外負擔。此時 Linux 的作用如同純粹的交換器或路由器。
為確保直接連線有效,具有特定網路拓撲的進階使用者應確認:設定 核心參數 並停用 dae 後,將安裝 dae 的裝置設為閘道時,其他裝置仍可正常連網。例如,存取 223.5.5.5 應收到 "UrlPathError" 回應。在安裝 dae 的裝置上執行 tcpdump 時,應可看見來自用戶端裝置的請求封包。
因此,dae 不會對直接連線流量執行 SNAT。在「旁路由」設定中,這會導致非對稱路由。在此情境下,送出時,用戶端裝置的流量會經 dae 前往閘道;接收時,流量會直接從閘道前往用戶端裝置,繞過 dae。
此處的「旁路由」是指:1) 作為閘道運作;2) 對 TCP/UDP 執行 SNAT;3) LAN 與 WAN 介面位於相同網段。
例如,若筆記型電腦位於 192.168.0.3,旁路由位於 192.168.0.2,路由器位於 192.168.0.1,則邏輯上的三層拓撲為:筆記型電腦 -> 旁路由 -> 路由器。在路由器端,只會看見來源 IP 為 192.168.0.2 的 TCP/UDP 流量,不會有來源 IP 為 192.168.0.3 的 TCP/UDP 流量。
據我們所知,我們是這個「旁路由」定義的先驅(笑)。
非對稱路由帶來一項優點及一項潛在問題:
- 可提升效能。由於回程流量不經過 dae,直接連線效能會如同未使用旁路由般快速,且可縮短路徑。
- 可能破壞具狀態防火牆的狀態維護並導致封包遺失(例如 Sophos Firewall)。不過,此問題通常不會出現在家用網路。
從效能測試來看,與其他代理方案相比,dae 的直接連線效能相當出色。
來源:dae 上游文件 · AGPL-3.0 授權條款。
