头图

如何阅读RFC

无论好坏,Requests for Comments (RFCs) 是互联网上许多协议内容的具体说明(specify)。这些文件被开发者视为圣典,他们分析这些文件的深层含义,然而又因为无法理解这些内容而把这些文件忽视掉或者忽视部分内容(irrelevant),这会给人带来挫败感,更重要的是可能会造成软硬件之间的信息交换和导致安全问题。然而如果你对它们的构建和发布过程有一些了解,就会对这些内容有一个更深的了解。

下面是我根据从HTTP以及其他一些事情中得出的经验。

Where to start? - 从什么地方查找我们需要的RFC

RFC Editor Web Site 是查找RFCs文档比较权威的地方。然而,正如我们在下面所看到的那样这个网站缺少一些关键信息,所以大多数人使用tools.inetf.org

你可以用浏览器搜索你想查看的RFC文档,但由于RFCs数量众多,(目前有近9000个),所以说找到自己所需的RFC是比较困难的。高效期间,你可以在 RFC Editor Web Site 网站上进行搜索。

另一个网站是rfc.fyi,这个网站允许你按 “标题” 和 “关键词” 搜索,可以点击界面上的一些 “标签” 快速访问一些内容。

RFC Editor Web Site 正在开发一种体验更好并带有自定义选项的新RFC格式,以此改善之前
纯文本的RFC难以阅读的问题,同时,如果你想获得更多可用的RFCs,你可以使用第第三方资源库来查询;例如,greenbytes保留了一个WebDAV相关的RFCs列表,HTTP工作组也保留了一些与HTTP相关的内容。

What kind of RFC is it? RFC的类型是什么

所有RFC文档顶部都有一个横幅,看起来像下面这样
What kind of RFC is it?

上面第一行,写着 "Internet Engineering Task Force (IETF)"。这表明该文档通过了IETF审查并对该协议内容达成了共识;尽管IETF并不广为人知,但还有其他方法可以发布RFC,而不需要IETF的共识;例如,独立个人或者其他团体(independent stream)。

事实上,有许多 "个人或者团体(streams)" 可以发布文件。只有 “IETF” 表示整个IETF已经审查了该协议并宣布了对该协议规范达成共识。(原文:Only the IETF stream indicates that the entire IETF has reviewed and has declared consensus on a protocol’s specification.)

较早的文件(大约在RFC5705之前)第一行写着 "Network Working Group",所以你必须多挖掘一些信息来查看它们是否通过IETF的审查并达成共识;首先看一下 "Status of this Memo" 部分,以及 RFC Editor Web Site 这个网站。 (Memo:备忘录)

第二行是 "Request for Comments" 的 “编号”。如果它写的是 "Internet-Draft",它就不是RFC;它只是一个互联网草案,任何人都可以写草案,该草案最后不一定会被IETF采纳。

Category 这行有4个可选值: “Standards Track”, “Informational”, “Experimental”, “Best Current Practice”. 四者之间的区别有时是模糊的,但如果它是由IETF发布(见第一行内容),它就经过了合理的审查。然而请注意即使由IETF发布的, "Informational" 和 "Experimental" 并不是标准。

最后,该文件的作者被列在标题的右侧。与学术界其他文档中作者含义不同的是: 这里的 “作者” 是指 “谁写了这个文件” 如果你看到附加的 "Ed.",这表明他们是编辑了该文件,该文件是预先存在的(比如当RFC被修改时),通常在接近整个文件底部的"致谢"部分会有谁为该文件做出贡献的全面的清单。

Is it current? 是否当前

RFCs是一系列的存档文件(已经归档);它们一个字符都不能改变 ( RFC7158和RFC7159之间的差异,这是一个极端的例子,他们把年份搞错了)

文档顶部的横幅包含的一些元数据帮助我们辨别该文档是不是我们所需的。
What kind of RFC is it?

Obsoletes: 列出了本文档完全取代的RFCs;也就是说你应该使用当前该文档,而不是那些个被淘汰的文档。请注意当一个较新的协议出现时,一个旧版本的协议不一定会被淘汰;例如,HTTP/2并没有淘汰HTTP/1.1,因为旧协议仍然是合法的(而且是必要的);然而RFC7230确实淘汰了RFC2616,因为现在RFC7230是该协议的参考。

