(原创)Bonjour协议分析

2016/09/16 网络协议

介绍

Bonjour这个词来源于法语,是“你好”的意思,应该是指遵从这个协议的设备可以通过主动打招呼的形式发现彼此。

Bonjour是Apple推出的零配置网络协议,主要的目的是在缺少中心服务器的情况下解决网络设备的IP获取,名称解析和服务发现等关键问题。

Bonjour主要基于两个协议:mDns协议 和 DNS-SD协议。

mDns协议是一个用于零配置网络发现协议,本身借鉴DNS协议,只不过作了些修改,DNS是点播基于53端口,mDns是组播基于5353端口。

DNS-SD协议是mDns协议的补充协议,因为mDns协议仅仅是约定了消息的基本格式和消息的收发顺序,具体的内容就由DNS-SD协议来补充。

mDns协议和Upnp协议发现部分功能类似,都是用于局域网设备服务发现,只不过Upnp是包含发现设备后,控制,通知等一套完整的协议,而mDns仅仅用于网络发现,至于发现之后怎么使用全凭用户自己架构。

在介绍mDns协议之前,我们有必要说明下Dns协议。

Dns协议

Dns报文结构:

img

Dns协议包含报头和正文两部分,其中报头固定12个字节,正文长度可变,而且分四种。

报头

img

以上就是12字节的报头格式,具体说下每个字段的意思吧:

ID:16位的标识符,主要用来配对请求和应答。

QR:占用1位,用以区分报文是请求还是应答。

OPCODE:占用4位,用于指定查询类型。

  • 0:标准查询
  • 1:逆向查询
  • 2:查询服务状态
  • 3:保留
  • 4:通知
  • 5:更新
  • 6-15:保留

AR:占用1位,仅当应答才设置为1。

TC:占用1位,截断标志,如果被截断为1.

RD:占用1位,可选项,表示要求递归与否,为1要求递归。

RA:占用1位,代表应答服务器可以执行递归查询。

Z:占用3位,保留,必须为0.

RCODE:占用4位,仅在DNS应答时才设置,意义如下:

  • 0:无错误
  • 1:格式错误
  • 2:严重失败
  • 3:名字错误
  • 4:没有实现
  • 5:拒绝
  • 6-15:保留

QDCOUNT:占用16位,指明DNS查询段中查询问题的数量。

ANCOUNT:占用16位,指明DNS应答中返回的资源记录的数量,在查询段中为0。

NSCOUNT:占用16位,指明DNS应答段中所包括的授权域名服务器的资源记录的数量,在查询段中该值为0。

ARCOUNT:占用16位,指明DNS附加段里所含资源记录的数量,在查询段中该值为0。

正文段

包含4种:查询段,应答段,授权段,附加段,其中应答段,授权段,附加段的格式一样。

查询段格式

img

QNAME:该字段是可变长字段,其中包含一个被请求的域名,用一系列标签表示,每一个标签由一个表示长度的十六进制数和相应长度的值组成。

QTYPE:该字段占用16位,指定查询的资源类型。

QCLASS:该字段占用16位,制定查询的类别。

其余三个格式

img

查询段是主机向域名服务器发出的报文,域名服务器按照主机查询类型,返回应答段,授权段或附加段。

NAME:可变字长,同查询段。

TYPE:占用16位,同查询段。

CLASS:占用16位,同查询段。

TTL:占用32位,代表资源记录的生命周期,以秒为单位。

RDLENGTH:占用16位,表示资源数据的长度,以字节为单位。

RDATA:可变字长,按不同的查询类型返回不同的数据。

抓包分析

使用wireshark抓包软件,使用window的命令行工具,ping www.sina.com 抓包如下:

查询报文:

img

应答报文:

img

注意在查询报文中,可以包含若干查询段,若干授权段,若干附加段的,同样在响应报文中,也可以包含若干应答段,若干授权段,若干附加段的,只是得按顺序排列下来,如上图的 Answers 里面就有7条响应段。

另外为了解释可变字长,打开二进制查看器如下:

img

03代表3个字节,后面跟了77 77 77,表示 w w w

04代表4个字节,后面跟了73 69 6e 61,表示s i n a

03代表3个字节,后面跟了63 6f 6d,表示c o m

00代表0个字节,表示可变数据完结

以上就是Dns协议的大概,结构上看还是很简单的。

mDns协议

mDns协议基于UDP/IP,使用多播地址224.0.0.251/5353来通信,除了借用Dns的所有概念之外,mDns还特别对其中的部分概念作了扩展,这里归纳下几个基本的概念。

资源记录:局域网中各个主机之间交换的消息内容。

资源记录包含几个关键字段:

  • 记录名称:表示消息内容(对应上面的NAME)。
  • 记录类型:表示消息内容的类型(对应上面的TYPE)。
  • 记录类别:在mDns中取值固定为1(对应上面的CLASS)。

其中的记录类型又分为以下几种:

  • A 类型:主机名称和IPV4之间的对应关系。
  • AAAA 类型:主机名称和IPV6之间的对应关系。
  • SRV 类型:标识服务实例名称对应哪一个主机名和端口号。
  • PTR 类型:标识服务实例名称和服务类型之间的对应关系,一般在查询具有相同服务类型的实例时使用。
  • TXT 类型:对某个服务实例提供的附加信息按照key/value形式给出。
  • ANY 类型:任意类型,一般用于查询中。

mDns协议的基本工作过程为:寻址,探测,宣告,查询/监听并响应。其中探测和宣告需要保证主机名和服务名在局域网中具有唯一性。

至于mDns格式方面也不用作多余的解释,基本和Dns一致,只是在报头中的FLAG标志里只有QR,AR,TC有意义,其它都是固定为0。

DNS-SD 协议

mDns协议规定了消息的基本格式和消息的收发的基本顺序,DNS-SD 协议在这基础上,首先对实例名,服务名称,域名长度/顺序等作出了具体的定义,然后规定了如何方便地进行服务发现和描述。

服务实例名称 = <服务实例>.<服务类型>.<域名>

服务实例一般由一个或多个标签组成,标签之间用 . 隔开。

服务类型表明该服务是使用什么协议实现的,由 _ 下划线和服务使用的协议名称组成,如大部分使用的 _tcp 协议,另外,可以同时使用多个协议标签,如: “_http._tcp” 就表明该服务类型使用了基于tcp的http协议。

域名一般都固定为 “local”

DNS-SD 协议使用了PTR、SRV、TXT 3种类型的资源记录来完整地描述了一个服务。当主机通过查询得到了一个PTR响应记录后,就获得了一个它所关心服务的实例名称,它可以同通过继续获取 SRV 和 TXT 记录来拿到进一步的信息。其中的 SRV 记录中有该服务对应的主机名和端口号。TXT 记录中有该服务的其他附加信息。

协议总结

以上只是总结了mDns协议和mDns-SD协议的大概,具体应用中还有许多需要看协议文档,比如:规定了设备入网第一次查询要求单播,之后使用多播,规定了一个消息包中尽可能地包含所有记录,规定了收到查询请求之后,主机在回应之前需要随机等待一段时间,以减少响应消息的数量等等。

协议实践

mDNSResponder获取源代码,里面有各个平台的client,可以在window及linux系统中编译使用。

在我的ubuntu系统中,使用mDNSPosix版的client,使用 make os=”linux” 和 make os=”linux” install 命令即可编译安装,window版本的直接使用virsual studio导入编译运行即可。

抓包如下:

img


知识共享许可协议
本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。

站内搜索

    撩我备注-博客

    joinee

    目录结构