【问题标题】:How can I update a non-windows DNS server A records from DHCP on a synology NAS如何从 Synology NAS 上的 DHCP 更新非 Windows DNS 服务器 A 记录
【发布时间】:2018-11-05 22:32:46
【问题描述】:

背景 我想从我的 DHCP 服务器动态更新我的 DNS A 记录,它们都在同一个 Synology NAS 上运行。不幸的是,Synology(仍然)没有为此提供有效的解决方案。

我一直在使用shell script 来完成此操作,但它似乎无法正常工作,因为一段时间(几天、几周)后,我的 DNS 服务器不再解析我的本地地址,很可能是因为 shell 脚本将dns 记录的顺序不兼容。

所以..

【问题讨论】:

  • 来自您的标题:您要求的是示例,而不是显示您所做的事情以及错误的地方。在您的帖子正文中,您不包含任何代码,仅包含指向其他人提供代码的问题的链接。快速搜索如何使用 C# 更新 DNS——我找到了 thisthis
  • 谢谢,但这不是我要找的;第一个示例使用 WMI,两个示例都针对基于 Windows 的 DNS 服务器。

标签: dns dhcp synology


【解决方案1】:

没关系,我找到了一种不同于 c# 和 mono 的方法来动态更新我的本地 dns。

我首先尝试的脚本是我找到的那个 here,但几天后我的本地 DNS 查询由于某种未知原因不再起作用。

事实证明,我的 Synology NAS (DS214Play) 上的 dhcp 服务器在租约更改后调用了一个 bash 脚本,位于位置 /usr/share/dhcpd/dhcpd-script.sh

在我发现您实际上可以使用 nsupdate 命令轻松更改您的(本地)dns 记录后,我将现有脚本更新为以下脚本。我添加的行标有我的首字母 HH。

关于 dns 更新的安全性:我没有使用密钥,因为我的 DNS 服务器只接受来自内部网络和本地主机的更新。

如果您觉得我的回答很有用,如果它仍然是否定的,也请点赞该问题。 (我自己回答了) 注意 1:我发现 DSM 更新可能会将文件恢复为原始文件 注意2:我的一些标记丢失了,所以我更新了下面的代码

#!/bin/sh
# Copyright (c) 2000-2013 Synology Inc. All rights reserved.
#HH20191123 Updated for dynamic DNS updates

DHCPD_DIR="/etc/dhcpd/"
LEASE_FILE="${DHCPD_DIR}/dhcpd.conf.leases"
LOG_FILE="${DHCPD_DIR}/dhcpd-leases.log"
TMP_FILE="${DHCPD_DIR}/tmp-dhcpd-leases.log"


# HH20191123: Define the zone (local domain name) here, but without a trailing point
ZONE_NAME="hhbhasenack.local"

# HH20191123: Prepare a file for updating the DNS through the nsupdate command
TMP_NSUPDATE="${DHCPD_DIR}/tmp-nsupdate.log"
NSUPDATE_LOG_FILE="${DHCPD_DIR}/nsupdate.log"
echo "server 127.0.0.1" > ${TMP_NSUPDATE}
echo "zone ${ZONE_NAME}." >> ${TMP_NSUPDATE}



del_leases() { # $2: mac
    local mac=$2
    grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
    cp ${TMP_FILE} ${LOG_FILE}
}

renew_record() { # $1: expired $2 mac $3 ip $4 hostname $5 iface
    local record=$@
    local mac=$2
    local iface=$5

    grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
    echo "${record}" >> ${TMP_FILE}
    cp ${TMP_FILE} ${LOG_FILE}

#HH20191123: Prepare dns update command
    local ip="$3"
    local hostname="$4"
    echo "update delete ${hostname}.${ZONE_NAME} A"  >> ${TMP_NSUPDATE}
    echo "update add ${hostname}.${ZONE_NAME} 3600 A ${ip}" >> ${TMP_NSUPDATE}

}

