微内核与沙箱模型

一、 插件类型与运行体系深度解析

Ghost Proxifier 采用现代微内核与插件化架构。第三方代码永远不进入主进程内存空间,所有插件均以独立子进程受控运行。

CORE SUPERVISOR
Ghost Proxifier 主进程 (ghost_proxifier.exe)
WinMain / 监督守护器 / Control API (127.0.0.1:23551)
管道监控与生命周期物理守护 ▼
HOST PROCESS
宿主托管进程 (ghost_plugin_host.exe)
Windows Job Object (设置 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,宿主退出强制内核级物理回收)
stdin 握手注入 (特权 Token) ▼
TIER 1 BUILTIN
内置特权插件 (In-Tree)
  • 随主程序安装分发(只读目录)
  • 编译期 SHA-256 固化白名单
  • 全局命名空间 (Global)
  • 掌控所有 Target 进程与出口节点
Low-IL 沙箱限制 (普通 Token) ▼
TIER 2 EXTERNAL
外部沙箱插件 (Standard)
  • 商店下载 (.gpkg) 或本地导入
  • 开发者 Ed25519 签名 + 官方代签
  • 严格属主单向隔离 (Owner-Only)
  • 受权限组约束,高危操作 30s 二次审批

1.1 插件的两大分类:内置插件 vs 外部插件

Ghost Proxifier 中的插件严格划分为两个信任层级(Two-Tier Trust Architecture):

  • 内置插件 (Tier 1: Builtin / In-Tree):
    随主安装包发行(位于 <InstallDir>\plugins\builtin\<id>\)。主程序在编译期固化二进制 SHA-256 白名单(trust_chain.h 中的 kBuiltinWhitelist)。拥有全局共享命名空间 (Global),可直接调度管理系统内所有 Target 进程与出口节点。
  • 外部插件 (Tier 2: External / Standard / Out-of-Tree):
    通过官方插件商店下载安装(registry)或开发者模式本地导入(local)。依赖 Ed25519 证书信任链签名验证。受属主单向隔离命名空间 (Owner-Only) 约束,只能读写自己名下创建的资源,严禁窥探或篡改其他插件或用户的全局配置。

1.2 进程拓扑:插件是谁拉起来的?

很多开发者会好奇:插件是一个 DLL 注入到主进程,还是一个独立进程?答案是:绝对的独立子进程!

  • 启动调用链路:ghost_proxifier.exe (主进程) ➔ supervisor.cpp (监督器) ➔ 启动 ghost_plugin_host.exe (插件宿主进程) ➔ 拉起具体插件子进程。
  • Job Object 物理绑定:ghost_plugin_host.exe 在启动插件时,使用 CREATE_SUSPENDED 挂起进程,将其加入 Windows Job Object(设置了 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE),然后再 ResumeThread。这保证了一旦宿主退出或发生崩溃,所有插件子进程会被 Windows 内核强制一次性物理回收,绝不会在后台残留僵尸进程。
  • Low-IL 与特权剥离沙箱:外部插件默认在受限令牌(Restricted Token)与低完整性级别(Low-IL S-1-16-4096)下运行,受 Windows 内核的 No-Write-Up 策略保护。插件无法写入当前用户的中高完整性文件目录,彻底隔绝恶意代码修改宿主配置。

1.3 Token 体系与注入机制(为什么不用命令行或环境变量?)

Ghost Proxifier 系统中存在三种 Token,各司其职:

  1. X-Ghost-Token:主界面(UI WebView)专用的全权会话 Token,外部插件绝对无法获取。
  2. X-Ghost-Host-Token:宿主管理进程特权 Token,仅用于握手与宿主健康同步。
  3. X-Ghost-Plugin-Token:宿主为每个插件独立签发的 128 位随机 GUID 临时凭据。
🛡️ Token 是如何安全下发到插件里的?

答案是:严格通过进程的标准输入流(stdin)第一行 JSON 握手数据下发!

数据只在主宿主与插件两个进程的内核缓冲区中瞬时流转,不落盘、不广播,由插件在内存中解析持有,重启即换。

管道握手链路 宿主 (ghost_plugin_host) ──[ stdin 第一行 JSON 数据流 ]──▶ 插件子进程
JSON
{
  "v": 1,
  "pluginId": "io.github.yourname.my-plugin",
  "token": "4a7f9b8c-1234-5678-abcd-ef0123456789",   <--- 插件内存临时凭据
  "apiBase": "http://127.0.0.1:23551",
  "dataDir": "C:\\Users\\...\\AppData\\Local\\GhostProxifier\\data\\...",
  "stopEvent": "GhostPluginStop_..."
}
⚠️ 为什么绝不通过命令行或环境变量传 Token?
  • 命令行传参极度危险:Windows 下同一登录会话中的任何普通程序,都可通过 WMI 查询、Process Explorer 或读取目标进程 PEB 查看到完整的启动命令行。如果把 Token 写在命令行参数里,等同于向本机所有运行中的程序明文广播凭据!
  • 环境变量存在继承泄漏:环境变量极其容易在调用系统 API、启动子进程时被隐式继承或扩散,同样可通过 PEB 轻松跨进程读取。

1.4 内置插件 vs 外部插件:核心差异矩阵

特性维度 Tier 1: 内置特权插件 (builtin) Tier 2: 外部沙箱插件 (external / local)
部署位置 <InstallDir>\plugins\builtin\<id>\ (只读安装目录) %LOCALAPPDATA%\GhostProxifier\plugins\<id>\ (用户数据目录)
完整性校验 编译期 SHA-256 固化白名单 开发者 Ed25519 签名 + 官方代签证书信任链
运行凭据 签发 Builtin 标记的特权 Token 签发 Standard 标记的普通 Token
资源命名空间 全局命名空间 (Global) 严格属主隔离 (Owner-Only)
Target 目标权限 可直接控制、启停系统中任意 Target 只能管理自己名下的 Target;启动需用户原生弹窗审批
Upstream 节点权限 自由调度全局节点 只能 CRUD 属于自己的节点;节点账密明文恒被脱敏为 ******
外网出网权限 天然拥有出网能力 默认严禁向外联网,必须显式申请 ghost.egress.v1
生命周期 随 Ghost 主程序升级,不可删除(仅可禁用) 独立生命周期,用户可随时安装、升级、卸载
最低版本要求 随主程序发行 依赖版本化权限组,最低需 Ghost Proxifier 1.2.2 或更高

1.5 为什么做这种分级别与多权限隔离?(架构初衷)

产品定位:浏览器的软硬件指纹伪装通常交由专业的指纹浏览器处理,而 Ghost Proxifier 专注于系统底层的 Winsock 接管与进程级网络流量治理。分级信任源于以下四个核心考量:

