Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature request] direct模式下port forwarding模式 #58

Closed
KusakabeShi opened this issue Jun 18, 2021 · 12 comments
Closed

[Feature request] direct模式下port forwarding模式 #58

KusakabeShi opened this issue Jun 18, 2021 · 12 comments
Labels
invalid This doesn't seem right

Comments

@KusakabeShi
Copy link

KusakabeShi commented Jun 18, 2021

可以設置一系列類似這樣的規則,

1314->192.168.11.2:1314/udp 
8080->192.168.22.3:80/tcp
8443->192.168.22.3:443/tcp

就會在主機listen udp 1314 等等port,forwarding到tun端對應ip:port

udp無狀態比較好弄些,tcp感覺上比較麻煩。

只有udp也好,加上這個功能也是挺實用的

@xjasonlyu
Copy link
Owner

我不知道你在说什么,而且这种奇怪的需求不应该就是自己去解决吗⋯

@KusakabeShi
Copy link
Author

KusakabeShi commented Jun 19, 2021

就是可以在tun端運行服務,比如http之類
讓外面的人連近來,類似路由器的port forwarding功能

8080->192.168.22.3:80/tcp

這樣設定就會使tun2socks在主機監聽tcp 8080,有連線建立就向tun端的192.168.22.3:80 發送 TCP SYN開始建立連線。
一樣要維護tcp狀態機,有點像是tun2sock原本在做的事情反過來

@xjasonlyu
Copy link
Owner

直接用iptables就可以做了吧,这种需求比较奇怪而且并不是tun2socks 的行为,所以没必要加吧

@KusakabeShi
Copy link
Author

KusakabeShi commented Jun 21, 2021

恩... 應該說,我的使用情境比較不一樣。博主設想的情境應該是這樣:

+--------------------------------------------------------+
|                +-----+      +----------+               |
|   user space   | app |      |tun2socks |-------+       |
|                +--|--+      +----^-----+       |       |
|-------------------|--------------|-------------|--------
|                +--v---+          |             |       |
|    kernel      | tun  |----------+      +------v--+    |
|                +------+                 |  eth0   |    |
+-----------------------------------------+---------+----+

然後用iptables呼叫netfilter把eth0上面的端口導向tun

+--------------------------------------------------------+
|                +-----+      +----------+               |
|   user space   | app |      |tun2socks |------+        |
|                +--|--+      +-^--------+      |        |
|-------------------|-----------|---------------|---------
|                +--v---+       |               |        |
|  kernel space  | tun  |-------+               |        |
|                +---^--+                   +---v-----+  |
|                    |    +----------+      |         |  |
|                    +-----port forw <-------  eth0   |  |
|                         +----------+      |         |  |
+-------------------------------------------+---------+--+

但我這邊,是想把這個tun2socks作為這個系統 https://www.kskb.eu.org/2021/06/dn42.html 的一個組件,作為layer3和layer4的轉換工具(下圖右上角的tun2socks)
使VPP網路能連接外網(現有tun2socks已能做到),並且暴露VPP裡面的服務給外網(feature request!!!)

+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|                                                +--------------------------|-----------------------------------+                                                              |
|                                                | VPP                      |          userspace imeplmentation |                                                              |
| +-----------------------+                      |       +----------------->|  Layer 4   of bind() socket()     |                                                              |
| | exabgp                |                      |       |                  |                  function         |                                                              |
| |                       |                      |       |                  |-----------------------------------|                                                              |
| |         +-------------|                      |       |                  |        +--------------+           |                                                              |
| |    +--- |BGP sessions |                      |       |          +--------------> |  Route table |   layer3  |                                                              |
| |+---v----+----------^--|  +--------------+    |       |          |       |        +--------------+           |  +---------------+                     +----------+          |
| ||python3-vpp-api|   |  |  |    nginx     |    |       |          |       |------------------------------------  |wireguard-go*2 |--+                  |tun2socks |--+       |
| +----|------------------+  ----------------    |  +--------+ +--------+   |          +-----+ +-----+ +------+ |  -----------------  |                  ------------  |       |
|      |    |ldpreload.so |  | ldpreload.so |    |  |api.sock| |cli.sock|   |  layer2  |memif| |memif| |memif | |  |  tap2tun*2    |  |                  | tap2tun  |  |       |
|      |    +------|------+  +-------|------+    +--+------|-+-+----^---+---|----------+--|--+-+--|--+-+---|--+-+  +-------^-------+  |                  +--^-------+  |       |
|      |           |                 |                     |        |                     |       |        |               |          |                     |          |       |
|------|-----------|-----------------|---------------------|--------|----------------------------------------------------------------------------------------------------------|
|      |           |                 |                     |        |                     |       |        |               |          |                     |          |       |
|      |           +----------------------unix socket------+        |                     -------------------unix soxket--------------|----------------------          |       |
|      +------unix socket-------------------------------------------|                                                                 |                                v       |
|                                                                                                                                    udp                            direct     |
+-------------+                                                                                                                +------------------------------------------+    |
|kernel space |                                                                                                                |      |            eth0                   |    |
+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
                                                                                                                                      |                                |        
                                                                                                                                      |                                |        
                                                                                                                             +----------------+               +--------v--+     
                                                                                                                             |                |               |           |     
                                                                                                                             |  DN42 Network  |               | Clearnet  |     
                                                                                                                             |                |               |           |     
                                                                                                                             +----------------+               +-----------+     