add_new_record() {
    local record="$@"
    local mac=$2

    # when disable dhcp-server and any lease is expired, then next time the dhcp client
    # renew the lease the action will be add, so remove the old record has same MAC address
    grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
    cp ${TMP_FILE} ${LOG_FILE}

    if [ -s ${LOG_FILE} ]; then
        sed -i "1 i${record}" ${LOG_FILE}
    else
        echo ${record} >> ${LOG_FILE}
    fi

#HH20191123: Prepare dns update command
    local ip="$3"
    local hostname="$4"
    echo "update add ${hostname}.${ZONE_NAME} 3600 A ${ip}" >> ${TMP_NSUPDATE}

}

get_hostname_from_logfile() {
    local mac="$1"
    local filename="";
    local line="`grep \"${mac}\" ${LOG_FILE}`"
    local tokens=( $line )

    if [ 5 -eq ${#tokens[@]} ]; then
        filename=${tokens[3]}
    fi

    echo $filename
}

get_new_record() {
    local mac="$2"
    local ip="$3"
    local hostname="$4"
    local fileHostname=$(get_hostname_from_logfile $mac)

    if [ "x" = "x${hostname}" ] && [ "xold" = "x${ACTION}" ];then
        if [ "x" != "x${DNSMASQ_SUPPLIED_HOSTNAME}" ]; then
            hostname=${DNSMASQ_SUPPLIED_HOSTNAME}
        elif [ "x" != "x${fileHostname}" ]; then
            hostname=${fileHostname}
        fi
    fi

    NEW_RECORD="${DNSMASQ_LEASE_EXPIRES} ${mac} ${ip} ${hostname} ${DNSMASQ_INTERFACE}"
}

# record format: action mac ip hostname
NEW_RECORD=$@
ACTION=`echo ${NEW_RECORD} | awk '{print $1}'`

if [ "${DNSMASQ_INTERFACE}" = "" ]; then
    exit 0
fi
get_new_record ${NEW_RECORD}

case "${ACTION}" in
    old)
        renew_record ${NEW_RECORD}
        ;;
    add)
        add_new_record ${NEW_RECORD}
        ;;
    del)
        del_leases ${NEW_RECORD}
        ;;
    *)
        ;;
esac


#HH20191123: complete command file for nsupdate with a send command
echo "send" >> ${TMP_NSUPDATE}

#HH20191123: actually execute the nsupdate command
nsupdate ${TMP_NSUPDATE} >>${NSUPDATE_LOG_FILE}



exit 0

