蒐集的Userspace 網路棧

之前在這篇提到我蒐集到的Userspace network stack,想說獨立一篇出來好了。之後有查到新東西直接加進來

目前我找到的提供網路隔離的程式列表,以及他們kernel bypass所用的技術

  1. 基於LD_PRELOAD
    1. VPP (我用起來相容性不好。後來發現BIRD能用)
    2. NUSE (聽說bug很多)
    3. The shadow simulator (很新的專案,資料蠻少的)
  2. 基於ptrace
    1. gVisor
    2. UML(User Mode Linux) (就是linux的網路棧)
    3. The shadow simulator (好像兩個一起用,增加穩定度)
  3. 重新編譯原始碼
    1. LKL(Linux Kernel Library) (C/C++版本,也是linux的網路棧)
    2. LKL.js (javascript版本的LKL,可以在瀏覽器上執行!)
    3. F-Stack
  4. 基於network namespace (只是用了linux的ns隔離,本質上還是跑在kernel)
    1. mininet
  5. 沒有kernel bypass功能,依賴tun/tap
    1. RARE/freertr
    2. ns3

什麼是kernel bypass? 和網路隔離有什麼關係?

一般情況,我們程式想要監聽port,多半會呼叫bind()這個系統呼叫。
想要連線,就會呼叫socket()這個系統呼叫。
如果呼叫成功,就會拿到一個file descriptor,是一個整數
之後呼叫Read/Write function時,傳入fd,OS就會把資料弄去buffer了
這一切,OS會在背後幫我們處理。從網路堆疊複製東西/tcp狀態機的維護之類

當我們想要隔離的網路,有很多技術。像是

  1. network namespace: 我們呼叫linux kernel的socket()這個系統呼叫。但是kernel維護不只一個網路堆疊。kernel會根據你的namespace,決定要和哪個堆疊作互動
  2. LD_PRELOADptrace: 則是劫持現有程式內部的系統呼叫。
    以VPP為例,VCL負責劫持程式的bind()/socket()系統呼叫,並且轉交給VPP。和VPP維護的網路堆疊作互動
    這個列表是被VPP劫持了的系統呼叫:https://github.com/KusakabeSi/RootlessRouter/blob/main/misc/readelf_libvcl.txt
  3. 重新編譯原始碼: 這個很容易理解。編譯的時候直接把 bind() socket()之類的改成 custom_bind() custom_socket()之類,實則和和自己維護的堆疊互動
它們的共通特性是,使用當應用程式使用 bind()/socket()/connect() 等網路相關API的時候,和不同的網路棧作互動,來達到網路隔離的效果

這個特性對我來說是至關重要的。因為我並沒有系統管理員權限
改動系統路由表/創建network space/veth/tun tap等等操作都是Operation Not Permitted

所以只能仰賴這種方式,不再依賴kernel提供的網路堆疊,使用自己實作的網路堆疊。再用kernel bypass的方式把第三方程式拉入使用自己的堆疊

能用的kernel bypass技術

Docker unprivileged container 裡面,只有方案1/3是可以用的,ptrace/ns都沒權限

更新: 有個好消息,kernel 4.8以後,ptrace就可以用了。因為linux kernel的ptrace security issues修好了!
所以docker 19.03以及kernel 4.8以後,方案2也可用了! 

現在方案2也納入我的考慮之中了!
不過我目前VPP已經搞一堆東西了,現在要我換跑道,改走gvisor路線,之前的努力就又白費了
還不想現在切換跑道,遇到問題能patch先考慮patch看看。這就是沉沒成本效應嗎?

留言