🌐
1. IP 层级的纯净与精准隔离
用户往往为不同进程绑定了不同的出口 IP(包括昂贵原生住宅 IP)。分级隔离确保外部插件绝无法越权篡改其他进程路由,更不能串用他人独立 IP,从底层杜绝 IP 交叉污染。
🛡️
2. 企业安全审计与凭据保护
外部沙箱插件受“凭据只写不读”约束,读取节点时密码恒被强行掩码为 ******,彻底封死脚本窃取企业代理账密的可能;拉进程、建隧道等动作均有审计日志与原生人工审批。
⚡
3. 开发者日常 Vibe 编程与工具扩展
插件作为独立进程运行在 Job Object 与 Low-IL 内,崩溃由内核即时回收,不会拖垮 Ghost 宿主或影响其他插件;开发者可放胆快速原型迭代,无惧代码写崩破坏系统环境。
🔀
4. 多个 VPN / 代理客户端混用共存
Ghost 采用细粒度的进程级精准接管,不篡改系统全局网络栈。通过限制外部插件随意操作出网(ghost.egress.v1 闸门),避免私自劫持全局流量造成网络环路。
WebView2 与跨源安全

嵌入式 UI (Embedded UI) 运行与集成规范

当插件在 manifest.json 中配置 "ui": { "embedded": true } 时,Ghost Proxifier 支持在主界面的插件卡片中通过 <iframe> 嵌入插件自己的可视化前端页面。

Ghost Proxifier 主界面 (WebView2)
插件管理卡片面板
<iframe src="http://127.0.0.1:<动态分配端口 0>/...">
插件前端交互面板(React / Vue / 原生 Web)
HTTP 请求 (受 CSP frame-ancestors 保护,严格跨源阻隔) ▼
插件内置本地 HTTP 服务
严格绑定 127.0.0.1 回环地址,端口指定 0(Windows 内核分配,严禁 80/23551)
01

端口动态分配 (Port 0)

插件内置的本地 Web 服务必须绑定到回环地址 127.0.0.1 且端口指定为 0(由 Windows 内核随机分配空闲端口)。
严禁硬编码固定端口,严禁使用 80 端口与 Ghost 宿主的 23551 端口(宿主安全策略会直接拒绝加载)。

02

握手回执携带 uiUrl

插件在从 stdin 读取完握手帧后,向 stdout 输出的第一行 JSON 回执必须携带 uiUrl 属性:
{"v": 1, "ok": true, "uiUrl": "http://127.0.0.1:53211/"}
若未提供或 URL 不合法,宿主将丢弃该属性并按无界面插件处理。

03

严格跨源隔绝准则

前端页面绝对不能直接获取或持有 Ghost 的主凭据或插件 Token! 前端如需与 Ghost 数据联动,必须请求插件自己的本地 HTTP 服务接口,由插件后端完成鉴权与校验后代调 Ghost Control API 并过滤结果返回。

04

CSP 与 DNS Rebinding 防护

插件本地 HTTP 服务的静态资源应配置 Content-Security-Policy,设置 frame-ancestors http://127.0.0.1:23551(取自握手中的 apiBase),防止未授权网页嵌入面板;同时严格校验请求的 Host 头是否等于 127.0.0.1:<port>。

动态权限模型

二、 外部插件权限申请与 API 运行机制

外部插件必须遵循“按需声明、用户授权、动态校验”的原则,未授权接口在网关层直接拦截并返回 HTTP 403 permission_denied。

1
清单声明 (Manifest Declaration)
在 manifest.json 的 permissions 数组中显式声明所需要的权限组。
▼
2
用户授权 (User Consent)
安装或启用插件时,系统弹出原生卡片逐项确认。
针对 Data 流量捕获与 Egress 出网权限会有高危警告
▼
3
运行时闸门 (Runtime Gate)
API 网关校验请求中的 Token 身份与权限映射表。
未授权接口直接拦截并返回 HTTP 403 permission_denied
高敏感操作首次触发
▼
4
动态二次审批 (Runtime Approval)
首次拉起目标进程、创建上游代理节点或建立出网隧道时,宿主弹出系统原生窗口要求人工审批(最长等待 30 秒)。
⚠️ 高危动作运行时二次审批 (Runtime Approval) 核心机制
  1. 受控命令范围:针对 plugin.target.launch(启动目标)、plugin.upstream.create(新建节点)、plugin.tunnel.connect(发起代理隧道)等高敏感动作,即使清单已声明权限,首次触发时仍会触发系统原生确认弹窗让用户核对执行快照。
  2. 30 秒等待超时:系统等待用户人工决策的超时时间上限为 30 秒 (kApprovalTimeoutSec = 30)。若点击“拒绝”,API 立即返回 approval_denied;超时未操作,自动撤销并返回 approval_timeout。
  3. 并发限制:每个插件同一时刻仅允许存在 1 个在途审批请求 (kMaxPluginApprovals = 1)。并发发起高危操作将直接返回 busy 或 rate_limited。
  4. 客户端超时配置黄金法则:插件在调用上述三类高敏接口时,HTTP 客户端请求超时(Timeout)必须设置为 35~40 秒以上! 若误用常规的 5 秒超时,将导致在用户还未来得及点击确认时,客户端就因套接字超时而提前断开并抛出异常。

2.2 多版本权限组与 API 命令映射表

Ghost Proxifier 自 1.2.2 起引入版本化权限组,网关默认拒绝一切未在对应包中声明的底层命令:

1. v1 标准权限组(官方推荐)

权限组名称 放行的底层命令 允许调用的核心 API 路径 敏感度说明
ghost.target.v1 plugin.target.create
plugin.target.update
plugin.target.list
plugin.target.launch
plugin.target.stop
plugin.target.remove
POST /api/plugin/v1/targets/create
POST /api/plugin/v1/targets/update
GET /api/plugin/v1/targets/list
POST /api/plugin/v1/targets/launch
POST /api/plugin/v1/targets/stop
POST /api/plugin/v1/targets/remove
高敏感
管理受控目标,启动需 30s 审批
ghost.upstream.v1 plugin.upstream.create
plugin.upstream.list
plugin.upstream.delete
POST /api/plugin/v1/upstream/create
GET /api/plugin/v1/upstream/list
POST /api/plugin/v1/upstream/delete
高敏感
增删节点,账密恒脱敏,创建需审批
ghost.egress.v1 plugin.tunnel.connect POST /api/plugin/v1/tunnel/connect 极高敏感
代理隧道出网,仅限原生 x64 可执行程序
ghost.stats.v1 plugin.stats.overview
plugin.stats.latencies
GET /api/plugin/v1/stats/overview
GET /api/plugin/v1/stats/latencies
低敏感
流量监控与延迟,剔除 env
ghost.events.v1 events.stream GET /api/plugin/v1/events/stream
GET /events?after=<seq>
中敏感
订阅实时 SSE,默认仅控制面事件
ghost.ui.v1 plugin.ui.toast POST /api/plugin/v1/ui/toast 低敏感
发送纯文本 Toast 通知
ghost.log.v1 plugin.log.ingest POST /api/plugin/v1/log/ingest 低敏感
写入主日志,打标 src=Plugin

