先破后立,不破不立.
什么不是计算机大佬?
在自媒体上发布 "黑客/红客技术正在失传", "寻找传人", "高中再学编程就彻底晚了", "学不会我退出黑客圈/红客圈", "别再盲目自学了,一般人我劝你还是算了吧", "能救一个是一个", "业内顶级大佬几个月时间倾力打造", "整整1000/666/568集,从入门到入狱", "kali学的好,牢饭吃得饱,kali渗透教程", "填志愿, 认准CS计算机"的营销号/卖课人.
在飞机上头像经典的黑色背景, 兜帽男, 匿名者面具, kali的logo, 一遇到笼统性总结的时候就跳出来开始装: "不就是waf吗我都绕了好多个了", "之前也打过几个这样的站","这个站我有全库直接拿0day打","刚刚又拿了一个大型国企的内网", "之前打gov的时候"的圈钱带嗨阔.
在频道里宣传: "保真不保漏", "无盲流水私户收单一个月180,3个月280,6个月360,所有流水一律挂米报单禁止扯皮.", "收单,当天必回" "源头直出, 价格200人名币, 十分钟左右回单, 实惠便宜", "防骗温馨提示, 交易请注意防骗, 建议走头部担保机构"(更多请见威胁猎人黑话词典2.0(数据泄漏篇), 以及信贷欺诈篇), "我们是一支Web3游戏创业团队, ..."的东南亚人.
举例: lidang 立党 (劝人卖房/学CS/买SP500/纳100/OpenAI/Anthrop第一人,yijinglab.
什么是计算机大佬?
在代码托管平台上拉取请求以及提问题,发布,提交,更改文档的人:
粗略看了一眼,xx里的代码从根本上就是有问题的,因为它可能会在xx之外xx,也就是说,这个操作不会被xx,目前我觉得你的那一行改动是可以的,不过它让xx里对xx变得毫无意义了.
目前的私有API已经完全能满足我的需求.我会尝试直接调用它们来解决需求.请问有什么特别的原因,导致API没有直接公开吗?至于使用xx,我可能不太需要它,我在xx中调用xx的原因并不是出于性能考虑,而是因为某些特定操作需要在专用队列上执行.不过,传递的参数可能会出现异常,所以我需要知道在调用xx之前这个函数的调用栈.
我在把xx和xx一起使用时遇到了问题.xx编译了两份独立的xx 这导致了xx(尤其是xx),并在xx上出现了以下链接错误: xx,为了解决这个问题,我做了一些修改,使用了xx x.x.x 版本.
- xx更新到vx.xx.x,一些xx协议级别改进
- xx工具现在默认使用时间模式,分别测试xx和xx各x秒.可通过xx自定义时长.之前基于大小的模式仍可通过xx使用.
- 小幅代码清理
xx函数发送一系列帧,并返回两个变量:
r: 包含查询及其匹配应答的列表
u: 包含未获应答数据包的列表
不过这倒是提醒我了, 我这的xx和xx更新是没有超时也没法手动取消的, 或许应该加一个超时(不过xx 里调用xx的xx可是个麻烦事)
以上的,因为xx的参与,是共性,且不局限于娱乐圈.大佬->大佬,而非大佬->用户,不然请参考以下:
你应该知道,只要对原始PoC修改一行代码,你的驱动程序就会失效,对吧?
然而现在的问题就是xx已经针对xx,而xx上没有更好的xx,就像某些xx存在xx,所以xx成了一个不得不长期存在,维护的xx,这么多年了有些人嘴里一口一个xx,丝毫没有想过完全不要xx的话遇到xx难道直接缴械投降吗?这么说吧是可以完全不要xx,你行你上.
举例: klzgrad, netsecfish.
引用一下ToutyRater的话
很遗憾, 我没有能力预测所有可能出现的问题. 但是, 我可以告诉你, 你遇到的所有问题都有人早就遇到了, 并且还给出了相应的解决办法(除非你是该行业的顶尖人才, 遇到的是需要调用浩瀚的资源才有希望解决的). 所以如果遇到问题, 可以通过搜索引擎搜索解决, 到社区里提问是迫不得已的办法.
我可以很明确地说,在部署的过程中,所遇到所有的问题有90%以上的问题可以通过搜索或者查看相关文档解决,要社区提问才能解决的不足5%. (当然, 意大利面条项目除外)
如果不是,那么只能说明你的综合能力还需提高(比如查资料的能力, 阅读理解能力的). 当然, 我的意思并不是反对到社区提问, 而是希望提问的东西能够有点意义, 谁也不愿意自己就像个复读机一样天天回答网友们千篇一律的问题. 如果有提问的需要, 强烈建议先认真学习一个提问的智慧.(http://www.catb.org/~esr/faqs/smart-questions.html)
不该问的问题中有几个经典问题, 我举两个不经典的问题(一个坏问题, 一个好问题).(被我简化, 第一个原版像懒婆娘的裹脚布一样, github.com/XTLS/Xray-core/issues/5997, 喵呜评价道: 这Agent简单的提示词还注入不了.)
问题一:
客户端配置
{
"inbounds": [
{
"listen": "127.0.0.1",
"port": 31096,
"protocol": "socks"
}
],
"outbounds": [
{
"protocol": "freedom",
"streamSettings": {
"network": "splithttp",
"splithttpSettings": {
"downloadSettings": {
}
}
}
}
]
}客户端日志
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x1259786]
goroutine 35 [running]:
github.com/xtls/xray-core/transport/internet/splithttp.Dial({0x19208c0, 0x339963072690}, {{0x19209a0, 0x3399632f00c0}, 0x50, 0x2}, 0x33996318e770)
github.com/xtls/xray-core/transport/internet/splithttp/dialer.go:393 +0x886
github.com/xtls/xray-core/transport/internet.Dial({0x19208c0, 0x339963072690}, {{0x19209a0?, 0x3399632f00c0?}, 0x0?, 0x0?}, 0x0?)
github.com/xtls/xray-core/transport/internet/dialer.go:63 +0x168
github.com/xtls/xray-core/app/proxyman/outbound.(*Handler).Dial(0x339963304870, {0x19208c0, 0x339963072690}, {{0x19209a0, 0x3399632f00c0}, 0x50, 0x2})
github.com/xtls/xray-core/app/proxyman/outbound/handler.go:312 +0x756
github.com/xtls/xray-core/proxy/freedom.(*Handler).Process.func1()
github.com/xtls/xray-core/proxy/freedom/freedom.go:341 +0xb7c
github.com/xtls/xray-core/common/retry.(*retryer).On(0x339963187538, 0x339963187568)
github.com/xtls/xray-core/common/retry/retry.go:27 +0xc3
github.com/xtls/xray-core/proxy/freedom.(*Handler).Process(0x33996330c120, {0x19208c0, 0x339963072690}, 0x3399633080e0, {0x191d748, 0x339963304870})
github.com/xtls/xray-core/proxy/freedom/freedom.go:288 +0x8cc
github.com/xtls/xray-core/app/proxyman/outbound.(*Handler).Dispatch(0x339963304870, {0x19208c0, 0x339963072690}, 0x3399633080e0)
github.com/xtls/xray-core/app/proxyman/outbound/handler.go:243 +0x992
github.com/xtls/xray-core/app/dispatcher.(*DefaultDispatcher).routedDispatch(0x3399632e7c70, {0x19208c0, 0x339963072690}, 0x3399633080e0, {{0x19209a0, 0x3399632f00c0}, 0x50, 0x2})
github.com/xtls/xray-core/app/dispatcher/default.go:504 +0xb26
github.com/xtls/xray-core/app/dispatcher.(*DefaultDispatcher).DispatchLink(0x3399632e7c70, {0x19208c0, 0x339963072690}, {{0x19209a0?, 0x3399632f00c0?}, 0xef40?, 0x0?}, 0x3399633080e0)
github.com/xtls/xray-core/app/dispatcher/default.go:344 +0x4e6
github.com/xtls/xray-core/common/mux.(*Server).DispatchLink(0x3399632f0870?, {0x19208c0?, 0x339963072690?}, {{0x19209a0?, 0x3399632f00c0?}, 0x80c0?, 0x3399?}, 0x3399633080e0?)
github.com/xtls/xray-core/common/mux/server.go:64 +0xda
github.com/xtls/xray-core/proxy/socks.(*Server).processTCP(0x3399632f9cb0, {0x19208c0, 0x3399630721b0}, {0x7435b9a2a600, 0x339963410018}, {0x1925b60, 0x3399632f0870}, {0x33996304610c, 0x1, 0x1})
github.com/xtls/xray-core/proxy/socks/server.go:157 +0xeff
github.com/xtls/xray-core/proxy/socks.(*Server).Process(0x3399632f9cb0, {0x19208c0, 0x3399630721b0}, 0x2, {0x7435b9a2a600, 0x339963410018}, {0x1925b60, 0x3399632f0870})
github.com/xtls/xray-core/proxy/socks/server.go:91 +0x294
github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).callback(0x33996330a000, {0x7435b9a2a600, 0x339963410018})
github.com/xtls/xray-core/app/proxyman/inbound/worker.go:123 +0xdad
created by github.com/xtls/xray-core/app/proxyman/inbound.(*tcpWorker).Start.func1 in goroutine 34
github.com/xtls/xray-core/app/proxyman/inbound/worker.go:142 +0x7a复现方式
python3 - <<'PY'
import socket, struct, time
s = socket.create_connection(('127.0.0.1', 31096), timeout=2)
s.sendall(b'\x05\x01\x00')
print('greet', s.recv(2))
req = b'\x05\x01\x00\x03' + bytes([len(b'cat.com')]) + b'cat.com' + struct.pack('>H', 80)
s.sendall(req)
PY
greet b'\x05\x00'为什么不该问留作课后作业, 提示: "// just panic".
问题二(坏问题-好问题之间):
XHTTP得开启Vless enc才支持Vision流控吗?
回答:
客户端配置
{
"log": {
"loglevel": "debug"
},
"inbounds": [
{
"port": 10800,
"protocol": "socks",
"settings": {
"udp": true
}
}
],
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "127.0.0.1",
"port": 8443,
"users": [
{
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
"encryption": "mlkem768x25519plus.native.0rtt.cly68i_cSafGfA7MeRR6ybrCwgDWCgUFGm0NnX9s6zk",
"flow": "xtls-rprx-vision"
}
]
}
]
},
"streamSettings": {
"network": "xhttp",
"security": "none"
}
}
]
}服务端配置
{
"log": {
"loglevel": "debug"
},
"inbounds": [
{
"port": 8443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
"flow": "xtls-rprx-vision"
}
],
"decryption": "mlkem768x25519plus.native.600s.QOO1bGLdzXhnxhO62Ui3ywZMA7rLh74kgrWnl5yUjHA"
},
"streamSettings": {
"network": "xhttp",
"security": "none"
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct",
"settings": {
"finalRules": [
{
"action": "allow",
"ip": [
"127.0.0.0/8",
"192.168.0.0/16"
]
}
]
}
}
]
}// xray的freedom outbound对vless Inbound 来的连接默认启用defaultBlockPrivateRule,会blackhole所有127.0.0.1的连接,这会挡住我的echo(压力测试). https://t.me/bytetiger/1027/1812
// 解决方案很煎蛋:
在freedom outbound的settings里加finalRules白名单,(handler的finalRules优先于defaultRule检查) https://t.me/bytetiger/1027/1813curl -v -x socks5://127.0.0.1:10800 http://192.168.1.1(放下板机!)
(形态一)
服务端日志
Xray 26.7.28 (Xray, Penetrates Everything.) 5ca6f4b (go1.26.5 linux/amd64)
A unified platform for anti-censorship.
2026/08/21 16:29:34.670428 [Info] infra/conf/serial: Reading config: &{Name:server.json Format:json}
2026/08/21 16:29:34.672121 [Debug] app/log: Logger started
2026/08/21 16:29:34.672424 [Debug] app/proxyman/inbound: creating stream worker on 0.0.0.0:8443
2026/08/21 16:29:34.675506 [Info] transport/internet/splithttp: listening TCP for XHTTP on 0.0.0.0:8443
2026/08/21 16:29:34.675558 [Warning] core: Xray 26.7.28 started
2026/08/21 16:29:51.083314 [Info] [458579467] proxy/vless/inbound: firstLen = 264
2026/08/21 16:29:51.083498 [Info] [458579467] proxy/vless/inbound: received request for tcp:192.168.1.1:80
2026/08/21 16:29:51.083569 [Info] [458579467] app/dispatcher: default route for tcp:192.168.1.1:80
2026/08/21 16:29:51.083725 [Info] [458579467] transport/internet/tcp: dialing TCP to tcp:192.168.1.1:80
2026/08/21 16:29:51.083742 [Debug] [458579467] transport/internet: dialing to tcp:192.168.1.1:80
2026/08/21 16:29:51.083726 from 127.0.0.1:55748 accepted tcp:192.168.1.1:80 [direct]
2026/08/21 16:29:51.086170 [Info] [458579467] proxy/freedom: connection opened to tcp:192.168.1.1:80, local endpoint 192.168.110.126:58450, remote endpoint 192.168.1.1:80
2026/08/21 16:29:51.086208 [Debug] [458579467] proxy: CopyRawConn (maybe) readv
2026/08/21 16:29:51.086459 [Debug] [458579467] proxy: Xtls Unpadding new block, content 74 padding 125 command 0
2026/08/21 16:29:51.088103 [Debug] [458579467] proxy: XtlsPadding 41 118 0
2026/08/21 16:29:51.089553 [Debug] [458579467] proxy: XtlsPadding 654 171 0客户端日志
Xray 26.7.28 (Xray, Penetrates Everything.) 5ca6f4b (go1.26.5 linux/amd64)
A unified platform for anti-censorship.
2026/08/21 16:29:39.765603 [Info] infra/conf/serial: Reading config: &{Name:client.json Format:json}
2026/08/21 16:29:39.768120 [Debug] app/log: Logger started
2026/08/21 16:29:39.768258 [Debug] app/proxyman/inbound: creating stream worker on 0.0.0.0:10800
2026/08/21 16:29:39.768601 [Info] transport/internet/tcp: listening TCP on 0.0.0.0:10800
2026/08/21 16:29:39.768910 [Warning] core: Xray 26.7.28 started
2026/08/21 16:29:51.031917 [Info] [3438378838] proxy/socks: TCP Connect request to tcp:192.168.1.1:80
2026/08/21 16:29:51.031951 [Info] [3438378838] app/dispatcher: default route for tcp:192.168.1.1:80
2026/08/21 16:29:51.031958 [Debug] [3438378838] transport/internet/splithttp: XMUX: creating xmuxClient because xmuxClients is empty
2026/08/21 16:29:51.031966 [Info] [3438378838] transport/internet/splithttp: XHTTP is dialing to tcp:127.0.0.1:8443, mode packet-up, HTTP version 1.1, host 127.0.0.1
2026/08/21 16:29:51.032120 from tcp:127.0.0.1:47380 accepted tcp:192.168.1.1:80
2026/08/21 16:29:51.032262 [Debug] [3438378838] transport/internet: dialing to tcp:127.0.0.1:8443
2026/08/21 16:29:51.032616 [Info] [3438378838] proxy/vless/outbound: tunneling request to tcp:192.168.1.1:80 via 127.0.0.1:8443
2026/08/21 16:29:51.033599 [Debug] [3438378838] transport/internet: dialing to tcp:127.0.0.1:8443
2026/08/21 16:29:51.068912 [Debug] [3438378838] proxy: XtlsPadding 74 125 0
2026/08/21 16:29:51.069258 [Debug] [3438378838] transport/internet: dialing to tcp:127.0.0.1:8443
2026/08/21 16:29:51.088380 [Debug] [3438378838] proxy: Xtls Unpadding new block, content 41 padding 118 command 0
2026/08/21 16:29:51.089683 [Debug] [3438378838] proxy: Xtls Unpadding new block, content 654 padding 171 command 0应用 encryption/decryption: "none" 后(形态二)
服务端日志
2026/08/21 16:15:33.838789 [Debug] app/log: Logger started
2026/08/21 16:15:33.838841 [Debug] app/proxyman/inbound: creating stream worker on 0.0.0.0:8443
2026/08/21 16:15:33.843025 [Info] transport/internet/splithttp: listening TCP for XHTTP on 0.0.0.0:8443
2026/08/21 16:15:33.843086 [Warning] core: Xray 26.7.28 started
2026/08/21 16:16:23.979887 [Info] [878277073] app/proxyman/inbound: connection ends > EOF客户端日志
2026/08/21 16:15:45.257504 [Debug] app/log: Logger started
2026/08/21 16:15:45.257588 [Debug] app/proxyman/inbound: creating stream worker on 0.0.0.0:10800
2026/08/21 16:15:45.258623 [Info] transport/internet/tcp: listening TCP on 0.0.0.0:10800
2026/08/21 16:15:45.258806 [Warning] core: Xray 26.7.28 started
2026/08/21 16:16:23.978589 [Info] [3715636210] proxy/socks: TCP Connect request to tcp:192.168.1.1:80
2026/08/21 16:16:23.978618 [Info] [3715636210] app/dispatcher: default route for tcp:192.168.1.1:80
2026/08/21 16:16:23.978625 [Debug] [3715636210] transport/internet/splithttp: XMUX: creating xmuxClient because xmuxClients is empty
2026/08/21 16:16:23.978696 from tcp:127.0.0.1:38022 accepted tcp:192.168.1.1:80
2026/08/21 16:16:23.978730 [Info] [3715636210] transport/internet/splithttp: XHTTP is dialing to tcp:127.0.0.1:8443, mode packet-up, HTTP version 1.1, host 127.0.0.1
2026/08/21 16:16:23.979025 [Debug] [3715636210] transport/internet: dialing to tcp:127.0.0.1:8443
2026/08/21 16:16:23.979282 [Info] [3715636210] proxy/vless/outbound: tunneling request to tcp:192.168.1.1:80 via 127.0.0.1:8443
2026/08/21 16:16:23.979336 [Info] [3715636210] app/proxyman/outbound: app/proxyman/outbound: failed to process outbound traffic > proxy/vless/outbound: XTLS only supports TLS and REALITY directly for now.执行sed -i '/flow/d' client.json server.json后(形态三)
服务端日志
2026/08/21 16:26:21.750256 [Info] [2170002380] proxy/vless/inbound: firstLen = 100
2026/08/21 16:26:21.750309 [Info] [2170002380] proxy/vless/inbound: received request for tcp:192.168.1.1:80
2026/08/21 16:26:21.750318 [Info] [2170002380] app/dispatcher: default route for tcp:192.168.1.1:80
2026/08/21 16:26:21.750324 [Info] [2170002380] transport/internet/tcp: dialing TCP to tcp:192.168.1.1:80
2026/08/21 16:26:21.750328 [Debug] [2170002380] transport/internet: dialing to tcp:192.168.1.1:80
2026/08/21 16:26:21.750289 from 127.0.0.1:48074 accepted tcp:192.168.1.1:80 [direct]
2026/08/21 16:26:21.752152 [Info] [2170002380] proxy/freedom: connection opened to tcp:192.168.1.1:80, local endpoint 192.168.110.126:53802, remote endpoint 192.168.1.1:80
2026/08/21 16:26:21.752242 [Debug] [2170002380] proxy: CopyRawConn (maybe) readv客户端日志
2026/08/21 16:26:21.748898 [Info] [360709338] proxy/socks: TCP Connect request to tcp:192.168.1.1:80
2026/08/21 16:26:21.748921 [Info] [360709338] app/dispatcher: default route for tcp:192.168.1.1:80
2026/08/21 16:26:21.748925 [Debug] [360709338] transport/internet/splithttp: XMUX: creating xmuxClient because xmuxClients is empty
2026/08/21 16:26:21.749011 from tcp:127.0.0.1:36128 accepted tcp:192.168.1.1:80
2026/08/21 16:26:21.749044 [Info] [360709338] transport/internet/splithttp: XHTTP is dialing to tcp:127.0.0.1:8443, mode packet-up, HTTP version 1.1, host 127.0.0.1
2026/08/21 16:26:21.749228 [Debug] [360709338] transport/internet: dialing to tcp:127.0.0.1:8443
2026/08/21 16:26:21.749591 [Info] [360709338] proxy/vless/outbound: tunneling request to tcp:192.168.1.1:80 via 127.0.0.1:8443
2026/08/21 16:26:21.749898 [Debug] [360709338] transport/internet: dialing to tcp:127.0.0.1:8443形态一和形态三中的curl命令将立刻返回 HTTP/1.1 200 OK,Content-Length: 444,HTML标题是"中国电信智能网关". 但形态二则会
* Trying 127.0.0.1:10800...
* Connected to 127.0.0.1 (127.0.0.1) port 10800
* SOCKS5 connect to 192.168.1.1:80 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 10800
> GET / HTTP/1.1
> Host: 192.168.1.1
> User-Agent: curl/8.5.0
> Accept: */*
>2026/08/21 16:16:23.979336 [Info] [3715636210] app/proxyman/outbound: app/proxyman/outbound: failed to process outbound traffic > proxy/vless/outbound: XTLS only supports TLS and REALITY directly for now.其中2026/08/21 16:16:23.979336是时间戳, [Info]是日志等级, [3715636210] app/proxyman/outbound: app/proxyman/outbound: failed to process outbound traffic > proxy/vless/outbound: 是错误传播链, XTLS only supports TLS and REALITY directly for now.才是错误消息.
搜索 "XTLS only supports TLS and REALITY directly for now." 后, 有两个文件, proxy/vless/outbound/outbound.go, proxy/vless/inbound/inbound.go. 肯定要选择proxy/vless/outbound开头的, 因为错误传播链说明了两件事: proxyman处理outbound流量时失败, 错误上下文属于proxy/vless/outbound.
找到了它的一个case分支
case protocol.RequestCommandTCP, protocol.RequestCommandRvs:
var t reflect.Type
var p uintptr
if commonConn, ok := conn.(*encryption.CommonConn); ok {
if _, ok := commonConn.Conn.(*encryption.XorConn); ok || !proxy.IsRAWTransportWithoutSecurity(iConn) {
ob.CanSpliceCopy = 3 // full-random xorConn / non-RAW transport / another securityConn should not be penetrated
}
t = reflect.TypeOf(commonConn).Elem()
p = uintptr(unsafe.Pointer(commonConn))
} else if tlsConn, ok := iConn.(*tls.Conn); ok {
t = reflect.TypeOf(tlsConn.Conn).Elem()
p = uintptr(unsafe.Pointer(tlsConn.Conn))
} else if utlsConn, ok := iConn.(*tls.UConn); ok {
t = reflect.TypeOf(utlsConn.Conn).Elem()
p = uintptr(unsafe.Pointer(utlsConn.Conn))
} else if realityConn, ok := iConn.(*reality.UConn); ok {
t = reflect.TypeOf(realityConn.Conn).Elem()
p = uintptr(unsafe.Pointer(realityConn.Conn))
} else {
return errors.New("XTLS only supports TLS and REALITY directly for now.").AtWarning()
}
i, _ := t.FieldByName("input")
r, _ := t.FieldByName("rawInput")
input = (*bytes.Reader)(unsafe.Pointer(p + i.Offset))
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))一个连接类型判断, 如果不是encryption.CommonConn,tls.Conn(TLS),tls.UConn(uTLS), reality.UConn(REALITY)其中的一种则会 return errors.New("XTLS only supports TLS and REALITY directly for now.").AtWarning().
搜索xhttp(企图找到xhttp的连接类型),看到了transport/internet/splithttp/这个目录,并根据 https://xtls.github.io/config/transports/xhttp.html, 得知了实现上下行分离的splithttp被更名为了xhttp.
建立连接的代码应该在transport/internet/splithttp/dialer.go(当时的假设: dial代表了拨号, dialer(拨号员?),因为在1970-1990年, Modem建立连接要向ISP发起拨号, 建立连接(dial)于是沿用至今)
dialer.go中Dial函数的外部接口定义
func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error)入参列表包含了net.Destination, 那必然是建立连接的地方了.
它的返回 return stat.Connection(&conn), nil
conn的定义
conn := splitConn{
writer: writer,
onClose: func() {
if closed.Add(1) > 1 {
return
}
if xmuxClient != nil {
xmuxClient.DoneRunning()
}
if xmuxClient2 != nil && xmuxClient2 != xmuxClient {
xmuxClient2.DoneRunning()
}
},
}搜索splitConn(企图找到结构体), 发现在transport/internet/splithttp/connection.go.
splitConn恰好继承了net.conn的所有方法, 而在transport/internet/stat/connection.go中
type Connection interface {
net.Conn
}这个接口嵌入的确说明了stat.Connection继承了net.conn的所有方法, 于是return stat.Connection(&conn), nil依旧splitConn. 而splithttp.splitConn不是encryption.CommonConn, tls.Conn(TLS),tls.UConn(uTLS), reality.UConn(REALITY)其中的一种.
所以服务端读请求体io.EOF的问题在于客户端建立了xhttp连接, 服务端xhttp inbound收到连接, 但客户端vless outbound在写入vless请求前就退出并关闭连接,不然服务端日志会有vless/inbound: received request...
形态一和形态二的差异在于ML-KEM-768(后量子密钥交换)会在建立连接后额外做一次握手, 把splitConn包装成encryption.CommonConn.
if h.encryption != nil {
var err error
if conn, err = h.encryption.Handshake(conn); err != nil {
return errors.New("ML-KEM-768 handshake failed").Base(err).AtInfo()
}
}h是handler, Vless出站处理器本身.
在proxy/vless/encryption/client.go中,func (i *ClientInstance) Handshake(conn net.Conn) (*CommonConn, error)会return c, nil
c := NewCommonConn(conn, protocol.HasAESGCMHardwareSupport)
func NewCommonConn(conn net.Conn, useAES bool) *CommonConn {
return &CommonConn{
Conn: conn,
UseAES: useAES,
}
}而这次vless outbound匹配到了 if commonConn, ok := conn.(*encryption.CommonConn); ok { 然后禁用splice(非RAW传输时会禁用splice优化,因为IsRAWTransportWithoutSecurity(iConn)为false),继续处理,服务端(vless inbound先赋值iConn -> decryption.Handshake -> ob.CanSpliceCopy = 3)同理. (CanSpliceCopy=1,当前可以splice;CanSpliceCopy=2,预计可以splice(Vision的padding帧还没处理完,等待处理结束后再切换到1);CanSpliceCopy=3,不会splice,直接回退普通拷贝(ReadV, buf.Copy).(Splice 是Linux Kernel提供的函数))
形态三去掉两端flow后,不会进入Vision分支(不使用XTLS,自然不能splice).
延伸阅读
https://x.com/bytecategory/status/2072653855301464394
https://toutyrater.github.io
https://t.me/nyarvexxx/730