深入浅出【迷雾通】之第二篇

本文章由 @为啥改名还要葱 冠名赞助!

他赞助了本文1600葱!


感嘆作者的更新速度!我每次讀完代碼,打算開始寫文章,作者就又提交代碼了。。。

還是繼續第一篇的主旋律【翻墻】,也就是客戶端到網橋這部分代碼。
如果,今天我能説完網橋部分,我在下一篇更新出口通信。也就是tinyss協議【講起來挺多的】

我們從網橋開始講起~
/cmd/geph-bridge/main.go 我們注意到listenLoop函數
人話版本:在網橋服務器上啓動隨機一個TCP的監聽端口,來接收客戶端發來的TCP請求
收到請求以後,通過cshirt2協議收發報文,處理邏輯在cmd/geph-bridge/handle.go的handle函數

那麽問題來了,客戶端如何知道網橋的地址呢?
首先,網橋往 https://checkip.amazonaws.com 這個地址,發送一個GET請求,應答就是自己的公網IP
然後,網橋往【警告:链接内容可能存在钓鱼网址,请勿打开】 https://bin der.geph.io/v2/add-bridge 這個地址,發送一個GET請求,添加自己的信息
{
    binderKey   用來鑒權,防止未授權的服務器發送此請求,把不安全的網橋加入到binder
    cookie        32字節隨機數,後面生成密鑰用到
    網橋的公網地址    包含IP:Port
}
現在輪到客戶端了~【隱去盲簽相關過程】
首先,客戶端往  https://netlify.com/v2/get-bridges 這個地址,發送一個GET請求【隨便一個CDN地址,不一定這個】
然後,客戶端得到了網橋信息
最後, 通過 getSingleTCP 去連接網橋,如果失敗,通過getWarpfrontCon 去連接網橋

重點講解 getSingleTCP ,也就是cshirt2協議,因爲getWarpfrontCon和Tor的meek原理一樣,實現差不多,沒有講解的價值【講了好幾次了~】
首先 , 調用 dialBridge(bi.Host, bi.Cookie)函數去連接服務器,獲得TCP連接【坑爹~】
{作者隱去了端口,讓我們猜端口號是多少,所以。。。自己改源碼吧}

接著,獲得連接以後,調用cshirt2.Client(cookie, conn)函數
1.先計算得到自己的私鑰和公鑰
2.調用 writePK(secret, 0, myPK, false, transport)
{
獲取當前時間【秒數 mod 30】,組裝字符串"handshake-[秒數 mod 30]-false"
以cookie為key,mac256(cookie, 組裝的字符串)得到臨時chacha20密鑰,加密自己的公鑰
得到的密文 ,後面append一堆隨機長度填充,然後發送給服務器
}
3.服務器收到handshake以後,返回應答
4.客戶端讀取前32個字節,就是服務器的公鑰
{
獲取當前時間【秒數 mod 30】+/-3秒,組裝字符串"handshake-[秒數 mod 30+/-3]-true"
以cookie為key,mac256(cookie, 組裝的字符串)得到臨時chacha20密鑰,解密報文
前32個字節就是服務器的公鑰,33-34字節是填充的長度
}
5.根據自己的私鑰和服務器的公鑰,通過ECDHE計算得到對稱密鑰SS
6.mac256(ss, []byte("c2s")) ,得到最終的cshirt2的通信密鑰
7.然後用chacha20加密解密收發報文就可以了
-------------------
8.最後 調用 connThroughBridge(bridgeConn)  往網橋發送
conn/feedback
exitName
來和出口節點橋接
9.接下來就是通過tinyss協議交互了,第三篇講解~
21
分享 2020-04-25

要发言请先登录注册

要发言请先登录注册