2. 兼容与细粒度权限

权限名称 放行命令 核心路径 说明
ghost.api.v1 只读聚合包 (config/stats/latencies) /config, /process-stats, /latencies 只读兼容 早期监控接口
events.read.data events.stream (开放数据面) GET /events?after=<seq> 极高敏感 开放 DNS 解析明文与外联目标 IP
events.read.control events.stream (仅控制面) GET /events?after=<seq> 中敏感 仅控制面事件
接口规格说明书

插件 API 文档

Ghost Proxifier 控制面网关为插件提供规范的 HTTP/1.1 RESTful 接口。每个接口的请求参数、响应字段与错误代码均以结构化表格呈现。

🌐 统一调用与认证规范
Base URL: 严格从 stdin 握手动态提取 apiBase(如 http://127.0.0.1:23551),切勿硬编码!
认证 Header: 每个请求必须携带 X-Ghost-Plugin-Token: <握手中的 token>
请求与响应格式: 固定 Content-Type: application/json; charset=utf-8
速率限制 (Rate Limit): 每个插件独立配额,基准 20 次/秒(突发 100 次),超限返回 HTTP 429

Target API 目标进程管理

ℹ️
目标进程在创建与启动时,其 env 字典不仅支持自定义环境变量,更支持 Ghost 内核专有的 GHOST_* 环境变量块 进行代理重载、DNS 加密与分流控制。直达 GHOST_* 枚举规范表 ↓
POST /api/plugin/v1/targets/create 创建受管目标
ghost.target.v1 高敏感 ⚡ 免二次审批

在 Ghost Proxifier 核心中登记一个新的受控目标进程。支持配置进程执行路径、启动参数、绑定的上游代理节点、DNS 模式与环境变量注入。

💡
上游节点级联权限约束:若 proxyNodeId 为 "direct"(本地直连),仅需 ghost.target.v1 权限;若指定了具体上游代理节点(如 "node-xxx"),插件必须同时申请拥有 ghost.egress.v1 权限,且该节点必须位于用户授权的 grantedUpstreams 名单中,否则服务端直接返回 permission_denied。
客户端推荐超时: 5 秒
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数 / Request Payload
参数字段 类型 必填 默认值 说明与校验约束
name string 必填 - 目标进程显示别名(展示在监控与卡片列表中)
exePath string 必填 - 目标可执行文件的绝对物理路径(例如 C:\Program Files\MyTool\scraper.exe)
args array<string> 选填 [] 进程启动参数列表数组
proxyNodeId string 选填 "direct" 绑定的代理上游节点 ID。"direct" 为本地直连,指定节点需拥有出网授权
dnsMode string 选填 "dot" DNS 策略模式。可选 "system" (系统默认)、"dot" (DNS-over-TLS 强加密) 或 "strict" (严格防泄漏防污染)
env object 选填 {} 注入到目标进程的环境变量键值对映射。支持自定义业务变量(如 APP_ENV=production),同时 Ghost 核心原生识别并解析内置的 GHOST_* 专有环境变量枚举(如 GHOST_PROXY_TYPE、GHOST_DNS_MODE、GHOST_STRICT 等,用于动态控制代理出口、DNS 防泄漏与分流,详见下方专有规范表)。
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 执行状态,成功时固定返回 "ok"
targetId string (UUID) 系统为该受管目标生成的全局唯一标识 ID
owner string 该目标的属主插件 ID(例如 io.github.yourname.my-plugin)
⚠️ 常见错误代码 / Error Codes
错误代码 HTTP 状态 原因与处理建议
permission_denied 403 未声明 ghost.target.v1 权限,或绑定了未授权的代理出口节点
invalid_path 400 exePath 路径格式不合法或目标文件不存在于本机
rate_limited 429 调用频率超出插件每秒 20 次预算
Request Body 示例
JSON
{
  "name": "自动化采集器",
  "exePath": "C:\\Program Files\\MyTool\\scraper.exe",
  "args": ["--port", "8080", "--silent"],
  "proxyNodeId": "direct",
  "dnsMode": "dot",
  "env": {
    "APP_ENV": "production"
  }
}
Response Body 示例
JSON
{
  "status": "ok",
  "targetId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "owner": "io.github.yourname.my-plugin"
}
POST /api/plugin/v1/targets/update 更新受管目标
ghost.target.v1 高敏感 ⚡ 免二次审批

热更新现有目标的别名、节点绑定、DNS 模式或环境变量。注意:严禁热修改 exePath 和 args;如需更换执行文件或启动参数,必须先调用 remove 删除后再重新 create。

客户端推荐超时: 5 秒
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数 / Request Payload
参数字段 类型 必填 默认值 说明与校验约束
targetId string (UUID) 必填 - 待更新的目标进程 ID
name string 选填 - 新的目标显示别名
proxyNodeId string 选填 - 新的上游节点 ID(更改出口路由)
dnsMode string 选填 - 新的 DNS 模式 (system / dot / strict)
env object 选填 - 注入到目标进程的环境变量键值对映射。支持自定义业务变量(如 APP_ENV=production),同时 Ghost 核心原生识别并解析内置的 GHOST_* 专有环境变量枚举(如 GHOST_PROXY_TYPE、GHOST_DNS_MODE、GHOST_STRICT 等,用于动态控制代理出口、DNS 防泄漏与分流,详见下方专有规范表)。
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 成功固定返回 "ok"
⚠️ 常见错误代码 / Error Codes
错误代码 HTTP 状态 原因与处理建议
target_not_found 404 指定的 targetId 不存在
owner_mismatch 403 目标非本插件所创建,外部插件严禁越权修改他方目标
Request Body 示例
JSON
{
  "targetId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "name": "自动化采集器 (新名称)",
  "proxyNodeId": "direct",
  "dnsMode": "system",
  "env": {
    "APP_ENV": "staging"
  }
}
Response Body 示例
JSON
{ "status": "ok" }
POST /api/plugin/v1/targets/launch 启动受管目标
ghost.target.v1 高敏感 (触发系统原生人工审批) ⚠️ 首次触发需用户人工审批 (30s)

启动指定受管目标的新进程实例,并自动将其纳入 Winsock 流量监控与代理接管体系。

💡
⚠️ 核心超时机制:首次启动未放行目标时,Ghost 宿主会弹出系统原生确认弹窗让用户核实执行路径与参数快照。用户等待上限为 30 秒。插件端 HTTP 客户端 Timeout 必须设为 35~40 秒以上,否则客户端将在用户点击允许前提前断开抛错!
客户端推荐超时: 35 ~ 40 秒 (必须预留用户审批时间)
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数 / Request Payload
参数字段 类型 必填 默认值 说明与校验约束
targetId string (UUID) 必填 - 待启动的受管目标 ID
env object 选填 {} 注入到目标进程的环境变量键值对映射。支持自定义业务变量(如 APP_ENV=production),同时 Ghost 核心原生识别并解析内置的 GHOST_* 专有环境变量枚举(如 GHOST_PROXY_TYPE、GHOST_DNS_MODE、GHOST_STRICT 等,用于动态控制代理出口、DNS 防泄漏与分流,详见下方专有规范表)。
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 成功启动返回 "ok"
pid integer Windows 内核分配的目标主进程 PID(若已注入)
⚠️ 常见错误代码 / Error Codes
错误代码 HTTP 状态 原因与处理建议
approval_denied 403 用户在弹出的原生审批框中主动点击了“拒绝”
approval_timeout 408 30 秒内用户未作答,审批超时自动撤销
target_changed 409 在用户审批期间目标配置被并发篡改
owner_mismatch 403 无权启动其他插件创建的目标
Request Body 示例
JSON
{
  "targetId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "env": { "EXTRA_FLAG": "1" }
}
Response Body 示例
JSON
{
  "status": "ok"
}
POST /api/plugin/v1/targets/stop 停止受管目标
ghost.target.v1 中敏感 ⚡ 免二次审批

向指定目标名下的所有正在运行的进程实例发送优雅终止信号,超时未退出则强制杀掉进程树。

客户端推荐超时: 5 秒
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数 / Request Payload
参数字段 类型 必填 默认值 说明与校验约束
targetId string (UUID) 必填 - 需要停止的受管目标 ID
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 停止成功返回 "ok"
⚠️ 常见错误代码 / Error Codes
错误代码 HTTP 状态 原因与处理建议
target_not_found 404 指定的 targetId 不存在
owner_mismatch 403 无权停止其他插件创建的目标
Request Body 示例
JSON
{ "targetId": "7c9e6679-7425-40de-944b-e07fc1f90ae7" }
Response Body 示例
JSON
{ "status": "ok" }
POST /api/plugin/v1/targets/remove 删除受管目标
ghost.target.v1 中敏感 ⚡ 免二次审批

停止该目标的所有正在运行的进程实例,并将其从监视配置列表中永久移除注销。

客户端推荐超时: 5 秒
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数 / Request Payload
参数字段 类型 必填 默认值 说明与校验约束
targetId string (UUID) 必填 - 待删除的受管目标 ID
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 成功删除返回 "ok"
⚠️ 常见错误代码 / Error Codes
错误代码 HTTP 状态 原因与处理建议
target_not_found 404 指定的 targetId 不存在
owner_mismatch 403 无权删除非本插件创建的目标
Request Body 示例
JSON
{ "targetId": "7c9e6679-7425-40de-944b-e07fc1f90ae7" }
Response Body 示例
JSON
{ "status": "ok" }
GET /api/plugin/v1/targets/list 查询目标列表
ghost.target.v1 低敏感 ⚡ 免二次审批

列出属于当前插件名下的所有受控目标。受属主隔离约束,外部插件仅能查看自己创建的目标,无法窥探全局其他用户的目标。

客户端推荐超时: 5 秒
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数
无需传递 Request Body(GET 请求或无参操作)。
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 成功状态 "ok"
targets array<object> 受管目标数组,每个对象包含 targetId, name, status, pid, dnsMode, proxyNodeId, env 等信息
Response Body 示例
JSON
{
  "status": "ok",
  "targets": [
    {
      "targetId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "name": "自动化采集器",
      "status": "running",
      "pid": 14208,
      "dnsMode": "dot",
      "proxyNodeId": "direct",
      "env": { "APP_ENV": "production" }
    }
  ]
}

Upstream API 上游节点管理

POST /api/plugin/v1/upstream/create 创建专用节点
ghost.upstream.v1 高敏感 (触发系统原生人工审批) ⚠️ 首次触发需用户人工审批 (30s)

在 Ghost 中动态登记一条属于插件自身的专用上游代理节点(如专线代理、住宅代理出口)。

💡
⚠️ 首次创建上游节点时,Ghost 会弹出原生安全卡片向用户展示目标代理服务器的 Host、Port 及协议类型。用户确认后方可入库。HTTP 请求客户端必须设置 35~40 秒超时。
客户端推荐超时: 35 ~ 40 秒 (需预留30s用户审批时间)
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数 / Request Payload
参数字段 类型 必填 默认值 说明与校验约束
name string 必填 - 上游节点名称别名(例如 香港专线 01)
type string 必填 - 代理协议类型。支持 "socks5"、"http"、"https"
host string 必填 - 代理服务器的域名或 IP 地址
port integer 必填 - 代理端口号 (1~65535)
username string 选填 "" 代理认证用户名(若有)
password string 选填 "" 代理认证明文密码(若有)
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 成功状态 "ok"
nodeId string (node-UUID) 系统为该节点分配的唯一节点 ID
owner string 属主插件标识
⚠️ 常见错误代码 / Error Codes
错误代码 HTTP 状态 原因与处理建议
approval_denied 403 用户在原生弹窗中拒绝添加该出口节点
approval_timeout 408 用户 30 秒内未作答审批超时
invalid_port 400 端口号不在 1~65535 合法范围内
Request Body 示例
JSON
{
  "name": "香港专线 01",
  "type": "socks5",
  "host": "103.21.244.12",
  "port": 10808,
  "username": "proxy_user",
  "password": "proxy_secret_password"
}
Response Body 示例
JSON
{
  "status": "ok",
  "nodeId": "node-8a1f2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
  "owner": "io.github.yourname.my-plugin"
}
GET /api/plugin/v1/upstream/list 读取节点列表
ghost.upstream.v1 高敏感 (含防泄漏脱敏) ⚡ 免二次审批

获取当前插件可用的上游代理节点列表。

💡
🔒 密码恒脱敏安全红线:外部插件受“凭据只写不读”策略保护。无论是读取自己名下的节点还是系统共享节点,所有节点的密码明文字段在返回时一律被强制脱敏为 "******",彻底杜绝恶意脚本窥探企业代理凭据。
客户端推荐超时: 5 秒
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数
无需传递 Request Body(GET 请求或无参操作)。
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 成功状态 "ok"
nodes array<object> 节点列表数组。每个对象包含 id, name, type, host, port, isOwner, auth(脱敏后)
Response Body 示例
JSON
{
  "status": "ok",
  "nodes": [
    {
      "id": "node-8a1f2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
      "name": "香港专线 01",
      "type": "socks5",
      "host": "103.21.244.12",
      "port": 10808,
      "isOwner": true,
      "auth": {
        "username": "proxy_user",
        "password": "******"
      }
    }
  ]
}
POST /api/plugin/v1/upstream/delete 删除专用节点
ghost.upstream.v1 中敏感 ⚡ 免二次审批

永久注销并删除属于本插件名下的专用代理节点。如该节点正被某个运行中的 Target 占用,删除将被拒绝。

客户端推荐超时: 5 秒
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数 / Request Payload
参数字段 类型 必填 默认值 说明与校验约束
nodeId string 必填 - 待删除的节点 ID
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 删除成功返回 "ok"
⚠️ 常见错误代码 / Error Codes
错误代码 HTTP 状态 原因与处理建议
node_not_found 404 指定的 nodeId 不存在
owner_mismatch 403 严禁删除他人或系统全局配置的公共节点
node_in_use 409 该节点当前仍有 Target 进程绑定使用,请先解绑或停止 Target
Request Body 示例
JSON
{ "nodeId": "node-8a1f2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c" }
Response Body 示例
JSON
{ "status": "ok" }

Egress API 代理出网隧道

POST /api/plugin/v1/tunnel/connect 建立代理出网隧道
ghost.egress.v1 极高敏感 (需原生 x64 语言) ⚠️ 首次触发需用户人工审批 (30s)

由 Ghost 负责向上游节点握手认证建立网络隧道,打通后通过 Windows WSADuplicateSocketW API 将底层 socket 句柄直接投递复制给插件进程收养使用。

💡
⚠️ 核心硬性约束:
1. 原生语言限制:仅限独立编译的 Windows x64 原生可执行程序(如 C++、Rust、Go)使用。解释型语言(Python、Node.js)调用时服务端将返回 tunnel_unsupported 错误。
2. 人工审批:首次出网需要用户人工审批放行(等待上限 30 秒)。
3. Fail-Closed:若代理节点连通失败,连接直接切断,绝对不可擅自回退直连!
客户端推荐超时: 35 ~ 40 秒 (需预留30s用户审批时间)
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数 / Request Payload
参数字段 类型 必填 默认值 说明与校验约束
nodeId string 必填 - 使用的上游代理出口节点 ID
proto string 选填 "tcp" 协议类型,支持 "tcp" 或 "udp"
targetHost string 必填 - 待连接的外网目标主机域名或 IPv4/IPv6 地址
targetPort integer 必填 - 外网目标端口 (1~65535)
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 连接成功状态 "ok"
proto string 连通的协议类型
protocolInfo string (Base64) Windows WSAPROTOCOL_INFOW 序列化结构体,插件用其调用 WSASocketW 收养 socket
protocolInfoBytes integer 协议信息结构体字节数 (通常为 628 字节)
node object 出口节点基本信息
⚠️ 常见错误代码 / Error Codes
错误代码 HTTP 状态 原因与处理建议
tunnel_unsupported 400 非原生 x64 架构运行,当前 runtime.kind 不支持句柄投递
approval_denied 403 用户拒绝了本次外网代理出网请求
approval_timeout 408 用户 30 秒内未点击确认,出网申请超时作废
upstream_unreachable 502 指定的上游节点超时或拒绝连接
Request Body 示例
JSON
{
  "nodeId": "node-8a1f2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
  "proto": "tcp",
  "targetHost": "api.github.com",
  "targetPort": 443
}
Response Body 示例
JSON
{
  "status": "ok",
  "proto": "tcp",
  "protocolInfo": "AQAA...",
  "protocolInfoBytes": 628,
  "node": {
    "id": "node-8a1f2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "name": "香港专线 01",
    "type": "socks5"
  }
}

UI / Log / Stats 交互与监控 API

POST /api/plugin/v1/ui/toast 弹出系统 Toast 通知
ghost.ui.v1 低敏感 ⚡ 免二次审批

在 Ghost Proxifier 客户端界面右上方弹出系统原生 Toast 轻提示。

💡
🛡️ XSS 安全防线:title 与 message 在宿主端均采用纯文本(textContent)安全转义渲染,严禁任何 HTML 或恶意 JavaScript 注入。
客户端推荐超时: 5 秒
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数 / Request Payload
参数字段 类型 必填 默认值 说明与校验约束
title string 必填 - 通知卡片标题文本(不超过 64 字符)
message string 必填 - 通知正文详细内容(不超过 512 字符)
level string 选填 "info" 消息级别。可选 "info"、"success"、"warning"、"error"
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 投递成功返回 "ok"
⚠️ 常见错误代码 / Error Codes
错误代码 HTTP 状态 原因与处理建议
rate_limited 429 Toast 发送频率过高被限流
Request Body 示例
JSON
{
  "level": "info",
  "title": "任务完成",
  "message": "数据同步已顺利结束,共处理 1,024 条数据。"
}
Response Body 示例
JSON
{ "status": "ok" }
POST /api/plugin/v1/log/ingest 上报插件日志
ghost.log.v1 低敏感 ⚡ 免二次审批

向 Ghost Proxifier 主程序的日志中心与审计流投递结构化运行日志条目,统一受系统审计流监视。

💡
所有由该接口上报的日志,在主程序端均会被强制打上 src=Plugin 及 plugin_id 来源标签,防止日志伪造。
客户端推荐超时: 5 秒
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数 / Request Payload
参数字段 类型 必填 默认值 说明与校验约束
level string 必填 - 日志等级: "debug", "info", "warn", "error"
message string 必填 - 日志摘要正文描述
fields object 选填 {} 结构化扩展元数据对象
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 写入成功返回 "ok"
Request Body 示例
JSON
{
  "level": "info",
  "message": "Worker thread pool initialized successfully.",
  "fields": { "workers": 4 }
}
Response Body 示例
JSON
{ "status": "ok" }
GET /api/plugin/v1/stats/overview 查询受管进程状态概览
ghost.stats.v1 低敏感 (剔除 env 凭据) ⚡ 免二次审批

获取当前插件名下所有受管进程组的实时网络状态,包括进程活跃度、已建立 TCP 连接数、已发送/接收累计网络字节数。

💡
🔒 脱敏策略:返回的 groups 进程组中,环境变量 env 字段会被服务端物理剔除,防止敏感环境变量通过 stats 监控接口泄露。
客户端推荐超时: 5 秒
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数
无需传递 Request Body(GET 请求或无参操作)。
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 成功状态 "ok"
groups array<object> 进程监控组列表,包含 id, alias, running, pids, tcpConnections, bytesSent, bytesReceived
Response Body 示例
JSON
{
  "status": "ok",
  "groups": [
    {
      "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "alias": "自动化采集器",
      "running": true,
      "pids": [14208],
      "tcpConnections": 3,
      "bytesSent": 1048576,
      "bytesReceived": 5242880
    }
  ]
}
GET /api/plugin/v1/stats/latencies 获取节点延迟状态
ghost.stats.v1 低敏感 ⚡ 免二次审批

获取所有授权上游代理节点的实时 ICMP / TCP 握手 RTT 往返延迟数据(毫秒)。

客户端推荐超时: 5 秒
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数
无需传递 Request Body(GET 请求或无参操作)。
📤 响应字段 / Response Body
返回字段 类型 字段说明
status string 成功状态 "ok"
latencies object 以节点 ID 为键、延迟毫秒数 (int) 为值的字典映射表
Response Body 示例
JSON
{
  "status": "ok",
  "latencies": {
    "node-8a1f2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c": 45,
    "direct": 5
  }
}

Events Stream 实时事件流 API

GET /api/plugin/v1/events/stream 实时事件流订阅
ghost.events.v1 控制面中敏感 / 数据面极高敏感 ⚡ 免二次审批

基于 Server-Sent Events (SSE) 协议的长连接事件订阅通道。用于实时监听控制面状态变更或数据面网络流量明细。

💡
🔒 平面分级安全防线:
1. 控制平面 (Control Plane):仅需 ghost.events.v1,可接收节点变更、进程启停与系统 Toast。
2. 数据平面 (Data Plane):如需接收敏感网络明细(如实时 DNS 解析域名明文、出网目标 IP:Port),必须显式申请细粒度 events.read.data 权限,否则数据流中自动屏蔽所有数据面事件。
3. 断线续传:支持通过请求头 Last-Event-ID: <seq> 或查询参数 ?after=<seq> 实现历史无损续传。
客户端推荐超时: 长连接 (Keep-Alive)
认证 Header: X-Ghost-Plugin-Token: <token>
限流配额: 20 次/秒 (突发 100)
📥 请求参数 / Request Payload
参数字段 类型 必填 默认值 说明与校验约束
after integer (query param) 选填 0 断线续传起始事件序列号,仅接收 seq 大于此值的增量事件
📤 响应字段 / Response Body
返回字段 类型 字段说明
Content-Type header 固定为 text/event-stream; charset=utf-8
SSE 帧格式 stream event 每条事件包含 id: <seq>\nevent: <type>\ndata: <json>\n\n
⚠️ 常见错误代码 / Error Codes
错误代码 HTTP 状态 原因与处理建议
permission_denied 403 未声明 ghost.events.v1 权限
Response Body 示例
JSON
id: 1042
event: target.status_changed
data: {"targetId":"7c9e6679...","status":"running","pid":14208}

id: 1043
event: node.latency_updated
data: {"nodeId":"node-8a1f...","latencyMs":42}
⚙️ Ghost 内核专有环境变量规范 (GHOST_* Environment Block)

在调用 targets/create 或 targets/launch 传入 env 字典时,除了可以注入目标程序自身需要的普通环境变量(如 APP_ENV=production)外,Ghost 底层接管核心(ghost_core.dll)还原生识别并解析以下 GHOST_* 专有环境变量,用于动态微调受管进程的路由、DNS 防泄漏与代理协议行为:

环境变量名 (Key) 支持枚举值 / 格式 默认值 Ghost 底层接管行为与生效语义
🌐 代理出口与节点重载 (Proxy & Upstream)
GHOST_PROXY_TYPE "socks5" | "http" "socks5" 指定目标外联的上游代理协议类型(大小写不敏感)。
GHOST_PROXY IPv4 字符串 (如 "127.0.0.1") 跟随节点 强制覆盖目标的代理服务器 IP 地址。
GHOST_PROXY_PORT 数字端口字符串 (如 "10808") 跟随节点 强制覆盖代理端口号 (1~65535)。
GHOST_PROXY_USER UTF-8 字符串 - 代理认证用户名。
GHOST_PROXY_PASS UTF-8 字符串 - 代理认证密码(内存中读取,API 监控中恒脱敏)。
GHOST_NODE UTF-8 节点显示名 - 注入目标上下文的节点别名标识。
🔒 DNS 加密与严格防泄漏 (DNS & Security)
GHOST_DNS_MODE "dot" | "strict" | "system" "dot" DNS 解析模式:
• "dot": DNS-over-TLS 强加密安全解析(默认 853 端口)
• "strict": 严格模式,防污染与越权直连阻断
• "system": 继承系统标准 DNS 解析
GHOST_DNS DNS 服务器 IP (如 "9.9.9.9") 跟随配置 专用的安全上游 DNS 解析服务器 IP。
GHOST_DNS_PORT 数字端口字符串 (如 "853" / "53") "853" 上游 DNS 解析服务端口。
GHOST_DOH DoH URL (如 "https://dns.google/dns-query") - DoT 解析异常时的备用 DNS-over-HTTPS 安全查询地址。
GHOST_STRICT "1" | "0" "1" Fail-Closed 严格防泄漏开关。"1" 表示当代理或 DNS 故障时立即切断并拒绝连接,绝对不向真实本地网络回落直连;"0" 允许降级直连。
⚡ 隧道协议与网络特性 (Tunnel & Protocols)
GHOST_UDP "1" | "0" "1" "1" 表示启用 SOCKS5 UDP ASSOCIATE 代理隧道,全面接管 WebRTC 与 UDP 流量;"0" 禁用 UDP 代理。
GHOST_SYNC "1" | "0" "1" "1" 强制首次发送流量前完成 Winsock 管道安全同步握手。
🔀 进程与域名分流规则 (Routing Policy)
GHOST_ROUTE_PROCESS 分号分隔规则 (如 "git.exe=direct;*=upstream") - 目标衍生子进程的动态继承分流规则。
GHOST_ROUTE_DOMAIN 分号分隔规则 (如 "*.internal=direct;*ads*=block;*=upstream") - 细粒度域名黑白名单与分流策略。
GHOST_ROUTE_DEFAULT "upstream" | "direct" "upstream" 无规则匹配时的默认回退路由方向。
📊 日志等级与诊断 (Logging & Diagnostics)
GHOST_LOG_LEVEL "debug" | "info" | "warn" | "error" "info" 注入到目标内部 NetLog 钩子的日志过滤门限。
跨语言与工具链

四、 支持的开发语言与 SDK 获取

Ghost Proxifier 的宿主通信基于标准系统管道(stdin/stdout)与 HTTP REST API,理论上支持任何能够运行于 Windows 平台的编程语言!

4.1 支持的开发语言推荐

Python runtime.kind: "python" ★★★★★

生态极其丰富,开发与迭代最快。推荐 Python 3.9 或更高版本。适用于数据爬虫、自动化巡检脚本、任务调度与本地数据分析。

Node.js / JavaScript runtime.kind: "node" ★★★★☆

搭配 Web 前端技术栈极佳,系统需安装 Node.js。非常适合带有嵌入式可视化面板、实时事件查看器或 Web 仪表盘的插件。

原生编译:C++ / Rust / Go runtime.kind: "none" ★★★★★

零环境依赖、极致原生性能! 独立编译为单一 Windows x64 .exe。
特权能力:若需调用 ghost.egress.v1 收养底层 socket 句柄(WSADuplicateSocketW),必须使用此类原生 x64 语言!

批处理 / Shell 脚本 .cmd / .bat ★★★☆☆

无需复杂运行时,适用于轻量级环境初始化脚本、进程启动包装器或一次性离线任务。

4.2 SDK 与官方模板仓库位置

开发者无需从零手写握手与打包代码,所有 SDK 工具链、规范与生产级实战示例均已开源在专门的 GitHub 独立仓库中:

OFFICIAL SDK 访问 GitHub ➔

ghost-plugin-sdk

Ghost Proxifier 官方 Plugin SDK 独立核心仓库。包含打包工具、签名脚本及全套协议规范。

📦 核心打包工具: tools/plugin/gpkg.py
🔑 签名校验脚本: tools/plugin/sign.ps1
📑 全景协议规范: docs/plugin-sdk/developer-guide.md
BASH
git clone https://github.com/liliBestCoder/ghost-plugin-sdk.git
EXAMPLE 1 访问 GitHub ➔

ghost-plugin-events-viewer

实时事件与流量监控示例插件。演示如何通过 Server-Sent Events (SSE) 订阅控制面事件流,并在本地可视化展示进程与网络状态。

BASH
git clone https://github.com/liliBestCoder/ghost-plugin-events-viewer.git
EXAMPLE 2 访问 GitHub ➔

ghost-plugin-showcase

官方参考全功能插件示例。全面覆盖并演示 Target 进程管理、Upstream 节点调度、Egress 代理出网、Stats 统计与 UI Toast 等每一项 v1 插件能力。

BASH
git clone https://github.com/liliBestCoder/ghost-plugin-showcase.git

ghost-plugin-registry

Ghost Proxifier 官方插件市场注册表仓库。包含已签名的官方插件中心索引目录(registry.json)与发布资产清单。

BASH
git clone https://github.com/liliBestCoder/ghost-plugin-registry.git
工具链与上架

五、 打包、本地调试与官方发布上架

Ghost Proxifier 采用中心化官方审核机制,以确保插件生态不被供应链病毒、木马或恶意挖矿程序污染。所有上架商店的插件均由官方离线私钥统一代签!

5.1 本地开发与调试流程(开发者模式)

1
开启插件开发者模式
进入 Ghost Proxifier 客户端 ➔ 设置 ➔ 插件设置 ➔ 勾选开启「插件开发者模式」。
2
使用 ghost-plugin-sdk 本地打包
克隆 ghost-plugin-sdk 后,使用其中的 tools/plugin/gpkg.py 打包源码(注意:--out 必须指向源码目录之外,--min-app-version 必须指定为 1.2.2 或更高):
BASH
python path/to/ghost-plugin-sdk/tools/plugin/gpkg.py pack --src . --out ../dist --min-app-version 1.2.2
3
从本地导入与测试
在客户端界面的「已安装插件」面板中,点击「从本地安装」,选择生成的 ../dist/<plugin_id>-<version>.gpkg 文件。
4
验证权限弹窗与优雅退出
在界面中点击“启用”,观察原生权限确认卡片、stdin 握手是否成功、UI 嵌入是否正常展示,以及禁用时是否能在 3 秒内优雅退出。

5.2 官方审核上架渠道与流程

💬 官方审核提交通道:官方开发者 QQ 群

目前官方审核的唯一定点通道为 Ghost Proxifier 官方开发者 QQ 群(群号:945138408)。开发者在本地完成功能测试后,在群内联系官方管理员或提交审核工单。

提交审核需准备的物料清单(5项):

物料项 说明与合规要求
1. 打包产物 经 gpkg.py pack 工具打包生成的合法 .gpkg 文件包。
2. 源码与 Commit 开源代码仓库地址(如 GitHub)以及本次打包对应的 Commit SHA(官方将进行源码安全性审计并复现校验哈希)。
3. 插件基础元数据 • 插件 ID:必须为至少三段的反向域名(如 io.github.yourname.my-plugin,上架后不可变更)
• 中英文双语:名称(name)与简介描述(description)
• 官方标准分类 (category):必须严格为以下 5 种枚举值之一(填入非标值将被系统自动降级归入 "other"):
  - "network": 网络代理、流量重定向与路由工具
  - "dev": 开发者调试、抓包与环境辅助工具
  - "security": 安全检测、凭据防护与审计工具
  - "productivity": 自动化工作流与日常生产力工具
  - "other": 其他杂项工具
• 高清图标:icon.png (128x128 像素 PNG,放置于包根目录)
4. 权限合规说明 逐项说明清单中申请权限(尤其是 ghost.egress.v1 或 events.read.data)的具体业务必要性。
5. 联系人信息 作者署名、主页链接以及面向用户的技术支持反馈方式。

官方审核与代签流程链路:

1
开发者提交材料
官方 QQ 群 (945138408) 提交 .gpkg 与 Commit
➔
2
自动扫描与源码审计
复现构建哈希与行为安全性检查
➔
3
测试环境复现运行
沙箱隔离验证生命周期与权限闸门
➔
4
官方 Ed25519 签名
离线私钥签名,打包装配官方证书链
➔
5
发布至官方商店
同步官方 CDN,全球用户一键安装
端到端参考实现

六、 生产级插件全流程实战案例 (Python)

下面是一个符合官方全部安全规范、功能完备的 Python 生产级插件示例。涵盖:管道握手、Token 安全持有、区分普通/审批超时 API 调用、优雅停止监听与降级保护。

6.1 manifest.json 清单配置

JSON
{
  "v": 1,
  "id": "io.github.dev.flow-guard",
  "version": "1.0.0",
  "name": {
    "zh": "流量巡检卫士",
    "en": "Flow Guard"
  },
  "description": {
    "zh": "实时监控目标进程的健康状态与流量,并在异常时发出提醒。",
    "en": "Monitor process health and traffic in real-time."
  },
  "author": { "name": "Dev Team", "url": "https://github.com/dev" },
  "homepage": "https://github.com/dev/flow-guard",
  "category": "productivity",
  "entry": "main.py",
  "runtime": { "kind": "python", "minVersion": "3.9" },
  "ui": { "embedded": false },
  "standalone": true,
  "permissions": [
    "ghost.target.v1",
    "ghost.stats.v1",
    "ghost.ui.v1",
    "ghost.log.v1"
  ]
}

6.2 main.py 完整业务代码

PYTHON
"tok-kw">import json
"tok-kw">import os
"tok-kw">import sys
"tok-kw">import threading
"tok-kw">import time
"tok-kw">import urllib.request
"tok-kw">import urllib.error

"tok-kw">class GhostPlugin:
    "tok-kw">def __init__(self):
        self.running = "tok-kw">True
        self.api_base = "tok-kw">None
        self.token = "tok-kw">None
        self.plugin_id = "tok-kw">None
        self.data_dir = "tok-kw">None
        self.stop_event_name = "tok-kw">None

    "tok-kw">def call_api(self, path: str, method: str = "GET", payload: dict = "tok-kw">None, timeout: int = 5):
        """
        统一 API 请求封装
        - 常规查询接口 timeout 默认设为 5 秒
        - 高危审批接口 (如 target/launch, upstream/create) timeout 必须传入 35~40 秒以等待用户决策
        """
        "tok-kw">if not self.api_base or not self.token:
            "tok-kw">return "tok-kw">None
        url = f"{self.api_base}{path}"
        headers = {
            "Content-Type": "application/json",
            "X-Ghost-Plugin-Token": self.token
        }
        data = json.dumps(payload).encode("utf-8") "tok-kw">if payload is not "tok-kw">None "tok-kw">else "tok-kw">None
        req = urllib.request.Request(url, data=data, headers=headers, method=method)
        "tok-kw">try:
            "tok-kw">with urllib.request.urlopen(req, timeout=timeout) "tok-kw">as resp:
                raw = resp.read().decode("utf-8")
                "tok-kw">return json.loads(raw) "tok-kw">if raw "tok-kw">else {}
        "tok-kw">except urllib.error.HTTPError "tok-kw">as e:
            "tok-kw">if e.code == 429:
                time.sleep(2)
            "tok-kw">elif e.code "tok-kw">in (401, 403):
                self.running = "tok-kw">False
            "tok-kw">return "tok-kw">None
        "tok-kw">except Exception:
            "tok-kw">return "tok-kw">None

    "tok-kw">def log_to_ghost(self, message: str, level: str = "info"):
        """通过 API 向 Ghost 主日志写入审计记录"""
        self.call_api("/api/plugin/v1/log/ingest", method="POST", payload={
            "level": level,
            "message": message
        }, timeout=5)

    "tok-kw">def show_toast(self, title: str, message: str, level: str = "info"):
        """向 Ghost 宿主界面发送纯文本 Toast 弹窗"""
        self.call_api("/api/plugin/v1/ui/toast", method="POST", payload={
            "title": title,
            "message": message,
            "level": level
        }, timeout=5)

    "tok-kw">def perform_health_check(self):
        """核心业务循环:周期性检查受管目标"""
        "tok-kw">while self.running:
            res = self.call_api("/api/plugin/v1/stats/overview", method="GET", timeout=5)
            "tok-kw">if res and res.get("status") == "ok":
                groups = res.get("groups", [])
                self.log_to_ghost(f"Active targets under inspection: {len(groups)}")

            # 每 10 秒巡检一次,支持快速退出
            "tok-kw">for _ "tok-kw">in range(10):
                "tok-kw">if not self.running:
                    "tok-kw">break
                time.sleep(1)

    "tok-kw">def listen_stop_signal(self):
        """监听 Windows 命名停止事件以实现优雅退出"""
        "tok-kw">if not self.stop_event_name:
            "tok-kw">return
        "tok-kw">try:
            "tok-kw">import ctypes
            kernel32 = ctypes.WinDLL("kernel32", use_last_error="tok-kw">True)
            # SYNCHRONIZE = 0x00100000
            event_handle = kernel32.OpenEventW(0x00100000, "tok-kw">False, self.stop_event_name)
            "tok-kw">if event_handle:
                kernel32.WaitForSingleObject(event_handle, 0xFFFFFFFF)
                self.running = "tok-kw">False
                kernel32.CloseHandle(event_handle)
        "tok-kw">except Exception:
            "tok-kw">pass

    "tok-kw">def run_hosted(self):
        # 1. 严格从 stdin 读取宿主下发的第一行 JSON 握手数据
        raw_line = sys.stdin.buffer.readline().decode("utf-8").strip()
        "tok-kw">if not raw_line:
            sys.exit(1)

        handshake = json.loads(raw_line)
        self.plugin_id = handshake.get("pluginId")
        self.token = handshake.get("token")
        self.api_base = handshake.get("apiBase")
        self.data_dir = handshake.get("dataDir")
        self.stop_event_name = handshake.get("stopEvent")

        # 2. 立即向 stdout 回写握手成功收据(必须立即 flush,防止宿主超时判定崩溃)
        # 注:若清单声明了 ui.embedded: true,回执中还必须携带 uiUrl: "http://127.0.0.1:<port>/"
        receipt = {"v": 1, "ok": "tok-kw">True}
        sys.stdout.buffer.write((json.dumps(receipt) + "\n").encode("utf-8"))
        sys.stdout.buffer.flush()

        # 握手完成,通知前端
        self.log_to_ghost("Plugin Flow Guard initialized.")
        self.show_toast("插件已启动", "流量巡检卫士已进入常驻监控模式。")

        # 3. 启动停止信号监听线程与工作巡检线程
        stop_thread = threading.Thread(target=self.listen_stop_signal, daemon="tok-kw">True)
        stop_thread.start()

        worker_thread = threading.Thread(target=self.perform_health_check, daemon="tok-kw">True)
        worker_thread.start()

        # 4. 主线程保持等待直至停止信号触发
        "tok-kw">while self.running:
            time.sleep(0.5)

        self.log_to_ghost("Plugin Flow Guard shutting down gracefully.")

"tok-kw">if __name__ == "__main__":
    # 根据环境变量判断是运行在 Ghost 宿主环境下还是独立单机运行
    "tok-kw">if "GHOST_PLUGIN_ID" "tok-kw">in os.environ:
        app = GhostPlugin()
        app.run_hosted()
    "tok-kw">else:
        print("[Standalone Mode] Ghost environment not detected. Running offline.")
安全开发规范

七、 总结与最佳实践准则

在开发与向官方提交插件前,请务必核对以下 5 条核心准则:

准则 01

Token 永不落盘

切忌将 token 输出至普通日志、写到本地临时文件或放入命令行参数。Token 只应存在于插件进程的受保护内存中,进程退出即销毁。

准则 02

UI 严格跨源隔绝

UI 网页如需访问 Ghost 数据,必须请求插件自己的 HTTP 服务由插件代调,严禁将 Token 传入 iframe。内置 Web 服务必须配置 frame-ancestors 与 Host 头校验。

准则 03

Fail-Closed 永不回落直连

网络代理隧道建立失败时,直接切断连接,绝对不可擅自回退为本地直连,以免造成真实环境下的真实真实 IP 泄露与网络污染安全事故。

准则 04

版本号规范与 minAppVersion

提交官方审核前,务必在 manifest.json 中严格遵循语义化版本号,并确保 minAppVersion >= 1.2.2,确保运行在版本化权限组之上。

准则 05

官方审核渠道:统一前往官方开发者 QQ 群

官方插件审核不设立任何第三方代理渠道,请统一前往 Ghost Proxifier 官方开发者 QQ 群(群号:945138408) 提交工单和 .gpkg 审核材料。官方技术团队将在群内协助进行沙箱运行测试与证书代签。