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

fix abstract UDS & add PROXY protocol support to DS inbound #164

Merged
merged 1 commit into from
Sep 7, 2020

Conversation

lucifer9
Copy link
Member

@lucifer9 lucifer9 commented Sep 4, 2020

  1. Fix abstract UDS path handling, now it really works.

  2. Although most modern applications, whether using abstract UDS or not, treat sockaddr_un.sun_path as a NULL-terminated string, there are some applications (such as haproxy) insist on using the full length of sockaddr_un.sun_path to make a connect(2) or bind(2) call when using abstract UDS. This indeed is right according to unix(7) but we have to do extra padding to satisfy them 😢

  3. PROXY protocol is here now. Say goodbye to the confusing "@" in access log.

@RPRX
Copy link
Contributor

RPRX commented Sep 5, 2020

好像不太对?abstract 就是要求 \x00 开头(VLESS fallbacks dest 是把 @ 转换成了 \x00

@RPRX
Copy link
Contributor

RPRX commented Sep 5, 2020

(另外 transport domainsocket 的代码本来存在一些问题,VS Code 无法分析它,而且效率上似乎还不如 TCP

@RPRX
Copy link
Contributor

RPRX commented Sep 5, 2020

(其实我有一个想法是把入站的 DS 扔掉,改为写在 listen 那里,像 VLESS fallbacks dest 一样自动识别

@lucifer9
Copy link
Member Author

lucifer9 commented Sep 5, 2020

好像不太对?abstract 就是要求 \x00 开头(VLESS fallbacks dest 是把 @ 转换成了 \x00

https://github.com/golang/go/blob/93810ac1f4574e1e2a79ea156781bafaf8b8ebe0/src/syscall/syscall_linux.go#L405

Golang 当前版本已经自己做转换了。如果用户自己非要写'\x00'开头,反而会导致后面计算长度出问题,结果就是传递给操作系统的sockaddr_un.sun_path第一个字符跟最后一个字符都是 '\x00',然后所有其他应用就都没法连接。

@lucifer9
Copy link
Member Author

lucifer9 commented Sep 5, 2020

(另外 transport domainsocket 的代码本来存在一些问题,VS Code 无法分析它,而且效率上似乎还不如 TCP

其实我想用 abstract UDS 最大的动力是不用考虑实际路径和权限,只要两边的path一致就行。要不haproxy默认跑在chroot下要用普通的UDS不是一般麻烦。
性能啥的,一般自己用估计也不至于到瓶颈。用 UDS 的估计也没几个真能跑到那种吞吐量,最多就是不想看一堆的端口麻烦吧。

@lucifer9
Copy link
Member Author

lucifer9 commented Sep 5, 2020

(其实我有一个想法是把入站的 DS 扔掉,改为写在 listen 那里,像 VLESS fallbacks dest 一样自动识别

👍
现在的配置,写起来太混乱了,还非得写个listen addr跟port...

@RPRX
Copy link
Contributor

RPRX commented Sep 5, 2020

好像不太对?abstract 就是要求 \x00 开头(VLESS fallbacks dest 是把 @ 转换成了 \x00

https://github.com/golang/go/blob/93810ac1f4574e1e2a79ea156781bafaf8b8ebe0/src/syscall/syscall_linux.go#L405

Golang 当前版本已经自己做转换了。如果用户自己非要写'\x00'开头,反而会导致后面计算长度出问题,结果就是传递给操作系统的sockaddr_un.sun_path第一个字符跟最后一个字符都是 '\x00',然后所有其他应用就都没法连接。

这倒是意料之外。。。我有空测试一下(而且 VLESS 的 @ 表示 abstract 的写法本来是自行决定的,逐渐发现它是广泛使用的

@RPRX
Copy link
Contributor

RPRX commented Sep 5, 2020

(另外 transport domainsocket 的代码本来存在一些问题,VS Code 无法分析它,而且效率上似乎还不如 TCP

其实我想用 abstract UDS 最大的动力是不用考虑实际路径和权限,只要两边的path一致就行。要不haproxy默认跑在chroot下要用普通的UDS不是一般麻烦。
性能啥的,一般自己用估计也不至于到瓶颈。用 UDS 的估计也没几个真能跑到那种吞吐量,最多就是不想看一堆的端口麻烦吧。

意思是现在 v2ray 的 transport domainsocket 应该存在些问题,不如逐步把现在的实现扔掉,而不是去增强它

你可以研究下写到 listen 那里的情况,这样DS 能直接获得现在 TCP 入站的所有功能,WS 等其它传输方式入站也能支持 DS 了

@lucifer9
Copy link
Member Author

lucifer9 commented Sep 5, 2020

好像不太对?abstract 就是要求 \x00 开头(VLESS fallbacks dest 是把 @ 转换成了 \x00

https://github.com/golang/go/blob/93810ac1f4574e1e2a79ea156781bafaf8b8ebe0/src/syscall/syscall_linux.go#L405
Golang 当前版本已经自己做转换了。如果用户自己非要写'\x00'开头,反而会导致后面计算长度出问题,结果就是传递给操作系统的sockaddr_un.sun_path第一个字符跟最后一个字符都是 '\x00',然后所有其他应用就都没法连接。

这倒是意料之外。。。我有空测试一下(而且 VLESS 的 @ 表示 abstract 的写法本来是自行决定的,逐渐发现它是广泛使用的

是啊,当初是因为显示时候总得找个字符来替换'\0x00',用@估计是因为ASCII NUL在终端里面输入的话,是要写 ^@ ([Ctrl]+[@]),这样的话 linux 的 cat -A 显示出来也是 ^@,所以就用了@来替换了。
所以 netstat -l 可以看到,如果自己手写 '\0x00',那么列出来的名称是 @path@,于是别人就怎么都连不上...
如果是haproxy创建的,那就是 @path@@@...后面一串儿@,凑够108字节。于是如果haproxy配置里面,listen或者bind 很多还都是用了 abns@,而且恰好终端配置的显示列数还比较少的话,那netstat -l的结果就会很壮观 😄

@XuuKoo
Copy link

XuuKoo commented Sep 5, 2020

proxy procotol的支持似乎有问题。

服务端版本:4.27.5
前端:haproxy

haproxy通过设置check send-proxy参数可以向后端传递客户端ip,详见https://www.haproxy.com/blog/using-haproxy-with-the-proxy-protocol-to-better-secure-your-database/

如此设置之后,nginx作为后端是可以正常获取客户端ip的。

v2ray使用tcp作为传输层协议时,在tcpSettings里通过设置acceptProxyProtocol:true之后也可以获取客户端ip。但是日志中伴随大量header读取错误的信息,使得日志几小时内就可以达到数兆字节。

同时,tcpSettings里的
"header": {
"type": "none"
}
无论header这个参数下的type设置成none还是干脆不写header参数,上述问题依旧。

不知道是我设置不对还是该功能有bug。

@lucifer9
Copy link
Member Author

lucifer9 commented Sep 6, 2020

@XuuKoo 如果方便的话,可以贴出相应 log 和配置吗?
只是描述的话很难判断

@RPRX
Copy link
Contributor

RPRX commented Sep 7, 2020

@RPRX RPRX merged commit f10f5b4 into v2fly:master Sep 7, 2020
@lucifer9 lucifer9 deleted the ds-enhance branch September 7, 2020 08:27
@nftbty
Copy link

nftbty commented Sep 23, 2020

关于domain socket,很早以前看到就觉得这个目前的实现有问题,这根本就不应该是跟ws,h2这些一起放在传输层,这很显然不合理,而是应该更底层,跟ip:port放在一个设置里。
一般V2Ray用户会用到本机进程间通讯的也就Nginx,caddy,haproxy这些,尤其webserver类,用来搭建ws+TLS或h2+TLS并隐藏在正常的网页服务之下,这应该是domain socket被用的最多的地方了,却只能用着127.0.0.1,眼巴巴看着domain socket却用不了。
其实Linux系统有fastpath,用localhost比uds在速度,延迟,资源消耗上都差不了多少。但,就如上面某层说的,我就单纯只是避免多开一个端口,哪怕是只监听本机的。
今天上v2fly.org找VmessAEAD的信息(是否正式定稿发布,4.28.1之后的版本相互之间可以兼容AEAD,不再要求同版本;以及服务器旧版alterid=0,客户端新版alterid>0是否可行)时,刚好看到DomainSocket,看文档还是放在传输层,就想来搜一搜这么久有没有人提issue,结果没有,这个想法还是项目维护者自己提出来的。既然开发者已经有这个想法,就更好了,期待修复这个问题的版本可以尽快上线。不过好像开发最近的重心在VLESS上?

@lucifer9
Copy link
Member Author

关于domain socket,很早以前看到就觉得这个目前的实现有问题,这根本就不应该是跟ws,h2这些一起放在传输层,这很显然不合理,而是应该更底层,跟ip:port放在一个设置里。
一般V2Ray用户会用到本机进程间通讯的也就Nginx,caddy,haproxy这些,尤其webserver类,用来搭建ws+TLS或h2+TLS并隐藏在正常的网页服务之下,这应该是domain socket被用的最多的地方了,却只能用着127.0.0.1,眼巴巴看着domain socket却用不了。
其实Linux系统有fastpath,用localhost比uds在速度,延迟,资源消耗上都差不了多少。但,就如上面某层说的,我就单纯只是避免多开一个端口,哪怕是只监听本机的。
今天上v2fly.org找VmessAEAD的信息(是否正式定稿发布,4.28.1之后的版本相互之间可以兼容AEAD,不再要求同版本;以及服务器旧版alterid=0,客户端新版alterid>0是否可行)时,刚好看到DomainSocket,看文档还是放在传输层,就想来搜一搜这么久有没有人提issue,结果没有,这个想法还是项目维护者自己提出来的。既然开发者已经有这个想法,就更好了,期待修复这个问题的版本可以尽快上线。不过好像开发最近的重心在VLESS上?

你说的对,具体到本项目中,Unix Domain Socket本来应该是跟TCP,UDP平级的,对应的是SOCK_STREAM和SOCK_DGRAM。目前来说,如果要修改的话,配置文件必然不能保持兼容,对现有已经实现的协议也要做一些增补。所以不知现在用到这个的用户有多少,感觉要是用户不是太多,那其实就这样凑合着也行 😄 ;如果用户很多,那引入配置文件变更似乎更不方便?

@nftbty
Copy link

nftbty commented Sep 23, 2020

关于这个功能的用户,我觉得已有用户不多(毕竟这个功能实现严格说是存在问题的,导致了我上面说的主要的一些使用场景都没法使用),但潜在用户是很多的(现在很多自己搭建的以及网上很多教程推荐,都是用ws/h2+tls+webserver,有的还套CDN,这些都是用的127.0.0.1:port,因为没法用uds,这部分用户里面,有很多应该是想用uds的。一旦这个功能改好了,其中一部分应该会马上更新使用,强迫症使然或者追求那一点点可能的性能上的提升。然后网上教搭配webserver提高隐蔽性的教程也会有很多更新后使用uds的设置,然后跟着教程学的很多新用户也就都开始使用了。

@RPRX
Copy link
Contributor

RPRX commented Oct 29, 2020

@nftbty

#367

机器人编译完成后可以测试一下

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

Successfully merging this pull request may close these issues.

4 participants