Repository navigation
fix: 同一台机器同一网络只允许一个客户端注册(含 ICMP NAT 权限降级) - #218
Merged
Merged
Conversation
device_id 由机器标识派生,因此同一台机器上的 vnt2_cli 与 VNT Desktop 内置内核会得出相同的 device_id。两者同时加入同一网络时,服务端把后注册 的连接当成同一设备的新连接并踢掉先注册的那条,双方随即互相替换、无限 重连——表现为虚拟网内所有节点都 ping 不通(对端本身完全正常)。 - 新增 vnt-core/src/utils/instance_lock.rs:以 device_id + network_code 为键的跨进程独占锁(Windows 命名互斥体 / Linux 抽象 Unix socket / macOS flock 锁文件)。同一进程内共享同一把锁(同一进程本来就共享 client_instance_id),跨进程互斥,正是 cli 与 Desktop 内核的冲突场景。 - NetworkManager 创建实例时抢锁,锁随实例销毁释放,不同网络互不影响。 - 抢锁失败按已有实例在工作处理:vnt2_cli 先通过 ctrl IPC 查询已有客户端, 失败再读 web_access.toml 调 Desktop 内核的 /api/instances,打印状态后 以 0 退出;vnt2_web 输出明确提示而非错误栈。
btsd321
marked this pull request as draft
October 30, 2026 06:23
创建 raw socket 需要 CAP_NET_RAW(Linux)或管理员(Windows)。非特权环境 (CI runner、容器、普通用户跑 no 模式)里 start_icmp_nat 会直接失败,进而 让整个网络启动失败,Linux/macOS 上 4 个既有测试因此一直红着。 改为仅在权限不足(PermissionDenied / EPERM / EACCES / ERROR_ACCESS_DENIED) 时记 warn 并跳过 ICMP NAT,其它错误照常上报,避免掩盖真实故障。ICMP NAT 只影响经本机出口的 ping 转发,TCP/UDP 组网与虚拟网互通不依赖它。
- acquire 的查表、抢平台锁、登记放进同一临界区:原实现两步分离,并发时 后到的线程会查到空条目后再抢已被占用的平台锁,被误判成外部占用。 - 新增并发共享、不同网络隔离两条用例;并发用例要求各线程持锁到齐再释放, 否则先返回的线程会 drop 掉锁,测不出竞态。 - macOS 锁文件写打开被拒(文件由同机其他用户创建)时退回只读,flock 只需 可读 fd,避免因此把启动打死。 - 探测模块排除含 CR/LF 的令牌(防请求头注入),并限制响应体积。 - README 常见问题补充单实例说明。
btsd321
marked this pull request as ready for review
October 30, 2026 06:29
btsd321
force-pushed
the
fix/single-instance-lock
branch
from
October 30, 2026 06:37
219771f to
fbe836a
Compare
clippy 的 suspicious_open_options 要求 create 与 truncate 必须成对声明, 该分支只在 macOS 编译,Windows/Linux 的本地 clippy 覆盖不到,CI 的 macOS job 因此报错。锁语义与文件内容无关,明确不截断。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
device_id来自机器标识(machine_uid),所以同一台机器上无论用哪个用户、哪个程序启动,派生出的device_id都相同。vnt2_cli与 VNT Desktop 内置内核(vnt2-web)同时加入同一网络时,服务端把后注册的连接视为「同一设备的新连接」,踢掉先注册的那条:被踢的一方立刻重连,又把对方踢掉,形成无限循环。客户端侧表现为:
Error on data_handle_loop: EOF重连一次vnt2_ctrl info在Online/Offline之间反复跳169.254.x(APIPA)修复一:内核单实例锁
新增
vnt-core/src/utils/instance_lock.rs,以device_id + network_code为键加跨进程独占锁:Global\vnt-<sha256 前 8 字节>sun_path[0] == 0)flock锁文件(临时目录)设计要点:
client_instance_id,重复注册没有意义;一个内核管理多个不同网络(Desktop 多配置)时各用各的键,互不干扰。DefaultHasher:不同版本、不同程序(cli 与 Desktop 内核)必须算出同一个名字,标准库哈希值不保证稳定。NetworkManager在创建实例时抢锁,锁作为字段随实例销毁释放。修复二:抢不到锁时报告已有实例
被拒绝属于正常情况(用户重复启动),按成功退出(退出码 0):
vnt2_cli:先通过 ctrl IPC 查询已有客户端(服务器 / 虚拟 IP / 在线节点),失败再读web_access.toml调 Desktop 内核的/api/instances,打印状态后退出。vnt2_web:输出明确提示后退出。顺带修复:ICMP NAT 的权限降级
不加这个改动,本 PR 的 Linux / macOS CI 会继续红(上游 main 现在就是红的,共 4 个用例):
创建 raw socket 需要
CAP_NET_RAW(Linux)或管理员(Windows),GitHub 的 Linux/macOS runner 都没有。原实现直接?上抛,让整个网络启动失败。改为仅在权限不足时(
PermissionDenied/EPERM/EACCES/ERROR_ACCESS_DENIED)记 warn 并跳过 ICMP NAT,其它错误照常上报。ICMP NAT 只影响经本机出口的 ping 转发,TCP/UDP 组网与虚拟网互通不依赖它,这也顺带修好了「普通用户跑--device-mode no起不来」的问题。验证
vnt-core全量测试 279 passed(含用同一network_code在单进程内模拟 4 节点的 loopback 测试)LockHeld穿透context后仍可 downcast;另有 4 个 ICMP 降级判定用例cargo clippy --workspace --all-targets -- -D warnings无警告vnt2_cli,第二个被干净拦下、退出码 0;第一个退出后第二个可正常启动已知限制
flock分支无法本地验证(无 macOS 环境),依赖 CI 的 macOS job 覆盖编译与用例。vnt2_cli时引导用户接管)属于 vnt-desktop 层,留待后续单独处理;内核已返回结构化错误,UI 侧接住即可。