基于 Wails v3 + Vue 3 开发的代理规则可视化管理工具,底层由 sing-box 驱动,提供简洁易用的图形界面来管理代理节点。
支持 Windows、macOS、Linux 三平台。
代理协议
- 支持 Shadowsocks、VMess、VLESS、Trojan、HTTP、SOCKS 协议
- 支持 Hysteria2、TUIC v5 协议
- 支持 TCP、WebSocket、gRPC、HTTP/2 传输协议
- 支持 TLS / Reality 传输层安全配置
规则管理
- 添加、编辑、删除代理规则,支持拖拽排序
- 批量编辑:多选节点后统一编辑,每个节点一张可折叠卡片
- 导入/导出规则为 JSON 文件(仅导出选中节点及其关联的分组/故障转移/链式代理)
- 前置代理:客户端内节点经指定前置节点出站,用于中转加速(设置 → 前置代理)。 可限定只对选中的分组生效,并单独排除个别节点(例如必须从本机 IP 出去的节点)
- 检查更新 / 自动更新:从 GitHub Releases 检测新版本,支持手动与启动时自动更新
- 多选 Delete 快捷键:选中节点后按 Delete 删除(弹窗确认)
- 解析分享链接(vmess://、vless://、ss://、trojan://、http(s)://、socks://、socks5://、hysteria2://、hy2://、tuic://);
暂不支持
hysteria://(Hysteria v1,与 hysteria2 是两套互不兼容的协议) - 批量导入分享链接为批量预分配 ID 与端口,几十上百条粘贴导入约 0.5 秒完成
- 选中普通节点后按 Ctrl+C 可复制标准分享链接,支持粘贴到 v2rayN 等其他客户端;Ctrl+V 可从其他客户端复制的分享链接直接导入
- Hysteria2 支持 pinSHA256(证书指纹,自动开启跳过证书验证)与端口跳跃(mport)
- 多选:Shift 连选、Ctrl 点选,配合批量启停 / 删除 / 编辑 / 分组
- 批量选择、启动、停止、删除(批量操作在后端并发执行,上千节点也能秒级完成)
- 列表虚拟滚动,上万节点仍可流畅滚动与操作
- 列显示可自定义:点表头右侧 ☰ 勾选要显示的列,选择自动保存
- 节点备注:独立于订阅下发的别名,由你自己填写,订阅更新永不覆盖;可排序、可搜索
- 绑定固定出口 IP:给节点绑定期望的出口 IP,启动后探测到的真实出口 IP 与它 不一致就自动停用,适合对端按 IP 做白名单的场景(机场换了落地 IP 后节点仍连得通, 但请求会被对端拒绝,而你毫无察觉)。留空则以首次探测到的 IP 为准,只有开启绑定的节点参与
- 本地代理统一为混合端口,同一端口同时支持 HTTP 和 SOCKS5,自动分配不重复的本地端口
- 多客户端实例通过操作系统端口占位协调推荐端口,未启动节点也不会与其他实例重复分配;端口冲突时不会终止其他客户端的代理进程
- 启动时端口被其他程序占用会指出是哪个进程(进程名 + PID),并可一键结束后自动重试; 自身进程与看不到详情的系统进程不提供该选项,避免误杀
故障转移与链式代理
- 链式代理:多节点链式串联,流量依次经过各节点转发;只含 1 个节点时等同普通代理
- 故障转移:多节点主备切换,主节点故障时自动切换到备用节点
- 二者均支持测速、健康检测、流量监控,可作为系统代理或 TUN 目标
- 编辑运行中的节点 / 链式代理 / 故障转移后按新配置自动重启,修改立即生效
动态会话代理(住宅代理多出口 IP)
- 单个端口按客户端用户名动态切换住宅代理出口 IP,无需为每个会话开一个端口
- 客户端在代理用户名中传入会话标识,按模板(含
{session}占位符)拼成上游真实用户名 - 混合端口:HTTP 与 SOCKS5 客户端均可接入,SOCKS5 侧会话标识取自用户名认证
- 可选前置加速节点(普通节点 / 链式 / 故障转移),用于直连境外网关很慢或不通的情况
- 上游密码保存在本机,客户端只需知道会话标识;可另设客户端密码防止本机其他程序滥用
出口端口(固定端口 ↔ 固定出口 IP)
- 一个本地端口始终对应一个出口 IP,背后由哪个节点承载自动选择,外部程序不必再跟着节点换端口
- 已启动且探测到的出口 IP 一致的节点自动成为候选,IP 变了自动退出,无需手动维护成员
- 多个节点落地同一个 IP 时优先走延迟最低的,挂了或 IP 变了自动切到下一个,端口与出口 IP 都不变
- 没有节点承载该 IP 时拒绝连接,绝不从别的 IP 出去;成员出口 IP 每 3 分钟复查一次,漂移的节点立即摘除并断开其连接
- 只需定义一次「出口 IP + 本地端口」,保存即开始监听;之后哪个节点启动后出口是这个 IP 就自动加入,不用挑选节点
- 可填写备注(如「某平台白名单 IP」),在列表备注列显示,可按备注搜索与排序
节点测速与健康检测
- 测速:普通节点直连测 TCP 延迟 + 通过代理测下载速度(限时采样,慢速网络不超时)
- 测速 URL 与请求 Header 可在设置中自定义(默认沿用内置浏览器 UA)
- 健康检测:无需启动即可检测普通节点连通性(DNS → TCP → TLS/Reality,QUIC 走 UDP 探测),支持后台定时自动检测
- 状态分级:在线、延迟较高、超时、TLS 失败、DNS 失败、Reality 失败、仅 IPv6
- 并发按节点规模自适应,上万节点约 100 秒完成一轮检测
- 按健康状态筛选与批量选中,可快速挑出失败节点批量删除
- 批量选中重复节点(按协议+地址+端口+凭证+传输层参数判重,忽略别名)与 重复出口 IP 的节点;只选中不自动删除,每组保留一个(优先保留运行中、 有出口 IP 绑定或有备注的那个),核对后自行删除
流量监控
- 实时上/下行速度
- 今日 / 累计流量统计(跨天自动清零),最近启停时间记录
- 支持手动清零
订阅管理
- 支持 Clash YAML、V2Ray JSON、SIP008、Base64 格式
- 添加与编辑订阅(名称、地址、自动更新、更新间隔、更新方式、所属分组)
- 更新方式可选:直连 / 系统代理 / 指定节点(临时建立代理,适合本机无法直连订阅链接的情况)
- 批量导入订阅:粘贴多条链接一次汇入同一分组,订阅名按「分组名-序号」自动编号, 再次导入会接着编号;单条失败不影响其余
- 自动定时更新,智能节点合并,订阅节点自动关联分组
- 拉取订阅默认伪装成 Shadowrocket 的 User-Agent(机场按 UA 返回不同内容,未知 UA 常只返回网页或精简列表),可在设置中自定义
- 多个订阅可汇入同一分组;节点按别名、协议、地址端口、凭证及传输层参数 (ws path / SNI 等)识别,重复更新不会累积重复节点
- 机场改名(附上剩余流量、到期日、重排序号)后仍能认出是同一个节点, 保留它原有的本地端口、备注与出口 IP 绑定,不会删掉重建
分组管理
- 手动创建自定义分组
- 订阅自动创建分组,也可让多个订阅共用一个分组
- 多选节点后批量设置分组
- 按分组批量启停节点,分组显示节点计数,支持筛选未分组节点
- 删除分组时级联清理该分组下节点的归属
HTTP API
- 可在设置中启用或关闭 HTTP API,并配置监听地址与端口
- 支持可选 Bearer Token 鉴权,非本机监听时强制启用鉴权
- 提供节点、分组、订阅、故障转移、链式代理、动态会话代理和出口端口的查询、创建、修改、删除与启停接口
- 支持获取全部、已启动、指定分组、指定订阅或指定复合代理的本地 HTTP/SOCKS5 地址
- 内置 OpenAPI 3.0 规范与 Swagger UI 文档
系统集成
- 系统代理:一键将节点设为系统代理(Windows/macOS 自动设置,Linux 需手动设置环境变量)
- TUN 模式:虚拟网卡接管所有程序的流量,转发到选中的节点,不遵循系统代理的程序也能走代理(与系统代理二选一;Windows 需管理员权限,未提权时可一键以管理员身份重启)
- 断网保护:系统代理 / TUN 的目标意外失效时保持代理、不让流量走直连并提示;只有手动停止或删除目标才自动关闭代理
- 系统托盘:最小化到托盘,右键菜单快捷操作(一键启停所有节点、故障转移、链式代理)
- 开机自启:支持设置开机自动启动
- 状态恢复:关闭应用时自动记录已启用的节点,重新打开后自动恢复(包括普通节点、故障转移、链式代理)
- 进程管理:启停时自动清理端口残留进程,避免僵尸进程导致端口占用
- 深色模式:亮色/深色主题切换
- 实时日志:支持搜索、按级别(警告 / 错误等)筛选,鼠标悬停时暂停自动滚动便于查看
- 嵌入式二进制:使用 go:embed 打包 sing-box 内核,开箱即用无需额外安装
新增
- 出口端口:一个固定的本地端口始终对应一个出口 IP,背后由哪个节点承载自动选择, 外部程序不必再跟着节点换端口。只需在侧边栏「添加出口端口」填好出口 IP 和本地端口, 保存即开始监听;之后任何节点启动、探测到的出口是这个 IP 就自动加入, IP 变了或节点停了自动退出,不用挑选节点
- 多个节点落地同一个 IP 时优先走健康且延迟最低的,连不上自动切到下一个; 成员失效时立即断开经它的现有连接,没有节点承载时拒绝连接,绝不从别的 IP 出去
- 出口端口成员的出口 IP 每 3 分钟复查一次,机场中途换落地 IP 也能及时发现
- 出口端口支持备注、分组、批量启停删除、导入导出,重启应用后自动恢复
- HTTP API:
/api/v1/exit-ports增删改查与启停;GET /api/v1/exit-ports/local-proxy?ip=出口IP按出口 IP 取本地代理, 加format=http/format=socks5直接返回http://127.0.0.1:端口这样的代理地址文本
新增
- TUN 模式:通过虚拟网卡接管所有程序的流量,转发到选中的节点 / 链式代理 / 故障转移。不遵循系统代理的程序(游戏、命令行工具等)也能走代理。 工具栏改为「系统代理 / TUN / 关闭代理」,两种模式二选一。 Windows 下需要管理员权限:以普通权限运行时会提示并通过 UAC 以管理员身份重启, 重启后自动恢复节点并开启 TUN。关闭程序即关闭 TUN,不跨重启保留
- 断网保护:系统代理 / TUN 的目标意外失效(进程崩溃、启动后验证不通被停用、 出口 IP 变化被停用等)时,代理保持开启、宁可断网也不让流量走直连,并提示你处理; 目标恢复运行后自动恢复。只有手动停止或删除目标时才自动关闭代理。 目标本地端口变更时代理自动改指向新端口;TUN 进程意外退出时自动重新拉起
- 编辑正在运行的节点、链式代理、故障转移后按新配置自动重启,修改立即生效。 普通节点只在连接参数变化时重启(只改别名、备注不打断连接), 运行中也可以直接修改本地端口
- 链式代理支持只包含 1 个节点,此时等同普通代理
修复
- 修复不先做健康检测、直接批量启动整个订阅时,几乎所有节点都被判为「代理连接失败」 并自动停用。原因是批量验证中每停用一个不通节点就重启一次整片进程,切断了同片其他 节点进行中的验证,好节点也跟着被判不通,连锁停掉整片。现在验证期间停用不通节点只作 标记,等整批验证结束后统一重建一次;探测途中进程被重启时换新进程重新探测
- 关闭程序时先关闭系统代理 / TUN 再停止节点,停止节点期间不再断网
新增
- 批量导入订阅:粘贴多条订阅链接,一次全部汇入同一个分组。
订阅名按「分组名-序号」自动编号(机场合集-1、机场合集-2……),
往已有订阅的分组里再导入会接着编号而不是从 1 重来;
#开头的行会被忽略,单条链接失败不影响其余, 一条都没成功时新建的空分组会被自动清理。 此前添加订阅一次只能一条,十几个机场就要重复十几遍,且每条默认各建一个分组 - 批量选中重复节点:跨订阅买到同一家落地、或同一机场在不同订阅里重复下发, 会攒下大量实际等价的节点,而它们的别名往往不同(机场爱加剩余流量和编号), 肉眼很难挑。判重按协议+地址+端口+凭证+传输层参数,忽略别名
- 批量选中出口 IP 重复的节点:不同节点可能共用同一个落地 IP (机场超售、同一台服务器挂多个入口),对按 IP 做白名单的用途来说留一个就够。 只比对运行中且已探到真实 IP 的节点
- 两个去重都是只选中、不自动删除:每组保留一个,你核对后自行点「删除」。 保留优先级为 运行中 > 有出口 IP 绑定 > 有备注 > 列表首位—— 每一档护住的都是重建不回来的东西,被选中待删的是克隆体
修复
- 修复批量场景下订阅 ID 可能撞车:订阅 ID 取自纳秒时间戳,而 Windows 的时钟 粒度是毫秒级,实测紧凑循环里取 50 次得到的是同一个值。多条订阅共用一个 ID 后, 更新其中一条会把其他几条的节点全部当成「已失效」删掉再重建。 批量导入改为一次性生成互不相同的 ID
新增
- 启动节点时若本地端口被其他程序占用,会查出占用进程并弹窗询问是否结束它, 确认后终止进程、等端口真正释放,再自动重试启动。 此前只报一句「端口已被占用,请更换端口」,既不说是谁占的也没有处理手段, 而占用方往往是临时借用端口的网盘、音乐客户端之类。 安全判定放在后端:自身进程一律不可终止,取不到进程名的(多半是权限不足 看不到的系统进程)同样不给;只终止界面显式点名的进程,不接受 「结束占用这个端口的一切」——探测与终止之间端口可能易主,照旧快照杀会误伤
- 两条启动路径的报错都带上占用者,例如「端口 11001 已被 CloudMusic.exe (PID:8472) 占用」
修复
- 修复端口注册表损坏导致程序完全打不开:桌面上只多出一个空的 xray-configs 目录,
窗口不出现,控制台留下一句
invalid character '\x00'。 成因是保存注册表时先 WriteFile 再 Remove/Rename,而 WriteFile 只保证数据进了 页缓存——此时断电会留下长度正确、内容全是 NUL 的文件。 现在注册表损坏会就地重建(原文件另存为 .corrupted 备查), 且保存改为写临时文件 + fsync + 原子替换,从源头上不再产生半截文件。 注册表同步失败也不再阻断启动与配置保存——它只是多实例协调端口用的缓存, 而此前一旦损坏,连用户的节点都保存不了 - 主配置文件的保存同样改为 fsync + 原子替换:它每次改动都要全量重写, 节点多时可达数 MB,写入窗口更长,而这份文件丢了就是全部节点、订阅、分组都没了
- 修复取消勾选「启用前置代理」后重启又被打回启用:该字段是普通 bool, 无法区分「老配置里没有这个字段」和「用户明确关掉了」——两者都是 false, 而启动时兼容旧配置的迁移会把「选了节点 + 未启用」补成启用, 于是每次重启都把用户取消的勾选打回去
新增
- 节点备注:与订阅下发的别名相互独立的一个字段,由你自己填写,订阅更新永不覆盖。 别名归机场所有,每次更新都会被改掉(常带上剩余流量、到期日、重新编号), 想在节点上记点自己的东西(「这个给爬虫用」「客户 A 专用」)此前无处可放。 备注列可排序,也可用顶部搜索框直接搜
- 绑定固定出口 IP:给节点绑定一个期望的出口 IP,启动后探测到的真实出口 IP 与它不一致就自动停用该节点。 本地端口常被交给外部程序使用(爬虫、浏览器、业务系统),而对端往往按 IP 做白名单;机场换了落地 IP 后节点仍然连得通,但请求会被对端全部拒绝—— 此时「能连上」反而是最坏的情况,外部程序还在往这个端口发流量,而你毫无察觉。 绑定后故障会显式暴露而不是静默失败。 只有显式开启绑定的节点参与检查,其余节点行为完全不变; 绑定值以首次成功探测到的 IP 为准(你无法在启动前预知机场分配的 IP), 也可在节点编辑里手填,或点击「绑定IP」列一键绑定/解绑当前 IP
- 探测真实出口 IP 时优先取 IPv4:兜底探测点改用只有 A 记录的域名, 并对结果做 IPv4 校验,拿到 IPv6 就换下一个探测点。 双栈出口的节点走双栈探测点时会随机返回 IPv4 或 IPv6,同一个节点两次探测 拿到不同家族的地址,绑定比对就会把没变的节点误判成「IP 变了」。 全部探测点都只给 IPv6 时仍然接受,能用的节点不该因为拿不到 IPv4 就被判成不通
修复
- 修复订阅更新后备注丢失、本地端口漂移:节点身份标识的第一个字段是别名, 机场一改名(附上剩余流量、到期日、重排序号)身份就对不上,旧记录被当作 已失效删除、同一个节点又以新 ID 和新分配的端口重新插入。 现对第一轮没配上的两侧再按「去掉别名的标识」配一次,认出「只是改了名」的节点, 保留它原有的 ID、本地端口、备注与出口 IP 绑定。 只在两侧都唯一时才认——同一 CDN 下若有多个仅靠别名区分的节点, 贸然按地址配对会把 A 的备注挪到 B 上,此时宁可退回原有的删除+新增
- 修复删除分组后左侧列表出现两个同名分组:分组管理器持有的是配置切片的内部指针, 而删除分组时切片就地前移,缓存里的指针会串到相邻分组上;之后重命名分组 (或更新订阅名)就改到了无关分组头上,并被写进配置。 已写坏的分组名不会自愈,启动时会按订阅名回正一次 (只处理被单个订阅独占的分组,多订阅共用的分组名和手动分组不受影响)
调整
- 节点列表的操作列去掉「检测」与「删除」两个按钮:两者在工具栏都已有批量入口 (勾选行后点「健康检测」「删除」,未勾选时健康检测作用于全部), 逐行再放一份既占地方,删除按钮逐行摆着也容易误点
新增
- 启动时检测节点端口与系统动态端口范围是否重叠,重叠时在日志中给出提示与修复命令。 Windows 的动态端口范围被改低(例如起始值 10000)时,节点端口会落在其中, 随时可能被其他程序借用为临时源端口,表现为「同一个节点时好时坏、换个端口就正常」。 这种占用处于 Bound 而非 Listen 状态,netstat 和常见的端口查看工具都看不到, 此前几乎无法自行定位
- 点击列表中的本地端口即可复制该节点的本地 HTTP 代理地址,
格式与工具栏的批量复制一致(
http://127.0.0.1:端口)
修复
- 修复分片启动失败时丢失节点级原因:整片节点都被剔除时,日志与界面只显示 「分片内没有可用节点」这句汇总结论,看不出是哪个节点、哪个端口、为什么。 现在会附上每个节点各自的原因(端口被占用、配置无效等), 且单个/批量启动都优先返回节点专属原因而非笼统的调谐错误
新增
- 前置代理支持限定生效范围:可选择多个分组,只有这些分组内的节点经前置节点出站; 也可单独排除个别节点,让它们直连(适合必须从本机 IP 出去、或经前置反而不通的节点)。 留空表示对全部节点生效,与此前的全局行为一致,旧配置无需改动
- 前置代理改用独立的启用开关:关闭时保留已选节点与生效范围, 下次启用不必重新配置(此前只能把节点选成「不使用」,等于清掉配置)
- 链式代理与故障转移也可作为前置代理:它们通过本地端口接入, 启动受影响的节点时会自动把未启动的前置代理先拉起来 (否则这些节点都会报「代理连接失败」,而问题其实不在它们身上)。 例外节点列表同样覆盖这两类
- HTTP API 的
PUT /api/v1/settings/pre-proxy相应支持enabled、groupIds与excludedIds
修复
- 修复批量启动后大部分节点跳过连通性验证、拿不到真实 IP:验证协程会跳过已被 用户停止的节点,但节点置为「已启用」发生在触发验证之后,先跑起来的协程 把正在启动的节点误当成已停止。实测上千节点里只有几十个走了验证
- 修复停止节点后仍显示「验证中」、状态灯一直黄色呼吸:批量启动会把整批标记为 验证中,而探测有并发上限,排队中的节点要等很久才轮到;停止操作没有清除该标记
- 修复验证期间列表不刷新,日志已出真实 IP 但界面计数半天不动: 刷新用的是防抖,而验证期间事件持续不断,计时器一直等不到空档。 改为节流(最多每 500ms 刷新一次),后台刷新不再闪烁加载遮罩
新增
- 「更多 → 复制本地代理 (HTTP / SOCKS5)」:把节点的本机监听地址按行复制到剪贴板, 供爬虫等程序直接使用。选中了节点就复制选中的,没选中则复制全部已启用节点 (验证中的除外,它们连通性尚未确认)
重大变更
-
普通节点改为分片运行:多个节点共享一个 sing-box 进程,不再是一节点一进程。 实测 1583 个节点从约 50 GB 降到约 210 MB(6 个分片),内存降低约 290 倍, 上千节点终于能同时启动而不闪退(实测批量启动 1477 个节点,筛出 1426 个可用)。 每个节点仍监听原有的本地端口,爬虫、健康检查、测速、系统代理的用法完全不变。 链式代理与故障转移有各自定制的配置,仍是独立进程
-
内核统一为 sing-box,移除 Xray-core。sing-box 支持的协议是 Xray 的超集 (Hysteria2 / TUIC 只有 sing-box 能运行),且单内核避免了两套配置生成逻辑 不同步——REALITY 就曾因此在 sing-box 侧被漏写。安装包体积因此减少约 96 MB。 节点配置无需改动,原有节点全部照常工作
-
内置 sing-box 升级至 1.13.16(原 1.13.14)
修复
- 修复 REALITY 节点经 Hysteria2 / TUIC 前置代理时连不通:设置全局前置代理后,
普通节点会并入链式配置改由 sing-box 运行,而 sing-box 侧的配置生成漏写了
REALITY,公钥与 short_id 被静默丢弃、退化成普通 TLS 握手。该配置在语法上
完全合法(
sing-box check通过),只在运行时报unknown version: 72 - 修复大量节点时界面打不开、按钮一直转圈无响应:
- 端口预留改为惰性记账。此前为每个未启动节点常驻一个 TCP 监听来「占住」端口, 上千节点即上千个套接字,启动阶段耗尽句柄并长时间持有全局锁
- Windows 上获取进程名不再 fork
tasklist。该命令依赖 RPC,在部分机器上会卡到 超时(实测单次 303 秒后报错返回空),足以让启动流程僵住;改用 Win32 进程快照, 耗时降至约 10 毫秒 - 端口占用查询改为一次取回全表并短时缓存,批量启动 N 个节点的
netstat/lsof调用从 N 次降到约 1 次
- 修复 Windows 端口匹配误判:此前用后缀匹配,
:110808会被误认为:10808; 同时正确处理 IPv6 的[::]:port写法 - 修复 Linux / macOS 上
lsof因部分文件无权限访问而退出码非 0 时, 整张端口占用表被丢弃、导致所有端口被误判为未占用
新增
- 内存容量保护:每个节点是一个独立内核进程,实测常驻约 33 MB,上千节点会超出 物理内存导致进程被系统终止(表现为闪退)。现在批量启动前按可用内存估算容量, 超出时明确提示「最多可启动约 N 个」而不是让机器被打崩。 崩溃恢复路径同样受保护:此前崩溃前启用了多少节点、重启就会全部自动拉起, 于是一开就再崩、陷入打不开的循环
- 自动启动改为后台执行,窗口不再等待节点全部拉起才显示。此前 Wails 要等
ServiceStartup返回才创建窗口,节点一多就只能看到进程、看不到界面 - 节点列表新增别名、协议、服务器地址、服务器端口、本地端口、真实 IP 六列排序, 文本列按拼音排序且「节点2 / 节点10」按数值大小排(此前排序只支持数值列, 文本列相减得到 NaN、结果随机)
- 列宽支持拖动调整并记忆,列设置里的「重置」会一并清空自定义列宽
- 批量启动时失败节点的提示合并为一条汇总,此前每个失败节点各弹一条会刷屏; 同时对节点列表的整表刷新做了合并,几百次连续事件只重载一次
- 启动后的连通性验证期间单独显示「验证中」状态(琥珀色呼吸圆点)。 此前这段时间显示为「运行中」,用户会以为节点已可用, 而它可能几秒后就被判定不通并自动停用。运行中计数不再包含验证中的节点, 底部另计「验证中 N 个」
- 批量启动后的可用性检测大幅提速:并发从 16 提到 64, 新增独立的建连超时(4 秒),连不通的节点几秒即可判定, 而已连上、只是响应慢的节点仍有完整时间读完响应
- 出口 IP 探测改用 CDN 静态资源(HEAD 请求 +
x-response-cinfo响应头)。 公共 IP 查询 API 在上千节点同时探测时会限流,把可用节点误判为不通—— 实测同一批 1477 个节点,可用数曾在 1426 / 970 / 1255 之间大幅波动。 其余查询服务作为兜底,按端口错开起始位置分摊压力 - 修复操作列「删除」按钮被截成省略号:五个按钮共需约 235px, 而列宽固定在 206px;同时取消该列的文本截断样式(那是给文本列用的)
修复
- 修复订阅更新时重复添加节点:此前仅按「地址:端口」识别,机场把多个节点挂在同一 CDN IP 上时会互相覆盖,每次更新都重复添加(实测 26 次更新后 4 个节点变成 104 条)。现按别名、协议、凭证及传输层参数识别,历史重复项在一次更新后自动收敛
- 修复分享链接与订阅导入丢失
allowInsecure:伪装 SNI 的节点(如sni=iosapps.itunes.apple.com)缺此参数会因证书不匹配而握手失败。同时兼容allow_insecure/insecure/skip-cert-verify写法 - 修复 REALITY 节点无法启动:解析时丢弃了
pbk/sid/spx/fp,导致内核拒绝加载配置、进程刚启动即退出 - 修复健康检测把可用节点误报为 DNS 失败:此前自行解析域名后只连第一个地址,本机无 IPv6 出口或 CDN 多 IP 时会误判;改为交给系统拨号器逐个尝试
- 修复「可用端口不足」误报:分配端口时未查询全局端口注册表,挑中的多是其他实例已占用的端口
- 修复 macOS 上删除节点 / 分组 / 订阅无响应:系统 WebView 不支持原生确认弹窗,改用应用内确认框
- 修复端口为 0 的节点被启动时写坏配置文件的问题
性能
- 批量停止提速约 3000 倍:Windows 上不再为每个节点 fork
taskkill(单次约 1.2 秒),改为直接终止进程;同时修复进程管理器在锁内完成终止导致并发退化为串行的问题 - 新增批量删除接口:并发停止、一次性移除并只保存一次配置,500 个节点约 0.02 秒
- 健康检测并发随规模自适应,200 个超时节点从 50 秒降至 2 秒;结果合批落库与推送,上万节点不再卡死界面
- 添加大订阅(上万节点)不再卡顿:ID 与端口批量分配、端口注册表单次写入
- 批量导入分享链接不再卡住:此前循环内逐个生成 ID(每次全表扫描)并逐个分配端口 (每次重扫端口段 + 抢文件锁写一次端口注册表),且全程持有全局锁,界面表现为整个应用无响应。 实测分配 50 个端口从 773 毫秒降至 14 毫秒,端到端导入 50 个节点约 0.5 秒。 导入配置文件走的同一段逻辑,一并修复
- 节点列表虚拟滚动,上万节点滚动与操作保持流畅
新增
- 节点列表新增「所属分组」列,并支持自定义显示 / 隐藏列(选择自动保存)
- 工具栏新增按健康状态筛选与批量选中,可快速挑出失败节点批量处理
- 订阅可指定所属分组,多个订阅能汇入同一分组统一管理
- 新增「仅 IPv6」健康状态:本机无 IPv6 出口时无法探测这类节点,如实提示而非误报失败,且不会被「选中失败」误删
- 导入
hysteria://(Hysteria v1)改为明确提示不支持,此前只报「不支持的链接格式」看不出原因 - 拉取订阅改为携带 User-Agent,默认伪装成 Shadowrocket,可在设置 → 订阅中自定义。
此前不带 UA,Go 默认发送
Go-http-client/1.1,部分机场因此只返回网页或精简节点列表 - HTTP API 新增批量删除节点接口
POST /api/v1/nodes/delete - 界面改为自适应宽度,消除窗口偏小时的横向滚动条与内容溢出
- 修复安装目录含中文(或其他多字节字符)时自动更新失败:更新脚本改用 CRLF 换行,此前纯 LF 会让 cmd.exe 在错误位置切行,出现
'ARGET' 不是内部或外部命令等报错,更新静默中止
此修复需先手动安装一次本版本,之后的自动更新才会恢复正常——旧版本内置的更新逻辑仍是有问题的。
- 新增动态会话代理:单个端口按客户端传入的用户名动态切换住宅代理出口 IP,不必再为每个会话开一个端口
- 会话代理为混合端口,HTTP 与 SOCKS5 客户端均可接入;上游用户名支持
{session}模板拼接或原样透传 - 会话代理可选前置加速节点(普通节点 / 链式 / 故障转移),并支持「跟随全局前置代理」自动联动
- 会话代理提供实时统计(活跃连接、累计连接、会话数、上下行流量),新会话首次出现时记录日志便于核对模板
- 新增会话代理的 HTTP API 与 OpenAPI 文档,支持查询、创建、修改、删除与启停
- 节点编辑器在 HTTP/SOCKS 用户名含会话标识时给出提示,避免误用普通节点(其用户名写死在内核配置中,只会有单一出口 IP)
- HTTP API 端口被占用时不再中止应用启动,改为记录日志后继续运行
- 新增全局前置代理,可搜索并选择中转节点,普通节点、故障转移和链式代理均可经前置节点出站
- 新增 GitHub Releases 更新检查、启动时自动检查及自动下载安装
- 新增跨客户端实例的端口注册与占位,端口冲突时可选择需要重新分配的资源,不再终止其他客户端进程
- 新增标准分享链接复制粘贴:选中普通节点后可用 Ctrl+C 导出,Ctrl+V 可直接导入分享链接
- 分享链接新增 HTTP、SOCKS5、Hysteria2 和 TUIC 等协议的解析与编码支持
- HTTP API 新增故障转移、链式代理和全局前置代理管理接口,并扩展本地代理查询范围
- 节点列表新增已选数量提示和 Delete 快捷删除,前置代理选择支持按别名、协议、地址及端口搜索
- 新增可配置 HTTP 管理 API,默认监听
127.0.0.1:9090 - 新增节点、分组、订阅的 RESTful 管理与批量启停接口
- 新增全部、已启动、按分组及按订阅获取本地代理地址的接口
- 新增 Bearer Token 鉴权,非本机监听时强制启用
- 设置界面新增 HTTP API 服务、监听地址、端口、鉴权和 Token 配置
- 内置 Swagger UI 与 OpenAPI 3.0 文档
- HTTP API 配置修改后立即重启服务,启动失败时自动回滚
前往 Releases 页面下载对应平台的安装包,或通过 GitHub Actions 获取最新构建产物。
- Windows (amd64): 下载并运行
xray-manager-windows-amd64.exe - macOS (arm64 / Apple Silicon): 下载
xray-manager-macos-arm64.dmg,拖入 Applications 即可 - Linux (amd64): 下载
xray-manager-linux-amd64,chmod +x后运行;需桌面环境(图形界面),并安装运行库libgtk-3-0 libwebkit2gtk-4.1-0
首次运行时会自动将内置的 sing-box 内核提取到可执行文件同级的
xray-bin/目录,请在有写入权限的目录中运行。
-
Go 1.24+
go version
-
Node.js 18+
node --version
-
Wails v3 CLI(需与项目锁定的版本一致,否则 Linux 可能出现 GTK 版本冲突)
go install github.com/wailsapp/wails/v3/cmd/wails3@v3.0.0-alpha.41
-
Task(任务运行器)
go install github.com/go-task/task/v3/cmd/task@latest
-
内核二进制文件(已内置于仓库)
仓库已包含三平台的 sing-box 二进制(通过
go:embed打包), 正常构建无需额外下载。如需自行更新版本,替换以下文件即可:internal/assets/singbox/{windows/sing-box.exe, linux/sing-box, darwin/sing-box}
注意:架构需与目标平台一致(Windows/Linux 为 amd64,macOS 为 arm64)。 替换后无需清理
xray-bin/:程序按文件大小判断是否复用,体积不同会自动覆盖旧的提取副本。
| 平台 | 依赖 |
|---|---|
| Windows | WebView2 Runtime(Windows 10+ 自带) |
| macOS | 无需额外依赖 |
| Linux | libgtk-3-dev libwebkit2gtk-4.1-dev(Ubuntu/Debian)gtk3-devel webkit2gtk4.1-devel(Fedora) |
wails3 dev# Windows
wails3 task windows:build PRODUCTION=true
# macOS(.app 包)
wails3 task darwin:package
# Linux(裸二进制)
wails3 task linux:build
# Linux(打包为 AppImage / deb / rpm)
wails3 task linux:package编译产物位于 bin/ 目录。
程序启动后默认监听 127.0.0.1:9090,API 前缀为 /api/v1。监听地址、端口、服务开关和 Bearer Token 鉴权可在程序的“设置 → HTTP API”中配置,保存后立即生效。监听非本机地址时必须启用鉴权。
Swagger UI 文档地址为 http://127.0.0.1:9090/api/docs/,OpenAPI 规范地址为 http://127.0.0.1:9090/api/openapi.yaml。Swagger UI 的 “Authorize” 按钮可填写设置中的 Token。
Swagger UI 页面资源由
unpkg.com加载;无法访问该 CDN 时仍可直接下载内置的 OpenAPI YAML。Token 会保存在程序目录的配置文件中,请限制该文件的访问权限,不要将 Token 提交到版本库。
开启鉴权后的请求示例:
curl -H "Authorization: Bearer YOUR_TOKEN" http://127.0.0.1:9090/api/v1/local-proxies/enabled本地代理接口返回同一混合端口的 HTTP 与 SOCKS5 地址,并通过 type 区分 rule、loadBalancer 和 chainProxy。全部接口也会返回尚未启动的资源配置;需要可立即使用的代理时,请调用对应的 /enabled 接口。
节点采用分片运行,上千个节点也只占几个进程、约几百 MB 内存,因此可以一次全部启动, 再由客户端在这些本地端口之间轮换,每个端口对应一个独立出口 IP。
不想写代码调接口时,可直接在界面上「更多 → 复制本地代理 (HTTP / SOCKS5)」, 把地址按行复制到剪贴板(选中了节点就复制选中的,没选中则复制全部已启用节点):
http://127.0.0.1:11000
http://127.0.0.1:11001
http://127.0.0.1:11002
也可以调接口自动获取:
import itertools, requests
# 取出全部已启动节点的本地代理地址
proxies = requests.get(
"http://127.0.0.1:9090/api/v1/local-proxies/enabled",
headers={"Authorization": "Bearer YOUR_TOKEN"},
).json()["data"]
pool = itertools.cycle([p["httpUrl"] for p in proxies])
for url in urls:
proxy = next(pool) # 每个请求换一个出口 IP
requests.get(url, proxies={"http": proxy, "https": proxy})返回的每项形如 {"id": ..., "type": "rule", "alias": ..., "localPort": 11000, "httpUrl": "http://127.0.0.1:11000", "socks5Url": "socks5://127.0.0.1:11000", ...}。
先用 POST /api/v1/nodes/start 批量启动(Body 为 {"ids": [...]}),
再调 /local-proxies/enabled 取实际可用的那批——启动失败或连不通的节点会被自动停用,
不会出现在结果里。
批量启动后有一段连通性验证期(界面上显示为「验证中」)。这期间节点已启动、 端口可用,因此也会出现在
/local-proxies/enabled里,但其中一部分随后会被 判定不通并自动停用。要拿到确定可用的那批,可等界面上「验证中」归零后再取, 或调GET /api/v1/nodes按verifying字段过滤。
主要接口:
| 方法 | 路径 | 功能 |
|---|---|---|
| GET / POST | /api/v1/nodes |
获取 / 创建节点 |
| GET / PUT / DELETE | /api/v1/nodes/{id} |
获取 / 修改 / 删除节点 |
| POST | /api/v1/nodes/{id}/start、/stop |
启动 / 停止节点 |
| POST | /api/v1/nodes/start、/stop、/delete |
批量启停 / 删除,Body 为 {"ids":["rule_id"]} |
| GET | /api/v1/local-proxies |
获取全部普通节点、故障转移和链式代理的本地地址 |
| GET | /api/v1/local-proxies/enabled |
获取全部已启动资源的本地代理地址 |
| GET | /api/v1/groups/{id}/local-proxies |
获取指定分组内三类资源的本地代理地址 |
| GET | /api/v1/subscriptions/{id}/local-proxies |
获取指定订阅的本地代理地址 |
| GET / POST | /api/v1/load-balancers |
获取 / 创建故障转移节点 |
| GET / PUT / DELETE | /api/v1/load-balancers/{id} |
获取 / 修改 / 删除故障转移节点 |
| POST | /api/v1/load-balancers/{id}/start、/stop |
启动 / 停止故障转移节点 |
| GET | /api/v1/load-balancers/{id}/local-proxy |
获取指定故障转移的本地代理地址 |
| GET | /api/v1/load-balancers/local-proxies、/enabled |
获取全部 / 已启动故障转移的本地代理地址 |
| GET / PUT | /api/v1/settings/pre-proxy |
获取 / 设置前置代理(含生效分组与例外节点) |
| GET / POST | /api/v1/chain-proxies |
获取 / 创建链式代理 |
| GET / PUT / DELETE | /api/v1/chain-proxies/{id} |
获取 / 修改 / 删除链式代理 |
| POST | /api/v1/chain-proxies/{id}/start、/stop |
启动 / 停止链式代理 |
| GET | /api/v1/chain-proxies/{id}/local-proxy |
获取指定链式代理的本地代理地址 |
| GET | /api/v1/chain-proxies/local-proxies、/enabled |
获取全部 / 已启动链式代理的本地代理地址 |
| GET / POST | /api/v1/session-relays |
获取 / 创建动态会话代理(返回含实时统计) |
| GET / PUT / DELETE | /api/v1/session-relays/{id} |
获取 / 修改 / 删除动态会话代理 |
| POST | /api/v1/session-relays/{id}/start、/stop |
启动 / 停止动态会话代理 |
| GET / POST | /api/v1/exit-ports |
获取 / 创建出口端口(返回含当前候选节点与实时统计) |
| GET / PUT / DELETE | /api/v1/exit-ports/{id} |
获取 / 修改 / 删除出口端口 |
| POST | /api/v1/exit-ports/{id}/start、/stop |
启动 / 停止出口端口 |
| GET | /api/v1/exit-ports/local-proxy?ip=出口IP&format=json|http|socks5 |
按出口 IP 获取对应的本地代理;format=http/socks5 直接返回代理地址文本 |
| GET / POST | /api/v1/groups |
获取 / 创建分组 |
| GET / PUT / DELETE | /api/v1/groups/{id} |
获取 / 修改 / 删除分组(删除会级联删除节点) |
| POST | /api/v1/groups/{id}/start、/stop |
启动 / 停止分组内节点 |
| GET / POST | /api/v1/subscriptions |
获取 / 创建订阅 |
| GET / PUT / DELETE | /api/v1/subscriptions/{id} |
获取 / 修改 / 删除订阅 |
| POST | /api/v1/subscriptions/{id}/update |
立即更新订阅 |
示例:curl http://127.0.0.1:9090/api/v1/nodes
创建时的字段说明(省略的字段取默认值):
curl -X POST http://127.0.0.1:9090/api/v1/session-relays \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"alias": "住宅代理-美国",
"localPort": 19100,
"upstreamAddr": "gw.dataimpulse.com:823",
"usernameTemplate": "login__cr.us;sessid.{session}",
"upstreamPassword": "上游密码",
"localPassword": "",
"preProxyNodeId": "",
"groupId": ""
}'| 字段 | 说明 |
|---|---|
localPort |
混合端口,HTTP 与 SOCKS5 客户端均可接入;填 0 或省略则自动分配 |
upstreamAddr |
上游住宅网关,必须是 host:port |
usernameTemplate |
含 {session} 占位符;留空表示原样透传客户端传入的完整用户名 |
upstreamPassword |
上游固定密码,保存在本机,客户端无需知道 |
localPassword |
客户端需提供的密码,留空则不校验(仅监听本机时可留空) |
preProxyNodeId |
留空 = 直连上游;__global__ = 跟随全局前置代理;也可填具体节点 / 链式 / 故障转移的 ID |
创建后处于停止状态,需再调用 /start。GET 返回中的 activeConns、totalConns、sessionCount 为实时统计,仅在运行时有值。
注意:前置加速节点必须已经启动,中继只做转发、不会代为拉起内核进程;未启动时 /start 会失败并在 lastError 中说明原因。
- 点击 "添加规则" 按钮
- 填写基本信息(别名、本地代理类型和端口)
- 选择协议类型并填写服务器信息
- 根据需要配置传输层和 TLS
- 点击 "添加链式代理"
- 从可用节点中添加节点(支持搜索框快速筛选),拖拽调整顺序
- 流量方向:第 1 个 → 第 2 个 → ... → 落地
- 点击 "添加故障转移"
- 选择参与的子节点(支持搜索框快速筛选),启动后默认走第一个节点,故障时切换到后续备用节点
适用于住宅代理服务商把会话标识编码在用户名里的场景(如 DataImpulse 的 sessid),
一个端口即可对应任意数量的出口 IP。
- 点击 "添加会话代理"
- 填写上游网关地址(如
gw.dataimpulse.com:823)和上游密码 - 填写用户名模板,其中
{session}会被替换为客户端传入的会话标识:login__cr.au;sessid.{session}(留空则原样透传客户端用户名) - 需要加速时选择一个已启动的前置节点,中继会经它连上游网关
- 启动后按会话标识访问,换用户名即换出口 IP:
# HTTP 客户端
curl -x "http://123:x@127.0.0.1:端口" https://api.ipify.org
curl -x "http://45:x@127.0.0.1:端口" https://api.ipify.org # 另一个出口 IP
# SOCKS5 客户端(用 socks5h 让域名交由远端解析)
curl -x "socks5h://123:x@127.0.0.1:端口" https://api.ipify.org说明:
- SOCKS5 客户端必须启用用户名认证,否则无法携带会话标识(未设客户端密码时密码可任意填)
- 出口 IP 由客户端用户名决定,因此这类节点不提供测速与健康检测
- 上游只支持 TCP CONNECT,SOCKS5 的 BIND / UDP ASSOCIATE 会被拒绝
适用于对端只放行固定来源 IP、而机场有多个节点(不同线路 / 中转)落地同一个 IP 的场景: 外部程序只认一个端口,背后哪个节点承载无所谓。
- 点侧边栏 "添加出口端口",填写出口 IP 和本地端口(输入框会列出运行中节点已探测到的出口 IP 供选择), 保存后立即开始监听
- 照常启动节点即可:节点启动探测到的出口是这个 IP 就自动加入,日志里会出现「节点「…」出口为 …,已自动加入」; 不用挑选节点,出口端口重启应用后也会自动恢复
- 外部程序改用该端口:
curl -x "http://127.0.0.1:端口" https://api.ipify.org # 始终返回该出口 IP
curl -x "socks5h://127.0.0.1:端口" https://api.ipify.org程序里按出口 IP 取本地代理地址:
curl "http://127.0.0.1:9090/api/v1/exit-ports/local-proxy?ip=203.0.113.10"
# data: { "httpUrl": "http://127.0.0.1:20001", "socks5Url": "socks5://127.0.0.1:20001",
# "exitIp": "203.0.113.10", "memberCount": 2, "available": true, ... }没有对应出口端口返回 404;available 为 false 表示出口端口未启动或暂无节点承载,此时连接会被拒绝。
加 format=http 或 format=socks5 直接返回一行代理地址文本,脚本拿来就能用:
curl "http://127.0.0.1:9090/api/v1/exit-ports/local-proxy?ip=203.0.113.10&format=http"
# http://127.0.0.1:20001
PROXY=$(curl -sf "http://127.0.0.1:9090/api/v1/exit-ports/local-proxy?ip=203.0.113.10&format=socks5") \
&& curl -x "$PROXY" https://api.ipify.org文本格式下出错同样返回纯文本信息:出口端口未启动或暂无节点承载时返回 503(而不是给出一个会被拒绝的地址),
找不到返回 404,参数错误返回 400;用 curl -f 即可按状态码判断成败。
多节点同出口时的处理:
- 已启动、验证完成且出口 IP 一致的节点都是候选,按「健康检测正常 > 未检测 > 检测失败」排序,同级按延迟
- 每条新连接走排在最前的候选;连不上(节点进程已退出)就换下一个,并让它冷却 30 秒
- 节点停止或出口 IP 变化(启动探测或每 3 分钟的复查发现)时立即移出候选,并断开经它的现有连接,客户端重连后落到其他同 IP 节点
- 没有任何候选时直接拒绝连接;节点稍后探测到该 IP 会自动纳入,无需重启出口端口
- 想让漂移的节点直接停用,可再给它开启节点级的「绑定出口 IP」
- 单个节点:点击节点行的 "测速" / "检测" 按钮
- 批量:多选后点击工具栏 "健康检测"(未选中时检测全部);测速在 "更多" 下拉里
- 故障转移 / 链式代理需先启动,测速与检测通过其本地代理端口进行
按健康状态筛选与选中
- 工具栏「健康」一行可按 全部 / 健康 / 失败 / 未检测 筛选,按钮上显示各类数量
- 双击某个分类按钮即可选中该类节点,接着可批量启停或删除
- 「健康」含在线与延迟较高(链路可通);「未检测」含尚未检测、检测中, 以及「仅 IPv6」——本机没有 IPv6 出口时无法直接探测这类节点, 它们不会被「选中失败」命中,避免批量删除时误删可用节点
- 多选普通节点后点击工具栏 "批量编辑"
- 每个节点一张可折叠卡片,改完后点 "全部保存" 统一提交
- 点击节点行的 "代理" 按钮设为系统代理
- 点击顶部 "取消系统代理" 按钮取消
- Linux 下需按提示手动设置
http_proxy/https_proxy环境变量
- 导出:选择节点后点击 "导出规则",仅导出选中节点及其关联的分组、故障转移、链式代理(可选是否包含订阅)
- 导入:点击 "导入规则",选择 JSON 配置文件
xray-manager/
├── main.go # 程序入口、系统托盘
├── app.go # 应用核心逻辑(API 方法)
├── sessionrelay.go # 动态会话代理的增删改查与启停
├── exitport.go # 出口端口的增删改查、启停、候选维护与出口 IP 复查
├── frontend/ # Vue 3 前端
│ └── src/
│ ├── components/ # 组件(NodeList, NodeEditor, Sidebar 等)
│ ├── stores/ # Pinia 状态管理
│ └── api.js # 前端 API 层
├── internal/
│ ├── models/ # 数据模型
│ ├── config/ # 配置管理、开机自启、系统代理
│ ├── process/ # 进程管理(sing-box 内核、端口清理、流量轮询、容量保护)
│ ├── singbox/ # sing-box 配置生成器
│ ├── relay/ # 动态会话代理中继(凭证改写、HTTP/SOCKS5 入站、前置代理拨号)
│ ├── exitport/ # 出口端口透明转发器(按优先级拨号、冷却、按上游切断连接)
│ ├── subscription/ # 订阅解析
│ ├── parser/ # 分享链接解析
│ ├── speedtest/ # 节点测速
│ ├── healthcheck/ # 节点健康检测
│ ├── group/ # 分组管理
│ ├── logger/ # 日志过滤
│ ├── utils/ # 端口检测与进程清理等工具
│ └── assets/ # 内置 sing-box 二进制与 go:embed 提取逻辑
├── build/ # 各平台构建配置
└── .github/workflows/ # GitHub Actions CI/CD
MIT