ITPub博客

首页 > IT基础架构 > 网络安全 > Dns解析(上) (转)

Dns解析(上) (转)

原创 网络安全 作者:worldblog 时间:2007-12-12 10:40:49 0 删除 编辑
Dns解析(上) (转)[@more@]

dns解析(上)


Dns(domain Name Server)即域名服务器,在网络中承担着将域名转换为IP地址的工作。在很多编程中都要用到这种技术,就是使用域名解析。这篇文章将说明这项技术。


通过Dns服务器,可以查询很多地址,比如Mail服务器地址,FTP服务器等等,我在这里就以mail服务器为例,并以Java实现。


+---------------------+XML:namespace prefix = o ns = "urn:schemas-microsoft-com:Office:office" />


  |  Header  |


  +---------------------+


  |  Question  |


  +---------------------+


  |  Answer  |


  +---------------------+


  |  Authority  |


  +---------------------+


  |  Additional  |


+---------------------+


这个表是从rfc1035文档中拷出来的,大致说明了dns包的格式。


Header

   0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F


  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


  |  ID  |


  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


  |QR|  Opcode  |AA|TC|RD|RA|  Z  |  RCODE  |


  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


  |  QDCOUNT  |


  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


  |  ANCOUNT  |


  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


  |  NSCOUNT  |


  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


  |  ARCOUNT  |


  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


  这个也是从rfc文档中拷出来的,只是我将其头部数字改成16进制了。



ID: 16位的一个标志,用以验证请求和回复消息的匹配。就实用程序产生一个16位的随机数。


QR: 1位数据表明这是一个请求,还是一个回复(0为请求,1为恢复)。


Opcode: 4位的数据表示查询的类型。


0   基本查找


1   反向查找


2   查询服务器情况


3-15  保留


RD:(recursion desired)即是否以递归方式的查询,RD=1为递归。

RA:(Recursion Available)表示服务器是否支持递归方式查询,只在回复中有效。

QDCOUNT:16位数据表示要查询的问题个数。

ANCOUNT:16位数据表示回复结果的个数,只在回复中有效。

 


其他几个请参考rfc文档,在这里我们只用这些,并将其他参数设为0。



Question

   0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F


  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


  |  |


  /  QNAME  /


  /  /


  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


  |  QTYPE  |


  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


  |  QCLASS  |


  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+



QNAME: 要求查询的域名地址邮件地址XXX@163.NET">。比如有这样一个邮件地址XXX@163.net,


  我们将@后面的地址提取出来,即163.net。然后将其变为这样一个序列,31633net0,也就是以 . 分界,并以各自的字符个数作为前缀,最后以0结束


QTYPE: 2位数据表示查询类型。


  A  1 a host address


NS  2 an authoritative name server


MD  3 a mail destination (Obsolete - use MX)


MF  4 a mail forwarder (Obsolete - use MX)


CNAME  5 the canonical name for an alias


SOA  6 marks the start of a zone of authority


MB  7 a mailbox domain name (EXPERIMENTAL


MG  8 a mail group member (EXPERIMENTAL)


MR  9 a mail rename domain name (EXPERIMENTAL)


NULL  10 a null RR (EXPERIMENTAL)


WKS  11 a well known service description


PTR  12 a domain name pointer


HINFO  13 host information


MINFO  14 mailbox or mail list information


MX  15 mail Exchange


TXT  16 text strings



这是在rfc文档中列出的各类type,我们在这里用MX,即QTYPE=15。


QCLASS: 2位数据表示查询方式。


  IN  1 the Internet


CS  2 the CSNET class (Obsolete - used only for examples in some obsolete RFCs)


  CH   3 the CHAos class


HS   4 Hesiod [Dyer 87]


这是在rfc文档中列出的各类class,我们在这里用IN,即QCLASS=15。



下面使用JAVA实现的原码:



说明:DnsTool.IntToBytes(int,int)是将一个整数转换为几个8位数的组合。


  DnsTool.StringToBytes(String)是将一个字符串转换为QNAME需要的格式,并以BYTE[]的格式返回。



class DnsHeader {



  private int ID;


  private int Flags=0;


  private byte[] head=new byte[]{0,0,0,0,0,0,0,0,0,0,0,0};


 


 /** Creates new DnsHeader */


  public DnsHeader()


 {


  setID();


  setFlags(Flags);


  setAnswer(false);//does not an answer


  setRecursionDesired(true);


  }



  private void setID()


  {


  byte[] tmp=new byte[2];


  ID=new Random().nextInt(10);


  tmp=DnsTool.IntToBytes(ID,2);


  head[0]=tmp[0];


  head[1]=tmp[1]; 


 }


 


 public int getID()


  {


  return this.ID;


  }


 


 private void setFlags(int Flags)


 {


  byte[] tmp=new byte[2];


  tmp=DnsTool.IntToBytes(ID,2);


  head[2]=tmp[0];


  head[3]=tmp[1];


 


 }


 


 public void setAnswer(boolean isAnswer)


  {


  head[2]=isAnswer?(byte)(head[2]|0x80):(byte)


(head[2]&0x7f);


  }


 


 public void setRecursionDesired(boolean isRecursionDesired)


 {


  head[2]=isRecursionDesired?((byte)(head[2]|0x1))


:((byte)(head[2] & 0xFE));


  }


 


  public void setQDcount(int num)//set the number of question


  {


   byte[] tmp=new byte[2];


  tmp=DnsTool.IntToBytes(num,2);


  head[4]=tmp[0];


  head[5]=tmp[1];



  }



  public byte[] getBytes()


  {


  return head;


  }


}



class Question {



  private byte[] question;


  private int QuestionLength;


  /** Creates new Question */


  public Question(String questionLabel,int questionType,


int questionClass)


 {


  byte[] transName=DnsTool.StringToBytes(questionLabel);


  byte[] ty=DnsTool.IntToBytes(questionType,2);


  byte[] cl=DnsTool.IntToBytes(questionClass,2);


 


 QuestionLength=0;


  //transfer the QuestionLabel to the bytes


  question=new byte[transName.length+4];


  System.arraycopy(transName,0,question,QuestionLength,


transName.length);


  QuestionLength+=transName.length;


 


 //transfer the type to the bytes


  System.arraycopy(ty,0,question,QuestionLength,


ty.length);


  QuestionLength+=ty.length;


 


 //transfer the class to the bytes


  System.arraycopy(cl,0,question,QuestionLength,


cl.length);


  QuestionLength+=cl.length;


  }



  public byte[] getBytes()


 {


  return question;


  } 


}


这里实现了dns 的包头和要查询的question的数据,然后只要将它们组合在一起就成了dns包了,接下来就只要将它发出去就可以了,下面这段程序就实现了这一功能。


说明:


DNSSERVER:就是dns服务器的地址。


  DNSPORT:dns服务器的端口,即53。


  DnsQuery:这个是header 和 question 组合的数据。



DatagramPacket ID_Packet;


  DatagramSocket ID_Socket;


  byte[] query=DnsQuery.getBytes();


  int i;


 


 try


  {


  ID_Packet=new DatagramPacket(query,query.length,InetAddress.getByName


(DNSSERVER),Constant.DNSPORT);


  ID_Socket=new DatagramSocket();


 


 //send query


  ID_Socket.send(ID_Packet);


 


 //close socket


  ID_Socket.close();


 


 }


  catch(IOException e)


  {


  System.out.println(e);


  return null;


  } 


 }


这里只讲了Dns的查询包,下篇将讲述Dns的返回包。



文章不免有错,请各位多指点craks@263.net


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752043/viewspace-991747/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
  • 博文量
    6241
  • 访问量
    2448670