BIND+GeoIP: 根据查询者IP的地理位置给出不同的DNS结果

为了能让访客访问到最快的服务器,可以在DNS上动手脚。有一些DNS服务商如dnspod可以根据DNS查询者的位置,给出相应的DNS解析结果。

自己搭建DNS服务器,也可以实现类似效果。在 BIND 9.10 中,提供了 GeoIP 的功能,利用 GeoIP 库查询访客IP所在区域,根据区域给出结果。参考:
https://kb.isc.org/article/AA-01149/0/Using-the-GeoIP-Features-in-BIND-9.10.html

在 RHEL7.3/CentOS7.3 中,BIND 开始支持 GeoIP.

BIND now supports GeoIP-based ACLs
With this update, the BIND DNS server is able to use GeoIP databases. The feature enables administrators to implement client access control lists (ACL), based on client's geographical location. (BZ#1220594) 

下面是验证这个功能的实验步骤。在这个例子中,对于 hehe.test.com, 来自美国的访客可以查询到 2.2.2.2 的结果,来自其他地区的访客得到 4.4.4.4 的结果。

1. 在 RHEL7.4 中,安装 bind 和 GeoIP:

 # yum install bind geoip
 

2. 更新 GeoIP 数据库:

 # geoipupdate -v
 

3. 修改 BIND 的配置。创建两个view, 其中一个是美国地区的View,一个是默认View. 两个View都能解析 test.com 的域名,但是使用不同的zone file, 使之得到不同的结果。

 [root@dns ~]# diff /etc/named.conf.bk /etc/named.conf
 13c13
 < 	listen-on port 53 { 127.0.0.1; };
 ---
 > 	listen-on port 53 { any; };
 19c19,20
 < 	allow-query     { localhost; };
 ---
 > 	allow-query     {  any; };
 > 	geoip-directory "/usr/share/GeoIP";
 52,54c53,79
 < zone "." IN {
 < 	type hint;
 < 	file "named.ca";
 ---
 > 
 > acl "redwoodcity" {
 > 	geoip country US;
 > };
 > 
 > view "redwoodcity" {
 > 	match-clients { redwoodcity; };
 > 	zone "test.com" {
 > 		file "named-us.test";
 > 		type master;
 > 	};
 > 
 > 	zone "." IN {
 > 		type  hint;
 > 		file "named.ca";
 > 	};
 > };
 > 
 > view "default" {
 > 	zone "test.com" {
 > 		file "named.test";
 > 		type master;
 > 	};
 > 	zone "." IN {
 > 		type  hint;
 > 		file "named.ca";
 > 	};
 57c82
 < include "/etc/named.rfc1912.zones";
 ---
 > #include "/etc/named.rfc1912.zones";

创建对应的 zone 文件:

For default view

 [root@dns ~]# cat /var/named/named.test 
 $TTL 3H
 @       IN SOA   root  root (
                                        20      ; serial
                                        300     ; refresh
                                        200     ; retry
                                        900     ; expire
                                        3H )    ; minimum
 @                       NS  master.test.com.
 master.test.com.        A   3.3.3.3
 hehe.test.com.		A   4.4.4.4
 

For US view

 [root@dns ~]# cat /var/named/named-us.test 
 $TTL 3H
 @       IN SOA   root  root (
                                        20      ; serial
                                        300     ; refresh
                                        200     ; retry
                                        900     ; expire
                                        3H )    ; minimum
 @                       NS  master.test.com.
 master.test.com.        A   1.1.1.1
 hehe.test.com.		A   2.2.2.2
 

4. 重启 BIND 服务。

 # systemctl restart named
 

5. 使用 dig 命令进行测试。这里可以给网卡添加一个美国的IP地址8.8.8.8,用于测试。

 # ip addr add 8.8.8.8/24 dev ens3
 
 [root@dns ~]# dig +short -b 8.8.8.8 -t A @localhost hehe.test.com
 2.2.2.2
 [root@dns ~]# dig +short -t A @localhost hehe.test.com
 4.4.4.4
 

可以看到,如果查询者的IP是8.8.8.8(位于美国),那么能得到2.2.2.2的返回。其他地区则得到4.4.4.4的返回。