分类目录归档:C/C++

路由追踪的原理和实现

Windows提供tracert命令追踪一个IP数据报从本地要目标主机经过的每个路由器的IP地址,在网络分析、网络故障诊断等方面有重要意义。

为了防止一个IP数据报中因为某些路由故障(如路由环路)而在网络逗留过长的时间导致网络环境出现进一步的恶化趋势,TCP/IP协议在IP数据报里设置了一个TTL(Time To Live)字段。在IP数据报被发送出来的时候TTL有一个初始值(如128),每经过一个路由器此值会被路由器执行减1操作,如果一个路由器发现它路由的某个IP数据报的TTL值被减1之后的结果为0,那么这个数据报将会被丢弃,然后路由器会发送一个内容为“TTL超时”的ICMP数据报通知这个IP数据报的发送者。利用这一点,可以用如下的办法实现路由追踪:

(1)构造一个TTL值为1,发往追踪目标的ICMP请求响应(Echo)数据报;
(2)发送数据报;
(3)等待回应,如果收到来自目标的ICMP响应(Reply)数据报则记录响应地址和耗时,并结束追踪;如果收到ICMP TTL超时数据报,则记录路由器地址和耗时,数据报TTL值加1,重复第(2)步,直到收到目标响应或超出最大跟踪跳数。

Windows下可以使用IcmpSendEcho函数来发送自定义TTL的ICMP请求数据报。http://msdn.microsoft.com/zh-cn/library/aa366050(v=VS.85).aspx

DNS协议及DNS客户端的实现

DNS(Domain Name System)是一个提供域名解析服务的分布式系统,主要功能是完成域名与其对应的IP地址之间的相互转换。网络中提供DNS服务的主机叫做DNS服务器,而向DNS服务器发起查询请求的主机叫做DNS客户端,客户端与服务器之间通过DNS协议这一种应用层协议来相互通信并交换数据。

DNS协议建立在UDP或TCP协议之上,DNS服务器开放UDP:53端口和TCP:53端口监听客户端发来的请求。一般情况下客户端通过UDP协议封装请求报文,服务器也用UDP协议封装回应报文;由于广域网中不适合传输过大的UDP数据包,因此规定当封装了DNS回应的UDP数据包长度可能超过512字节时,客户端应该使用TCP协议连接DNS服务器并传输请求和回应,具体包括以下两种情况:(1)客户端认为UDP回应包长度可能超过512字节,主动使用TCP协议;(2)客户端第一次使用UDP协议发送DNS请求,服务端发现UDP回应包会超过512字节,截断UDP包中的回应报文,并在回应报文中为TC字段置1以通知客户端该报文已经被截断,客户端收到之后再发起一次TCP请求。

DNS数据报由头部和记录部分组成,其中请求报文只有问题部分,而回应报文可以有问题部分、回答部分、授权部分和附加部分。
net

DNS头部包含了标识、标志以及各个记录部分的记录个数。net_dns_header

其中标识字段用于确定请求会话,DNS服务保证请求和其对应的回应报文中标识字段的值是相等的。标志字段被分成若干子字段,用于标识数据包的各个属性。DNS头部的C语言结构可以表示如下:

问题部分由问题记录组成,资源部分、授权部分和附加部分由资源记录组成,问题记录和资源记录的结构是不一样的。
问题记录的格式如下图所示
net_a_record
查询名字是将要查询的域名,域名是一个由圆点分为若干节的字符串,这里的名字也由若干节组成,每一节第一个字节是这一个节中包含字符的长度。如下图
net_query_name

查询类型一般是A(地址)记录,表示把域名转换为32位的IPv4地址。全部的查询类型如下所示

查询类别一般都为1(Internet)。

资源记录的格式如下图所示
net_res_record
其中前三个字段与问题记录一致。生存时间表示该DNS回应记录可以在主机缓存中生存的时间,以秒为单位。资源数据长度是紧随其后的资源数据的长度,资源数据的具体内容与域类型字段有关,在只考虑A类型的时候这里的记录是一个32位的IP地址。

为了使DNS报文尽可能短,DNS协议对于可能重复出现的域名节采取压缩策略,因此通常情况下在一个报文中不会存有完全相同的域名节。当出现重复的域名节时,域名节的第一个字节将不是这个节的字符长度,而是以11开头的一个指针,指向该节在报文中第一次出现的位置。
net_pointer

下面是一个用UDP协议实现的DNS客户端类(没有实现TCP方式),测试Demo运行结果如图所示

dns_resolver


最新的相关文章

DNS:域名系统(一)
DNS:域名系统(二)