ss協議解析


根據本人調試ss的經驗,寫出本文,以便讓自己不會忘記ss協議的實現細節。這里ss用縮寫,是因為寫全了過不了審核,懂的自然懂。

整體流程

  1. 瀏覽器配置好socks5代理,瀏覽器訪問目標服務器的時候,請求就會轉發到sslocal
  2. sslocal收到socks5請求,解析出請求對象,將請求對象最前面加上ss頭部(見詳細說明->ss頭部),再生成一個32字節的鹽(也稱為IV),再用aes-256-gcm進行加密,將鹽和加密后的數據一起發送給ssserver
  3. ssserver收到sslocal傳輸的數據,先讀取出32字節的鹽,再用aes-256-gcm進行解密,再從解密完的數據中取出ss頭部,根據ss頭部的指示連接目標服務器,接着把剩余的數據發送給目標服務器
  4. 目標服務器處理請求,將結果返回給ssserver
  5. ssserver收到結果,生成一個32字節的鹽,再用aes-256-gcm進行加密,將鹽和加密后的數據一起發送給sslocal
  6. sslocal收到數據,取出32字節的鹽,再用aes-256-gcm進行解密,將解密好的數據通過socks5協議返回給瀏覽器
  7. 瀏覽器收到數據,展示頁面結果

詳細說明

基本概念

password

ss的密碼,這個在配置ss連接的時候會用到

method

aes-256-gcm,這是加密方式,此外還有aes-128-gcm、aes-192-gcm、chacha20-ietf-poly1305、xchacha20-ietf-poly1305,因為時間有限我只研究了aes-256-gcm

key

密鑰,根據password和method生成

method決定key的長度,例如aes-256-gcm就是32字節

第一個16字節 = md5(password)

第二個16字節 = md5(md5(password) + password)

參考代碼:CryptServiceImpl#getKey

salt

鹽,也稱為IV,在aes-256-gcm中為32字節

subkey

子密鑰,根據key和salt生成,aes-256-gcm是32字節

具體怎么生成的,我也不是特別清楚,好像跟HKDF(SHA1)有關

參考代碼:CryptServiceImpl#genSubkey

tag

標簽,aes-256-gcm中每次加密都會生成一個16字節的tag,具體干嘛用的我也不知道

nonce

不知道怎么稱呼它,在aes-256-gcm中它是12字節byte數組,每次加密都會使最前面的byte加1,前面的byte滿了會讓下一個byte加1

aes-256-gcm加密

每一次請求,都先會產生一個隨機的32字節salt

根據password和method,可以產生key

根據key和salt,可以產生subkey

根據method、nonce、subkey,可以將明文變成密文

下面是具體加密流程

數據按最大0x3fff字節分塊,每一塊將長度明文加密,生成一個tag,nonce遞增,數據內容明文加密,生成一個tag,nonce遞增。一直這么處理,直到數據全部加密完畢

最后的結構如下所示:

注意:每一次請求只會有一個salt,不管本次請求數據有多長salt都是不會變的。不同的請求salt是不同的。

aes-256-gcm解密

每一次請求,在aes-256-gcm中都先取出頭部32字節salt

根據password和method,可以產生key

根據key和salt,可以產生subkey

根據method、nonce、subkey,可以將密文變為明文

具體解密流程,就是先取2+16字節,解密解析出長度,再取長度+16字節,解密解析出內容

將所有內容拼起來就是解密后的結果

ss頭部

ss頭部與加密解密無關,因為正常的數據中只有請求數據,而沒有請求服務器的地址,所以在請求數據的頭部加了1+n+2個字節表示請求服務器的地址

ss頭部格式如下圖所示

ss頭部與正常請求數據結合在一起形成明文,和加密解密中的salt一樣,ss頭部每次請求也只有一個

總結

一圖勝萬言

代碼地址

ss

鳴謝

感謝github上面的相關代碼,這里我就不貼了,貼了過不了審核


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM