diff --git a/dns-functions.sh b/dns-functions.sh index 48ad97f..fd7396f 100755 --- a/dns-functions.sh +++ b/dns-functions.sh @@ -83,6 +83,11 @@ GetReverseDomains() { TraceErrAndExit "$1"" is no valid Subnet" fi } +ExpandHostname() { + Hostname="$1" + [ -n "${Hostname##*.}" ] && Hostname="$Hostname"".""$2" + echo "$Hostname" +} GetServernameSEDEntry() { CommunityName="$1" ServerName="$DNSSCRIPT_SERVER_NAME" @@ -94,13 +99,20 @@ GetServernameSEDEntry() { echo "$ServerName" | sed -r 's/\./\\\./g' } +NormalizeZoneFileFormatting() { + awk 'BEGIN{FS="\t"}{l=length($1);f=substr(" ", 1+length($1)); + s=substr(" ", 1+length($2)); + x=substr($0,length($1)+length($2)+3); + print $1 f " " $2 s " " x}' +} GetOwnGlueRecords() { ServerName="$DNSSCRIPT_SERVER_NAME" if [ -n "${ServerName##*$1}" ]; then ServerName="$ServerName""$1" fi ServerName="$ServerName""." - sed -ne 's/^\s*'"$(GetServernameSEDEntry "$1")"'\(\s\+[Ii][Nn]\s\+\([Aa]\|[Aa]\{4\}\)\s\+.*\)$/'"$ServerName"'\2/p' "$2" + sed -ne 's/^\s*'"$(GetServernameSEDEntry "$1")"'\s\+[Ii][Nn]\s\+\([Aa]\|[Aa]\{4\}\)\s\+\(.*\)$/'"$ServerName"'\tIN \2\t\3/p' "$2" | \ + NormalizeZoneFileFormatting } GetOwnHoods() { Entries="$(sed -ne "s/^\s*\(\S*\).*\s\+[Ii][Nn]\s\+[Nn][Ss]\s\+""$(GetServernameSEDEntry "$1")""\s*;\s*Subnets:\s*\([^;]*\)/\1 \3/p" "$2")" @@ -153,7 +165,7 @@ ReloadZone() { systemctl reload bind9 elif [ $((DNSSCRIPT_BIND_RELOAD_VER)) -eq 1 ]; then for Zone in $2; do - rndc reload "$1" IN "$Zone" + rndc reload "$1" IN "$Zone" || touch "/tmp/dnsscript-forcereconf" done elif [ $((DNSSCRIPT_BIND_RELOAD_VER)) -eq 2 ]; then /etc/init.d/named reload diff --git a/update-dns.sh b/update-dns.sh index 3fd66e1..a511619 100755 --- a/update-dns.sh +++ b/update-dns.sh @@ -6,7 +6,7 @@ set -e # Communityconfig CommunityDomain="fff.community" CommunitySubnets="10.50.0/16 10.83.0/16 fd43:5602:29bd::/48" -MasterFileRemoteLocation="https://git.freifunk-franken.de/freifunk-franken/dns/raw/branch/master/db.fff.community" +RemoteLocation="https://git.freifunk-franken.de/freifunk-franken/dns/raw/branch/master/" # Serverconfig export DNSSCRIPT_CONTACT_EMAIL=info.freifunk-herpf.de. @@ -16,13 +16,10 @@ UpdateScriptsFolder="/usr/lib/ffdns/" ZoneFilesFolder="/etc/bind/fff/" BindIncludeFileFolder="/etc/bind/" -# -1 -> disable bind restarting/reloading +# -1 -> disable bind [restart|reload] # 0 -> Debian (and like) systemctl [reload|restart] bind9 -# 1 -> use rndc to [reload zone|restart] (recommended; rndc needs setup first) +# 1 -> use rndc to [reload zone|reconfig] (recommended; rndc needs setup first) # 2 -> OpenWRT /etc/init.d/named [reload|restart] -# -# Set -1 for first run to prevent exiting on error and let the script generate the config and zonefiles -# after first run edit your config and set appropriate value export DNSSCRIPT_BIND_RELOAD_VER=0 # only necessary when rndc is used @@ -38,6 +35,7 @@ ForwardZones="$CommunityDomain""/""$ZoneFilesFolder""db.""$CommunityDomain" ############################################################# cd "$UpdateScriptsFolder" + . ./dns-functions.sh MasterFile="$ZoneFilesFolder""db.""$CommunityDomain" @@ -49,7 +47,7 @@ BindExternalConf="$BindIncludeFileFolder""$CommunityDomain""-external.conf" BindIcvpnAcl="$BindIncludeFileFolder""icvpn-acl.conf" PreFetchMasterSerial="$(GetZoneFileSerial "$MasterFile")" -curl -s -S "$MasterFileRemoteLocation" --output "$MasterFile" +curl -s -S -f "$RemoteLocation""db.""$CommunityDomain" --output "$MasterFile" PostFetchMasterSerial="$(GetZoneFileSerial "$MasterFile")" if [ $((PostFetchMasterSerial)) -gt $((PreFetchMasterSerial)) ]; then @@ -58,20 +56,23 @@ fi rm -f "$BindInternalConfTmp" rm -f "$BindExternalConfTmp" -InsertZoneToIncludeFile "$CommunityDomain" "$ZoneFilesFolder""db.""$CommunityDomain" "$BindExternalConfTmp" +InsertZoneToIncludeFile "$CommunityDomain" "$MasterFile" "$BindInternalConfTmp" +InsertZoneToIncludeFile "$CommunityDomain" "$ZoneFilesFolder""dbextern.""$CommunityDomain" "$BindExternalConfTmp" for Subnet in $CommunitySubnets; do ReverseDomains="$(GetReverseDomains "$Subnet")" for RDomain in $ReverseDomains; do - ./update-rdnszone.sh "$RDomain" "$ForwardZones" "$ZoneFilesFolder" "$TTLReReExMi" "$InternalViews" - InsertZoneToIncludeFile "$RDomain" "$ZoneFilesFolder""$(GetReverseZoneFileFromZone "${RDomain%*.}")" "$BindInternalConfTmp" + ReverseZoneFile="$(GetReverseZoneFileFromZone "${RDomain%*.}")" + ! curl -s -f "$RemoteLocation""static.""$ReverseZoneFile" \ + --output "$ZoneFilesFolder""static.""$ReverseZoneFile" && \ + rm -f "$ZoneFilesFolder""static.""$ReverseZoneFile" + ./update-rdnszone.sh "$RDomain" "$ForwardZones" "$ZoneFilesFolder""$ReverseZoneFile" "$TTLReReExMi" "$InternalViews" + InsertZoneToIncludeFile "$RDomain" "$ZoneFilesFolder""$ReverseZoneFile" "$BindInternalConfTmp" done done -InternFile="$MasterFile" ExternFile="$ZoneFilesFolder""dbextern.""$CommunityDomain" -Domain="$CommunityDomain" -./update-extzone.sh "$InternFile" "$ExternFile" "$Domain" "$ExternalView" +./update-extzone.sh "$MasterFile" "$ExternFile" "$CommunityDomain" "$ExternalView" # set shorter TTL for Hoods TTLReReExMi="420 360 180 1800 360" @@ -79,39 +80,45 @@ TTLReReExMi="420 360 180 1800 360" Hoods="$(GetOwnHoods "$CommunityDomain" "$MasterFile")" for Hood in $Hoods; do - HoodSubDomain="${Hood%%\#*}" + HoodDomain="${Hood%%\#*}"".""$CommunityDomain" Subnets="$(echo "${Hood#*\#}" | sed -e 's/#/ /g')" - HoodZoneFile="$ZoneFilesFolder""db.""$HoodSubDomain"".""$CommunityDomain" + HoodZoneFile="$ZoneFilesFolder""db.""$HoodDomain" if [ ! -f "$HoodZoneFile" ]; then { echo "\$TTL ${TTLReReExMi%% *}" - echo "$HoodSubDomain"".""$CommunityDomain"". ${TTLReReExMi%% *} IN SOA $DNSSCRIPT_SERVER_NAME""."" $DNSSCRIPT_CONTACT_EMAIL 1 ${TTLReReExMi#* }" - echo "$HoodSubDomain"".""$CommunityDomain"". ${TTLReReExMi%% *} IN NS $DNSSCRIPT_SERVER_NAME"".""" + echo "@ IN SOA $DNSSCRIPT_SERVER_NAME""."" $DNSSCRIPT_CONTACT_EMAIL (" + echo " 1 ; Serial" + echo " ""$(echo "$TTLReReExMi" | awk '{print $2}')"" ; Refresh" + echo " ""$(echo "$TTLReReExMi" | awk '{print $3}')"" ; Retry" + echo " ""$(echo "$TTLReReExMi" | awk '{print $4}')"" ; Expire" + echo " ""$(echo "$TTLReReExMi" | awk '{print $5}')"" ) ; Negative Cache TTL" + echo ";" + echo "@ IN NS $DNSSCRIPT_SERVER_NAME"".""" GetOwnGlueRecords "$CommunityDomain" "$MasterFile" + echo ";" } > "$HoodZoneFile" fi - ./update-hoodzone.sh "$HoodZoneFile" "$HoodSubDomain"".""$CommunityDomain" "$Subnets" "$InternalViews" - InsertZoneToIncludeFile "$HoodSubDomain"".""$CommunityDomain" "$ZoneFilesFolder""db.""$HoodSubDomain"".""$CommunityDomain" "$BindExternalConfTmp" + ./update-hoodzone.sh "$HoodZoneFile" "$HoodDomain" "$Subnets" "$InternalViews" - HoodForwardZones="$ForwardZones $HoodSubDomain"".""$CommunityDomain""/""$ZoneFilesFolder""db.""$HoodSubDomain"".""$CommunityDomain" + InsertZoneToIncludeFile "$HoodDomain" "$HoodZoneFile" "$BindInternalConfTmp" + InsertZoneToIncludeFile "$HoodDomain" "$ZoneFilesFolder""dbextern.""$HoodDomain" "$BindExternalConfTmp" + + HoodForwardZones="$ForwardZones $HoodDomain""/""$HoodZoneFile" for Subnet in $Subnets; do ReverseDomains="$(GetReverseDomains "$Subnet")" for RDomain in $ReverseDomains; do - ./update-rdnszone.sh "$RDomain" "$HoodForwardZones" "$ZoneFilesFolder" "$TTLReReExMi" "$InternalViews" - InsertZoneToIncludeFile "$RDomain" "$ZoneFilesFolder""$(GetReverseZoneFileFromZone "${RDomain%*.}")" "$BindInternalConfTmp" + ReverseZoneFileFullPath="$ZoneFilesFolder""$(GetReverseZoneFileFromZone "${RDomain%*.}")" + ./update-rdnszone.sh "$RDomain" "$HoodForwardZones" "$ReverseZoneFileFullPath" "$TTLReReExMi" "$InternalViews" + InsertZoneToIncludeFile "$RDomain" "$ReverseZoneFileFullPath" "$BindInternalConfTmp" done done - InternFile="$ZoneFilesFolder""db.""$HoodSubDomain"".""$CommunityDomain" - ExternFile="$ZoneFilesFolder""dbextern.""$HoodSubDomain"".""$CommunityDomain" - Domain="$HoodSubDomain"".""$CommunityDomain" - ./update-extzone.sh "$InternFile" "$ExternFile" "$Domain" "$ExternalView" + ExternFile="$ZoneFilesFolder""dbextern.""$HoodDomain" + ./update-extzone.sh "$HoodZoneFile" "$ExternFile" "$HoodDomain" "$ExternalView" done -sed -i "1i include \"""$BindExternalConf""\";\n" "$BindInternalConfTmp" ./update-public-acl.sh "$BindIcvpnAclTmp" - ReConfigBind=1 UpdateBindConfig() { if [ -f "$1" ] && ! cmp -s "$1" "$2"; then @@ -126,7 +133,7 @@ UpdateBindConfig "$BindIcvpnAclTmp" "$BindIcvpnAcl" UpdateBindConfig "$BindInternalConfTmp" "$BindInternalConf" UpdateBindConfig "$BindExternalConfTmp" "$BindExternalConf" -if [ $ReConfigBind -eq 0 ]; then +if [ $ReConfigBind -eq 0 ] || [ -f "/tmp/dnsscript-forcereconf" ]; then if [ $((DNSSCRIPT_BIND_RELOAD_VER)) -eq 0 ]; then systemctl restart bind9 elif [ $((DNSSCRIPT_BIND_RELOAD_VER)) -eq 1 ]; then @@ -134,4 +141,5 @@ if [ $ReConfigBind -eq 0 ]; then elif [ $((DNSSCRIPT_BIND_RELOAD_VER)) -eq 2 ]; then /etc/init.d/named restart fi -fi + rm -f "/tmp/dnsscript-forcereconf" +fi \ No newline at end of file diff --git a/update-hoodzone.sh b/update-hoodzone.sh index a08ed87..e285038 100755 --- a/update-hoodzone.sh +++ b/update-hoodzone.sh @@ -40,10 +40,7 @@ NewLeases="$(echo "$NewLeases" | awk '!a[$0]++' | # uncomment and duplicate to secure static DNS-Entries # sed -e '/^dns\s\+.*/d' | - awk 'BEGIN{FS="\t"}{l=length($1);f=substr(" ", 1+length($1)); - s=substr(" ", 1+length($2)); - x=substr($0,length($1)+length($2)+3); - print $1 f " " $2 s " " x}' )" + NormalizeZoneFileFormatting)" if [ "$NewLeases" != "$OldLeases" ]; then NewSerial="$(GetZoneFileSerial "$HoodZoneFile")" NewSerial=$((NewSerial+1)) diff --git a/update-rdnszone.sh b/update-rdnszone.sh index a89ad8a..77c00ed 100755 --- a/update-rdnszone.sh +++ b/update-rdnszone.sh @@ -5,7 +5,7 @@ ReverseDomain="$1" ReverseZone="${ReverseDomain%*.}" ForwardZones="$2" -ReverseZoneFile="$3""db.""$(echo "$ReverseZone" | awk -F. '{ printf $(NF-2);for(i=NF-3;i>0;--i) printf "."$i}')" +ReverseZoneFile="$3" TempDir="/tmp/""$ReverseZone" TTL="${4%% *}" ReReExMi="${4#* }" @@ -18,7 +18,7 @@ GetIPEntries() { IPPattern="[aA]\{4\}\s\+\([0-9a-f:]\+\)" fi - sed -ne "s/^\s*\(\S\+\)\s\+\([0-9]*\s\)\?\s*[Ii][Nn]\s\+""$IPPattern"".*/\1\/\3/p" "$ForwardZoneFile" + sed -ne "s/^\s*\(\S\+\)\s\+\([0-9]*\s\)\?\s*[Ii][Nn]\s\+""$IPPattern"".*/\1\/\3/p" "$1" } ReverseEntry() { @@ -40,13 +40,9 @@ fi mkdir -p "$TempDir" for ForwardZone in $ForwardZones; do - ZoneName="${ForwardZone%%/*}" ZoneFile="${ForwardZone#*/}" - named-checkzone -f text -i local -o "$TempDir/$ZoneName" -D "$ZoneName" "$ZoneFile" >/dev/null - Serial="$(GetZoneFileSerial "$TempDir/$ZoneName")" + Serial="$(GetZoneFileSerial "$ZoneFile")" NewReverseSerial=$((Serial + NewReverseSerial)) - ZoneRevNSSubnets="$(sed -ne 's/^\s*\S\+\s\+\([0-9]*\s\)\?\s*[Ii][Nn]\s\+[Nn][Ss]\s\+\(\S\+\).*;\s*Subnets:\s*\([^;]*\)$/\2@\3/p' "$ZoneFile" | - sed -e 's/\(.*[^\.]\)@/\1\.'"$ZoneName"'\.@/;s/@/ /;s/\s\+/@/g')" done OldSerial="$(GetZoneFileSerial "$ReverseZoneFile")" @@ -55,36 +51,43 @@ if [ $((NewReverseSerial)) -gt $((OldSerial)) ]; then { echo "$ReverseDomain $TTL IN SOA $DNSSCRIPT_SERVER_NAME""."" $DNSSCRIPT_CONTACT_EMAIL $NewReverseSerial $ReReExMi" echo "$ReverseDomain $TTL IN NS $DNSSCRIPT_SERVER_NAME"".""" + Static="/""$ReverseZoneFile" + Static="${Static%/*}""/static.""${Static##*/}" + Static="${Static#*/}" + [ -f "$Static" ] && cat "$Static" + echo } > "$TempDir/$ReverseZone" - for NSSubnets in $ZoneRevNSSubnets; do - Subnets="$(echo "${NSSubnets#*@}" | sed -e 's/@/ /g')" - for Subnet in $Subnets; do - for ReverseNS in $(GetReverseDomains "$Subnet"); do - if [ -n "$ReverseNS" ] && [ -z "${ReverseNS##*$ReverseDomain}" ]; then - echo "$ReverseNS $TTL IN NS ${NSSubnets%%@*}" >> "$TempDir/$ReverseZone" - fi + for ForwardZone in $ForwardZones; do + ZoneName="${ForwardZone%%/*}" + ZoneFile="${ForwardZone#*/}" + ZoneRevNSSubnets="$(sed -ne 's/^\s*\S\+\s\+\([0-9]*\s\)\?\s*[Ii][Nn]\s\+[Nn][Ss]\s\+\(\S\+\).*;\s*Subnets:\s*\([^;]*\)\s*\(;[^;]*\s*\)$/\2@\3/p' "$ZoneFile" | + sed -e 's/\(.*[^\.]\)@/\1\.'"$ZoneName"'\.@/;s/@/ /;s/\s\+/@/g')" + for NSSubnets in $ZoneRevNSSubnets; do + Subnets="$(echo "${NSSubnets#*@}" | sed -e 's/@/ /g')" + for Subnet in $Subnets; do + for ReverseNS in $(GetReverseDomains "$Subnet"); do + if [ -n "$ReverseNS" ] && [ -z "${ReverseNS##*$ReverseDomain}" ]; then + echo "$ReverseNS $TTL IN NS ${NSSubnets%%@*}" >> "$TempDir/$ReverseZone" + fi + done done done - done - for ForwardZoneFile in "$TempDir"/*; do - if [ -n "${ForwardZoneFile##*$ReverseZone}" ]; then - IPEntries="$(GetIPEntries)" + + IPEntries="$(GetIPEntries "$ZoneFile")" for IPEntry in $IPEntries; do IP="${IPEntry#*/}" - # IP syntax checked by named-checkzone IP="$(ReverseEntry "$IP")" if [ -z "${IP##*$ReverseDomain}" ]; then - Host="${IPEntry%/*}" + Host="$(ExpandHostname "${IPEntry%%/*}" "$ZoneName"".")" echo "$IP $TTL IN PTR $Host" >> "$TempDir/$ReverseZone" fi done - fi done named-checkzone -o "$ReverseZoneFile" "$ReverseDomain" "$TempDir/$ReverseZone" >/dev/null ReloadZone "$ReverseDomain" "$View" fi -rm -r "$TempDir" +rm -r "$TempDir" \ No newline at end of file