{"openapi":"3.1.0","info":{"title":"cc19-reverse-server","description":"\n基于 **FastAPI** 的 WS/WSS 隧道反向代理。用于把公网 HTTP/HTTPS 请求转发给\nIP 不固定、只能主动外连的 WS/WSS 客户端（内网穿透方向相反的那种）。\n\n### 三块能力\n\n| 能力 | 入口 | 说明 |\n| --- | --- | --- |\n| 站点静态文件 | `GET /<path>` | 直接读取站点目录下的文件 |\n| 隧道接入（WS/WSS） | `wss://<domain>/private/ws/<key>` | 校验 `key`，通过后成为隧道客户端 |\n| 请求转发（HTTP/HTTPS） | `https://<domain>/private/<prefix>/<subpath>` | 广播给全部隧道客户端 |\n\n### 转发语义\n\n1. 请求到达 → 生成 `id` → 登记等待表并启动超时定时器；\n2. `http_request` **广播**给全部 WS 客户端（正常只有一个连接）；\n3. **同一 `id` 只采纳第一个响应**，其余丢弃；\n4. 定时器先到 → `504 服务已断开`；无客户端在线 → `503 服务已断开`。\n\n### 线协议\n\nWS 通道不受 OpenAPI 描述，消息模型已注入本页 `components.schemas`\n（`WelcomeMessage` / `HttpRequestMessage` / `HttpResponseMessage` 等），\n概览见 [`/api/protocol`](/api/protocol)，完整说明见仓库内 `docs/PROTOCOL.md`。\n","version":"1.0.0"},"paths":{"/healthz":{"get":{"tags":["ops"],"summary":"探活","description":"仅表示进程存活，不做任何依赖检查。","operationId":"healthz_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Healthz Healthz Get"}}}}}}},"/api/status":{"get":{"tags":["ops"],"summary":"隧道运行状态","description":"公开只读，**不返回 key**。可用于探活面板与告警。","operationId":"get_status_api_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Status Api Status Get"}}}}}}},"/api/protocol":{"get":{"tags":["ops"],"summary":"隧道线协议自描述","description":"机器可读的协议概览；字段级定义见 `/openapi.json` 的 components.schemas。","operationId":"get_protocol_api_protocol_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Protocol Api Protocol Get"}}}}}}},"/api/admin/clients":{"get":{"tags":["ops"],"summary":"隧道连接明细","description":"返回每个 WS 客户端的 id、名称、来源 IP、在线时长与计数。需要 `X-Tunnel-Key`。","operationId":"admin_clients_api_admin_clients_get","parameters":[{"name":"x-tunnel-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tunnel-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Admin Clients Api Admin Clients Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/endpoint":{"get":{"tags":["ops"],"summary":"取带 key 的真实接入地址","description":"需要 `X-Tunnel-Key`。用于在不登服务器读 config.json 的情况下，拿到远端客户端该连的完整 URL。响应含密钥，别往浏览器/日志里留。","operationId":"admin_endpoint_api_admin_endpoint_get","parameters":[{"name":"x-tunnel-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tunnel-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Admin Endpoint Api Admin Endpoint Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/broadcast":{"post":{"tags":["ops"],"summary":"向全部隧道客户端广播一条消息","description":"下发 `broadcast` 帧，用于运维通知/调试。需要 `X-Tunnel-Key`。","operationId":"admin_broadcast_api_admin_broadcast_post","parameters":[{"name":"x-tunnel-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tunnel-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Admin Broadcast Api Admin Broadcast Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/reload":{"post":{"tags":["ops"],"summary":"热重载 config.json","description":"重新读取配置文件并就地生效。\n\n- 新配置**校验失败时保持旧配置不变**并返回 400；\n- `tunnel.key` / `tunnel.prefix` 的变更只影响**新**连接，已建立的隧道不踢下线；\n- 已连接客户端的心跳间隔在下次连接时生效（当前连接沿用旧值）；\n- **启动期参数不热生效**：`ssl.*`、`site.directory`、监听端口在进程启动时\n  就已绑定，改了必须重启服务。","operationId":"admin_reload_api_admin_reload_post","parameters":[{"name":"x-tunnel-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tunnel-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReloadResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/private/{subpath}":{"head":{"tags":["proxy"],"summary":"转发到 WS/WSS 隧道客户端","description":"把请求广播给所有已连接的 WS/WSS 客户端；**同一 id 只采纳第一个响应**。\n\n- 无客户端在线：`503` 服务已断开\n- 客户端未在超时内响应：`504` 服务已断开\n- 路径必须形如 `/private/<prefix>/<subpath>`（`<prefix>` 见 `config.json` 的 `tunnel.prefix`）。去掉前缀后的部分会放进 `http_request.request.path`，原始完整路径见 `raw_path`","operationId":"tunnel_proxy_private__subpath__head","parameters":[{"name":"subpath","in":"path","required":true,"schema":{"type":"string","title":"Subpath"}}],"responses":{"200":{"description":"由隧道客户端返回的响应（状态码透传）"},"404":{"description":"前缀不匹配"},"503":{"description":"服务已断开：当前没有 WS/WSS 客户端在线"},"504":{"description":"服务已断开：等待 WS/WSS 客户端响应超时"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["proxy"],"summary":"转发到 WS/WSS 隧道客户端","description":"把请求广播给所有已连接的 WS/WSS 客户端；**同一 id 只采纳第一个响应**。\n\n- 无客户端在线：`503` 服务已断开\n- 客户端未在超时内响应：`504` 服务已断开\n- 路径必须形如 `/private/<prefix>/<subpath>`（`<prefix>` 见 `config.json` 的 `tunnel.prefix`）。去掉前缀后的部分会放进 `http_request.request.path`，原始完整路径见 `raw_path`","operationId":"tunnel_proxy_private__subpath__head","parameters":[{"name":"subpath","in":"path","required":true,"schema":{"type":"string","title":"Subpath"}}],"responses":{"200":{"description":"由隧道客户端返回的响应（状态码透传）"},"404":{"description":"前缀不匹配"},"503":{"description":"服务已断开：当前没有 WS/WSS 客户端在线"},"504":{"description":"服务已断开：等待 WS/WSS 客户端响应超时"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"trace":{"tags":["proxy"],"summary":"转发到 WS/WSS 隧道客户端","description":"把请求广播给所有已连接的 WS/WSS 客户端；**同一 id 只采纳第一个响应**。\n\n- 无客户端在线：`503` 服务已断开\n- 客户端未在超时内响应：`504` 服务已断开\n- 路径必须形如 `/private/<prefix>/<subpath>`（`<prefix>` 见 `config.json` 的 `tunnel.prefix`）。去掉前缀后的部分会放进 `http_request.request.path`，原始完整路径见 `raw_path`","operationId":"tunnel_proxy_private__subpath__head","parameters":[{"name":"subpath","in":"path","required":true,"schema":{"type":"string","title":"Subpath"}}],"responses":{"200":{"description":"由隧道客户端返回的响应（状态码透传）"},"404":{"description":"前缀不匹配"},"503":{"description":"服务已断开：当前没有 WS/WSS 客户端在线"},"504":{"description":"服务已断开：等待 WS/WSS 客户端响应超时"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"options":{"tags":["proxy"],"summary":"转发到 WS/WSS 隧道客户端","description":"把请求广播给所有已连接的 WS/WSS 客户端；**同一 id 只采纳第一个响应**。\n\n- 无客户端在线：`503` 服务已断开\n- 客户端未在超时内响应：`504` 服务已断开\n- 路径必须形如 `/private/<prefix>/<subpath>`（`<prefix>` 见 `config.json` 的 `tunnel.prefix`）。去掉前缀后的部分会放进 `http_request.request.path`，原始完整路径见 `raw_path`","operationId":"tunnel_proxy_private__subpath__head","parameters":[{"name":"subpath","in":"path","required":true,"schema":{"type":"string","title":"Subpath"}}],"responses":{"200":{"description":"由隧道客户端返回的响应（状态码透传）"},"404":{"description":"前缀不匹配"},"503":{"description":"服务已断开：当前没有 WS/WSS 客户端在线"},"504":{"description":"服务已断开：等待 WS/WSS 客户端响应超时"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["proxy"],"summary":"转发到 WS/WSS 隧道客户端","description":"把请求广播给所有已连接的 WS/WSS 客户端；**同一 id 只采纳第一个响应**。\n\n- 无客户端在线：`503` 服务已断开\n- 客户端未在超时内响应：`504` 服务已断开\n- 路径必须形如 `/private/<prefix>/<subpath>`（`<prefix>` 见 `config.json` 的 `tunnel.prefix`）。去掉前缀后的部分会放进 `http_request.request.path`，原始完整路径见 `raw_path`","operationId":"tunnel_proxy_private__subpath__head","parameters":[{"name":"subpath","in":"path","required":true,"schema":{"type":"string","title":"Subpath"}}],"responses":{"200":{"description":"由隧道客户端返回的响应（状态码透传）"},"404":{"description":"前缀不匹配"},"503":{"description":"服务已断开：当前没有 WS/WSS 客户端在线"},"504":{"description":"服务已断开：等待 WS/WSS 客户端响应超时"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["proxy"],"summary":"转发到 WS/WSS 隧道客户端","description":"把请求广播给所有已连接的 WS/WSS 客户端；**同一 id 只采纳第一个响应**。\n\n- 无客户端在线：`503` 服务已断开\n- 客户端未在超时内响应：`504` 服务已断开\n- 路径必须形如 `/private/<prefix>/<subpath>`（`<prefix>` 见 `config.json` 的 `tunnel.prefix`）。去掉前缀后的部分会放进 `http_request.request.path`，原始完整路径见 `raw_path`","operationId":"tunnel_proxy_private__subpath__head","parameters":[{"name":"subpath","in":"path","required":true,"schema":{"type":"string","title":"Subpath"}}],"responses":{"200":{"description":"由隧道客户端返回的响应（状态码透传）"},"404":{"description":"前缀不匹配"},"503":{"description":"服务已断开：当前没有 WS/WSS 客户端在线"},"504":{"description":"服务已断开：等待 WS/WSS 客户端响应超时"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["proxy"],"summary":"转发到 WS/WSS 隧道客户端","description":"把请求广播给所有已连接的 WS/WSS 客户端；**同一 id 只采纳第一个响应**。\n\n- 无客户端在线：`503` 服务已断开\n- 客户端未在超时内响应：`504` 服务已断开\n- 路径必须形如 `/private/<prefix>/<subpath>`（`<prefix>` 见 `config.json` 的 `tunnel.prefix`）。去掉前缀后的部分会放进 `http_request.request.path`，原始完整路径见 `raw_path`","operationId":"tunnel_proxy_private__subpath__head","parameters":[{"name":"subpath","in":"path","required":true,"schema":{"type":"string","title":"Subpath"}}],"responses":{"200":{"description":"由隧道客户端返回的响应（状态码透传）"},"404":{"description":"前缀不匹配"},"503":{"description":"服务已断开：当前没有 WS/WSS 客户端在线"},"504":{"description":"服务已断开：等待 WS/WSS 客户端响应超时"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["proxy"],"summary":"转发到 WS/WSS 隧道客户端","description":"把请求广播给所有已连接的 WS/WSS 客户端；**同一 id 只采纳第一个响应**。\n\n- 无客户端在线：`503` 服务已断开\n- 客户端未在超时内响应：`504` 服务已断开\n- 路径必须形如 `/private/<prefix>/<subpath>`（`<prefix>` 见 `config.json` 的 `tunnel.prefix`）。去掉前缀后的部分会放进 `http_request.request.path`，原始完整路径见 `raw_path`","operationId":"tunnel_proxy_private__subpath__head","parameters":[{"name":"subpath","in":"path","required":true,"schema":{"type":"string","title":"Subpath"}}],"responses":{"200":{"description":"由隧道客户端返回的响应（状态码透传）"},"404":{"description":"前缀不匹配"},"503":{"description":"服务已断开：当前没有 WS/WSS 客户端在线"},"504":{"description":"服务已断开：等待 WS/WSS 客户端响应超时"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"BroadcastRequest":{"properties":{"topic":{"type":"string","title":"Topic","description":"主题标签，客户端可据此过滤","default":""},"data":{"type":"object","title":"Data","description":"任意 JSON 负载"}},"type":"object","title":"BroadcastRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ReloadResult":{"properties":{"reloaded":{"type":"boolean","title":"Reloaded"},"source":{"type":"string","title":"Source","default":""},"changed":{"items":{"type":"string"},"type":"array","title":"Changed"},"note":{"type":"string","title":"Note","default":""}},"type":"object","required":["reloaded"],"title":"ReloadResult"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WelcomeMessage":{"description":"握手成功后服务端下发的第一条消息，用于对齐双方参数。","properties":{"v":{"default":1,"title":"V","type":"integer"},"type":{"const":"welcome","default":"welcome","title":"Type","type":"string"},"connection_id":{"description":"本次连接的 id，重连后会变化","title":"Connection Id","type":"string"},"server_time":{"description":"服务端时间，Unix 秒","title":"Server Time","type":"number"},"heartbeat_interval":{"description":"服务端心跳间隔秒数，0 表示关闭","title":"Heartbeat Interval","type":"number"},"request_timeout":{"description":"服务端等待响应的超时秒数","title":"Request Timeout","type":"number"},"max_body_bytes":{"description":"请求/响应体上限（解码后字节数）","title":"Max Body Bytes","type":"integer"},"proxy_prefix":{"description":"HTTP 转发前缀，如 /private/agent","title":"Proxy Prefix","type":"string"},"features":{"description":"服务端已启用的可选能力列表","items":{"type":"string"},"title":"Features","type":"array"}},"required":["connection_id","server_time","heartbeat_interval","request_timeout","max_body_bytes","proxy_prefix"],"title":"WelcomeMessage","type":"object"},"TunnelRequest":{"description":"转发给 WS 客户端的一条 HTTP 请求。","properties":{"method":{"description":"HTTP 方法，如 GET / POST","title":"Method","type":"string"},"path":{"description":"去掉前缀后的子路径，如 /api/users","title":"Path","type":"string"},"raw_path":{"description":"服务端收到的完整路径，如 /private/agent/api/users","title":"Raw Path","type":"string"},"query_string":{"default":"","description":"原始查询串，不含 '?'","title":"Query String","type":"string"},"headers":{"additionalProperties":{"type":"string"},"description":"请求头（已剔除 hop-by-hop 头，并补充 X-Forwarded-*）","title":"Headers","type":"object"},"body_b64":{"default":"","description":"请求体 base64；无请求体时为空串","title":"Body B64","type":"string"},"body_size":{"default":0,"description":"请求体解码后字节数","minimum":0,"title":"Body Size","type":"integer"},"client_ip":{"default":"","description":"HTTP 调用方 IP","title":"Client Ip","type":"string"},"received_at":{"description":"服务端接收时刻，Unix 秒","title":"Received At","type":"number"}},"required":["method","path","raw_path","received_at"],"title":"TunnelRequest","type":"object"},"HttpRequestMessage":{"description":"服务端广播给**全部** WS 客户端的转发请求。","properties":{"v":{"default":1,"title":"V","type":"integer"},"type":{"const":"http_request","default":"http_request","title":"Type","type":"string"},"id":{"description":"请求 id（UUID4）。同 id 只有第一个响应有效","title":"Id","type":"string"},"request":{"$ref":"#/components/schemas/TunnelRequest"}},"required":["id","request"],"title":"HttpRequestMessage","type":"object"},"PingMessage":{"description":"服务端心跳。","properties":{"v":{"default":1,"title":"V","type":"integer"},"type":{"const":"ping","default":"ping","title":"Type","type":"string"},"ts":{"description":"服务端发送时刻，Unix 秒","title":"Ts","type":"number"}},"required":["ts"],"title":"PingMessage","type":"object"},"CancelMessage":{"description":"服务端撤销一个尚未响应的请求（例如 HTTP 调用方已断开）。","properties":{"v":{"default":1,"title":"V","type":"integer"},"type":{"const":"cancel","default":"cancel","title":"Type","type":"string"},"id":{"title":"Id","type":"string"},"reason":{"default":"","title":"Reason","type":"string"}},"required":["id"],"title":"CancelMessage","type":"object"},"BroadcastMessage":{"description":"服务端向所有 WS 客户端下发的通知（预留，供运维/调试使用）。","properties":{"v":{"default":1,"title":"V","type":"integer"},"type":{"const":"broadcast","default":"broadcast","title":"Type","type":"string"},"topic":{"default":"","title":"Topic","type":"string"},"data":{"title":"Data","type":"object"}},"title":"BroadcastMessage","type":"object"},"ServerErrorMessage":{"description":"服务端因协议错误要断开连接时下发的原因。","properties":{"v":{"default":1,"title":"V","type":"integer"},"type":{"const":"error","default":"error","title":"Type","type":"string"},"code":{"description":"机器可读的错误码","title":"Code","type":"string"},"message":{"default":"","title":"Message","type":"string"},"fatal":{"default":false,"title":"Fatal","type":"boolean"}},"required":["code"],"title":"ServerErrorMessage","type":"object"},"HelloMessage":{"description":"客户端连接后的自我介绍（可选，但便于日志与运维识别）。","properties":{"v":{"default":1,"title":"V","type":"integer"},"type":{"const":"hello","default":"hello","title":"Type","type":"string"},"name":{"default":"","description":"客户端名称，例如主机名","title":"Name","type":"string"},"version":{"default":"","description":"客户端版本","title":"Version","type":"string"},"capabilities":{"description":"客户端支持的可选能力，用于未来扩展协商","items":{"type":"string"},"title":"Capabilities","type":"array"},"meta":{"description":"自定义元数据","title":"Meta","type":"object"}},"title":"HelloMessage","type":"object"},"TunnelResponse":{"description":"WS 客户端返回的一条 HTTP 响应。","properties":{"status":{"default":200,"description":"HTTP 最终响应状态码（200-599）。客户端返回 1xx 会被判为非法帧","maximum":599,"minimum":200,"title":"Status","type":"integer"},"headers":{"additionalProperties":{"type":"string"},"description":"响应头；Content-Length 由服务端重算，无需（也不应）填写","title":"Headers","type":"object"},"body_b64":{"default":"","description":"响应体 base64","title":"Body B64","type":"string"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"可选的原因短语，仅用于日志","title":"Reason"}},"title":"TunnelResponse","type":"object"},"HttpResponseMessage":{"description":"客户端返回的响应。同一 id 的后续响应会被服务端丢弃。","properties":{"v":{"default":1,"title":"V","type":"integer"},"type":{"const":"http_response","default":"http_response","title":"Type","type":"string"},"id":{"title":"Id","type":"string"},"response":{"$ref":"#/components/schemas/TunnelResponse"}},"required":["id","response"],"title":"HttpResponseMessage","type":"object"},"PongMessage":{"description":"客户端对 ``ping`` 的应答，也用于客户端主动保活。","properties":{"v":{"default":1,"title":"V","type":"integer"},"type":{"const":"pong","default":"pong","title":"Type","type":"string"},"ts":{"default":0.0,"description":"回填收到的 ping 的时间戳","title":"Ts","type":"number"}},"title":"PongMessage","type":"object"},"EventMessage":{"description":"客户端主动上报的事件（选填，服务端只记日志）。","properties":{"v":{"default":1,"title":"V","type":"integer"},"type":{"const":"event","default":"event","title":"Type","type":"string"},"level":{"default":"info","enum":["debug","info","warning","error"],"title":"Level","type":"string"},"message":{"default":"","title":"Message","type":"string"},"data":{"title":"Data","type":"object"}},"title":"EventMessage","type":"object"},"ClientErrorMessage":{"description":"客户端上报的错误（选填）。","properties":{"v":{"default":1,"title":"V","type":"integer"},"type":{"const":"error","default":"error","title":"Type","type":"string"},"code":{"default":"","title":"Code","type":"string"},"message":{"default":"","title":"Message","type":"string"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"关联的请求 id（如有）","title":"Id"}},"title":"ClientErrorMessage","type":"object"}},"securitySchemes":{"TunnelKey":{"type":"apiKey","in":"header","name":"X-Tunnel-Key","description":"与 config.json 中 tunnel.key 一致；用于 /api/admin/* 鉴权。"}}},"tags":[{"name":"ops","description":"探活、状态与运维接口"},{"name":"proxy","description":"HTTP 转发到 WS/WSS 隧道客户端"},{"name":"tunnel","description":"WS/WSS 隧道接入点"}]}