服务与端口
Workspace 里的服务可以从本机浏览器或客户端打开,可以发布成公开 URL 给别人看,也可以让自己的程序直接连接 guest 内的端口或 socket。本页逐一介绍这几种方式,先讲 kibo 命令。
概述
按谁需要访问服务来选:
| 需要 | 用法 | 谁能访问 |
|---|---|---|
| 在本机浏览器打开 Web 服务 | kibo workspace service http | 只有这台机器 |
用本机客户端(如 psql、SSH、VNC)连接 | kibo workspace service forward | 本机上的任何进程 |
| 让本机的网页连接端口或 socket | kibo workspace service bridge | 来自同一个本机 origin 的网页 |
| 把 Web 服务给别人看 | kibo exposure create | 任何拿到地址的人 |
| 让自己的程序连接端口或 socket | 服务连接 | 只有持有会话凭证的一方 |
只有公开 URL 需要域名,由部署方配置。
在本机浏览器打开 HTTP 服务
kibo workspace service http 把 Workspace 里一个 HTTP 端口代理到本机的 127.0.0.1,用浏览器直接打开。只有这台机器能访问,不需要部署方配置域名。
代理 Workspace 里的 5173 端口,打开命令输出的 URL:
kibo workspace service http "$workspace_id" --tcp-port 5173
# URL http://127.0.0.1:5173/代理一直运行到按 Ctrl-C 为止,正在进行的连接一并结束。
代理可以一直开着。凭证在到期前自动换新,Workspace 重新启动后也不用重开。
参数
| 参数 | 默认值 | 说明 |
|---|---|---|
--tcp-port | 必填 | 服务在 Workspace 里监听的端口 |
--family | ipv4 | 服务监听在 ::1 时写 ipv6 |
--listen-port | 与 --tcp-port 相同 | 本机端口;0 取一个空闲端口 |
注意
- 本机端口默认与 Workspace 里的端口相同,应用写死的
localhost:5173回调地址和跨域配置照常可用。 - 本机端口被占用时,命令以退出码
2失败,换一个--listen-port。 - 服务只监听
127.0.0.1也能用,不需要改成监听0.0.0.0。 - 服务可以晚于代理启动,未启动期间请求返回
502。 - 代理只接受
Host为127.0.0.1或localhost加本机端口的请求,其他Host返回403。这挡住了把别的域名解析到127.0.0.1的网页。 - 应用看到的
Host就是浏览器发来的值,它生成的重定向与绝对地址会回到本机代理。 - keep-alive、SSE 等流式响应与 WebSocket 都可用。
- 代理同时最多持有 32 条到服务的连接,空闲、使用中与已升级为 WebSocket 的合计。找不到空闲连接的请求会等待。WebSocket 关闭前一直占着它的连接,所以开着 32 个 WebSocket 时其他请求都要等。
要把服务给别人看时,发布一条公开 URL。
本机端口转发
kibo workspace service forward 把 Workspace 里的一个 TCP 端口或受管 Unix socket 转发到本机 127.0.0.1 的一个端口。它不理解应用协议,所以数据库、SSH、VNC、gRPC 这类不走 HTTP/1.1 的服务都能用本机客户端直接连。
转发 5432 端口上的 PostgreSQL,再用 psql 连接:
kibo workspace service forward "$workspace_id" --tcp-port 5432
# Address 127.0.0.1:5432
psql -h 127.0.0.1 -p 5432 -U postgres用原生 VNC 客户端连桌面时,把桌面的 VNC socket 转发到本机 5900 端口:
kibo workspace service forward "$workspace_id" \
--unix-path /run/kibotos/services/desktop/vnc.sock --listen-port 5900转发一直运行到按 Ctrl-C 为止,正在进行的连接一并重置。
警告
转发不检查经过的数据。本机上任何进程都能连这个端口,包括其他账号的进程;浏览器里的网页也能向它发请求。对 HTTP 服务,网页可以借 DNS rebinding 读写它,所以 HTTP 服务请用 service http,它会校验 Host。这与 kubectl port-forward、ssh -L 的风险相同。
参数
| 参数 | 默认值 | 说明 |
|---|---|---|
--tcp-port | 与 --unix-path 二选一 | 服务在 Workspace 里监听的端口 |
--family | ipv4 | 服务监听在 ::1 时写 ipv6 |
--unix-path | 与 --tcp-port 二选一 | Workspace 里 /run/kibotos/services/ 下的 Unix socket |
--listen-port | 与 --tcp-port 相同;Unix socket 必填 | 本机端口;0 取一个空闲端口 |
注意
- 本机每条连接对应 Workspace 里的一条连接。连上就建立,服务端先发数据的协议(MySQL、SSH、VNC)不用等客户端先写。
- 两个方向的数据原样转发,一端结束写入后另一端读到 EOF。
- 一端不读时另一端的写入会等待,连接不会因此断开,也没有空闲超时。
- 最多同时转发 32 条连接,超出的新连接被重置。
- 连不上服务、Workspace 停止或连接中途失败时,本机连接被重置,stderr 写一行原因,例如
connection from 127.0.0.1:52144 reset: unavailable: …。 - 服务可以晚于转发启动。
- 转发可以一直开着。凭证在到期前自动换新,Workspace 重新启动后也不用重开。
- 本机端口被占用时,命令以退出码
2失败,换一个--listen-port。 - Unix socket 必须属于 root、权限为
0600,路径不能经过符号链接,否则连接以permission_denied失败。
本机 WebSocket 桥接
kibo workspace service bridge 把 Workspace 里的一个服务变成 127.0.0.1 上的 WebSocket,供本机上直接与服务通信的网页使用。它输出以 /stream 结尾的 WebSocket 地址,以及一个内置测试页的地址,测试页检查 guest 里的回显服务是否原样送回字节。
为你在 http://127.0.0.1:8080 提供的网页桥接 Workspace 的 7000 端口:
kibo workspace service bridge "$workspace_id" --tcp-port 7000 --origin http://127.0.0.1:8080- 目标参数
--tcp-port、--family、--unix-path与service forward相同。--listen-port设置本机端口,默认取一个空闲端口。 - 只接受
Origin与--origin完全一致的握手。不给--origin时,只有内置测试页能连接。 - 每个 WebSocket 各自建立一条到服务的连接。每条消息都是 binary,原样承载字节,没有 opcode 字节,单条最多 32 KiB。收到 text 消息时关闭 WebSocket。
- 服务结束写入时,桥接结束这条连接,以
1000关闭 WebSocket,网页之后不能再发送。 - 最多同时桥接 16 个 WebSocket,超出的握手返回
503。 - 凭证自动换新。桥接一直运行到按 Ctrl-C 为止,开着的 WebSocket 一并关闭。
公开 URL
kibo exposure 把 Workspace 内一个 HTTP 端口换成一条 https:// 地址,任何拿到这条地址的人都能在浏览器里打开它。适用于 Agent 在 Workspace 里写出一个 Web 服务、你需要直接看到它的场景。
前提条件
- 部署方已配置一个专供公开 URL 使用的域名,见安装 Exposure 网关。
没有配置这个域名时,kibo 不会列出 kibo exposure 这组命令,创建也会失败。
创建公开 URL
把 Workspace 的 3000 端口公开两小时:
workspace_id=workspace-example
kibo exposure create --workspace "$workspace_id" --port 3000 --ttl 2h输出里的 url 就是可以直接打开、也可以发给别人的地址。它不带结尾斜杠,要访问某个路径时直接接在后面。
警告
没有访问控制。拿到地址的人就能访问,没有口令、来源或 IP 限制。地址是随机的,这是它唯一的保护。不要用它公开不该被看到的东西。
查看与撤销
列出一个 Workspace 的 Exposure、查看其中一条,再撤销它:
kibo exposure list --workspace "$workspace_id"
kibo exposure get exposure-example
kibo exposure revoke exposure-example撤销后该地址立即停止服务,正在进行的连接一并结束。重复撤销不报错。
注意
- 端口在 guest 的 loopback 上读。服务只监听
127.0.0.1也能用,不需要为此改成监听0.0.0.0。服务监听在::1时加--ipv6。 - Exposure 撤销之后,它的地址不会再分给别人。
--ttl必填,上限 24 小时。到期自动停止服务。- Workspace 停止或删除时,它的全部 Exposure 一并撤销。Workspace 再次启动后要重新创建 Exposure,地址也是新的。
- 协议只有 HTTP,其中 WebSocket 与 SSE 可用。TCP、TLS 直通、UDP 与 QUIC 不在范围内。
Exposure 的 API
程序通过 ExposureService 的 CreateExposure、GetExposure、ListExposures 与 RevokeExposure 管理公开 URL。只有部署方配置了专用域名时,服务端才宣告 exposure.* 能力,见能力名。
需要的是一条给自己程序用的字节通道,而不是一个给浏览器的地址时,用服务连接:它要凭证,不需要域名,也不对公网开放。
用 API
服务连接把程序连接到 guest 内某个 TCP loopback 端口或 Unix socket,例如 VNC、Chrome DevTools 或应用端口。kibo workspace service 各命令与桌面查看页面都建立在它之上。
申请会话
两条连接路径的第一步相同:申请数据面会话时请求 SERVICE_CONNECT 权限范围,并在 service_targets 中列出目标。会话申请本身见申请会话凭证。
| 目标 | 字段 |
|---|---|
TCPLoopbackTarget | address_family、port |
UnixStreamTarget | path |
- 目标必须精确,不支持通配、端口范围或任意 IP。
- Unix socket 目标的规则与
--unix-path相同,见本机端口转发。 - 凭证只对列出的目标有效。
- 目标列表参与幂等判断。
选择路径
之后有两条路径,语义相同,编码不同:
| WebSocket(默认) | 双向流 | |
|---|---|---|
| 入口 | session.endpoint 上的 GET /v1/service | ServiceConnectionService/Connect |
| 需要 | 一次普通的 WebSocket 升级 | 每一跳端到端 HTTP/2 |
| 适合 | 前面有 L7 反向代理或 CDN 的部署;浏览器 | 直连或 L4 代理的部署 |
WebSocket
用下面的请求连接 guest 内的 TCP 端口或 Unix socket。完整参数见 /v1/service。
GET <endpoint>/v1/service?tcp_family=ipv4&tcp_port=9222
GET <endpoint>/v1/service?unix_path=/run/kibotos/services/desktop/vnc.sock凭证放在请求头里:
- 凭证放
Authorization: Bearer。 - 浏览器不能给 WebSocket 握手设请求头,改用
Sec-WebSocket-Protocol: kibotos-dp-credential.<credential>,服务端在 101 里回选同一个 subprotocol。
警告
不要把凭证放进 query,它会进访问日志和 Referer。
鉴权与连接 guest 都在升级之前完成,所以 101 就表示 guest 内的 socket 已经连上。在这之前的失败是普通 HTTP 响应,错误体与 /v1/files 一致。
升级之后,字节走 binary frame,每帧首字节是 opcode;失败以关闭帧送达。opcode 见帧,关闭码见关闭码。
警告
只有关闭码 1000 表示连接正常完成。1001 在这里是失败,尽管很多 WebSocket 库把它当作正常结束:例如 guest 内的服务重置了连接时,服务端以 1001 和 unavailable 开头的原因关闭。请自行判断关闭码。
双向流
- 向
session.endpoint发起ServiceConnectionService/Connect。这是 Connect 协议的双向流,基于 HTTP/2。 - 第一条消息发
open{target},目标必须在会话授予的列表中。服务端连上 socket 后回复一条connected,之后才开始传数据。 - 双向都用
data消息传原始字节。发送half_close表示不再写入,之后不能再发请求消息;收到eof表示对端已关闭写入。
两个方向都结束后,RPC 正常完成。
连接数上限
- 每个 Workspace 最多同时有 128 条服务连接,每台 node 最多 1024 条,两条路径合计。超出时新连接以
resource_exhausted失败。 - 两条路径的单条消息大小、拨号期限与速率上限相同,结束方式也相同,见
/v1/service的限制与说明。
从浏览器连接
浏览器只信任系统根证书,而数据面证书由内部 CA 签发,所以浏览器直连只在数据面前面有公共可信证书时可用。
没有这种边缘时,用 kibo workspace service bridge 或桌面查看页面:它们在本机把连接转成 loopback 上的 WebSocket。guest 里的服务本身是 HTTP 时,用 kibo workspace service http 在本机 loopback 上直接代理它,见在本机浏览器打开 HTTP 服务。