Kibotos

Egress

Egress调用方运营的 SOCKS5 出口代理。Workspace 的网络策略引用它之后,发往指定网段的 TCP 连接从调用方的网络离开。 是调用方运营的 SOCKS5 端点。Workspace 的网络策略引用它之后,发往指定网段的 TCP 连接从调用方的网络离开。本页介绍怎样创建、引用、更新和删除 Egress,以及连接在什么情况下经它离开。

前提条件

服务端必须支持 Egress。不支持时,kibo egress,以及带 Egress 参数或 --drain-seconds 的 kibo workspace network 命令退出 14,不发请求。能力名见用 API。

创建 Egress

下面的命令创建一个带 label 的 Egress,查看它,再列出带这个 label 的 Egress:

egress_id=$(kibo egress create --address proxy.example.com:1080 --username alice --password-file ./proxy-password --label team=infra -q)
kibo egress get "$egress_id"
kibo egress list -l team=infra

创建与更新描述完整的端点:

参数规则
--address必填,host:port,host 是 IP 地址或主机名
--username 与口令可省略;给出时两个都要有,各 1 到 255 字节,按 RFC 1929 认证,见口令
--tls、--tls-server-name、--tls-ca-cert-file开启 TLS,SOCKS5 协商与转发的流量都在 TLS 内。给出后两个参数之一也会开启 TLS。校验名缺省取端点的 host;CA 是 PEM,至多 64 KiB,给出时替代系统信任库
--udp缺省关闭。开启后,引用它的策略才能让 udp Resolver 的查询经它离开,SOCKS5 用 UDP ASSOCIATE 承载
--label、--annotation只在创建时给出,之后单独修改,见 labels 与 annotations

警告

开启 TLS 时 UDP 数据报不受 TLS 保护,以明文发往端点答复的中继地址。

  • 端点在创建与更新时先核对一次。 IP 地址落在私网、本机、组播、文档用途等固定的特殊用途网段,或主机名在 ctrl 解析一次的结果里有这样的地址,返回 invalid_argument。这一步只是提早发现错误:node 每次拨号都会重新解析,去掉不允许的地址,只连剩下的。
  • 每个 Egress 有自己的版本。 由服务端分配:创建时为 1,端点设置变化时加一,与引用它的策略的版本互不影响。

口令

kibo 没有直接写口令值的参数,口令因此不进入命令历史与进程列表。

  • 用 --password-stdin 从标准输入读,或用 --password-file 从文件读。
  • 只给 --username 时,kibo 在终端上不回显地询问口令;没有终端时退出 2。
  • 标准输入与文件末尾的一个换行会被去掉,其余字符都是口令的一部分。
  • 口令只写。任何读取、列表、命令输出与错误信息都不返回它;用户名照常返回,详情里只说明有没有配置凭证。

让连接经 Egress 离开

public-internet 的策略可以引用一个 Egress,并写明经它离开的目的网段。目的地落在这些网段里的新建 TCP 连接经 Egress 转发,其余照常直出。下图的网段只写了 10.0.0.0/8:

10.0.0.5:落在网段 10.0.0.0/8 里,经 Egress公网目的地:不在网段里,直出

下面的命令让全部 IPv4 与 IPv6 目的地经 Egress 离开,再加上并删掉网段 10.0.0.0/8,最后解除引用:

kibo workspace network set "$workspace_id" public-internet --egress "$egress_id" --egress-destination 0.0.0.0/0 --egress-destination ::/0
kibo workspace network add "$workspace_id" --egress-destination 10.0.0.0/8
kibo workspace network remove "$workspace_id" --egress-destination 10.0.0.0/8
kibo workspace network remove "$workspace_id" --egress "$egress_id"
命令对 Egress 的效果
network set、workspace create--egress 加至少一个 --egress-destination 写入一项;不带 --egress 时策略不引用 Egress
network add策略还没有 Egress 时,--egress 加 --egress-destination 引用它;已有时 --egress-destination 给它加网段,--egress 只能写同一个 ID
network remove--egress-destination 删掉网段,至少留一条;只写 --egress 时解除引用,这些网段恢复直出

add 与 remove 编辑 --allow、--deny 时保留已有的 Egress 项。读到的策略已引用 Egress 时,add 与 remove 同样要求 Egress 的能力。

  • 一个策略至多引用一个 Egress,网段 1 到 256 条。 多于一项、网段为空或超过 256 项、条目写法不规范、DENY_ALL 带 Egress,都返回 invalid_argument,期望不变。
  • 网段的写法与 allow、deny 相同。 各自只作用于本地址族。
  • Egress 必须存在。 不存在或已删除时返回 not_found。
  • 只交给支持 Egress 的 node。 创建或启动时没有宣告出口能力的 node,返回 failed_precondition,reason 为 CAPABILITY_UNAVAILABLE,不会以不带 Egress 的策略运行;运行中加 Egress 而所在的 node 不支持时,返回同样的错误,期望不变。
  • 只改网段的顺序是内容变化,版本加一,但不改变任何连接的走向。

连接的走向

目的地在网段里的新建 TCP 交给 node 上的转发服务,由它向 SOCKS5 端点发起 CONNECT,请求的是 guest 原本要连的目的地址:

一个连接按下面的顺序判定:

  1. 到链路 DNS 地址的 53 端口:交给链路 DNS,不按目的地经 Egress 转发。
  2. 在 deny 里且不在 allow 里:拒绝,私网条目同样生效。
  3. 目的地在网段里的新建 TCP:经 Egress 转发,不做私网与特殊用途地址的拒绝。
  4. 目的地在网段里的 ping:立即拒绝,回 ICMP 管理性禁止。
  5. 其余:按目的地的判定直出。

