使用 GeoDNS 绑定补丁,只有当加载页面的请求 IP 地址位于美国时,我们才能让 example.com 解析到美国的服务器,然后将所有其他请求转发到位于另一个国家的服务器。
我们将能够使用此方法将来自任何国家/地区代码的域请求指向指定的 DNS 记录。
在此示例中,我们将从充当名称服务器的测试服务器 (CentOS 6.3) 上的源代码编译 Bind,即它用于提供 DNS。
使用 GeoDNS 补丁编译绑定
下载并安装 Maxmind 的 GeoIP C API 我使用的是当前最新版本 1.4.8.
wget http://geolite.maxmind.com/download/geoip/api/c/GeoIP-1.4.8.tar.gz tar xf GeoIP-1.4.8.tar.gz cd GeoIP-1.4.8 ./configure --prefix=/usr/local/geoip ... checking zlib.h usability... no checking zlib.h presence... no checking for zlib.h... no configure: error: Zlib header (zlib.h) not found. Tor requires zlib to build. You may need to install a zlib development package.
要修复此错误,我们只需要安装 zlib 开发包(Debian 上的 zlib1g-dev)。
yum install zlib-devel.x86_64 ./configure --prefix=/usr/local/geoip make make install
下载用于绑定的 GeoDNS 补丁。
cd .. wget http://www.caraytech.com/geodns/bind-9.4.1-geodns-patch.tar.gz tar xf bind-9.4.1-geodns-patch.tar.gz
接下来下载绑定。
请注意,我正在使用此版本的 Bind (9.4.1-P1),因为这是当前补丁所针对的版本。
我尚未使用较新版本的 Bind 测试该补丁,但相信它仍然有效,但请在应用到生产环境之前进行测试。
wget http://ftp.isc.org/isc/bind9/9.4.1-P1/bind-9.4.1-P1.tar.gz tar xf bind-9.4.1-P1.tar.gz
现在我们将使用 Patch 命令,最初我没有安装它,所以它是使用 yum 安装的。
patch -p0 < bind-9.4.1-geodns-patch/patch.diff bash: patch: command not found yum install patch ... patch -p0 < bind-9.4.1-geodns-patch/patch.diff ... patching file bind-9.4.1-P1/lib/dns/acl.c patching file bind-9.4.1-P1/lib/dns/include/dns/acl.h patching file bind-9.4.1-P1/lib/isccfg/aclconf.c
现在我们将编译绑定,指定我们之前在 /usr/local/geoip/ 中的 GeoIP 安装。
cd bind-9.4.1-P1 CFLAGS="-I/usr/local/geoip/include" LDFLAGS="-L/usr/local/geoip/lib -lGeoIP" ./configure --prefix=/usr/local/bind ... checking for C compiler default output file name... a.out ./a.out: error while loading shared libraries: libGeoIP.so.1: cannot open shared object file: No such file or directory See `config.log' for more details.
这只发生在我运行的 CentOS 6.3 测试中,而在 Debian 6 中没有发生,修复很简单。
nano /etc/ld.so.conf Add "/usr/local/geoip/lib/" into file and save. ldconfig
现在再次尝试应该会成功。
CFLAGS="-I/usr/local/geoip/include" LDFLAGS="-L/usr/local/geoip/lib -lGeoIP" ./configure --prefix=/usr/local/bind make make install
配置
现在 Bind 已经编译并安装了 GeoDNS 补丁,我们只需要按照我们想要的方式配置我们的 DNS。
这是通过 named.conf 文件完成的,我在 /usr/local/bind/etc/ 中创建了这个文件,它包含以下内容:
include "/etc/rndc.key"; controls { inet 127.0.0.1 allow { localhost; } keys { "rndc-key"; }; }; options { directory "/var/named"; // the default pid-file "/var/run/named/named.pid"; dump-file "data/cache_dump.db"; statistics-file "data/named_stats.txt"; allow-transfer {"none";}; } logging { channel default_debug { file "data/named.run"; severity dynamic; }; };
在此示例中,包含文件“/etc/rndc.key”存在并包含以下内容。
key "rndc-key" { algorithm hmac-md5; secret "RSQjVF5KKE0pI0VNVA=="; };
秘密是一个简单的 base 64 字符串。
现在在此之下我们定义我们的观点。
在这个例子中,我们将把请求 example.com 的所有北美用户发送到托管在 1.1.1.1 的站点,同时将世界其他地区的用户发送到 2.2.2.2.
view "north_america" { match-clients { country_US; country_CA; country_MX; }; recursion no; zone "example.com" { type master; file "/var/named/example-us.com.db"; }; }; view "other" { match-clients { any; }; recursion no; zone "private-software.com" { type master; file "/var/named/example.com.db"; }; };
所以我们的 named.conf 文件用于指定应该使用哪个 .db 区域文件,在这个例子中,我们有两个文件 example.com 给出了不同的 DNS,如下所示。
/var/named/example-us.com.db
; Zone file for example.com $TTL 14400 example.com. 86400 IN SOA ns1.example.com. admin.example.com. ( 2012080500 ;Serial Number 86400 ;refresh 7200 ;retry 3600000 ;expire 86400 ) example.com. 300 IN A 1.1.1.1
/var/named/example.com.db
; Zone file for example.com $TTL 14400 example.com. 86400 IN SOA ns1.example.com. admin.example.com. ( 2012080500 ;Serial Number 86400 ;refresh 7200 ;retry 3600000 ;expire 86400 ) example.com. 300 IN A 2.2.2.2
一旦所有更改都到位,named 就可以开始了。
cd /usr/local/bind/sbin/ ./named
我们需要确认它已启动且没有错误,因为 named.conf 的问题会导致此操作失败。
查找错误的好地方是 /var/log/messages。
或者运行 netstat -antp 并查看服务器是否在端口 53 上侦听 DNS。