Updates: 该行列出了该文件对“哪些其他的RFCs”进行了重大改变;换句话说,如果你正在阅读那些被更新的文件,那么你可能也应该阅读该文件。

不幸的是,ASCII格式的RFC(例如,在RFC Editor Web Site 这个网站RFC)并没有告诉你哪些文件更新或淘汰了你目前正在看的文件。这就是为什么大多数人使用 tools.inetf.org上的RFC库,它把这些信息放在一个像下面这样的横幅

xxx

上面横幅中每个数字都是一个链接,所以你可以很容易地找到数字所链接的文件。

即使是最新的RFC也经常有问题。在上面的横幅上,你还会看到右边有一个:"Errata Exist(勘误表)",上面还有一个勘误的链接。

勘误表是不值得发布新的RFC情况下对文件的更正和澄清。有时它们会对RFC的实施产生实质性的影响(例如,如果规范中的一个错误导致了重大的误解),所以它们是值得去看的。

例如,这里是RFC7230的勘误表。当阅读勘误表时,请记住它们的状态;许多被拒绝是因为有人误读了规范。

Understanding context

开发者按照RFC中的规范,并实现了一些内容,但却做了与作者意图相反的事情,这比你想象的更常见。

这是因为要把规范写得在有选择地阅读时不会被误解是非常困难的(任何圣经都是如此)

因此,不仅要阅读直接相关的文本,还要(至少)阅读它所引用的任何内容,无论是在同一个规范中还是在另一个规范中; 在紧要关头,如果你不能阅读整个文件,阅读任何可能相关的部分会有很大的帮助。

例如,HTTP消息头被定义为由CRLF分隔,但如果你跳到这里,当你看到 "接收者可以将单个LF识别为行结束符,并忽略前面的CR"。你觉得对吗?

同样重要的是许多协议设立了IANA注册处来管理他们的扩展点;这些不是规范,是真理的来源。例如,HTTP方法的规范列表就在这个注册表中,而不是在任何HTTP规范中。
It’s also important to keep in mind that many protocols set up IANA registries to manage their extension points; these, not the specifications, are the sources of truth. For example, the canonical list of HTTP methods is in this registry, not any of the HTTP specifications.

Interpreting requirements

在靠近文档顶部的部分,几乎所有的RFC都有类似这样的内容

这些RFC2119关键字有助于定义互操作性,但它们有时也会使开发者感到困惑。很常见的情况是看到一个规范说:

这个requirement被放在 "Foo Message"这个协议上,如果你要发送一个Foo Message,很明显它不需要包含一个Bar Header;如果你包含了 Bar Header 它就不是一个符合要求的消息。

然而,收件人的行为就不那么清楚了;如果你看到一个带有Bar Header 的Foo Message,你会怎么做?

尽管规范中没有说要怎么做,但一些开发者会拒绝包含有Bar Header 的 Foo Message。另一些人仍然会剥去Bar Header 并处理该 Foo Message 或忽略它 --即使规范明确指出所有头都需要处理。

所有这些事情都会--无意中--导致 互操作性 问题。正确的做法是遵循正常的Header处理,除非有相反的具体要求。

这是因为在一般情况下,规范的编写是为了公开地规定行为; 换句话说,所有没有明确禁止的行为都是允许的。因此,在规范中读到太多的内容会无意中造成伤害(Reading too much into specifications can unintentionally cause harm):也就是不要对规范过分的解读,因为你会引入新的行为,而其他人将不得不绕过这些行为。

在一个理想的世界里,规范将以 处理信息的人的行为 来定义,就像这样:

如果没有这一点,最好在规范的其他地方寻找关于错误处理的一般性建议(例如:HTTP的一致性和错误处理部分)

另外,请记住requirements 的目标(the target of requirements);大多数规范都有一套术语,它们用来区分协议中的不同角色。

例如: HTTP有代理,这是一种proxies,它同时实现了客户端和服务器(但不是User-Agent 或 an origin server); 需要注意针对所有这些角色的需求(pay attention to requirements targeted at all of those roles)。

同样,HTTP在一些要求中区分了 "generating"消息和 仅仅"forwarding"消息,这取决于具体的情况。注意这种特定的术语可以让你省去很多猜测的麻烦。

SHOULD

Should是一个模棱两可的术语,RFC2119中的描述如下:
xx

在实践中作者经常使用Should和Should not 来表示:"我们希望你这样做,但我们知道我们不可能总是要求你这样做"。

例如:overview of HTTP methods 我们可以看到:

xxx

这些 "SHOULDs"不是 "MUSTs",因为服务器可能合理的采取一些行动:如果请求来自一个被认为是攻击者的客户端可能会放弃该连接,如果需要HTTP认证,它可能会返回401(Not Authenticated)代替405

有时我们会看到这种形式的Should:

xx

注意上面的 "unless" 指定了一种Should"允许的情况。

Reading examples

另一个非常常见的陷阱是搬运文档的中的示例(examples),然而示例通常很少受到作者的关注,因为它们需要随着协议的每次更改而更新。

因此示例(examples)通常是规范中最不可靠的部分,尽管作者在发表之前应该会再次检查示例但错误总会出现。

此外即使是一个完美的示例也不可能覆盖到该协议的方方面面;为了简洁这些示例会被简化。

你应该花费更多的时间去阅读真正的文本内容而不是这些示例。

On ABNF

BNF:(Backus-Naur Form)是由John Backus和Peter Naur首先引入的用来描述计算机语言语法的符号集,RFC2234定义了扩展的ABNF,在Internet的定义中ABNF被广泛使用。

Augmented BNF is often used to define protocol artefacts. For example:

xxxx

Once you get used to it, ABNF offers an easy-to-understand sketch of what protocol elements should look like.

However, ABNF is “aspirational” - it identifies an ideal(理想的) form for a message, and those messages that you generate really need to match it. It doesn’t specify what to do with received messages that fail to match it. In fact, many specifications fail to say what the relationship of ABNF is to processing requirements at all.

Most protocols will fail badly if you try to enforce their ABNF strictly, but sometimes it matters. In the example above, whitespace isn’t allowed around the semicolon, but you can bet(打赌) that some people will put it there, and some implementations will accept it.

So, make sure you read the text around the ABNF for additional requirements or context, and realise(意思到) that absent a direct requirement, you may have to adjust parsing to be more accepting of input than the ABNF implies.

Some specifications are starting to acknowledge(认可,承认) the aspirational nature of ABNF and specifying explicit(显示的) parsing algorithms that incorporate(包含,含有) error handling. When specified, these should be followed exactly, to ensure interoperability(互操作性).

Security considerations

RFC3552以来RFC就包括了 "Security Considerations"部分。

一般RFC在发布时都含一个 "Security Considerations"的重要部分;审查过程不允许该草案中没有“Security considerations"部分。无论你是协议的起草者或者使用者都要阅读并确保你理解了“Security considerations";如果你不这样做你很可能会遇到麻烦。

如果遇到一些需要讨论的问题可以查看该文档的参考文献(如果有的话),也可以尝试查找其他的关于该问题的一些条目。

Finding out more

如果在RFCs文档中你还没有找到问题的答案,或者你不太明白RFCs文档所表达的真正含义,那么你可以先找到与你的问题关系最为密切的”相关工作组“(relevant Working Group) 并在其邮件列表中提出自己的疑问。如果没有工作组涉及到你提的这个问题,请尝试在 "相应领域"(appropriate area) 的邮件列表中提问。

然而你最应该做的是与了解该问题的人进行讨论而不是提交勘误。

许多工作组现在都使用Github来管理他们的规范,如果你对一个 "active specification" 有疑问,就去提交你的问题。如果它已经是一个RFC,通常最好使用邮件列表进行沟通,除非你发现要求使用其他的沟通方式。

我敢肯定还有更多的关于如何阅读RFCs的文章,而且有些人会质疑我写的内容,但这是我的看法并希望对你有用。

这篇文章最初出现在 mnot 的博客上并经许可后转载于此。

本篇文章转载于 www.ietf.org ; 感谢作者的付出。

Ready enjoy it


Stephanie
1.8k 声望1.2k 粉丝

发上等愿,结中等缘,享下等福;


« 上一篇
Rust Self Control

引用和评论

0 条评论