socket DNS查询之实现昨天突然无法访问任何网站了,可是QQ还在正常工作 ~~~~~ `嗯,肯定是DNS出了问题 ~~ 用自己做的TraceRoute察看了一下,6个网关都工作正常 ~~~ 确实是DNS坏了 ~~ 烂铁通的DNS太差 ~~ 换 ~~~ 可是哪个DNS更好? 自己做一个工具比较一下吧 ~~ 可是还不懂DNS的工作原理 ^ _ ^ 搜索百度,下载TCP / IP 详解2卷 ~~ 竟然没有一个能下的了......还中了木马 ~~~~ `晕倒! 不过有收获!找到了全国的各大城市DNS列表! 看来只有自己蒙了!好在还有IRIS。不过试用期只剩10天了!呵呵,抓包......原来是这样的:Windows向DNS发送了一个UDP包,这个包中当然有 ' www.xxx.com ' ,然后DNS服务器返回一个包含IP地址的UDP包,我们的工作就是分解这个包 ~~~~~ DNS服务器的端口是53,接受的Query package格式如下: PDomainQuery = ^ YDomainQuery; YDomainQuery = record u16id : word; // 任意 u16flag : word; // $0100; // 标准查询 u16question : word; // 1 u16answer : word; // 0 u16author : word; // 0 u16addition : word; // 0 u8secB : byte ; // section begin u8secE : byte ; // section end u16type : word; // 1 u16class : word; // 1 end; 我们这样填充这个包: procedure FillDomainQuery( pdq: PDomainQuery; sAddr: string ); var pData, pTemp : PChar; i, cbLen : Integer; pu16 : PWord; begin FillChar( pdq ^ , sizeof (YDomainQuery) + Length(sAddr), 0 ); pdq ^ .u16id : = htons( DNS_ID ); pdq ^ .u16flag : = htons( DNS_STAND_QUERY ); pdq ^ .u16question : = htons( DNS_QUESTION ); // pdq^.u16answer := 0; // pdq^.u16author := 0; // pdq^.u16addition := 0; // 初始化域名数据缓冲区 cbLen : = Length(sAddr) + 2 ; pData : = AllocMem( cbLen ); Inc( pData ); Move( sAddr[ 1 ], pData ^ , Length(sAddr) ); Dec( pData ); // 填充域名数据缓冲区 pTemp : = pData; i : = Pos( ' . ' , sAddr ); // www.baidu.com --- example while i > 0 do begin // i=4; i=6 pTemp ^ : = Chr(i - 1 ); // 3 5 Inc( pTemp, i ); // ^ ^ Delete( sAddr, 1 , i ); // s='baidu.com'; s='com' i : = Pos( ' . ' , sAddr ); end; pTemp ^ : = Chr( Length(sAddr) ); // s='com' Inc( pTemp, Length(sAddr) + 1 ); pTemp ^ : = # 0 ; // 把域名数据拷贝到pdq^.u8secB pTemp : = @pdq ^ .u8secB; Move( pData ^ , pTemp ^ , cbLen ); FreeMem( pData ); // 最后填写Type/Class pu16 : = PWord( pTemp + cbLen ); pu16 ^ : = htons( DNS_TYPE_HOST ); Inc( pu16 ); pu16 ^ : = htons( DNS_CLASS_INET ); end; // 把构造好的包发送出去 var pdq : PDomainQuery; pdq : = AllocMem( sizeof (YDomainQuery) + Length(edtDomain.text) ); FillDomainQuery( pdq, edtDomain.text ); udp.SendBuf( PChar(pdq), sizeof (YDomainQuery) + Length(edtDomain.text) ); // 不过DNS返回的包更复杂~~~不给它定义什么结构了,直接整!!! function DecodeDomainAnwser( pbuf: PChar; len: Integer ): string ; var p : PChar; w : Word; j : Integer; s1,s2,s3,s4: string ; begin p : = pbuf; j: = 0 ; result : = ' TransactionID: ' + IntToStr( PWord(p) ^ ) + # 13 # 10 ; Inc( p, 2 ); Inc( j, 2 ); result : = result + ' Response Flag: ' + Format( ' %x ' , [ntohs(PWord(p) ^ )]) + # 13 # 10 ; if ntohs( PWord(p) ^ ) <> DNS_STAND_RES then begin result : = result + ' Response error... ' + # 13 # 10 ; Exit; end; Inc( p, 2 ); Inc( j, 2 ); result : = result + ' Question: ' + IntToStr( ntohs(PWord(p) ^ ) ) + # 13 # 10 ; Inc( p, 2 ); Inc( j, 2 ); result : = result + ' Answer: ' + IntToStr( ntohs(PWord(p) ^ ) ) + # 13 # 10 ; Inc( p, 2 ); Inc( j, 2 ); result : = result + ' Authority: ' + IntToStr( ntohs(PWord(p) ^ ) ) + # 13 # 10 ; Inc( p, 2 ); Inc( j, 2 ); result : = result + ' Addition: ' + IntToStr( ntohs(PWord(p) ^ ) ) + # 13 # 10 ; Inc( p, 2 ); Inc( j, 2 ); w : = Byte( p ^ ); while w > 0 do // 跳过DNS HOST返回的要查询的域名 begin Inc( p, w + 1 ); Inc( j, w + 1 ); w : = Byte( p ^ ); end; Inc( p ); Inc( j ); Inc( p, 4 ); Inc( j, 4 ); // type/class Inc( p, 6 ); Inc( j, 6 ); // name/type/class Inc( p, 4 ); Inc( j, 4 ); // time w : = ntohs( PWord(p) ^ ); // 得到数据长度 Inc( p, 2 ); Inc( j, 2 ); // 到达真正的数据地址 Inc( p, w ); Inc( j, w ); Inc( p, 10 ); Inc( j, 10 ); Inc( p, 2 ); Inc( j, 2 ); s1 : = IntToStr( Byte(p ^ ) ); Inc( p ); Inc( j ); s2 : = IntToStr( Byte(p ^ ) ); Inc( p ); Inc( j ); s3 : = IntToStr( Byte(p ^ ) ); Inc( p ); Inc( j ); s4 : = IntToStr( Byte(p ^ ) ); Inc( p ); Inc( j ); result : = result + ' IP: ' + s1 + ' . ' + s2 + ' . ' + s3 + ' . ' + s4 + # 13 # 10 ; if len < j + 32 then Exit; Inc( p, 6 ); // +name/type/class Inc( p, 4 ); // +time Inc( p, 2 ); // 到达真正的数据地址 s1 : = IntToStr( Byte(p ^ ) ); Inc( p ); s2 : = IntToStr( Byte(p ^ ) ); Inc( p ); s3 : = IntToStr( Byte(p ^ ) ); Inc( p ); s4 : = IntToStr( Byte(p ^ ) ); result : = result + ' IP: ' + s1 + ' . ' + s2 + ' . ' + s3 + ' . ' + s4 + # 13 # 10 ; end; 呵呵,试验一下,全国的各大城市DNS列表中的Host竟然大都不能用 ~~~~~~~