您的位置:首页 > 其它

DNS域名解析

2016-07-26 16:41 127 查看
DNS(Domain Name System)域名系统,即域名解析系统,作用就是将浏览器中输入的网址解析为IP地址,然后发起http请求。

虽然不知道最初什么原因产生的域名系统,但是一个很明显的驱动力就是直接输入地址来访问网站是太麻烦的。域名的划分有几个等级,最常见的几个顶级的域名域,例如.edu表示的教育机构,.gov表示政府机构等,域名最后的一个“.”,表示根域,不过通常我们都不写,根域名服务器有十三个IP地址,在域名解析服务器的应用中是最先访问的域名服务器。

域名的解析过程使用的是一个树的结构,进行层次查询,例如访问www.abc.com这样的网址:

第一步:查询当前浏览器中是否具有该网址的缓存IP地址,有则直接使用

第二步:如果浏览器中不存在该域名缓存,则查询主机hosts文件,是否有该域名对应的记录,有则直接使用

第三步:如果主机中也没有,则查找配置的DNS服务器,该DNS服务器如果有对应域名的缓存,则返回使用,因为缓存的周期性,所以不保证返回的是有效的地址,可能已经发生了更改

第四步:如果配置的DNS服务器中没有,则进行正式的域名解析过程(前面也算域名解析,不过这个过程更为标准,返回的地址也更为权威),配置的DNS服务器向根域名服务器发出请求,根域名服务器会返回一个com的域名服务器地址

第五步:配置的DNS服务器又向com的域名服务器发出请求,返回一个abc.com的域名服务器地址

第六步:配置的DNS服务器又向abc.com的域名服务器发出请求,返回www.abc.com的地址,主机拿到配置的DNS服务器的返回地址,根据返回地址即可向目标网站发出http请求。

配置的DNS服务器一般都是距离较近的,常见的是ISP提供的域名服务器,因为缓存的关系,发生正式的域名解析次数其实不多,这也充分说明了如果缓存中存在的是错误的域名地址,其他主机对该域名请求时也会得到错误的地址,可能会造成很大的影响。在这里配置的DNS服务器充当的角色就像设计模式中的一个外观类对象,实现主机与域名解析服务器之间的解耦。

在域名解析的过程中容易发生的两个问题:

1.域名劫持

域名劫持是指对正常存在的域名记录进行修改,返回错误的地址,常见如ISP(因为常用的域名解析服务器是由ISP提供的)修改一些网址到广告推送网页或者对某些网站的解析结果直接返回错误地址。

2.域名欺骗

域名欺骗也称为域名投毒,因为DNS协议使用的是无连接不可靠的UDP协议,对域名查询结果没有认证,所以主机会接受最先到达的格式正确结果,并丢弃之后的结果。从上面的步骤可以看出,DNS解析过程存在时延,所以如果攻击者位于解析通讯链路之间,完全可以伪造一个假的地址返回给主机。之所以称之为投毒,如果攻击者持续对访问某个网站的结果返回错误地址,可能会造成很多域名解析服务器存储错误的域名记录,造成大面积影响。

递归查询示例:

abstract class IP{//抽象域名服务器
public abstract void addIP(IP ip);
public abstract IP getIP(String dom_name);
public abstract String getName();
public String getAddress(){
return null;
}
}
class DNS_Server extends IP{//为了简写,集合类只写一个
private String name;
private ArrayList<IP> arr=null;//包含了下级的域名解析服务器
public DNS_Server(String name){
this.name=name;
arr=new ArrayList<IP>();
}
public void addIP(IP ip){
arr.add(ip);
}
public String getName(){
return name;
}
public IP getIP(String dom_name){//遍历寻找下级服务器,返还给配置DNS服务器
String te=dom_name.substring(dom_name.lastIndexOf(".")+1);
for(Object obj:arr){
if(((IP)obj).getName().equals(te)){
return (IP)obj;
}
}
return null;
}
}

class lastLevelIP extends IP{//叶子解析服务器
private String name;
private String address;
public lastLevelIP(String name,String address){
this.name=name;
this.address=address;
}
public void addIP(IP ip){
System.out.println("**无法添加----");
}
public IP getIP(String dom_name){
return this;
}
public String getName(){
return name;
}
public String getAddress(){
return address;
}
}
class DNS{//主机配置的DNS服务器
private static volatile Map<String,String> map=new HashMap<String,String>();//缓存记录
//此处为了简便示例,只写了三层服务器,根域、顶级域和子域
private IP Root_DNS_Server;//一个根域名解析服务器
private IP Top_DNS_Server1,Top_DNS_Server2;//两个顶级域名解析服务器
private IP Server1,Server2;//两个子域
private IP ip1,ip2;//域中的元素,此处的叶子节点

public String getAddress(String str){
String s=str;
if(map.containsKey(s)){
return map.get(s);//返回的可能是if中判断后即时更新的
}
//叶子节点初始化
ip1=new lastLevelIP("3w","123.156");
ip2=new lastLevelIP("4w","234.678");
//子域添加元素,添加叶子节点,不能添加相同叶节点的,不过此时无所谓了
Server1=new DNS_Server("baidu");
Server1.addIP(ip1);
Server1.addIP(ip2);
Server2=new DNS_Server("taobao");
Server2.addIP(ip1);
Server2.addIP(ip2);
//顶级域添加元素,添加子域
Top_DNS_Server1=new DNS_Server("com");
Top_DNS_Server1.addIP(Server1);
Top_DNS_Server1.addIP(Server2);
Top_DNS_Server2=new DNS_Server("edu");
Top_DNS_Server2.addIP(Server1);
Top_DNS_Server2.addIP(Server2);
//根域添加元素,添加顶级域
Root_DNS_Server=new DNS_Server(".");
Root_DNS_Server.addIP(Top_DNS_Server1);
Root_DNS_Server.addIP(Top_DNS_Server2);

IP ip=Root_DNS_Server;
while(s.indexOf(".")>0){
ip=ip.getIP(s);
s=s.substring(0,s.lastIndexOf("."));
}
ip=ip.getIP(s);
map.put(str,ip.getAddress());//更新缓存记录
return ip.getAddress();
}

}
public class t{
public static void main(String[] args){
DNS f=new DNS();
System.out.println("the address="+f.getAddress("3w.taobao.com"));
}
}

总结

DNS服务器提供将域名转为IP地址的功能,不过在转化过程可能存在劫持修改记录的行为,通过配置权威的域名解析服务器可以在一定程度上作出改善,不过在中间传输过程中仍会发生欺骗现象,因为使用的为不可靠服务。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  域名 dns服务器