|
|
Socket DNS查询之实现 |
|
|
作者:未知 来源:月光软件站 加入时间:2005-5-13 月光软件站 |
昨天突然无法访问任何网站了,可是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竟然大都不能用~~~~~~~
|
|
相关文章:相关软件: |
|