在做一些实验时,经常需要一个内网的DNS服务器。本文详细描述了构建整个DNS服务器的过程。
强烈推荐在安装任何服务之前先把SELinux和iptables(也就是防火墙)暂时禁止掉,这样的话我们可以专注于安装服务本身,而不会被各种SELinux上下文和防火墙规则所干扰。
在全部服务都安装好之后,你可以根据需要,开启SELinux和iptables。注意,本文不包含SELinux和iptables的配置。
- # vim /etc/sysconfig/selinux
- SELINUX=disabled # 由enforcing 改成 disabled
-
- # iptables -F
- # iptables -L
- # service iptables save
-
也可以彻底关闭iptables服务:
- # service iptables stop
- # chkconfig iptables off
-
之所以打开这个功能,是因为我想把Linux当做一个路由器来用。
- # vim /etc/sysctl.conf
- net.ipv4.ip_forward = 1 #修改:由0改成1
-
- # sysctl -p
-
为了让SELinux的禁用的设置生效,必须重启机器。
如下图所示:
这里不使用图形界面,使用命令行的方式来配置。
首先配置一下IP(192.168.0.2)以及相关的参数(因为我的虚拟机有多个网卡,这里用第二个网卡 eth1 来进行配置)。
- # vim /etc/sysconfig/network-scripts/ifcfg-eth1
- DEVICE=eth1
- TYPE=Ethernet
- UUID=06dbc3e2-4d24-4cb5-9b24-89c166a71e5a
- ONBOOT=yes
- NM_CONTROLLED=yes
- BOOTPROTO=none
- HWADDR=08:00:27:6D:CA:57
- IPADDR=192.168.0.2
- NETMASK=255.255.255.0
- PREFIX=24
- DEFROUTE=no
- IPV4_FAILURE_FATAL=yes
- IPV6INIT=no
- NAME="System eth1"
- HWADDR=08:00:27:C6:79:2B
- MTU=1500
- UUID=9c92fad9-6ecb-3e6c-eb4d-8a47c6f50c04
- LAST_CONNECT=1409908255
重启网络服务,并查看eth1的配置信息:
- # service network restart
- # ip addr show eth1
- 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
- link/ether 08:00:27:c6:79:2b brd ff:ff:ff:ff:ff:ff
- inet 192.168.0.2/24 brd 192.168.0.255 scope global eth1
- inet6 fe80::a00:27ff:fec6:792b/64 scope link
- valid_lft forever preferred_lft forever
- ```language
修改主机名(server.example.com),先:
- # vim /etc/sysconfig/network
- NETWORKING=yes
- HOSTNAME=server.example.com
再:
- # vim /etc/hosts
- 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
- ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
- 192.168.0.2 server.example.com
重启,使 hostname 生效:
- # reboot
-
使用yum进行安装:
- # yum -y install bind bind-chroot
-
编写一个 chroot(/root/bind-chroot-admin)脚本,内容如下:
- #!/bin/sh
- #bind-chroot install check
- rpm -q bind-chroot > /dev/null 2>&1
- [ $? -ne 0 ] && echo bind-chroot not install && exit 1
- # bind-chroot enabled
- sed -i '/^ROOTDIR=/d' /etc/sysconfig/named
- echo ROOTDIR=/var/named/chroot >> /etc/sysconfig/named
- # file copy
- filelist=`mktemp`
- rpm -ql bind|grep ^/etc >> ${filelist}
- rpm -ql bind|grep ^/var >> ${filelist}
- for file in `cat ${filelist}`
- do
- # directory make
- if [ -d ${file} ]; then
- DIRNAME=/var/named/chroot${file}
- [ ! -d ${DIRNAME} ] && mkdir -p ${DIRNAME}
- fi
- # file copy
- if [ -f ${file} ]; then
- DIRNAME=/var/named/chroot`dirname ${file}`
- [ ! -d ${DIRNAME} ] && mkdir -p ${DIRNAME}
- /bin/cp -a ${file} ${DIRNAME}
- fi
- done
- rm -f ${filelist}
- chown named:named /var/named/chroot/var/named/data
- chmod 770 /var/named/chroot/var/named/data
- chown named:named /var/named/chroot/var/named/dynamic
- exit
执行此脚本:
- # sh bind-chroot-admin
-
- //
- // named.conf
- //
- // Provided by Red Hat bind package to configure the ISC BIND named(8) DNS
- // server as a caching only nameserver (as a localhost DNS resolver only).
- //
- // See /usr/share/doc/bind*/sample/ for example named configuration files.
- //
- options {
- #listen-on port 53 { 127.0.0.1; }; #注释掉
- #listen-on-v6 port 53 { ::1; }; #注释掉
- directory "/var/named";
- dump-file "/var/named/data/cache_dump.db";
- statistics-file "/var/named/data/named_stats.txt";
- memstatistics-file "/var/named/data/named_mem_stats.txt";
- allow-query { localhost; localnets; }; # 修改: 添加 localnets
- recursion yes;
- empty-zones-enable no; #追加: 启动时对于空的zone的错误日志不输出
- dnssec-enable no; #修改: yes -> no, 不使用DNSSEC
- dnssec-validation no; #修改: yes -> no, 不使用DNSSEC
- #dnssec-lookaside auto; #注释掉
- /* Path to ISC DLV key */
- bindkeys-file "/etc/named.iscdlv.key";
- forwarders{ #追加
- 192.168.0.2; #追加: 路由器的IP,我把本机当路由了
- }; #追加
- managed-keys-directory "/var/named/dynamic";
- };
- logging {
- channel default_debug {
- file "data/named.run";
- severity dynamic;
- };
- category lame-servers { null; }; #追加
- };
- view "internal" { #追加
- match-clients { localnets; }; #追加
- match-destinations { localnets; }; #追加
- zone "." IN {
- type hint;
- file "named.ca";
- };
- include "/etc/named.rfc1912.zones";
- include "/etc/named.root.key";
- include "/etc/named.example.com.zone"; #追加
- }; #追加
- view "external" { #追加,可选,如果你的DNS服务器不准备连接外网的话,这里不用写
- match-clients { any; };#追加,可选,如果你的DNS服务器不准备连接外网的话,这里不用写
- match-destinations { any; };#追加,可选,如果你的DNS服务器不准备连接外网的话,这里不用写
- recursion no; #追加,可选,如果你的DNS服务器不准备连接外网的话,这里不用写
- include "/etc/named.example.com.zone.wan"; #追加:注意这里和你的域名做相应的调整,,可选,如果你的DNS服务器不准备连接外网的话,这里不用写
- }; #追加,可选,如果你的DNS服务器不准备连接外网的话,这里不用写
文件名:/var/named/chroot/etc/named.example.com.zone
- zone "example.com" {
- type master;
- file "example.com.db";
- };
- zone "0.168.192.in-addr.arpa" {
- type master;
- file "0.168.192.in-addr.arpa.db";
- };
文件名:/var/named/chroot/etc/named.example.com.zone.wan
如果你的DNS服务器不打算接入Internet的话,这个文件不需要。
- zone "example.com" {
- type master;
- file "example.com.db.wan";
- allow-query { any; };
- };
- zone "1.168.192.in-addr.arpa" {
- type master;
- file "1.168.192.in-addr.arpa.db";
- allow-query { any; };
- };
文件名:/etc/sysconfig/named
- OPTIONS="-4" # 在文件的最后加入这行
再次提醒,如果你只是内网使用DNS的话,这一小节的内容请无视。
- # dig . ns @198.41.0.4 +bufsize=1024 > /var/named/chroot/var/named/named.ca
-
为了方便起见,可以使用一个自动脚(named.root_update)本来跟新根DNS域名服务器的列表:
- #!/bin/bash
- new=`mktemp`
- errors=`mktemp`
- dig . ns @198.41.0.4 +bufsize=1024 > $new 2> $errors
- if [ $? -eq 0 ]; then
- sort_new=`mktemp`
- sort_old=`mktemp`
- diff_out=`mktemp`
- sort $new > $sort_new
- sort /var/named/chroot/var/named/named.ca > $sort_old
- diff --ignore-matching-lines=^\; $sort_new $sort_old > $diff_out
- if [ $? -ne 0 ]; then
- (
- echo '-------------------- old named.root --------------------'
- cat /var/named/chroot/var/named/named.ca
- echo
- echo '-------------------- new named.root --------------------'
- cat $new
- echo '---------------------- difference ----------------------'
- cat $diff_out
- ) | mail -s 'named.root updated' root
- cp -f $new /var/named/chroot/var/named/named.ca
- chown named. /var/named/chroot/var/named/named.ca
- chmod 644 /var/named/chroot/var/named/named.ca
- /etc/rc.d/init.d/named restart > /dev/null
- fi
- rm -f $sort_new $sort_old $diff_out
- else
- cat $errors | mail -s 'named.root update check error' root
- fi
- rm -f $new $errors
然后让这个脚本可执行;
- # chmod 700 named.root_update
-
最后让这个脚本每个月自动执行(前提是你的crond已经打开):
- # mv named.root_update /etc/cron.monthly/
-
也就是从域名到IP地址的解析关系。
文件名:/var/named/chroot/var/named/example.com.db
- $TTL 86400
- @ IN SOA example.com. root.example.com.(
- 2013120801; Serial
- 28800 ; Refresh
- 14400 ; Retry
- 3600000 ; Expire
- 86400 ) ; Minimum
- IN NS example.com.
- IN MX 10 example.com.
- @ IN A 192.168.0.2
- * IN A 192.168.0.2
- dns IN A 192.168.0.2
- server IN A 192.168.0.2
- ldap IN A 192.168.0.2
- www IN A 192.168.0.2
- mail IN A 192.168.0.2
- ftp IN A 192.168.0.2
- sgd-server IN A 192.168.0.3
- win IN A 192.168.0.4
- lin IN A 192.168.0.5
- sol IN A 192.168.0.6
- wins IN A 192.168.0.7
也就是从IP到域名的关系。
文件名:/var/named/chroot/var/named/0.168.192.in-addr.arpa.db
- $TTL 86400
- @ IN SOA example.com. root.example.com.(
- 2013120801 ; Serial
- 28800 ; Refresh
- 14400 ; Retry
- 3600000 ; Expire
- 86400 ) ; Minimum
- IN NS example.com.
- 2 IN PTR example.com.
- 2 IN PTR dns.example.com.
- 2 IN PTR server.example.com.
- 2 IN PTR ldap.example.com.
- 2 IN PTR www.example.com.
- 2 IN PTR mail.example.com.
- 2 IN PTR ftp.example.com.
- 3 IN PTR sgd-server.example.com.
- 4 IN PTR win.example.com.
- 5 IN PTR lin.example.com.
- 6 IN PTR sol.example.com.
- 7 IN PTR wins.example.com.
也就是从外部访问时,从域名到IP地址的解析关系。
文件名:/var/named/chroot/var/named/example.com.db.wan
- $TTL 86400
- @ IN SOA ns1.example.com. root.example.com.(
- 2013120801 ; Serial
- 7200 ; Refresh
- 7200 ; Retry
- 2419200 ; Expire
- 86400 ) ; Minimum
- IN NS ns1.example.com.
- IN MX 10 example.com.
- ns1 IN A 192.168.1.2
- @ IN A 192.168.1.2
- www IN A 192.168.1.2
- ftp IN A 192.168.1.2
- mail IN A 192.168.1.2
- server IN A 192.168.1.2
- ldap IN A 192.168.1.2
- dns IN A 192.168.1.2
- example.com. IN TXT "v=spf1 ip4:192.168.1.2 ~all"
文件名:/var/named/chroot/var/named/1.168.192.in-addr.arpa.db
- $TTL 86400
- @ IN SOA example.com. root.example.com.(
- 2013120801 ; serial
- 3600 ; refresh (1 hour)
- 900 ; retry (15 minutes)
- 604800 ; expire (1 week)
- 86400 ; negative (1 day)
- )
- IN NS example.com.
- 2 IN PTR example.com.
- ```languag
启动服务:
- # service named start
-
开机自动运行DNS服务:
- # chkconfig named on
-
配置网卡eth1的DNS,使用本机做为DNS服务器:
- # vim /etc/sysconfig/network-scripts/ifcfg-eth1
- DNS1=127.0.0.1
-
先测试正向解析:
- # dig example.com
- ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.17.rc1.0.2.el6_4.6 <<>> example.com
- ;; global options: +cmd
- ;; Got answer:
- ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5153
- ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0
- ;; QUESTION SECTION:
- ;example.com. IN A
- ;; ANSWER SECTION:
- example.com. 86400 IN A 192.168.0.2
- ;; AUTHORITY SECTION:
- example.com. 86400 IN NS example.com.
- ;; Query time: 4 msec
- ;; SERVER: 127.0.0.1#53(127.0.0.1)
- ;; WHEN: Tue Sep 9 15:08:27 2014
- ;; MSG SIZE rcvd: 59
观察上面的ANSWER SECTION,可以看出解析成功了。
接下来试试反向解析:
- # dig -x 192.168.0.2
- ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.17.rc1.0.2.el6_4.6 <<>> -x 192.168.0.2
- ;; global options: +cmd
- ;; Got answer:
- ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31947
- ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 7, AUTHORITY: 1, ADDITIONAL: 1
- ;; QUESTION SECTION:
- ;2.0.168.192.in-addr.arpa. IN PTR
- ;; ANSWER SECTION:
- 2.0.168.192.in-addr.arpa. 86400 IN PTR mail.example.com.
- 2.0.168.192.in-addr.arpa. 86400 IN PTR ftp.example.com.
- 2.0.168.192.in-addr.arpa. 86400 IN PTR example.com.
- 2.0.168.192.in-addr.arpa. 86400 IN PTR dns.example.com.
- 2.0.168.192.in-addr.arpa. 86400 IN PTR server.example.com.
- 2.0.168.192.in-addr.arpa. 86400 IN PTR ldap.example.com.
- 2.0.168.192.in-addr.arpa. 86400 IN PTR www.example.com.
- ;; AUTHORITY SECTION:
- 0.168.192.in-addr.arpa. 86400 IN NS example.com.
- ;; ADDITIONAL SECTION:
- example.com. 86400 IN A 192.168.0.2
- ;; Query time: 4 msec
- ;; SERVER: 127.0.0.1#53(127.0.0.1)
- ;; WHEN: Tue Sep 9 15:09:31 2014
- ;; MSG SIZE rcvd: 210
- ```language
观察上面的ANSWER SECTION,可以看出解析也成功了。
至于外部解析,因为和上面的步骤相同,这里就不在赘述。
至此为止,所有的配置都完成了。