【讨论】:

    【解决方案2】:

    这对我不起作用。我的区域是在安装 Synology Directory Server 的过程中创建的。由于该区域是通过 samba 进行管理的,因此对于 nsupdate 来说,再多的敲诈和乱搞密钥也不会起作用。

    Smb-tool 已经安装并且可以很好地处理我的用例。除了脚本之外,唯一的其他任务是创建一个非特权服务帐户并将其添加到“DNSAdmins”组。

    这是我的版本:

    #!/bin/sh
    # Copyright (c) 2000-2013 Synology Inc. All rights reserved.
    #GB: define our variables
    ZONE="example.com"
    REVERSE="1.168.192.in-addr.arpa"
    SERVER="127.0.0.1"
    USERNAME="dhcp-to-dns"
    PASSWORD="insertreallyinsecurepasswordhere"
    
    DHCPD_DIR="/etc/dhcpd/"
    LEASE_FILE="${DHCPD_DIR}/dhcpd.conf.leases"
    LOG_FILE="${DHCPD_DIR}/dhcpd-leases.log"
    TMP_FILE="${DHCPD_DIR}/tmp-dhcpd-leases.log"
    
    del_leases() { # $2: mac
        local mac=$2
        local IP=$3
    #GB: Define Reverse IP address and Hostname. Could have defined this global but stuck with the conventions of the original script
        local REVIP=$(echo $IP | cut -d '.' -f 4)
        local HOSTNAME=$4
        grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
        cp ${TMP_FILE} ${LOG_FILE}
    #GB: use samba-tool to delete forward/reverse DNS entries of expired leases.
        samba-tool dns delete $SERVER $ZONE $HOSTNAME A $IP --username=$USERNAME --password=$PASSWORD 2> /dev/null
        samba-tool dns delete $SERVER $REVERSE $REVIP PTR ${HOSTNAME}.${ZONE} --username=$USERNAME --password=$PASSWORD 2> /dev/null
    }
    
    renew_record() { # $1: expired $2 mac $3 ip $4 hostname $5 iface
        local record=$@
        local mac=$2
        local iface=$5
    
        grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
        echo "${record}" >> ${TMP_FILE}
        cp ${TMP_FILE} ${LOG_FILE}
    }
    
    add_new_record() {
        local record="$@"
        local mac=$2
    #GB: Variables again
        local IP=$3
        local REVIP=$(echo $IP | cut -d '.' -f 4)
        local HOSTNAME=$4
    
        # when disable dhcp-server and any lease is expired, then next time the dhcp client
        # renew the lease the action will be add, so remove the old record has same MAC address
        grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
        cp ${TMP_FILE} ${LOG_FILE}
    
        if [ -s ${LOG_FILE} ]; then
            sed -i "1 i${record}" ${LOG_FILE}
        else
            echo ${record} >> ${LOG_FILE}
        fi
    #GB: Use samba-tool to add forward/reverse DNS Entries.
        samba-tool dns add $SERVER $ZONE $HOSTNAME A $IP --username=$USERNAME --password=$PASSWORD 2> /dev/null
        samba-tool dns add $SERVER $REVERSE $REVIP PTR ${HOSTNAME}.${ZONE} --username=$USERNAME --password=$PASSWORD 2> /dev/null
    }
    
    get_hostname_from_logfile() {
        local mac="$1"
        local filename="";
        local line="`grep \"${mac}\" ${LOG_FILE}`"
        local tokens=( $line )
    
        if [ 5 -eq ${#tokens[@]} ]; then
            filename=${tokens[3]}
        fi
    
        echo $filename
    }
    
    get_new_record() {
        local mac="$2"
        local ip="$3"
        local hostname="$4"
        local fileHostname=$(get_hostname_from_logfile $mac)
    
        if [ "x" = "x${hostname}" ] && [ "xold" = "x${ACTION}" ];then
            if [ "x" != "x${DNSMASQ_SUPPLIED_HOSTNAME}" ]; then
                hostname=${DNSMASQ_SUPPLIED_HOSTNAME}
            elif [ "x" != "x${fileHostname}" ]; then
                hostname=${fileHostname}
            fi
        fi
    
        NEW_RECORD="${DNSMASQ_LEASE_EXPIRES} ${mac} ${ip} ${hostname} ${DNSMASQ_INTERFACE}"
    }
    
    # record format: action mac ip hostname
    NEW_RECORD=$@
    ACTION=`echo ${NEW_RECORD} | awk '{print $1}'`
    
    if [ "${DNSMASQ_INTERFACE}" = "" ]; then
        exit 0
    fi
    get_new_record ${NEW_RECORD}
    
    case "${ACTION}" in
        old)
            renew_record ${NEW_RECORD}
            ;;
        add)
            add_new_record ${NEW_RECORD}
            ;;
        del)
            del_leases ${NEW_RECORD}
            ;;
        *)
            ;;
    esac
    
    exit 0
    

    【讨论】:

    • 我还没有使用 NAS 上的目录服务器。那么您可以使用注释行标记您对文件所做的修改吗? - 这肯定有助于理解您所做的更改。顺便说一句,我最近将我的 NAS 从 DS214Play 升级到 DS718Plus,我的解决方案也运行良好。
    【解决方案3】:

    另一个使用NAS diagram1中的图表的示例

    用于完成上述图表的角色是:域服务器、DNS 服务器、DHCPD 服务器。 管理 DNS 更改的用户是 dhcptodns(Synology Directory Server 中 DNSAdmin 组的一部分)。 在这种情况下,脚本 /usr/share/dhcpd/dhcpd-script.sh 是:

    #!/bin/sh
    # Copyright (c) 2000-2013 Synology Inc. All rights reserved.
    ZONE="yourdomain.local"
    REVERSE="1.168.192.in-addr.arpa"
    SERVER="127.0.0.1"
    USERNAME="dhcptodns"
    PASSWORD="change_me_with_a_real_password"
    
    DHCPD_DIR="/etc/dhcpd/"
    LEASE_FILE="${DHCPD_DIR}/dhcpd.conf.leases"
    LOG_FILE="${DHCPD_DIR}/dhcpd-leases.log"
    TMP_FILE="${DHCPD_DIR}/tmp-dhcpd-leases.log"
    
    internal_logger() {
         local _tmp_msg1="$1"
             /usr/syno/bin/synologset1 sys info 0x11100000 "DHCP:$$:${_tmp_msg1} "
         return 0
    }
    
    del_leases() {
    # $1: expired
    # $2: mac
    # $3: ip
    # $4: hostname
    # $5: iface
       local del_MAC=$2
       local del_IP=$3
       local del_REVIP=$(echo ${del_IP} | cut -d '.' -f 4)
       local del_HOSTNAME=$4
       internal_logger  "del $2 $3 $4"
       grep -vi "$del_MAC" ${LOG_FILE} > ${TMP_FILE}
       cp ${TMP_FILE} ${LOG_FILE}
       cat  ${LOG_FILE}
       if [ `samba-tool dns query $SERVER $ZONE ${del_HOSTNAME} --username=${USERNAME} A --password=${PASSWORD} 2>/dev/null|grep 'A:'|sed 's/(.*//;s/.*A: //'|wc -l|cut -d ' ' -f 1` -gt 0 ] ; then
       {
         for del_i in `samba-tool dns query $SERVER $ZONE ${del_HOSTNAME} A --username=${USERNAME} --password=${PASSWORD} 2>/dev/null|grep 'A:'|sed 's/(.*//;s/.*A: //'` ; do
            internal_logger  "Record to be cleaned.... ${del_i}"
            samba-tool dns delete $SERVER $ZONE ${del_HOSTNAME} A ${del_i} --username=$USERNAME --password=${PASSWORD} 2>/dev/null
            internal_logger  "samba-tool dns delete $SERVER $ZONE ${del_HOSTNAME} A ${del_i} --username=${USERNAME} --password=<masked>"
         done
       }
       fi
       # Reverse is already cleaned up
       samba-tool dns delete $SERVER $REVERSE ${del_REVIP} PTR ${del_HOSTNAME}.${ZONE} --username=${USERNAME} --password=${PASSWORD} 2>/dev/null
       internal_logger  "samba-tool dns delete $SERVER $REVERSE ${del_REVIP} PTR ${del_HOSTNAME}.${ZONE} --username=${USERNAME} --password=<masked>"
       return 0
    }
    
    renew_record() {
    # $1: expired
    # $2: mac
    # $3: ip
    # $4: hostname
    # $5: iface
       local record=$@
       local mac=$2
       local iface=$5
    
       grep -vi "${mac}" ${LOG_FILE} > ${TMP_FILE}
       echo "${NEW_RECORD}" >> ${TMP_FILE}
       cp ${TMP_FILE} ${LOG_FILE}
       return 0
    }
    
    add_new_record() {
    # $1: expired
    # $2: mac
    # $3: ip
    # $4: hostname
    # $5: iface
       local record="$@"
       local mac=$2
       local IP=$3
       local REVIP=$(echo $IP | cut -d '.' -f 4)
       local HOSTNAME=$4
    
       # when disable dhcp-server and any lease is expired, then next time the dhcp client
       # renew the lease the action will be add, so remove the old record has same MAC address
       grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
       cp ${TMP_FILE} ${LOG_FILE}
       if [ -s ${LOG_FILE} ]; then
           sed -i "1 i${record}" ${LOG_FILE}
       else
           echo ${record} >> ${LOG_FILE}
       fi
       # DEBUG
       #internal_logger `samba-tool dns query $SERVER $ZONE $HOSTNAME --username=$USERNAME A --password=$PASSWORD 2>/dev/null|grep 'A:'|sed 's/(.*//;s/.*A: //'|wc -l|cut -d ' ' -f 1`
       if [ `samba-tool dns query $SERVER $ZONE $HOSTNAME --username=$USERNAME A --password=$PASSWORD 2>/dev/null|grep 'A:'|sed 's/(.*//;s/.*A: //'|wc -l|cut -d ' ' -f 1` -gt 0 ] ; then
       {
          del_leases  ${NEW_RECORD}
       }
       fi
       samba-tool dns add $SERVER $ZONE $HOSTNAME A $IP --username=$USERNAME --password=$PASSWORD 2> /dev/null
       internal_logger  "samba-tool dns add $SERVER $ZONE $HOSTNAME A $IP --username=$USERNAME --password=<masked>"
       samba-tool dns add $SERVER $REVERSE $REVIP PTR ${HOSTNAME}.${ZONE} --username=$USERNAME --password=$PASSWORD 2> /dev/null
       internal_logger  "samba-tool dns add $SERVER $REVERSE $REVIP PTR ${HOSTNAME}.${ZONE} --username=$USERNAME --password=<masked>"
       return 0
    }
    
    get_hostname_from_logfile() {
       local mac="$1"
       local filename="";
       local line="`grep \"${mac}\" ${LOG_FILE}`"
       local tokens=( $line )
    
       if [ 5 -eq ${#tokens[@]} ]; then
           filename=${tokens[3]}
       fi
       echo $filename
    }
    
    get_new_record() {
    # $1: expired
    # $2: mac
    # $3: ip
    # $4: hostname
    # $5: iface
       local VALIDHOSTMAC="$2"
       local VALIDHOSTIP="$3"
       local VALIDHOST="$4"
       local VALIDHOSTIF="$5"
       local FILEVALIDHOST=$(get_hostname_from_logfile $mac)
       if [[ "X${VALIDHOST}" == "X" ]] && [[ "Xold" == "X${ACTION}" ]]; then
       {
        [[ "X${DNSMASQ_SUPPLIED_HOSTNAME}" == "X" ]] || VALIDHOST=${DNSMASQ_SUPPLIED_HOSTNAME}
        [[ "X${VALIDHOST}" == "X" ]] &&  export VALIDHOST=${FILEVALIDHOST}
        [[ "X${VALIDHOST}" == "X" ]] && VALIDHOST="unknown_`echo $VALIDHOSTMAC|tr -d ':'`"
            # DEBUG
            #internal_logger  "Exception found: $1 $2 $3 $4"
       }
       fi
       [[ "X$VALIDHOST" == "X" ]] && VALIDHOST="unknown_`echo $VALIDHOSTMAC|tr -d ':'`"
       NEW_RECORD="${DNSMASQ_LEASE_EXPIRES} ${VALIDHOSTMAC} ${VALIDHOSTIP} ${VALIDHOST} ${DNSMASQ_INTERFACE}"
       return 0
    }
    
    # record format: action mac ip hostname
    NEW_RECORD=$@
    ACTION=`echo ${NEW_RECORD} | awk '{print $1}'`
    
    [[ "X${DNSMASQ_INTERFACE}" == "X" ]] && exit 0
    
    get_new_record ${NEW_RECORD}
    
    case "${ACTION}" in
        old)
            renew_record ${NEW_RECORD}
            ;;
        add)
            add_new_record ${NEW_RECORD}
            ;;
        del)
            del_leases ${NEW_RECORD}
            ;;
        *)
            ;;
    esac
    
    exit 0
    

    我已将日志功能添加到 Synology 系统日志中:

    internal_logger() {
         local _tmp_msg1="$1"
         #[ -t ] || echo -e "${_tmp_msg1}" && echo -e "${_tmp_msg1}" |tee -a /etc/dhcpd/debug.log
         /usr/syno/bin/synologset1 sys info 0x11100000 "DHCP:$$:${_tmp_msg1} "
         return 0
    }
    

    并修复了添加不提供 DNSMASQ_SUPPLIED_HOSTNAME 字段的主机。添加主机名如unknown_mac的块:

             [[ "X${DNSMASQ_SUPPLIED_HOSTNAME}" == "X" ]] || VALIDHOST=${DNSMASQ_SUPPLIED_HOSTNAME}
             [[ "X${VALIDHOST}" == "X" ]] &&  export VALIDHOST=${FILEVALIDHOST}
             [[ "X${VALIDHOST}" == "X" ]] && VALIDHOST="unknown_`echo $VALIDHOSTMAC|tr -d ':'`"
    

    【讨论】:

    • 看起来不错,除了我没有在我的 NAS 中使用 AD 服务器(还没有?)。如果我有时间我一定会调查此事,因为几个月前我已将我的 DS214Play 升级到 DS718Plus。
    猜你喜欢
    • 1970-01-01
    • 2011-10-12
    • 2014-03-09
    • 1970-01-01
    • 1970-01-01
    • 2015-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多