Kibotos

DNS 与 Resolver

本页介绍 guest 的 DNS 查询发往哪里,以及怎样用 Resolver 把查询交给调用方选定的上游。

链路 DNS

guest 只向自己链路上的一个地址发 DNS 查询,查询去哪里由策略决定。下图依次是三种去向:不引用 Resolver、Resolver 的路径为 direct、Resolver 的路径经 Egress。

不引用 Resolver:部署 DNS 服务器Resolver,路径 directResolver,路径经 Egress
项规则
链路 DNS 地址第一个部署 DNS 服务器所在地址族的 guest 网关地址;IPv6 是 fe80::1
/etc/resolv.conf只有一个 nameserver,即链路 DNS 地址
端口53,UDP 与 TCP
策略查询的去向
DENY_ALL立即失败:UDP 收到端口不可达,TCP 被重置,没有报文离开 Workspace
PUBLIC_INTERNET,不引用 Resolver转给与链路 DNS 地址同族的第一个部署 DNS 服务器,其余的不使用
PUBLIC_INTERNET,引用 Resolver按 Resolver 的协议与路径转给调用方的上游,见在策略中引用 Resolver
  • allow、deny 与 Egress 网段都不作用于这些查询。 只有 Resolver 能让查询经 Egress 离开。
  • 改策略不改 guest 的 DNS 配置。 改 mode、引用、更换或解除 Resolver,/etc/resolv.conf 都不变。
  • guest 直接发往部署 DNS 服务器的 UDP 被拒绝。 只有发往链路 DNS 地址的查询算 DNS。
  • 升级前启动的 Workspace 保持原来的 DNS 配置,直到重启。 它的 /etc/resolv.conf 仍列出部署 DNS 服务器,不能引用 Resolver:这样的修改返回 failed_precondition,reason 为 CONFLICT,期望与生效的策略都不变。停止再启动后换到链路 DNS 地址,之后可以引用。

Resolver

Resolver调用方提供的 DNS 服务器。Workspace 的网络策略引用它之后,guest 的 DNS 查询发往它。 是调用方选定的 DNS 上游。服务端必须支持 Resolver;不支持时,kibo resolver 与带 Resolver 的 kibo workspace network 命令退出 14,不发请求。能力名见用 API。

创建 Resolver

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