网段可以写私网与平台网段。经 Egress 的连接从调用方的网络离开,不受直出时的私网拒绝约束。下图表明同一个地址直出时照常被拒绝:

目的地在网段里时,各类流量的去向:

流量去向
guest 发起的 TCP经 Egress 转发
ping立即拒绝,回 ICMP 管理性禁止
guest 发起的其他 UDP与直出相同,PUBLIC_INTERNET 不放行
发往链路 DNS 地址的查询不经 Egress。只有 Resolver 的路径指名这个 Egress 时,转发的查询才经它离开,见 DNS 与 Resolver

出口失败不回退直出:端点连不上、TLS 校验失败、SOCKS5 协商或认证失败时,guest 的连接被重置,原因见 Egress 的故障。

改变连接走向

改变连接走向的修改(直出改为经 Egress、反过来,或换掉网段)不立即切断已有连接:

  • 新连接立即按新策略建立,旧连接沿原路径继续传输,到宽限期结束后关闭,draining_revision 在这段时间里是旧的策略 revision。
  • 宽限期是这次修改的 --drain-seconds,取 0 到 3600,缺省 600,0 表示切换时立即关闭。
  • 宽限期内再次修改不延长更早的截止时间。
  • 新的 mode、allow 或 deny 不再放行的连接不等宽限期,立即终止。
修改已建立的连接
网段从 10.0.0.0/8 改成 0.0.0.0/0原来直出的公网连接继续传输,宽限期满后关闭;新连接经 Egress
解除对 Egress 的引用经 Egress 到 10.0.0.5 的连接继续传输,宽限期满后关闭;新连接直出,被拒绝
同一次修改把 10.0.0.5 加进 deny立即终止
解除引用后删除 Egress仍在宽限期内的连接立即关闭

更新 Egress

更新在 ctrl 保存后返回,不等待 Workspace。引用它的运行中 Workspace 随后把新连接切到新 revision,已有连接按这次更新的宽限期关闭。下图是切换的过程:

时间发生什么怎样看到
运行 kibo egress update(UpdateEgress)ctrl 保存,revision 3 变为 4 后返回Egress 的 revision 为 4
切换之前node 取得新配置,新连接仍用 revision 3Workspace 里这个 Egress 的 applied_revision 为 3
切换,通常在 30 秒内新连接用 revision 4;revision 3 的连接继续传输applied_revision 为 4,draining_revision 为 3
宽限期满revision 3 的连接关闭draining_revision 为 0

下面的命令更新 Egress,旧 revision 的连接在切换 60 秒后关闭:

kibo egress update "$egress_id" --address proxy.example.com:1080 --username alice --password-file ./proxy-password --drain-seconds 60
  • 更新是整体替换。 kibo egress update 没写的参数为空。口令读不回来,每次更新都要重新给出。
  • 并发的更新被拒绝。 不传 --expected-revision 时,kibo 先读取当前版本再提交,期间被别人改过时退出 13。脚本重放时把 --command-id 与 --expected-revision 一起传入。
  • 内容相同的更新成功,版本不变。
  • 宽限期是这次更新的参数。 --drain-seconds 取 0 到 3600,缺省 600,0 表示切换时立即关闭,不随 Egress 保存。
  • node 一时取不到新配置时保持原 revision。 ctrl 会重试,Workspace 状态不变。
  • 仍有 udp Resolver 经它离开时不能关闭 UDP。 这样的更新返回 failed_precondition(CONFLICT),kibo 退出 13,内容不变。
  • 比较两个 revision 判断是否生效。 Workspace 状态里这个 Egress 已应用的 revision 等于 Egress 的 revision 时,新连接已经用上新配置,见确认策略已经生效。

删除 Egress

被引用的 Egress 不能删除,所以下面的命令先解除引用,再删除 Egress:

kibo workspace network remove "$workspace_id" --egress "$egress_id"
kibo egress delete "$egress_id"
  • 还有未删除的 Workspace 的策略引用它时,删除返回 failed_precondition(CONFLICT),kibo 退出 13。
  • 删除后,仍经它在宽限期内的连接立即关闭。
  • 已删除的 Egress 对所有读取与引用都返回 not_found。

用 API

Egress 用 EgressService 管理,写操作都带幂等键,见幂等键。创建 Egress 里的参数对应这些字段:

kibo 参数API 字段
--addresssocks5.address
--username 与口令socks5.username、socks5.password
--tls、--tls-server-name、--tls-ca-cert-filesocks5.tls
--udpudp_enabled
--label、--annotationlabels、annotations
  • spec.socks5 是端点协议。 目前只有 SOCKS5。创建与更新不选协议时返回 invalid_argument。
  • revision 由服务端分配: 创建时为 1,spec 变化时加一。
  • 更新必须带期望版本。 与当前版本不符返回 aborted(reason 为 CONFLICT),内容不变。
  • 网络策略里的 Egress 是 egresses。 每一项写一个 egress_id 与它的 destinations。
  • 宽限期在修改策略与更新 Egress 时都是 drain_seconds。

服务端支持时宣告能力 workspace.network_policy.egress.socks5。以后每种出口协议一个能力名,调用方据此判断部署支持哪些协议。

警告

老版本的服务端会静默丢掉 egresses。写入前先确认能力名存在。

下一步

  • DNS 与 Resolver:用 Resolver 让 DNS 查询也经 Egress 离开。
  • 网络排查:确认更新已经生效,以及经 Egress 的连接被重置时怎样找原因。
  • 网络策略:目的地规则,以及策略的修改什么时候生效。

本页内容