#!/bin/sh #----------------------------------------------------------------------------- # /var/install/config.d/bind.sh - BIND configuration # Creation: 2004-08-19 jv jens@eisfair.org #----------------------------------------------------------------------------- # define bind_run_user bind_run_usr="root" bind_run_grp="named" # use unix-time for zone serial bind9_zoneserial=$(date '+%s') bind9_zonerefresh='6H' . /etc/config.d/base bind9_hostname="$HOSTNAME" #include eisdate-time . /var/install/include/eistime # include name of bind run user for chroot and daemon #. /etc/bind/binduser.conf bind9_pri="/var/bind/pri" # master zone bind9_sec="/var/bind/sec" # slave zone # global parameters dns_master="" znr=0 ### -------------------------------------------------------------------------- ### generate a zone file ### -------------------------------------------------------------------------- write_zone_file() { local zone_name=$1 local tempipnr="" local temprvip="" local tempname="" eval dns_master='$BIND_'${znr}'_MASTER_NS' [ -z "$dns_master" ] && dns_master="${bind9_hostname}.${zone_name}" ### --------------------------------------------------------------------------------- ### write header ### --------------------------------------------------------------------------------- cat > ${bind9_pri}/${zone_name}.zone <<EOF \$TTL 86400 ; 1 day @ IN SOA ${dns_master}. root.${zone_name}. ( ${bind9_zoneserial} ; serial ${bind9_zonerefresh} ; refresh 1H ; retry after 1 hour 1W ; expire after 1 week 1D ) ; minimum TTL of 1 day @ IN NS ${dns_master}. EOF ### --------------------------------------------------------------------------------- ### create secondary NS records ### --------------------------------------------------------------------------------- eval ncnt='$BIND_'${znr}'_NS_N' if [ -n "$ncnt" ] ; then xn="1" while [ $xn -le $ncnt ] do eval tempname='$BIND_'${znr}'_NS_'$xn'_NAME' if ! grep -q "^@ IN NS ${tempname}. " ${bind9_pri}/${zone_name}.zone then echo "@ IN NS ${tempname}. " >> ${bind9_pri}/${zone_name}.zone fi xn=$((xn+1)) done fi ### --------------------------------------------------------------------------------- ### create all MX records ### --------------------------------------------------------------------------------- eval ncnt='$BIND_'${znr}'_MX_N' if [ -n "$ncnt" ] ; then xn=1 while [ $xn -le $ncnt ] do eval tempname='$BIND_'${znr}'_MX_'${xn}'_NAME' eval tempprio='$BIND_'${znr}'_MX_'${xn}'_PRIORITY' echo "@ IN MX $tempprio ${tempname}. " >> ${bind9_pri}/${zone_name}.zone xn=$((xn+1)) done fi ### --------------------------------------------------------------------------------- ### append the "empty" A record ### --------------------------------------------------------------------------------- eval ncnt='$BIND_'${znr}'_HOST_N' if [ -n "$ncnt" ] ; then xn=1 while [ $xn -le $ncnt ] do eval tempname='$BIND_'${znr}'_HOST_'${xn}'_NAME' if [ -z "$tempname" ] ; then eval tempipnr='$BIND_'${znr}'_HOST_'${xn}'_IP' if [ -n "$tempipnr" ] ; then echo "@ IN A $tempipnr " >> ${bind9_pri}/${zone_name}.zone break fi fi xn=$((xn+1)) done # add default localhost echo "localhost IN A 127.0.0.1 " >> ${bind9_pri}/${zone_name}.zone ### --------------------------------------------------------------------------------- ### check and append the named A records ### --------------------------------------------------------------------------------- xn=1 while [ $xn -le $ncnt ] do eval tempname='$BIND_'${znr}'_HOST_'${xn}'_NAME' eval tempipnr='$BIND_'${znr}'_HOST_'${xn}'_IP' if [ -n "$tempname" -a -n "$tempipnr" ] ; then if ! grep -q "^$tempname " ${bind9_pri}/${zone_name}.zone then echo "$tempname IN A ${tempipnr} " >> ${bind9_pri}/${zone_name}.zone fi fi xn=$((xn+1)) done ### --------------------------------------------------------------------------------- ### append the wildcard "*" A record ### --------------------------------------------------------------------------------- xn=1 while [ $xn -le $ncnt ] do eval tempname='$BIND_'${znr}'_HOST_'${xn}'_NAME' if [ "$tempname" = "*" ] ; then eval tempipnr='$BIND_'${znr}'_HOST_'${xn}'_IP' if [ -n "$tempipnr" ] ; then echo "* IN A $tempipnr " >> ${bind9_pri}/${zone_name}.zone break fi fi xn=$((xn+1)) done ### --------------------------------------------------------------------------------- ### create all CNAME alias records ### --------------------------------------------------------------------------------- xn=1 set -f while [ $xn -le $ncnt ] do eval tempalias='$BIND_'${znr}'_HOST_'${xn}'_ALIAS' if [ -n "$tempalias" ] ; then eval tempname='$BIND_'${znr}'_HOST_'${xn}'_NAME' [ -n "$tempname" ] && tempname="${tempname}." for s in $tempalias do # exists entry? if ! grep -q "^$s " ${bind9_pri}/${zone_name}.zone then echo "$s IN CNAME ${tempname}${zone_name}. " >> ${bind9_pri}/${zone_name}.zone fi done fi xn=$((xn+1)) done set +f fi ### --------------------------------------------------------------------------------- ### create A record from SOA if not defined ### --------------------------------------------------------------------------------- eval tempipnr='$BIND_'${znr}'_MASTER_IP' if [ -n "$tempipnr" ] ; then if ! grep -q "^$bind9_hostname " ${bind9_pri}/${zone_name}.zone then echo "$bind9_hostname IN A $tempipnr " >> ${bind9_pri}/${zone_name}.zone fi fi chmod 0640 ${bind9_pri}/${zone_name}.zone chown ${bind_run_usr}:${bind_run_grp} ${bind9_pri}/${zone_name}.zone } ### -------------------------------------------------------------------------- ### generate a reverse ip number ### -------------------------------------------------------------------------- get_revip() { local ip_addr=$1 local revip="0" case "$zonemask" in 255.255.255.*) revip=`echo $ip_addr | sed "s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\4/"` ;; 255.255.*) revip=`echo $ip_addr | sed "s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\4.\3/"` ;; 255.*) revip=`echo $ip_addr | sed "s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\4.\3.\2/"` ;; esac echo $revip } ### -------------------------------------------------------------------------- ### generate a reverse zone file ### -------------------------------------------------------------------------- write_reverse_zone_file() { local zone_name=$1 local zone_netw=$2 local zone_mask=$3 local tempipnr="" local temprvip="" local tempname="" local write_header="0" # check if exists a revers file with the same serial if [ -f ${bind9_pri}/${zone_name}.zone ] ; then if ! grep -q "${bind9_zoneserial} ; serial" ${bind9_pri}/${zone_name}.zone then write_header='1' fi else write_header='1' fi if [ "$write_header" = '1' ] ; then eval dns_master='$BIND_'${znr}'_MASTER_NS' [ -z "$dns_master" ] && dns_master="${bind9_hostname}.${zone_name}" cat > ${bind9_pri}/${zone_name}.zone <<EOF \$TTL 86400 ; 1 day @ IN SOA ${dns_master}. root.${zone_name}. ( ${bind9_zoneserial} ; serial ${bind9_zonerefresh} ; refresh 1H ; retry after 1 hour 1W ; expire after 1 week 1D ) ; minimum TTL of 1 day @ IN NS ${dns_master}. EOF fi ### --------------------------------------------------------------------------------- ### check and append all NS records ### --------------------------------------------------------------------------------- eval ncnt='$BIND_'${znr}'_NS_N' if [ -n "$ncnt" ] ; then xn="1" while [ $xn -le $ncnt ] do eval tempname='$BIND_'${znr}'_NS_'$xn'_NAME' if ! grep -q "^@ IN NS ${tempname}." ${bind9_pri}/${zone_name}.zone then echo "@ IN NS ${tempname}. " >> ${bind9_pri}/${zone_name}.zone fi xn=$((xn+1)) done fi ### --------------------------------------------------------------------------------- ### append PTR for SOA ### --------------------------------------------------------------------------------- if [ "$write_header" = '1' ] ; then eval tempipnr='$BIND_'${znr}'_MASTER_IP' if [ -n "$tempipnr" ] then temprvip=`get_revip $tempipnr` echo "${temprvip} IN PTR ${bind9_hostname}.${zonename}. " >> ${bind9_pri}/${zone_name}.zone fi fi ### --------------------------------------------------------------------------------- ### check and append all PTR records ### --------------------------------------------------------------------------------- eval ncnt='$BIND_'${znr}'_HOST_N' if [ -n "$ncnt" ] ; then xn="1" while [ $xn -le $ncnt ] do eval tempname='$BIND_'${znr}'_HOST_'$xn'_NAME' if [ ! "$tempname" = '*' ] ; then if [ -z "$tempname" ] ; then tempname="${zonename}." else tempname="${tempname}.${zonename}." fi if ! grep -q "PTR $tempname" ${bind9_pri}/${zone_name}.zone then eval tempipnr='$BIND_'${znr}'_HOST_'$xn'_IP' # if the reverse ip in the network? tmpnetwork=$(/var/install/bin/netcalc dnsnet $tempipnr $zone_mask) if [ "$zone_netw" = "$tmpnetwork" ] ; then temprvip=`get_revip $tempipnr` echo "$temprvip IN PTR $tempname " >> ${bind9_pri}/${zone_name}.zone fi fi fi xn=$((xn+1)) done fi chmod 0640 ${bind9_pri}/${zone_name}.zone chown ${bind_run_usr}:${bind_run_grp} ${bind9_pri}/${zone_name}.zone } ### -------------------------------------------------------------------------- ### Write the BIND named configuration files ### -------------------------------------------------------------------------- write_named_file() { local ftmp="" local idx=1 # remove old zone files: for ftmp in ${bind9_pri}/* do case "$ftmp" in */127.zone) # don't remove local zone ;; */localhost.zone) # don't remove local zone ;; *) [ -f "$ftmp" ] && rm -f "$ftmp" ;; esac done rm -f ${bind9_sec}/* >/dev/null { echo "options {" echo " directory \"/var/bind\";" echo " pid-file \"/run/named/named.pid\";" if [ -n "$BIND_BIND_IP_ADDRESS" ] ; then echo " listen-on {" for ipaddr in $BIND_BIND_IP_ADDRESS do echo " 127.0.0.1; " [ "$ipaddr" = "127.0.0.1" ] || echo " ${ipaddr};" done echo " }; " echo " listen-on-v6 { none; };" else echo " listen-on { any; }; " echo " listen-on-v6 { any; };" fi echo " // to allow only specific hosts to use the DNS server:" echo " //allow-query {" echo " // 127.0.0.1;" echo " //};" if [ $BIND_PORT_53_ONLY = 'yes' ] ; then echo " // if you have problems and are behind a firewall:" echo " query-source address * port 53;" echo " transfer-source * port 53;" echo " notify-source * port 53;" fi # query and reverse query: any, localnets, localhost if [ "$BIND_ALLOW_QUERY" = 'localnets' ] ; then echo " allow-query { localhost; localnets; };" echo " allow-recursion { localhost; localnets; };" else echo " allow-query { ${BIND_ALLOW_QUERY}; };" echo " allow-recursion { localhost; localnets; internals; };" fi # accept notify message echo " allow-notify { forwarder; localnets; };" echo " sortlist {" echo " { localhost; localnets; };" echo " { localnets; };" echo " };" echo " forwarders {" idx=1 while [ $idx -le $BIND_FORWARDER_N ] do eval ipaddr='$BIND_FORWARDER_'$idx'_IP' echo " ${ipaddr};" idx=$((idx+1)) done echo " };" # read forwarders before use root server if [ "$BIND_FORWARDER_N" -gt 0 ] ; then if [ "$BIND_N" -gt 0 ] ; then echo " forward first;" else echo " forward only;" fi fi echo " auth-nxdomain no; # conform to RFC1035" echo "};" echo "" # edns settings idx="1" while [ $idx -le $BIND_FORWARDER_N ] do eval fwedns='$BIND_FORWARDER_'$idx'_EDNS' if [ "$fwedns" = "no" ] ; then eval ipaddr='$BIND_FORWARDER_'$idx'_IP' echo "server $ipaddr {edns no;};" fi idx=$((idx+1)) done echo "" # syslog setup echo "logging {" echo " channel default_syslog {" echo " syslog daemon;" echo " print-category yes;" if [ $BIND_DEBUG_LOGFILE = 'yes' ] ; then echo " severity debug;" else echo " severity error;" fi echo " };" # echo " category default { null; };" # echo " category general { null; };" # echo " category database { null; };" # echo " category security { null; };" # echo " category resolver { null; };" # echo " category xfer-in { null; };" # echo " category xfer-out { null; };" # echo " category client { null; };" # echo " category unmatched { null; };" # echo " category network { null; };" # echo " category update { null; };" # echo " category update-security { null; };" # echo " category queries { null; };" # echo " category dispatch { null; };" # echo " category dnssec { null; };" # echo " category lame-servers { null; };" # echo " category delegation-only { null; };" echo "};" # acl's echo "" echo "acl forwarder {" idx="1" while [ $idx -le $BIND_FORWARDER_N ] do eval ipaddr='$BIND_FORWARDER_'$idx'_IP' echo " ${ipaddr};" idx=$((idx+1)) done echo "};" echo "" echo "acl nslist {" znr=1 s_found='' # echo "BEGIN zone: $idx " >/dev/tty while [ ${znr} -le $BIND_N ] do eval ncnt='$BIND_'${znr}'_NS_N' if [ -n "$ncnt" ] ; then idx="1" while [ $idx -le $ncnt ] do eval ipaddr='$BIND_'${znr}'_NS_'$idx'_IP' if [ -n "$ipaddr" ] ; then echo " ${ipaddr};" s_found='yes' fi idx=$((idx+1)) done fi znr=$((znr+1)) done [ -z "$s_found" ] && echo " none;" echo "};" echo "" echo "acl internals {" echo " 127.0.0.0/8;" echo " 10.0.0.0/8;" echo " 169.254.0.0/16;" echo " 172.16.0.0/12;" echo " 192.168.0.0/16;" echo "};" # zone entries echo "" echo "//zone \"COM\" { type delegation-only; };" echo "//zone \"NET\" { type delegation-only; };" echo "" echo "zone \".\" IN {" echo " type hint;" echo " file \"named.ca\";" echo "};" echo "zone \"localhost\" IN {" echo " type master;" echo " file \"pri/localhost.zone\";" echo " allow-update { none; };" echo " notify no;" echo "};" echo "zone \"127.in-addr.arpa\" IN {" echo " type master;" echo " file \"pri/127.zone\";" echo " allow-update { none; };" echo " notify no;" echo "};" } > /etc/bind/named.conf #------------------------------------------------------------------ # append alle zone entries to config #------------------------------------------------------------------ znr="1" # echo "BEGIN zone: $idx " >/dev/tty while [ "$znr" -le "$BIND_N" ] do eval zonename='$BIND_'${znr}'_NAME' eval zonemast='$BIND_'${znr}'_MASTER' eval zonenetw='$BIND_'${znr}'_NETWORK' eval zonemask='$BIND_'${znr}'_NETMASK' eval masterip='$BIND_'${znr}'_MASTER_IP' [ "$zonemast" = "yes" ] && zonetype='master' || zonetype='slave' #------------------------------------------------------------------ # create forward zone #------------------------------------------------------------------ { echo "" echo "zone \"${zonename}\" IN {" echo " type ${zonetype};" if [ "$zonetype" = "master" ] ; then echo " file \"pri/${zonename}.zone\";" echo " allow-update { localhost; key dns_updater; };" # transfer: any, localnets, nslist, none eval allow_tr='$BIND_'${znr}'_ALLOW_TRANSFER' [ -z "$allow_tr" ] && allow_tr='any' echo " allow-transfer { ${allow_tr}; };" echo " notify yes;" #------------------------------------------------------------------ # create zone file write_zone_file "$zonename" else echo " file \"sec/${zonename}.zone\";" echo " masters { ${masterip}; };" echo " notify no;" fi echo "};" } >> /etc/bind/named.conf #------------------------------------------------------------------ # create reverse zone #------------------------------------------------------------------ reversezone=$(/var/install/bin/netcalc dnsrev $zonenetw $zonemask) forwardzone=$(/var/install/bin/netcalc dnsnet $zonenetw $zonemask) # check for double reverse zone name if ! grep -q "$reversezone" /etc/bind/named.conf then { echo "" echo "zone \"${reversezone}\" in {" echo " type ${zonetype};" if [ ${zonetype} = 'master' ] ; then echo " file \"pri/${reversezone}.zone\";" echo " allow-update { localhost; key dns_updater; };" # transfer: any, localnets, nslist, none eval allow_tr='$BIND_'${znr}'_ALLOW_TRANSFER' [ -z "$allow_tr" ] && allow_tr='any' echo " allow-transfer { ${allow_tr}; };" echo " notify yes;" # create reverse zone file write_reverse_zone_file $reversezone $forwardzone $zonemask else echo " file \"sec/${reversezone}.zone\";" echo " masters { ${masterip}; };" echo " notify no;" fi echo "};" } >> /etc/bind/named.conf fi znr=$((znr+1)) done chmod 0644 /etc/bind/named.conf } ### -------------------------------------------------------------------------- ### Main ### -------------------------------------------------------------------------- [ -f /etc/config.d/named ] && . /etc/config.d/named if [ "$START_BIND" = 'yes' ]; then if [ ! -f /etc/bind/rndc.key ] ; then rndc-confgen -r /dev/urandom -a >/dev/null 2>&1 chmod 0640 /etc/bind/rndc.key chown root:$bind_run_grp /etc/bind/rndc.key fi write_named_file fi exit 0 ###############################################################################