resolver_id=$(kibo resolver create --https https://dns.example.com/dns-query --label team=infra -q)
kibo resolver get "$resolver_id"
kibo resolver list -l team=infra

创建与更新必须选一种协议,不选时返回 invalid_argument:

参数规则
--udpIP 地址或 IP:port,端口缺省 53,不接受主机名。guest 经 TCP 发来的查询经 TCP 发往同一地址
--tcpIP 地址或 IP:port,端口缺省 53,不接受主机名
--tlsDNS over TLS,host 或 host:port,host 可以是主机名,端口缺省 853
--httpsDNS over HTTPS,https://host[:port]/path,端口缺省 443,路径必须给出,至多 2048 字节;不接受用户信息、查询串与片段。查询用 POST 发送
--label、--annotation只在创建时给出,之后单独修改,见 labels 与 annotations
  • IP 地址的写法同 allow、deny 的条目。 IPv6 后面跟端口时写在方括号里,例如 [2001:db8::53]:53。
  • kibo 在发请求前拒绝写法不对的地址,退出 2。
  • 读取原样返回写入的内容,缺省的端口不补上。
  • tls 与 https 用系统信任库校验证书,校验的名字是 host。 host 是 IP 地址时,证书要带这个 IP。
  • 每个 Resolver 有自己的版本。 由服务端分配:创建时为 1,上游设置变化时加一,与引用它的策略的版本互不影响。

警告

Resolver 没有凭证,读取返回全部内容。URL 的路径对同一部署里能读 Resolver 的其他调用方可见,不要把访问令牌放在路径里。

在策略中引用 Resolver

public-internet 的策略引用一个 Resolver 后,guest 的 DNS 查询转给它。下面的命令引用一个直接发往上游的 Resolver:

kibo workspace network set "$workspace_id" public-internet --resolver "$resolver_id" --resolver-path direct

策略还没有 Resolver 时,下面的命令在一次修改里加上一个 Egress 和经它离开的 Resolver:

kibo workspace network add "$workspace_id" --egress "$egress_id" --egress-destination 10.0.0.0/8 --resolver "$resolver_id" --resolver-path "egress:$egress_id"

下面的命令解除引用:

kibo workspace network remove "$workspace_id" --resolver "$resolver_id"

一个策略至多引用一个 Resolver,它必须存在,不存在或已删除时返回 not_found。路径决定到上游的连接怎么离开,没有默认值:

--resolver-path到上游的连接
direct从 node 的上联地址直接发往上游
egress:<egress-id>经这个 Egress 发往上游。它必须是同一策略引用的 Egress,与网段是否覆盖上游无关;上游可以在调用方的内网。udp Resolver 还要求这个 Egress 开启 UDP
命令对 Resolver 的效果
network set、workspace create--resolver 加 --resolver-path 写入一项;不带 --resolver 时策略不引用 Resolver
network add策略还没有 Resolver 时引用它;已有时只能写同一个 ID 与路径。换 Resolver 或改路径用 set
network remove--resolver 解除引用,查询回到部署 DNS 服务器。Resolver 路径指名的 Egress 只能与 --resolver 一起删

读到的策略已引用 Resolver 时,add 与 remove 同样要求 Resolver 的能力。

上游不可用时 guest 收到 SERVFAIL,不回退部署 DNS 服务器。转发查询有下面的时限与上限:

项规则
一次查询从收到到应答至多 4 秒
udp 上游的重发2 秒没有应答时重发一次
同时处理的查询每个 Workspace 至多 256 个,超出的立即回 SERVFAIL
guest 经 UDP 收的应答上限取查询里 EDNS 声明的大小,没有 EDNS 时为 512 字节;超出时回带 TC 位的应答,guest 改用 TCP 重查
  • 直出的上游在引用时先核对一次。 IP 地址落在私网、本机、组播、文档用途等固定的特殊用途网段,或主机名在 ctrl 解析一次的结果里有这样的地址,返回 invalid_argument;被直出引用的 Resolver 更新成这样的上游也返回 invalid_argument。
  • 这一步只是提早发现错误。 与 Egress 端点一样,node 拨号时用部署 DNS 服务器解析主机名,去掉不允许的地址,只连剩下的,全被去掉时这次查询得到 SERVFAIL。
  • 经 Egress 时 node 不解析也不核对上游。 主机名交给端点解析;udp 上游经 UDP ASSOCIATE,其余经 CONNECT。端点答复的 UDP 中继地址按端点的规则核对。
  • Egress 更新后, 经它的查询与 TCP 一起换用新 revision;宽限期只作用于 TCP 连接。
  • 非法组合返回 invalid_argument,期望不变:DENY_ALL 带 Resolver、多于一项、没有路径、路径指名的 Egress 不在策略里、udp Resolver 经未开启 UDP 的 Egress、直出的上游落在特殊用途网段。
  • 只交给支持 Resolver 的 node。 创建或启动时没有宣告 Resolver 能力的 node,返回 failed_precondition,reason 为 CAPABILITY_UNAVAILABLE,不会以不带 Resolver 的策略运行;运行中加 Resolver 而所在的 node 不支持时,返回同样的错误,期望不变。
  • 引用、更换或解除 Resolver 都是内容变化,版本加一;请求在新配置生效后返回,之后的新查询按新配置发出。

更新与删除 Resolver

下面的命令把 Resolver 改为 DNS over TLS,然后解除引用并删除它:

kibo resolver update "$resolver_id" --tls dns.example.com
kibo workspace network remove "$workspace_id" --resolver "$resolver_id"
kibo resolver delete "$resolver_id"
  • 更新是整体替换。 内容相同时成功且版本不变。
  • 并发的更新被拒绝。 不传 --expected-revision 时,kibo 先读取当前版本再提交,期间被别人改过时退出 13;脚本重放时把 --command-id 与 --expected-revision 一起传入。
  • 更新在保存后返回,不等待 Workspace。 引用它的运行中 Workspace 随后把新查询切到新 revision,通常在 30 秒内完成;已经发出的查询按原配置完成。
  • 比较两个 revision 判断是否生效。 Workspace 状态里对应项已应用的 revision 等于 Resolver 的 revision 时,更新已经生效,见确认策略已经生效。
  • 被直出引用时不能改成特殊用途地址。 核对规则见在策略中引用 Resolver。
  • 被引用的 Resolver 不能删除。 还有未删除的 Workspace 的策略引用它时,删除返回 failed_precondition(CONFLICT),kibo 退出 13。先解除引用。
  • 已删除的 Resolver 对所有读取与引用都返回 not_found。

用 API

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

kibo 参数API 字段
--udpudp.address
--tcptcp.address
--tlstls.address
--httpshttps.url
--label、--annotationlabels、annotations
  • revision 由服务端分配: 创建时为 1,spec 变化时加一。
  • 更新必须带期望版本。 与当前版本不符返回 aborted(CONFLICT),内容不变。
  • 网络策略里的 Resolver 是 resolvers。 至多一项,每项用 resolver_id 写一个 Resolver 与它的路径;direct 对应 path.direct,经 Egress 的路径对应 path.egress_id。
  • 更新是否生效看 Workspace 状态里对应项的 applied_revision。

服务端支持时宣告能力 workspace.network_policy.resolver。

警告

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

下一步

  • Egress:创建 Resolver 路径经过的 Egress。
  • 网络排查:查询得到 SERVFAIL 时找原因。
  • 网络策略:目的地规则,以及策略的修改什么时候生效。

本页内容