Syncing DNS Zones from Windows DNS Server to Linux Bind9 DNS Server

Windows Setup

First step is to dump the DNS zones from Windows into a file. Then generate an FTP command file which will upload the DNS zone file dump to your bind server. I’ve created a batch script to handle all of this:

@echo off
dnscmd /enumzones > dns.zones.txt
echo user ftp_bind_user> ftpcmd.dat
echo ftp_bind_password>> ftpcmd.dat
echo bin>> ftpcmd.dat
echo put dns.zones.txt>> ftpcmd.dat
echo quit>> ftpcmd.dat
ftp -n -s:ftpcmd.dat 192.168.1.101
del ftpcmd.dat
del dns.zones.txt

Some notes about the above script:

192.168.1.101 is the bind9 server’s IP address.

ftp_bind_user is the ftp user name setup on the bind9 server

ftp_bind_password is the ftp password setup on the bind9 server

I have this batch script run every hour, on the hour, using the Window task scheduler. This script will most likely need to run as an administrator in order to dump the DNS zones to a file.

Linux Setup

Now we setup the bash script. This script will first parse and format dns.zones.txt into a usable bind format, then it will scan all the current zone files and remove any that are not listed in the updated zone file. I set this script to run every hour, ten minutes after each hour. This script assumes you have bind running as user “bind” in group “bind”, please change the chown line accordingly.

#!/bin/bash

ZONE_PATH="/home/bind"
BIND_PATH="/var/lib/bind"
TMP=$(mktemp)
FC="dns.zones.txt"

for ZONE in $(awk '$2=="Primary" {print $1}' "${ZONE_PATH}/${FC}") do
   printf "zone ${ZONE} {\n\ttype slave;\n\tmasters { 192.168.1.100; };\n\tfile \"${BIND_PATH}/${ZONE}.zone\";\n};\n"
done > ${TMP}

for ZONE in "$BIND_PATH"/*.zone do
   grep -q "${ZONE}" "${TMP}" || rm -rf "${ZONE}"
done

mv ${TMP} /etc/bind/named.conf.slave-zones
chown bind:bind /etc/bind/named.conf.slave-zones

rndc reload

Some notes about the above script:

ZONE_PATH is where the dns.zones.txt file is uploaded to, this is of course determined by your FTP server setup (I setup proftpd with SQL backend, but you could easily setup vsftpd)

BIND_PATH is where we are telling bind to store the zone files.

192.168.1.100 is the IP Address of the Windows DNS Server

/etc/bind/named.conf.slave-zones is setup to be included in the “named.conf” file with the line:

include “/etc/bind/named.conf.slave-zones”;

Compiling bind9 on linux with Response Rate Limiting (to prevent DDoS DNS attacks)

This tutorial can easily be applied to most any linux system. I went through these steps on Debian 7 server.

First let’s setup the environment, this tutorial assumes you have no previous install of bind on the server.

mkdir -p /var/local/cache/bind
mkdir -p /usr/local/etc/bind

We are assuming group id and user id 5005 are free, you may need to substitute ids

groupadd -g 5005 bind
useradd -u 5005 -g 5005 -d /var/local/cache/bind -M -s /bin/false bind


Now let’s download the bind9 source code. This tutorial assumes you have the required dependencies installed. The only one I found tricky to locate was libkrb5-dev (on Debian you can install it with apt-get install libkrb5-dev)

cd /usr/src
wget http://ftp.isc.org/isc/bind9/cur/9.9/bind-9.9.5-P1.tar.gz
tar zxvf bind-9.9.5-P1.tar.gz
cd bind-9.9.5-P1
./configure '--enable-threads' '--enable-largefile' '--with-libtool' '--enable-shared' '--enable-static' '--with-openssl=/usr' '--with-gssapi=/usr' '--with-gnu-ld' '--with-geoip=/usr' '--enable-ipv6' '--enable-rrl'
make
make install
wget --user=ftp --password=ftp ftp://ftp.rs.internic.net/domain/db.cache -O /usr/local/etc/bind/db.root


Last step is to install the configuration files and startup scripts.

rndc-confgen -a -c /usr/local/etc/bind/rndc.key
cat > /etc/named.conf <<EOT
 include "/usr/local/etc/bind/rndc.key";
 include "/usr/local/etc/bind/named.conf";
EOT
cat > /usr/local/etc/named.conf <<EOT
#
controls {
 inet 127.0.0.1 port 953
 allow { 127.0.0.1; 192.168.1.100; } keys { "rndc-key"; };
 };
options {
 directory "/var/local/cache/bind";
 allow-new-zones yes;
 transfers-in 500;
 empty-zones-enable yes;
 //forwarders { 8.8.8.8; 8.8.4.4; };
 recursion no;
 //allow-transfer {"none";};
 allow-query { any; };
 dnssec-validation auto;
 auth-nxdomain no;    # conform to RFC1035
 listen-on-v6 { any; };
 rate-limit {
  responses-per-second 5;
  #window 5;
  #log-only yes;
  };
};
zone "." {
 type hint;
 file "/usr/local/etc/bind/db.root";
};
EOT
chown bind:bind -R /var/local/cache/bind
chown bind:bind -R /usr/local/etc/bind

Please note the init.d scripts only work on Debian based systems. I do not have init.d scripts for any other distribution.

Download the init.d script here

Download the init.d default file here


Copy the init.d script to /etc/init.d/bind9

Copy the init.d default file to /etc/default/bind9

chmod +x /etc/init.d/bind9
/etc/init.d/bind9 start