Skip to content
New issue

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

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

Already on GitHub? # to your account

对上游应用实现 Cone NAT 提供支持 #1429

Closed
eycorsican opened this issue Nov 24, 2018 · 10 comments
Closed

对上游应用实现 Cone NAT 提供支持 #1429

eycorsican opened this issue Nov 24, 2018 · 10 comments

Comments

@eycorsican
Copy link
Contributor

eycorsican commented Nov 24, 2018

我正在为 tun2socks 实现 Cone NAT (NAT Type 1/2/3):https://github.com/eycorsican/go-tun2socks/tree/nat3 ,但发现 V2Ray 并没有提供相关的接口。

为了能够实现 Cone NAT,希望能够有以下接口:

func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPConn, error)

所返回的 UDPConn 至少实现了以下方法( https://golang.org/pkg/net/#PacketConn ):

func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error)
func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error)

其中 ReadFrom 需要返回目的地址(非代理服务器地址),WriteTo 中的地址也是目的地址。

另一个 issue 提到了实现 NAT 2,看起来目前 VMess 从协议层面上缺乏支持,不过这似乎并不影响对其它协议提供支持,比如 Freedom, Socks, Shadowsocks。

@VictoriaRaymond
Copy link
Member

是的,目前的框架不能方便地添加这一特性。如果你只需要本地Freedom的话,可以用ListenPacket 获取一个系统的 PacketConn。我也正打算把所有 Dial(UDP) 的操作改为 ListenPacket。这个做法无法获取最终的目标地址(协议不支持),但能一定程度上改善UDP NAT的状况。

如果你需要一个类似 socks port binding 的功能的话,实现起来会需要一点时间。

@eycorsican
Copy link
Contributor Author

eycorsican commented Nov 25, 2018 via email

@VictoriaRaymond
Copy link
Member

哦,这个不难,VMess也是可以的。

@eycorsican
Copy link
Contributor Author

VMess 怎么可以?我没看到协议中的答应部分有地址和端口字段啊,没有这些字段就无法判断数据是哪个机器发来的

@VictoriaRaymond
Copy link
Member

已经添加 DialUDP 方法 ( b52725c ),另外现在 Freedom 已可以接收 NAT 2的数据 ( a1b552f )。

现在的问题是,部分UDP包的源地址不能正确返回。但这不是这个issue的问题。

@Vigilans
Copy link
Contributor

Vigilans commented Nov 4, 2019

现在 dokodemo-door, socks5 与 shadowsocks 协议的 NAT 支持如何了?我目前了解到的:

正在尝试用 v2ray + mellow 做一站式配置,需要在用 ZeroTier 建立的内网里用 socks5/ss 作代理加速网络不好的朋友的局域网联机,所以想知道 v2ray 在这些方面的支持度……

@eycorsican
Copy link
Contributor Author

@Vigilans

目前 v2ray-core 不支持 Full Cone(尽管有某些测试软件结果显示 Full Cone),原因 @VictoriaRaymond 前面也说了有部分 UDP 包的源地址不能正确返回。

关于 UDP 源地址不正确返回的问题,简单来说,正常情况,假设本地 1.1.1.1:1111 用 UDP 先后分别发 abc 和 def 两条信息给 2.2.2.2:2222 和 3.3.3.3:3333,然后他们分别返回 cba 和 fed 给 1.1.1.1:1111,1.1.1.1:1111 接收这两条返回的信息,会看到 cba 来自 2.2.2.2:2222,fed 来自 3.3.3.3:3333,但如果中间插了个 v2ray-core 进来,1.1.1.1:1111 看到的是 cba 和 fed 都同样来自 2.2.2.2:2222(因为它是),所以这里 fed 这条信息的 3.3.3.3:3333 地址没有正确返回(被 v2ray-core 改写为 2.2.2.2:2222 了)。

另外在 Mellow 中使用 freedom/socks/shadowsocks 是支持 Full Cone 的,Mellow 修改过 v2ray-core 的代码让这些协议的 UDP 包源地址可以正确返回。

@Vigilans
Copy link
Contributor

Vigilans commented Nov 5, 2019

@eycorsican

好的,我理解了这里面的问题了……我查了一下相关的 commit,请问 Mellow 是通过 go-tun2socks 的这个commit一样,在 v2ray-core 上包装一层中间接口来实现正确返回 UDP 包源地址,以及添加扩展功能的吗?

如果是这样的话,是不是应当考虑只以 Mellow 作为 V2ray 的 Client 比较合适?

@eycorsican
Copy link
Contributor Author

并没这么简单,这里的根本问题在于 v2ray-core 设计初只考虑到流式 IO,在它的核心 IO 模块(https://github.com/v2ray/v2ray-core/blob/master/transport/pipe/impl.go) 中没有像 ReadFrom/WriteTo 这类可以带上地址的 IO 机制,导致就算在 outbound 读到远端地址信息,也没办法通过中间 IO 传给 inbound,inbound 也就没办法把地址传给客户端,所以 inbound 只是保存着第一次客户端传过来的目的地址,然后所有返回的数据都当作是这个地址的。

需要 Full Cone NAT 的情况真不多,也就 Mellow 这种全局透明代理适用,还有路由器透明代理。

@Vigilans
Copy link
Contributor

Vigilans commented Nov 5, 2019

@eycorsican 了解了。

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants