Write Your Own DNS Query

大部分人应该都知道 DNS 协议,以及它的用处。但是考虑过自己动手写 DNS message transmission 的应该不占多数。

我们不妨考虑如何自己实现一个简单的 DNS client,完成基本的 domain name query and response parsing。

因为 DNS 协议通常使用 UDP 作为其传输层协议,而且数据包是二进制包,所以实现一个这样简单的 demo 考虑用 golang 可能会省事儿不少。

DNS Message Format

大体上 DNS 不是一个复杂的协议(虽然各类坑实在不少),所有的消息,不管是 query 还是 reply,都共享一个消息格式:

1
2
3
4
5
6
7
8
9
10
11
+---------------------+
| Header |
+---------------------+
| Question | the question for the name server
+---------------------+
| Answer | Resource Records (RRs) answering the question
+---------------------+
| Authority | RRs pointing toward an authority
+---------------------+
| Additional | RRs holding additional information
+---------------------+
  • Header:消息头,包含一些参数、标志位
  • Question:包含 query 的信息,例如需要查询的 domain
  • Answer:reply 的信息
  • Authority:如果有信息,则表明应答的服务器是 ultimate authority server。别忘了 DNS 服务器是树形结构,通常终端用户查询的 DNS 服务器都是 local DNS server。
  • Additional:服务器传回的一些额外数据,非用户显式需要的

对于一个 query message,Answer section 是空的;而对于一个 reply message,Question 保存着对应 query 的数据。

一般而言,终端设备收到的 reply 消息里,AuthorityAdditional 是空的。所以下面会跳过这两个 section 的描述。

Read More

统一 ezio Buffer 的算术类型读写接口

ezio Buffer 一开始的时候只为 read, write 和 peek 提供了从 int8_tint64_t 的函数重载,如果需要处理 unsigned integers,那么就需要自己额外做 static_cast

ezio 的主要客户藏心同学早前抱怨过这个问题,并且同时建议我加上对 float/double 的浮点数支持。

对于这个建议我一开始是抵触的:

  • 自己 cast 又不是不能用,额外加重载支持三个操作工作量都要翻一番呢
  • 浮点数的 binary serialization 本来就是很难跨平台的,不是每个环境都(虽然大部分)要求使用 IEEE 754 spec。如果真的需要直接把浮点数存到网络包里,自己直接操作 underlying binary layout 不就好了…

于是藏心同学一开始开的 issue 我一直没理他,于是最后他自己关掉了…

等到我自己动手写一个 socks4a proxy 的时候我发现,自己 cast 真的是…太蛋疼了…而且代码看上去还非常丑,大面积的 static_cast 制造了相当一部分内容噪音。那会儿我大概有点理解藏心同学的内心感受。

于是我思考良久,打算改造 Buffer 的这部分接口,以支持绝大多数 integer types,顺带也增加入 floating piont types 的支持,这样 read, write, peek 就基本支持了绝大多数 arithmetic types。

通过直接增加重载是我极力避免的,因为除了接口签名外,大部分实现几乎是一样的,不外乎:

  • 如果是单字节,直接写/读操作
  • 如果是多字节,首先字节序转换,然后做写/读操作
  • 如果是浮点数,首先按照对应字节大小的整数类型解释内存,然后参考普通整数的处理

于是自然而然的想到直接将函数做成 function templates 来增强语义。

Read More

Monthly Read Posts in Mar 2019

Networking

The State of Browser Caching, Revisited

Read More

socks4a 协议代理

对于网络编程学习而言,尝试实现一个 proxy 是一个很好的途径。因为一个 proxy 对于 clients 来说是 server,对 remote servers 来说又是 client,一下就覆盖到了网络编程的两个大块。

同时,需要管理/协调两侧的连接对如何正确的处理网络连接的关闭也是一个挑战。

Read More

推荐 Google API Design Guide

Google API Design Guide

基本上 可以看作是 Google 开放的 API 设计指南。

大体上,Google 对外公开的 API 设计有如下几个特点:

Read More

Monthly Read Posts in Feb 2019

Network

Designing Headers for HTTP Compression

看起来是 HTTP/2 的 header compression 使用建议


How to Think About HTTP Status Codes

HTTP status codes 使用建议。

适合结合 Rest API design 相关文章一起食用。

Programming Languages

论golang Timer Reset方法使用的正确姿势

golang 这破 timer 坑真多


Guaranteed Copy Elision

C++ 17 Guaranteed copy elision explained.

Read More

在 Linux 上使用深信服 VPN

因为公司使用 Windows 和 MacOS 的人最多,因此导致两个后果:

  1. 连接公司内网需要使用的深信服 VPN 基本只支持 Windows 和 MacOS
  2. 后端 golang 大仓代码基本只能在 MacOS 或者 Linux 上提交和调试

求一下交集可以发现,在贵司使用 Linux 作为开发平台的同学应该很难过。很不幸的是,我刚好属于那种在 Linux (虚拟机里跑 Mint) 上写后端服务的人。

公司买的深信服的 VPN 服务,那个客户端虽然官方宣称支持 ubuntu,但是事实是压根不能用,连接成功后一旦有数据包就自动断开。

官方论坛有人反映过类似的问题,得到的回答千篇一律都是推荐使用 Windows 和 MacOS。

然而让我使用屎一样的 MacOS 是不可能的;让我在自己的主力台式机的 Windows 上装深信服的客户端也是不可能的。

Read More