在這個場景中,我沒有kernel的任何權限,tun0之類的虛擬網卡也沒有註冊在kernel裡面。
唯一用的kernel功能只有unix socket和普通的tcp/udp socket。幾乎所有東西都在userspace完成

tun2socks的tun端被我用libmemif經由tap2tun註冊在VPP裡面,所以也不可能用iptables直接把封包轉送到tun端。而且要捕獲網卡的tcp封包也是要root權限。所以還是只能在tun2socks這端用 bind() 去listen然後送進tun端

qemu在沒有root的情況下,是用SLIRP這個工具來做layer2-layer4的轉換的。layer2端對應VM的虛擬網卡,layer4端則是tun2socks的direct模式,以在沒有root的情況下和使VM上網(vm的kernel跑在主系統的user space,vm裡的網卡也沒註冊進主系統)。slirp也有提供port forward的功能,讓外界可以連線到vm裡面的服務

為甚麼我不用SLIRP而是在這邊提交feature request呢...
是希望有一個go版本的SLIRP可以用,各種編譯問題比C++好處理多了。
還有一個因素是我對layer4-layer3轉換的知識比較不足,一個linux tcp socket的狀態和tcp狀態機的對應和轉換,還有gvisor裡面的處裡邏輯。我可能要重頭開始看。想說博主比我還要更熟悉這塊

如果博主暫時不打算加入此功能,想問問博主有沒有知道go語言實現的其他類似的工具,要搞C++(SLIRP)太痛苦了...

@xjasonlyu
Copy link
Owner

啊我好像明白你的意思了,有点意思🤨

所以如果我没有理解错的话,你FR是不是想增加一个类似-device udp://1270.0.0.1:1234的UDP套接字来模拟tun设备,作为L3-L4的入口?

@KusakabeShi
Copy link
Author

KusakabeShi commented Jun 21, 2021

不太一樣, 是L4->L3的入口 -p 9000:192.168.0.1:9000/tcp
L3->L4的部分比較好弄,我去改 https://github.com/xjasonlyu/tun2socks/blob/main/core/device/tun/tun.go ,弄一個tun_vpp之類的就行了,改寫他的Read() Write() function

我目前的理解是這樣(來源網路),L3->L4的原理是中继程式运行一个独立TCP/IP协议栈,並建立一个侦听 “TCP_SYN” 任何地址与端口的虚拟TCP服务器。每當建立一個虛擬服務器,就開一個對外的tcp連接,與之互相通信。也就是博主已經完成的部分

但是L4->L3就觸及我的知識盲區了。我想到可能的工作原理大概是這樣,一樣有userspace的TCP/IP协议栈,並且 listen port 8080。當外部連建立,則運行一個虛擬TCP客戶端,和L3內部這邊的服務器交互

@xjasonlyu
Copy link
Owner

你是想绕过kernel,自己在userspace网络栈上实现tcp状态机?即tcp2raw这样?

@xjasonlyu
Copy link
Owner

假设有这么个东西,那你的SYN包要以什么形式出来,直接发到tun接口上还是以UDP形式封装发给其他端口?

@KusakabeShi
Copy link
Author

KusakabeShi commented Jun 21, 2021

你是想绕过kernel,自己在userspace网络栈上实现tcp状态机?即tcp2raw这样?

是阿,博主的這個專案不是已經用gVisor的TCP/IP协议栈實現了L3->L4的部分了嗎?

假设有这么个东西,那你的SYN包要以什么形式出来,直接发到tun接口上还是以UDP形式封装发给其他端口?

直接发到tun接口。 這個專案的tun接口看上去有在 core/device/tun 作抽象。之後要轉發到UDP還是轉去其他地方,只要改寫 core/device/tun/io_unix.go 裡面的Read和Write就行了對吧?

@xjasonlyu
Copy link
Owner

直接发到tun接口。 這個專案的tun接口看上去有在 core/device/tun 作抽象。之後要轉發到UDP還是轉去其他地方,只要改寫 core/device/tun/io_unix.go 裡面的Read和Write就行了對吧?

不是哦,device抽象的是入口,默认出口是tunnel,即将所有的包重组成至L4然后通过proxy转发。

那你需要的应该是tcp2tun吧🌚,实现不复杂,只是似乎和这个项目没有太大关系了。这样的话就是要么iptables,要么自己造轮子了。

@KusakabeShi
Copy link
Author

KusakabeShi commented Jul 30, 2021

sorry之後忙別的忘記回復

我想說這個專案已經實現了L3->L4的部分,再多實現一個L4->L3,變成一個全功能的L3<->L4轉換器,我就可以直接拿來用

自己實現也可以,我再看看相關資料好了

@xjasonlyu xjasonlyu added the invalid This doesn't seem right label Sep 4, 2021
@KusakabeShi
Copy link
Author

我說的功能在這邊找到了! https://github.com/KusakabeSi/slirpnetstack

有兩個端,一邊是L2/L3 raw packet,另一邊則是linux tcp/udp session。這隻程式可以做轉換

當Layer 3端收到TCP SYN的時候,就在Layer 4呼叫connect() 系統呼叫
當Layer 4端監聽端口的 accept() 被觸發,就對Layer 3那邊發出TCP SYN 觸發遠端系統的accept()

剛好對應這個的 "local forward" 和 "remote forward" 模式!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
invalid This doesn't seem right
Projects
None yet
Development

No branches or pull requests

2 participants