-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Sockopt: Fix Darwin (macOS, iOS...) UDP interface
bind
#4530
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
Conversation
测试过了吗? |
yep |
|
|
我记得之前试过 这个PacketConnWrapper有用的 随便绕会导致核心里有的东西炸掉 就是ListenSystemPacket传进来的conn然后对fd进行操作 wrapper一下怎么会炸呢 有问题也是ListenSystemPacket传进来的packetconn的问题吧 |
|
|
删掉bind部分试试? |
Xray-core/transport/internet/sockopt_darwin.go Lines 227 to 228 in 29e37e8
While I was working on macOS/iOS sockopt, remember that I used this function to get interface index by reason, but don't really remember the reason. BTW |
我先修复一下Test的问题
会炸 |
Thanks for your work, do you have any suggestions for this PR. |
|
看了下代码,这个 PacketConnWrapper 是 *ray 为了把 net.PacketConn 包装成 net.Conn,绕过的话一些断言相关的代码会炸 至于要绕过 ListenSystemPacket 才能 bind 成功,大概是因为 bind 哪个 interface 必须在它 listen 时指定,而 ListenSystemPacket() -> effectiveListener.ListenPacket() -> getControlFunc() 内调用的只有 applyInboundSocketOptions,而没有 outbound 但是说实话吧我觉得既然是 dial 就别调用 ListenSystemPacket 了,这东西是 inbound 用的,正确做法是把上面关于 UDP 的整块代码删掉,而最后 return 的那个系统 dialer.DialContext 返回的 net.Conn 其实是 net.UDPConn,不需要 PacketConnWrapper 所以为啥 Xray 一开始 fork 来的代码,dial UDP 就是 ListenSystemPacket+PacketConnWrapper?好奇怪。。。 |
…etConnWrapper struct #4530 (comment)
基于 8b89abc rebase 一下,你们试一下 FullCone 没问题的话就行,底层 dialer 这块代码以后还得继续简化 |
Done |
a3f3fba
to
a048d01
Compare
8b89abc 的 test 炸了很多,感觉是还有哪个地方要改,@Fangliding 你看看? |
我看到了,use of WriteTo with pre-connected connection,不知道是 Golang 的限制还是操作系统的限制 绕不过的话还是得先 Listen,但是不能用 ListenSystemPacket(),而要用带 applyOutboundSocketOptions() 的代码 |
dial出去的连接和远端地址绑定的 write to 会炸 |
还是回滚回去吧 这样改肯定是不行的 |
没办法提供真机给你远程 亚马逊有个EC2 Mac,白嫖个学生优惠去试试? |
Anyway,现有代码 dial UDP 时调用的却是入站的 ListenSystemPacket(),导致涉及到 controllers、applyInboundSocketOptions()、setReusePort(fd) 等入站专属的东西,过于劣质了,我先把这个改掉,试试 applyOutboundSocketOptions() 放 lc.Control 里 |
这样会把Android客户端搞坏 还是得listensystempacket出去 用点其他东西标记来自inbound还是outbound然后在getControlFunc识别比较好 |
|
这 ListenSystemPacket() 是个函数,effectiveListener 是未导出的变量,第三方调用者都改不了,只有 controllers 能加料进去吧 |
Linux 上出入站 sockopt UDP 相关代码的差距也就入站多了 ReceiveOriginalDestAddress 和 V6Only,出站多了 Interface 如果仍想要这两项,应当把它们加到出站的代码,而不是出站 dial UDP 去调用入站 ListenSystemPacket() 的劣质行为 |
有一个 UseAlternativeSystemDialer 啊 |
这是 effectiveSystemDialer,不是 effectiveListener,后者我看了代码里没地方改它,只有往 controllers 加料的可能 |
@92613hjh 你试下能用了吗 |
8284a0e 经过测试,darwin可以绑定 |
interface
bind
感谢 PR 与测试!我盲猜最开始是 applyOutboundSocketOptions() 前面有 setReusePort(fd) 的锅,你测试一下 |
在原版去掉getControlFunc()中的setReusePort(fd)还是无法bind |
话说我看只有 Darwin 上的 inbound 有绑 interface, |
好像是祖传代码,不过似乎并不能在入站起过滤效果 |
|
打破 #4504 |
XTLS#4530 (comment) (cherry picked from commit 8284a0e)
fix #4007