macOS 路由 process 匹配:双栈 socket(IPv4-mapped)连接始终 process not found;非 root 运行时进程查找完全失效
### 完整性要求
- [x] 我读完了 issue 模板中的所有注释,确保填写符合要求。
- [x] 我保证阅读了文档,了解所有我编写的配置文件项的含义,而不是大量堆砌看似有用的选项或默认值。
- [x] 我提供了完整的配置文件和日志,而不是出于自己的判断只给出截取的部分。
- [x] 我搜索了 issues, 没有发现已提出的类似问题。
- [x] 问题在 Release 最新的版本上可以成功复现
### 描述
环境:macOS 26(Darwin 25.5.0)arm64,Xray 26.7.11 官方 release(50231ea)。#6447 引入的 macOS 进程查找存在两个问题。
**问题一(主要):双栈 socket 的 IPv4 连接永远无法匹配**
.NET / Java 等运行时默认创建 AF_INET6 双栈 socket,以 v4-mapped(`::ffff:a.b.c.d`)方式连接 IPv4 目标。此类连接在路由评估 process 规则时 100% 报 `process not found`。
代码原因:`common/net/find_process_darwin.go` 的 `darwinSocketInfoMatchLevel`:
```go
if srcAddr.Is4() {
if family != unix.AF_INET || vflag&darwinInSockInfoIPv4 == 0 {
return darwinSocketNoMatch
}
}
```
实测内核数据(proc_pidfdinfo PROC_PIDFDSOCKETINFO,arm64):双栈 v4-mapped TCP 连接呈现 `soi_family=30 (AF_INET6)`、`insi_vflag=0x1 (INI_IPV4)`,被 `family != unix.AF_INET` 排除。
修复建议:`family == unix.AF_INET6 && vflag&darwinInSockInfoIPv4 != 0` 的条目也应参与 IPv4 匹配。地址比较无需改动:insi_laddr/insi_faddr 是 in4in6 布局,IPv4 地址在 16 字节的最后 4 字节,现有 `darwinAddrMatches` 的 `raw[12:16]` 比较已兼容。
实际影响:v2rayN macOS 每秒轮询 metrics(/debug/vars)的 .NET HttpClient 即双栈 socket,Error 日志每秒刷屏;所有 .NET/Java 桌面应用的流量都无法按 process 分流。
**问题二(附加):非 root 运行时查找对任何进程都失败**
非 root 启动 xray(普通代理模式,无 TUN),即使纯 AF_INET 的同用户客户端也一律 `process not found`(见日志:AF_INET + IP 目标、域名目标、目标恰为代理端口三种情况全部失败)。
同一台机器上用 C 复刻同一算法(sysctl kern.proc.all → proc_pidinfo(PROC_PIDLISTFDS) → proc_pidfdinfo(PROC_PIDFDSOCKETINFO)),非 root 可正确命中目标进程(996 个进程枚举、683 个 fd 可访问、精确命中 1 个)。已逐一核对 struct socket_fdinfo 相关 offset 与实现中的硬编码常量完全一致(sizeof=792、proc_fdinfo=8、psi=24、soi_protocol=180、soi_family=184、soi_kind=256、tcpsi_ini=264、insi_lport=268、insi_vflag=288、insi_faddr=296、insi_laddr=312)。
root 运行时 AF_INET 客户端可正常匹配(TUN 生产环境日志验证:浏览器流量无报错,仅双栈客户端报错),因此问题二仅影响非 root 部署。
### 重现方式
1. 非 root 启动:`xray run -c config.json`(配置见下,仅 socks 入站 + freedom 出站 + 一条 process 规则,无需服务端)
2. 运行以下 python 客户端,先后用 AF_INET 与 AF_INET6 双栈 socket 通过 socks5 发起 CONNECT:
```python
import socket, struct, time
def socks5_request(family, connect_addr, label):
s = socket.socket(family, socket.SOCK_STREAM)
try:
s.settimeout(3)
s.connect((connect_addr, 11080))
s.sendall(b"\x05\x01\x00")
s.recv(2)
s.sendall(b"\x05\x01\x00\x01" + socket.inet_aton("127.0.0.1") + struct.pack(">H", 11081))
try:
s.recv(10)
except socket.timeout:
pass
print(f"{label}: local port {s.getsockname()[1]}")
finally:
s.close()
socks5_request(socket.AF_INET, "127.0.0.1", "AF_INET")
time.sleep(0.5)
socks5_request(socket.AF_INET6, "::ffff:127.0.0.1", "AF_INET6 dual-stack v4-mapped")
```
3. 观察日志:
- 非 root:两种客户端全部报 `process not found`(问题二)
- root:AF_INET 客户端正常,双栈客户端报 `process not found`(问题一)
### 客户端配置
<details><pre><code>
{
"log": {
"loglevel": "debug"
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": 11080,
"protocol": "socks",
"tag": "socks-in"
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
}
],
"routing": {
"rules": [
{
"type": "field",
"process": ["self/"],
"outboundTag": "direct"
}
]
}
}
</code></pre></details>
### 服务端配置
<details><pre><code>
无需服务端。仅本机 socks 入站 + freedom 出站即可复现(见客户端配置),bug 触发点在路由 process 规则评估阶段,与出站无关。
</code></pre></details>
### 客户端日志
<details><pre><code>
(非 root,最小配置,问题二:AF_INET + IP 目标 / 域名目标 / 目标恰为代理端口,三种情况全部 process not found)
Xray 26.7.11 (Xray, Penetrates Everything.) 50231ea (go1.26.5 darwin/arm64)
A unified platform for anti-censorship.
2026/07/23 17:01:52.170996 [Info] infra/conf/serial: Reading config: &{Name:.../repro-config.json Format:json}
2026/07/23 17:01:52.171774 [Debug] app/log: Logger started
2026/07/23 17:01:52.171906 [Debug] app/proxyman/inbound: creating stream worker on 127.0.0.1:11080
2026/07/23 17:01:52.172033 [Info] transport/internet/tcp: listening TCP on 127.0.0.1:11080
2026/07/23 17:01:53.693980 [Info] [1875774516] proxy/socks: TCP Connect request to tcp:127.0.0.1:11081
2026/07/23 17:01:53.697514 [Error] app/router: Unables to find local process name: common/net: process not found for tcp connection from 127.0.0.1:62467 to 127.0.0.1:11081
2026/07/23 17:01:53.697608 from tcp:127.0.0.1:62467 accepted tcp:127.0.0.1:11081 [socks-in >> direct]
2026/07/23 17:01:54.296428 [Info] [3575305247] proxy/socks: TCP Connect request to tcp:www.example.com:80
2026/07/23 17:01:54.302871 [Error] app/router: Unables to find local process name: common/net: process not found for tcp connection from 127.0.0.1:62474 to :0
2026/07/23 17:01:54.302880 from tcp:127.0.0.1:62474 accepted tcp:www.example.com:80 [socks-in >> direct]
2026/07/23 17:01:54.900447 [Info] [3758766399] proxy/socks: TCP Connect request to tcp:127.0.0.1:11080
2026/07/23 17:01:54.906525 [Error] app/router: Unables to find local process name: common/net: process not found for tcp connection from 127.0.0.1:62478 to 127.0.0.1:11080
2026/07/23 17:01:54.906530 from tcp:127.0.0.1:62478 accepted tcp:127.0.0.1:11080 [socks-in >> direct]
(root + TUN 生产环境,问题一:仅 .NET 双栈客户端每秒轮询报错,浏览器 AF_INET 客户端正常无报错)
2026/07/23 15:24:37.196628 [Error] app/router: Unables to find local process name: common/net: process not found for tcp connection from 127.0.0.1:49548 to 127.0.0.1:49316
2026/07/23 15:24:37.196640 from 127.0.0.1:49548 accepted http://127.0.0.1:49316/debug/vars [socks -> direct]
2026/07/23 15:24:37.745609 from 127.0.0.1:49550 accepted //chat.openai.com:443 [socks >> proxy]
2026/07/23 15:24:38.209920 [Error] app/router: Unables to find local process name: common/net: process not found for tcp connection from 127.0.0.1:49552 to 127.0.0.1:49316
</code></pre></details>
### 服务端日志
<details><pre><code>
不适用(无服务端,freedom 直连复现)。
</code></pre></details>
关闭于 13 天前 1 条评论