摘要

  • WKS 用一个 IPv4 地址、一个 IP 协议号和一串端口比特,发布某地址“应当”提供哪些知名服务;它表达的是区文件维护者的配置主张,而不是当下探测结果。
  • RFC 974 一度鼓励邮件程序用 WKS 筛掉没有 SMTP 位的 MX 目标;RFC 1123 随后依据部署经验撤回这一步,因为很少发布的目录无法让“没有记录”等于“没有服务”。
  • 一个端口号的登记、DNS 中的声明、进程监听、路径放行和应用身份分别由不同主体控制。缓存中的一位无法替这些主体共同作证,客户端最终仍须尝试连接。

邮件程序先问了一个看似便宜的问题

假设 1986 年的一台邮件中继拿到三个 MX 候选。真正连接每台主机需要等待,失败还会拖慢下一次尝试。DNS 已经告诉它候选名称和地址,何不再让 DNS 告诉它哪台机器运行 SMTP?

WKS 正是这种思路的产物。邮件程序查询目标的 Well Known Service 记录,选中 TCP 协议,再查看从零开始编号的位图。第 25 位若为一,就代表 TCP 端口 25;依据当时的文字,这台地址上应有 SMTP 服务器监听。若为零,服务被视为不支持。

这个判断甚至可以发生在 TCP SYN 之前。它看起来节省了一次必然失败的连接,也把多个候选缩成更“干净”的列表。然而,一位只会陈述 DNS 发布内容,并不会观察另一台机器此刻正在做什么。WKS 的历史价值,不在于位图编码多么奇特,而在于它暴露了目录证据与运行事实之间的落差。

1983 年的服务清单长在地址上

RFC 883 在 1983 年 11 月定义 WKS。RFC 1035 于 1987 年保留其格式:前 32 位是 Internet 地址,随后 8 位是 IP 协议号,剩余部分是一段长度为整字节倍数的可变位图。

位号就是该协议的端口号。第零位对应端口 0,第 25 位对应端口 25;传输内容结束之后没有出现的位一律按零处理。一个地址同时支持 TCP 和 UDP,需要不同记录;一台多宿主机器有多个地址,也需要多条记录。服务主张因而牢牢绑定在具体 IPv4 地址与传输协议上。

这种编码很适合一个端口集中在低位、服务随主机稳定存在的世界。它的成本由最高的置一端口决定,而不是由服务数量决定:即使只声明两个服务,中间每一位也要占据位置,只有末尾连续的零可以省掉。这里不是说历史网络一定因此遭遇了某项性能故障,而是说明格式本身把“服务”定义成端口空间里的坐标。

位图也只能回答有或无。它没有主备顺序,没有同级分流权重,没有独立的目标主机名,没有为某个实例选择另一端口的字段,更没有维护窗口或健康状态。多条 WKS 可以列出多组地址与协议,却不能告诉客户端应当先选哪一组。

在早期环境中,这仍有合理性。Assigned Numbers 已经为常用协议协调端口。只要主机配置、端口表和 DNS 区文件由同一套运维节奏维护,一张公开清单就能减少远端试错。问题在于,“谁能登记号码”“谁能发布区数据”和“谁能维持进程在线”从来不是同一种权力。

RFC 974 把缺失变成了淘汰理由

1986 年 1 月的 RFC 974 不只介绍 WKS,而是让它参与邮件路由决策。文档强烈鼓励邮件程序针对每个 MX 目标查询 WKS;如果目标没有表明支持所需邮件服务,就从列表中丢弃。

这一步把负面证据赋予了直接后果。理想情况下,区文件是一份完整且及时的服务清单,零位确实可以免去一次无用连接。现实只要稍微偏离理想,语义就改变了:没有 WKS,可能只是站点从未采用;没有 SMTP 位,可能是新增服务后忘了改区文件;不同管理员可能分别维护 DNS 与主机;缓存可能仍保存旧版本。

一旦发布不普遍,“未声明”便不再等于“不存在”。邮件程序如果坚持这层过滤,就会把可用的 MX 当成不可投递目标。目录原本想省下失败成本,反而制造了无需发生的失败。

正面记录也无法保证成功。DNS 数据按 TTL 缓存,期间进程可能退出,地址可能换主机,防火墙可能改变,端口上也可能换成另一种程序。即使 TCP 建连成功,SMTP 对话仍可能拒绝邮件。缓存不是缺陷;它是 DNS 可扩展的基础。正因缓存有价值,WKS 才不可能同时充当瞬时健康探针。

