如何从 synology NAS 上的 DHCP 更新非 windows DNS 服务器 A 记录
How can I update a non-windows DNS server A records from DHCP on a synology NAS
背景
我想从我的 DHCP 服务器动态更新我的 DNS A 记录,两者都 运行 在同一个 synology NAS 上。不幸的是,Synology(仍然)没有为此提供有效的解决方案。
我一直在使用 shell script 来完成此操作,但它似乎无法正常工作,因为过了一段时间(几天、几周)我的 DNS 服务器不再解析我的本地地址,很可能是因为shell 脚本以不兼容的顺序放置 dns 记录。
所以..
没关系,我找到了一种不同于 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() { # : mac
local mac=
grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
cp ${TMP_FILE} ${LOG_FILE}
}
renew_record() { # : expired mac ip hostname iface
local record=$@
local mac=
local iface=
grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
echo "${record}" >> ${TMP_FILE}
cp ${TMP_FILE} ${LOG_FILE}
#HH20191123: Prepare dns update command
local ip=""
local hostname=""
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=
# 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=""
local hostname=""
echo "update add ${hostname}.${ZONE_NAME} 3600 A ${ip}" >> ${TMP_NSUPDATE}
}
get_hostname_from_logfile() {
local mac=""
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=""
local ip=""
local hostname=""
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 }'`
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
这对我不起作用。我的区域是作为 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() { # : mac
local mac=
local IP=
#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=
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() { # : expired mac ip hostname iface
local record=$@
local mac=
local iface=
grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
echo "${record}" >> ${TMP_FILE}
cp ${TMP_FILE} ${LOG_FILE}
}
add_new_record() {
local record="$@"
local mac=
#GB: Variables again
local IP=
local REVIP=$(echo $IP | cut -d '.' -f 4)
local HOSTNAME=
# 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=""
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=""
local ip=""
local hostname=""
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 }'`
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 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=""
/usr/syno/bin/synologset1 sys info 0x11100000 "DHCP:$$:${_tmp_msg1} "
return 0
}
del_leases() {
# : expired
# : mac
# : ip
# : hostname
# : iface
local del_MAC=
local del_IP=
local del_REVIP=$(echo ${del_IP} | cut -d '.' -f 4)
local del_HOSTNAME=
internal_logger "del "
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() {
# : expired
# : mac
# : ip
# : hostname
# : iface
local record=$@
local mac=
local iface=
grep -vi "${mac}" ${LOG_FILE} > ${TMP_FILE}
echo "${NEW_RECORD}" >> ${TMP_FILE}
cp ${TMP_FILE} ${LOG_FILE}
return 0
}
add_new_record() {
# : expired
# : mac
# : ip
# : hostname
# : iface
local record="$@"
local mac=
local IP=
local REVIP=$(echo $IP | cut -d '.' -f 4)
local HOSTNAME=
# 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=""
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() {
# : expired
# : mac
# : ip
# : hostname
# : iface
local VALIDHOSTMAC=""
local VALIDHOSTIP=""
local VALIDHOST=""
local VALIDHOSTIF=""
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: "
}
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 }'`
[[ "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=""
#[ -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 ':'`"
背景 我想从我的 DHCP 服务器动态更新我的 DNS A 记录,两者都 运行 在同一个 synology NAS 上。不幸的是,Synology(仍然)没有为此提供有效的解决方案。
我一直在使用 shell script 来完成此操作,但它似乎无法正常工作,因为过了一段时间(几天、几周)我的 DNS 服务器不再解析我的本地地址,很可能是因为shell 脚本以不兼容的顺序放置 dns 记录。
所以..
没关系,我找到了一种不同于 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() { # : mac
local mac=
grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
cp ${TMP_FILE} ${LOG_FILE}
}
renew_record() { # : expired mac ip hostname iface
local record=$@
local mac=
local iface=
grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
echo "${record}" >> ${TMP_FILE}
cp ${TMP_FILE} ${LOG_FILE}
#HH20191123: Prepare dns update command
local ip=""
local hostname=""
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=
# 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=""
local hostname=""
echo "update add ${hostname}.${ZONE_NAME} 3600 A ${ip}" >> ${TMP_NSUPDATE}
}
get_hostname_from_logfile() {
local mac=""
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=""
local ip=""
local hostname=""
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 }'`
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
这对我不起作用。我的区域是作为 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() { # : mac
local mac=
local IP=
#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=
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() { # : expired mac ip hostname iface
local record=$@
local mac=
local iface=
grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
echo "${record}" >> ${TMP_FILE}
cp ${TMP_FILE} ${LOG_FILE}
}
add_new_record() {
local record="$@"
local mac=
#GB: Variables again
local IP=
local REVIP=$(echo $IP | cut -d '.' -f 4)
local HOSTNAME=
# 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=""
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=""
local ip=""
local hostname=""
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 }'`
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 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=""
/usr/syno/bin/synologset1 sys info 0x11100000 "DHCP:$$:${_tmp_msg1} "
return 0
}
del_leases() {
# : expired
# : mac
# : ip
# : hostname
# : iface
local del_MAC=
local del_IP=
local del_REVIP=$(echo ${del_IP} | cut -d '.' -f 4)
local del_HOSTNAME=
internal_logger "del "
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() {
# : expired
# : mac
# : ip
# : hostname
# : iface
local record=$@
local mac=
local iface=
grep -vi "${mac}" ${LOG_FILE} > ${TMP_FILE}
echo "${NEW_RECORD}" >> ${TMP_FILE}
cp ${TMP_FILE} ${LOG_FILE}
return 0
}
add_new_record() {
# : expired
# : mac
# : ip
# : hostname
# : iface
local record="$@"
local mac=
local IP=
local REVIP=$(echo $IP | cut -d '.' -f 4)
local HOSTNAME=
# 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=""
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() {
# : expired
# : mac
# : ip
# : hostname
# : iface
local VALIDHOSTMAC=""
local VALIDHOSTIP=""
local VALIDHOST=""
local VALIDHOSTIF=""
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: "
}
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 }'`
[[ "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=""
#[ -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 ':'`"