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竟然大都不能用~~~~~~~
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DNS服务器通常需要两个主要组件:查询解析和响应生成。以下是一个简单的Python示例,演示如何实现一个基本的DNS服务器: ```python import socket # DNS查询解析 def parse_dns_query(data): # 解析DNS查询请求 # 返回请求域名 return domain_name # DNS响应生成 def generate_dns_response(data): # 从请求中解析出请求域名 domain_name = parse_dns_query(data) # 构造DNS响应报文 # 返回响应报文 return response_data # 创建UDP套接字 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 绑定UDP套接字到指定IP和端口 server_address = ('127.0.0.1', 53) sock.bind(server_address) # 循环监听客户端DNS请求并响应 while True: data, client_address = sock.recvfrom(4096) response_data = generate_dns_response(data) sock.sendto(response_data, client_address) ``` 该示例中,`parse_dns_query`函数从DNS查询请求中解析出请求域名,`generate_dns_response`函数根据请求域名构造DNS响应报文。`parse_dns_query`和`generate_dns_response`函数中的具体实现将根据DNS协议规范进行。 接下来,创建一个UDP套接字并将其绑定到指定的IP地址和端口,然后在一个无限循环中监听客户端DNS请求并响应。当收到DNS查询请求时,该程序将调用`generate_dns_response`函数生成DNS响应报文,并将其发送回客户端。 请注意,上述示例仅演示了DNS查询解析和响应生成的基本概念。实际上,实现一个完整的DNS服务器需要更多的代码和处理逻辑,包括缓存DNS响应、处理各种DNS记录类型等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值