專案地址#
注:開發者的全部言論僅代表個人觀點,程式碼開源,不提供任何關於協議的額外說明。
專案屬性#
-
優點
- 可與現有 TCP 代理工具無縫整合
- 抗檢測、通報、嗅探
- 不加密明文模式對中轉設備性能開銷極低
- 程式碼開源,可自行修改以使用 DPDK,eBPF 等技術實現大吞吐。
- 針對目前全部防火牆的弱點(即使用 TCP 三 / 四元組對連結進行追蹤)
-
缺點
- 不加密時對於二進制匹配無抵抗力
- 加密流會增強防火牆對於流量的關注度,出現延遲升高或丟包,但 5TB 單向未出現端口阻斷。
- 會導致 DDoS 緩解機制誤判,進而阻塞流量或重置現有連結。
-
玩具
該專案的本質只是作者的玩具和對於一個概念的驗證,並不打算持續維護。
開放的原因僅打算為當前環境提供一點新的思路。
實現#
楔子#
如今互聯網上如此之多的翻牆協議,各類實現層次不齊但卻都有著各自的問題在。以 Shadowsocks 為首的全加密流在解決了主動嗅探以及全隨機流量精確識別的問題後仍然是不少人的首選。R 佬所開發的各類基於 TLS 的花活也成功將個人流量代表的一棵樹隱藏在一片森林之中。
但這些協議在實際應用的過程中仍有自己的軟肋:在防火牆逐步將審查、監測等功能下放到邊緣設備上進行的今日,個人用戶設備上流出的全加密流量如同社區區域網絡中的一盞明燈;普通用戶在中轉設備上使用 R 佬提供的偷證書功能時往往忘記了來自於信管局的嗅探和監測,最終被通報、清退。
並且兩種設計思路都具有嚴重的一個問題:加密開銷。絕大多數代理工具的客戶端設備往往使用著近 5 年生產的 CPU 和完整的物理設備性能,可以輕鬆提供 OpenSSL 加密套件運行需要的性能;而服務端往往是性能限制嚴格的虛擬主機。為了實現更高的吞吐帶寬主流 1core512MB 的配置早已顯得捉襟見肘。常用開發語言 Golang 對於內存的開銷更是讓服務端雪上加霜。
目的#
針對防火牆監控流量的原理設計協議以降低服務端加密強度成為了專案的首要目標。而在回顧過去的各類開源專案之後,一個痛苦的事實浮出水面 —— 早年提出的西廂計畫,是目前唯一一個從原理層面出發,繞過防火牆識別,進而訪問外界網絡的專案。
就如今而言,這樣的漏洞已經幾乎不可能找到了,必須從防火牆識別流量的原理上著手去處理。現代防火牆以及目前市售防火牆的流量嗅探均基於三元組或更精細的四元組,即:
(source IP, destination IP, destination PORT)
(source IP, source PORT, destination IP, destination PORT )
一個想法在我們腦海浮出水面:將原本的一個三元組拆分為兩個不同的三元組之後,防火牆是否還有能力對內部數據包建立關聯或監控?
設計思路#
內部早有提前歸納 usenix23 中列舉的防火牆流量豁免規則甚至更為深入,我們設計了一個幾乎完全符合該五條規則的握手響應,全部由可打印字節構成,在字符層面隨機,二進制層面低熵。
鑒於可能沒有公網 IP 的場景,該設計中全部連結均由客戶端主動建立,數據流傳輸到服務端後合併。
考慮到部分省市地區和一些特殊場合使用的防火牆和規則具有二進制匹配能力,我們仍然在協議中集成了可選的加密套件。
不足#
-
在通過明文握手包初步令防火牆忽略該 TCP 連結後,我們未對該三元組延遲增大程度和丟包情況做持續檢測,無法確認大流量情況下是否存在目前沒有發現的探測機制接入。
-
我們進行了單邊大流量測試以及泉州新疆等地區的簡單測試均確認了連通性,但對於伊朗等地區的情況仍無法深入測試。
-
在持續運行 48 小時左右,移動會直接阻斷連結,但不知道觸發了什麼機制。電信聯通未見任何異常。
-
無法確認是明文握手包起了作用還是對於三元組的切割起了作用。(考慮可能存在的 AES 特徵爆破…… 個人認為都起了作用)
配置文件#
範例#
[app]
alignment=4096
mode=client
ip=::
port=30000
inbound-ip=localhost
inbound-port=10000
outbound-ip=localhost
outbound-port=20000
turbo=true
backlog=511
fast-open=true
keep-alived=true
connect.timeout=10
handshake.timeout=5
protocol=tcp
更多配置參考 samples 目錄
參數解釋#
-
alignment
alignment_malloc 內存對齊參數
-
mode
運行模式,[client, server]
-
ip
若運行模式為 client,則該值表示監聽 IP;若運行模式為 server,該值表示原本的 destination IP
-
port
若運行模式為 client,則該值表示監聽 PORT;若運行模式為 server,該值表示原本的 destination PORT
-
inbound-ip
設置承載上行鏈路的 TCP 連結使用的 IP
-
inbound-port
設置承載上行鏈路的 TCP 連結使用的 PORT
-
outbound-ip
設置承載下行鏈路的 TCP 連結使用的 IP
-
outbound-port
設置承載下行鏈路的 TCP 連結使用的 PORT
-
turbo
TCP 連結加速
-
backlog
TCP 連結 backlog 參數
-
fast-open
啟用 TCP-Fast-Open
-
keep-alived
啟用 TCP Keep-alive
-
connect.timeout
設置 TCP 超時時間
-
handshake.timeout
設置協議握手超時時間
-
protocol
傳輸協議,TCP 表示除握手包之外不加密。
使用案例#
warp+uds#
Cloudflare 提供的 warp 常常作為改善國際路由的工具部署於一些網絡質量一般的虛擬主機上。Cloudflare 針對大多數 Linux 發行版均提供了包管理器安裝方式
-
安裝 WARP
此處請參考Cloudflare 官方教程 -
切換模式
成功安裝 warp 並註冊客戶端之後,將客戶端運行模式切換為 proxy 模式。warp-cli set-mode proxy
-
更改 warp 使用的端口(可選)
warp 在 proxy 模式下默認監聽 1080 端口。warp-cli set-proxy-port [PORT]
warp 默認只監聽 127.0.0.1 上的端口,不用擔心該 socks5 端口被掃描到。
-
啟動 UDS 服務端
配置文件如下
[app]
alignment=4096
mode=server
ip=127.0.0.1
port=1080
inbound-ip=::
inbound-port=10000
outbound-ip=::
outbound-port=20000
turbo=true
backlog=511
fast-open=true
keep-alived=true
connect.timeout=10
handshake.timeout=5
protocol=tcp
啟動 uds 服務端
./udss --config=config.ini
- 啟動 UDS 客戶端
[app]
alignment=4096
mode=client
ip=127.0.0.1
port=1080
inbound-ip=[remote IP]
inbound-port=10000
outbound-ip=[remote IP]
outbound-port=20000
turbo=true
backlog=511
fast-open=true
keep-alived=true
connect.timeout=10
handshake.timeout=5
protocol=tcp
- 連接
使用你喜歡的工具連接 socks5://127.0.0.1:1080 即可
Dante + UDS#
如果不是 warp 能夠通過 Cloudflare 的網絡對國際路由進行優化和減少被送中的可能,我個人更加喜歡輕量的 Dante 來創建 socks5 連接
操作流程和 warp 非常接近,不再贅述
現有中轉接入 UDS#
測試中可不加密中轉純 vless 數據流
-
在落地設備上下載 udss
-
設置服務端目標端口為原有代理的監聽端口
-
在中轉機上下載 udsc
-
設置客戶端上行連接和下行連接與服務端對應
-
設置客戶端監聽地址和端口
如果需要平滑遷移則不可使用原有端口,建議中斷原有服務再啟動 UDS
-
啟動 uds 客戶端
尾言#
uds 只是個概念性實現,不建議在生產環境中大規模使用,並且不適合用於 UDP over TCP 的傳輸場景。如有 UDP 流量的需求請自行修改程式碼實現。
uds 全部程式碼遵循 MIT 協議。