1989 年的修正不是新格式,而是亲自尝试

RFC 1123 在 1989 年 10 月记录了运行经验。它要求应用不要依赖能够找到一条准确列出某地址全部服务的 WKS,因为 Internet 站点并不经常使用这种记录。确认服务是否存在的办法,被压缩成一句务实建议:直接尝试使用它。

文档还专门改写邮件规则。RFC 974 建议过用 WKS 验证每个 MX 是否支持 SMTP;后来经验显示 WKS 没有广泛支持,因此 MX 处理不应再走这一步。

这不是宣布每条 WKS 都是假数据,也不是删除 DNS type 11。如今的 IANA DNS 参数表 仍把 WKS 登记为类型 11,描述为“well known service description”。保留代码点能避免另作他用,并让旧数据仍可解释;它不等于当前使用率或健康认证。

真正改变的是证据门槛。一个置一位最多可当作发布者的提示;一个缺失或零位,却不能在覆盖不完整时承担否决权。对邮件而言,错误淘汰可用服务器的损失大于尝试一次连接的成本。于是验证权回到协议交互本身。

一位背后其实有五种事实

把“这台机器提供 SMTP”拆开,WKS 的权限边界就会清楚。

第一种事实来自号码协调。端口 25 与 SMTP 的关联,让不同实现共享词汇,避免随意冲突。号码登记不观察任何具体主机。

第二种来自 DNS 发布者。区管理员声明某地址、某协议的某些位为一。这是一条有权威来源和 TTL 的配置主张,但权威性只覆盖“谁发布了它”,不覆盖“它现在仍准确”。

第三种来自主机。只有系统与进程能决定端口是否真的绑定,重启后是否恢复,监听程序是否还是预期软件。

第四种来自路径策略。路由、包过滤和访问控制会让同一监听端口对不同来源呈现不同结果。全局 DNS 记录无法列出每条路径上的许可。

第五种来自应用协议。打开 TCP 端口不等于完成 SMTP 握手,更不等于对端身份可信或邮件已被接受。应用层证据只能在对话中取得。

后来的 RFC 6335 对号码边界说得更直白:分配服务名或端口号并非对产品背书,流向已分配端口的流量甚至未必属于登记服务。防火墙与系统管理员应依据对流量的认识制定策略,而非仅看号码是否分配。这段文字晚于 WKS,却准确说明为何一张号码位图不能变成信任名单。

SRV 改变表达能力,却没有接管健康证明

2000 年的 RFC 2782 处理的是另一种服务定位。客户端查询某个域中的服务与传输组合,记录返回 Priority、Weight、Port 和 Target。目标是有地址记录的主机名,而不是嵌在记录里的 32 位地址。多条记录可以区分主服务器与备用服务器,也能在同一优先级内表达静态选择倾向。

与 WKS 相比,服务不再只是某个端口位。它有名称,可以在指定目标上使用明确端口,也可以随目标主机迁移。客户端拿到的是一套有限的选择规则,而不是一个地址的整张服务目录。

RFC 6335 又把服务名与固定端口进一步分开:若 SRV 一类机制能在运行时找端口,服务可以只登记名称而不占用固定端口。号码仍是协调资源,却不再是服务身份的唯一表达。

不过 SRV 的权重并非实时负载,目标也可能在缓存期间故障。客户端仍需解析、连接并核验应用身份。因此这段演化不是“旧 DNS 不可靠、新 DNS 全知”,而是后来的格式更诚实地分开服务名称、定位意图、客户端选择与端点验证。

这些来源没有证明什么

本文只使用七项官方来源:RFC 883、RFC 974、RFC 1035、RFC 1123、RFC 2782、RFC 6335,以及现行 IANA DNS 参数表。它们能证明格式、规范建议、建议被撤回的理由、后续定位方式和当前代码点状态。

它们不能测量今天有多少区发布 WKS、多少查询仍发生、哪些实现支持 type 11,也不能证明某条历史记录曾经陈旧。位图长度的讨论来自格式本身的算术,不是实测网络开销。本文也不把 SRV 说成 WKS 所有用途的直接替代品。

WKS 最值得保留的历史结论,是一个精确编码也可能承载模糊证据。第 25 位可以无歧义地读成端口 25,却无法同时回答进程、路径、许可与身份。Internet 最终没有靠更用力地相信这一位来修复问题,而是让客户端跨出目录,向服务本身求证。