Initial commit.

This commit is contained in:
2015-11-06 00:41:56 +01:00
commit 72d76f6029
5 changed files with 513 additions and 0 deletions

11
dhclient-dnsupdate.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/bash
dnsupdate_config() {
/usr/bin/dnsupdate "${interface}" "${new_ip_address}"
return 0
}
dnsupdate_restore() {
return 0
}

427
dnsupdate Executable file
View File

@@ -0,0 +1,427 @@
#!/bin/bash
# Dynamic DNS update script using ISC nsupdate
# Copyright (c) 2015 Zoran Pericic (zpericic@netst.org) all rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
#
# There is three type of options:
# DDNS_*
# - Global default if in /etc/sysconfig/network
# - First hostname options if in ifcfg- of conection.
# - Default for other hostnames.
# DDNS*_ (eg. DDNS0_HOSTNAME) - Where * is number starting from 0
# - Options for updating specific hostname.
# - DDNS*_HOSTNAME must be set to activate update.
# DDNS_PTR* -
# - Options for updating PTR record.
# - Have all options except ZONE and REPLACE as DDNS*
#
# Valid variables are:
# DDNS=yes|no
# Run Dynamic DNS update (default:yes if not public address).
# DDNS_HOSTNAME
# Hostname to update. Defaults to DHCP_HOSTNAME, HOSTNAME and hostname.
# DDNS*_HOSTNAME
# Hostname to update.
# DDNS*_ZONE
# Zone to update (default: from hostname).
# DDNS*_TTL
# Record TTL (default:300).
# DDNS*_REPLACE
# Delete old records (default: yes).
# DDNS*_SERVER
# Server to send updates (default: hostname zone SOA).
# DDNS*_TCP
# Use TCP protocol for update (default: no, except for PTR).
# DDNS*_GSS_TSIG=yes|no
# "no" to disable GSS-TSIG. Default authentification type if not tcp and other
# authentification is set and kinit runned succesfully. If not nsupdate is
# called without authentification.
# DDNS*_GSS_KEYTAB="filename"
# Kerberos keytab filename with credential
# DDNS*_GSS_PRINCIPAL="principal"
# GSS Principal (eg. 'host/example.com')
# DDNS*_TSIG_FILE=filename
# Filename of key file which containing a named.conf-format key statement
# DDNS*_TSIG_KEY_TYPE
# Name of the key algorithm (default: hmac-md5)
# DDNS*_TSIG_KEY_NAME
# Key name
# DDNS*_TSIG_KEY_SECRET
# Base64 encoded shared secret
#
# There is four way to authentificate:
# 1. GSS-TSIG authentification (default)
# Set DDNS*_GSS_TSIG=yes or don't set any authenctification.
# 2. TSIG authentification using file
# Set DDNS*_TSIG_FILE to key file.
# 3. TSIG authentification with key
# Set DDNS*_TSIG_KEY_NAME and DDNS*_TSIG_KEY_SECRET and optionaly
# DDNS*_TSIG_KEY_TYPE.
# 4. No authentifiaction
# Used if DDNS*_GSS_TSIG=no or DDNS*_GSS_TSIG not set and keytab
# not found.
#
# Update PTR
#
# DDNS_PTR=yes|no
# "no" to disable update of PTR record (default: yes).
# DDNS_PTR_HOSTNAME
# Hostname to use for PTR record. Defaults to DDNS_HOSTNAME.
# DDNS_PTR_ZONE
# Not used. Constructed from IP adress.
# DDNS_PTR_REPLACE
# Not used. Always yes.
#
# DDNS_PTR_TTL
# DDNS_PTR_SERVER
# DDNS_PTR_GSS_TSIG
# DDNS_PTR_TSIG_FILE
# DDNS_PTR_TSIG_KEY_TYPE
# DDNS_PTR_TSIG_KEY_NAME
# DDNS_PTR_TSIG_KEY_SECRET
# Same as DDNS*.
#
[ ! -x /usr/bin/nsupdate ] && exit 0;
# Debugging is disabled by default
DDNS_DEBUG=${DDNS_DEBUG:=no}
function run_nsupdate() {
local rr_name=${1}
local ttl=${2}
local type=${3}
local rr_data=${4}
local replace=${5}
local server=${6}
local tcp=${7}
local zone=${8}
local gss_tsig=${9}
local gss_keytab=${10}
local gss_principal=${11}
local tsig_file=${12}
local tsig_key_type=${13}
local tsig_key_name=${14}
local tsig_key_secret=${15}
local cmd_server
local cmd_zone
local cmd_key
local cmd_replace
local cmd_params
local cc_file
[ -z "${rr_name}" ] && return 1
[ -z "${ttl}" ] && return 1
[ -z "${type}" ] && return 1
[ -z "${rr_data}" ] && return 1
[ -n "${server}" ] && cmd_server="server ${server}"
[ -n "${zone}" ] && cmd_zone="zone ${zone}"
[ "x${tcp}x" == "xyesx" ] && cmd_params="-v"
if [ "x${DDNS_DEBUG}x" != "xnox" ]; then
# cmd_params='-d'
echo "dnsupdate: updating: $rr_name $ttl IN $type $rr_data"
echo -e \
"Params: \n" \
" RR Name: \"${rr_name}\"\n" \
" TTL: \"${ttl}\"\n" \
" Type: \"${type}\"\n" \
" RR Data: \"${rr_data}\"\n" \
" Replace: \"${replace}\"\n" \
" Server: \"${server}\"\n" \
" TCP: \"${tcp}\"\n" \
" Zone: \"${zone}\"\n" \
" GSS-TSIG: \"${gss_tsig}\"\n" \
" GSS Keytab: \"${gss_keytab}\"\n" \
" GSS Principal: \"${gss_principal}\"\n" \
" TSIG File: \"${tsig_file}\"\n" \
" TSIG Key type: \"${tsig_key_type}\"\n" \
" TSIG Key name: \"${tsig_key_name}\"\n" \
" TSIG Key secret: \"${tsig_key_secret}\"\n"
fi
if [ -n "${tsig_file}" ]; then
[ -f "${tsig_file}" ] && logger -p daemon.info "TSIG keyfile not exists." && return 1;
cmd_params="${cmd_params} -k ${tsig_file}"
elif [ -n "${tsig_key_name}" ] && [ -n "${tsig_key_secret}" ]; then
if [ -n "${tsig_key_type}" ]; then
cmd_key="${tsig_key_type}:"
fi
cmd_key="key ${cmd_key}${tsig_key_name} ${tsig_key_secret}"
fi
#
# Init kerberos credential cache if needed.
#
if [ "x${tsig_gss}x" == "xyesx" ] || [ "x${tcp}x" != "xyesx" ] && [ "x${tsig_gss}x" != "xnox" ] && [ -z "${tsig_file}" ] && [ -z "${cmd_key}" ]; then
cc_file=`mktemp`
if [ -n "${tsig_gss_keytab}" ] && [ -f "${tsig_gss_keytab}" ] && [ -n "${tsig_gss_principal}" ]; then
kinit -k ${tsig_gss_keytab} -c ${cc_file} ${tsig_gss_principal}
[ $? -ne 0 ] | logger -p daemon.info "dnsupdate: kinit (1) failed" | return 1
cmd_params="${cmd_params} -g"
elif [ -n "${tsig_gss_principal}" ]; then
kinit -k -c ${cc_file} ${tsig_gss_principal}
[ $? -ne 0 ] && logger -p daemon.info "dnsupdate: kinit (2) failed" | return 1
cmd_params="${cmd_params} -g"
else
kinit -k -c ${cc_file}
if [ $? -eq 0 ]; then
cmd_params="${cmd_params} -g"
else
[ "x${tsig_gss}x" == "xyesx" ] && logger -p daemon.info "dnsupdate: kinit (3) failed: ${cc_file}" | return 1
fi
fi
fi
# Should we replace record
if [ "x${replace}x" != "xnox" ]; then
cmd_replace=$(cat <<EOF
${cmd_zone}
${cmd_key}
prereq yxrrset ${rr_name} IN ${type}
update delete ${rr_name} IN ${type}
send
EOF
)
fi
# Runing nsupdate
KRB5CCNAME="FILE:${cc_file}" /usr/bin/nsupdate ${cmd_params} >/dev/null 2>&1 <<EOF
${cmd_server}
${cmd_replace}
${cmd_zone}
${cmd_key}
update add ${rr_name} ${ttl} IN ${type} ${rr_data}
send
EOF
if [ $? -eq 0 ]; then
logger -p daemon.info "dnsupdate: updating: $rr_name $ttl IN $type $rr_data: Successfully"
echo "dnsupdate: updating: $rr_name $ttl IN $type $rr_data: Successfully"
else
logger -p daemon.info "dnsupdate: updating: $rr_name $ttl IN $type $rr_data: Failed"
echo "dnsupdate: updating: $rr_name $ttl IN $type $rr_data: Failed"
fi
# Destroy kerberos credential cache
[ -f "${cc_file}" ] && kdestroy -c ${cc_file}
return 0
}
function check_ip() {
local ips=`nslookup $1 | awk '/^Address: / { print \$2 }'`
local count=`echo $ips | wc -l`
if [ "$3" == "yes" ]; then
[ "$count" -gt "1" ] && return 1
[ "$ips" == "$2" ] && return 1 || return 0
else
[[ $ips =~ $2 ]] && return 1 || return 0
fi
}
function parse_ddns_config() {
local rr_name
local ttl
local type
local rr_data
local replace
local server
local tcp
local zone
local gss_tsig
local gss_keytab
local gss_principal
local tsig_file
local tsig_key_type
local tsig_key_name
local tsig_key_secret
local hostnum=0
local default_hostname=${DHCP_HOSTNAME-${HOSTNAME-$(hostname)}}
local ip_address=${1}
local public_ip=no
[[ ! $ip_address =~ ^192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\. ]] && public_ip=yes
[ $public_ip == "yes" ] && [ "${DDNS}" != "yes" ] && return 0
#
# Update $DDNS_HOSTNAME
#
if [ -n "${DDNS_HOSTNAME}" ] || [ -z "${DDNS0_HOSTNAME}" ] && [ -n "${DDNS_HOSTNAME-${default_hostname}}" ]; then
rr_name=${DDNS_HOSTNAME:-${default_hostname}}
ttl=${DDNS_TTL:-300}
type=${DDNS_TYPE:-A}
rr_data=$ip_address
replace=${DDNS_REPLACE:-yes}
server=${DDNS_SERVER}
tcp=${DDNS_TCP:-no}
zone=${DDNS_ZONE}
gss_tsig=${DDNS_GSS_TSIG}
gss_keytab=${DDNS_GSS_KEYTAB}
gss_principal=${DDNS_GSS_PRINCIPAL}
tsig_file=${DDNS_TSIG_FILE}
tsig_key_type=${DDNS_TSIG_KEY_TYPE}
tsig_key_name=${DDNS_TSIG_KEY_NAME}
tsig_key_secret=${DDNS_TSIG_KEY_SECRET}
echo replace $DDNS_REPLACE
if check_ip "$rr_name" "$rr_data" "$replace"; then
run_nsupdate "${rr_name}" "${ttl}" "${type}" "${rr_data}" "${replace}" "${server}" "${tcp}" "${zone}" "${gss_tsig}" "${gss_keytab}" "${gss_principal}" "${tsig_file}" "${tsig_key_type}" "${tsig_key_name}" "${tsig_key_secret}"
fi
fi
#
# Update DDNS*_HOSTNAME
#
while [ -n "$(eval echo \$$(echo DDNS${hostnum}_HOSTNAME))" ]; do
rr_name=$(eval echo "\${DDNS${hostnum}_HOSTNAME}")
ttl=$(eval echo "\${DDNS${hostnum}_TTL-\${DDNS_TTL:-300}}")
type=$(eval echo "\${DDNS${hostnum}_TYPE-\${DDNS_TYPE:-A}}")
rr_data=$ip_address
replace=$(eval echo "\${DDNS${hostnum}_REPLACE-\${DDNS_REPLACE:-yes}}")
server=$(eval echo "\${DDNS${hostnum}_SERVER-\${DDNS_SERVER}}")
tcp=$(eval echo "\${DDNS${hostnum}_TCP-\${DDNS_TCP:-no}}")
zone=$(eval echo "\${DDNS${hostnum}_ZONE-\${DDNS_ZONE}}")
gss_tsig=$(eval echo "\${DDNS${hostnum}_GSS_TSIG-\${DDNS_GSS_TSIG}}")
gss_keytab=$(eval echo "\${DDNS${hostnum}_GSS_KEYTAB-\${DDNS_GSS_KEYTAB}}")
gss_principal=$(eval echo "\${DDNS${hostnum}_GSS_PRINCIPAL-\${DDNS_GSS_PRINCIPAL}}")
tsig_file=$(eval echo "\${DDNS${hostnum}_TSIG_FILE-\${DDNS_TSIG_FILE}}")
tsig_key_type=$(eval echo "\${DDNS${hostnum}_TSIG_KEY_TYPE-\${DDNS_TSIG_KEY_TYPE}}")
tsig_key_name=$(eval echo "\${DDNS${hostnum}_TSIG_KEY_NAME-\${DDNS_TSIG_KEY_NAME}}")
tsig_key_secret=$(eval echo "\${DDNS${hostnum}_TSIG_KEY_SECRET-\${DDNS_TSIG_KEY_SECRET}}")
if check_ip "$rr_name" "$rr_data" "$replace"; then
run_nsupdate "${rr_name}" "${ttl}" "${type}" "${rr_data}" "${replace}" "${server}" "${tcp}" "${zone}" "${gss_tsig}" "${gss_keytab}" "${gss_principal}" "${tsig_file}" "${tsig_key_type}" "${tsig_key_name}" "${tsig_key_secret}"
fi
(( hostnum++ ))
done
#
# Update PTR record
#
if [ "x${DDNS_PTR}x" != "xnox" ]; then
# Do not update public IP if not forced with DDNS_PTR=yes
[ "x${public_ip}x" == "xyesx" ] && [ -z "${DDNS_PTR+x}" ] && return 0
# Get hostname for PTR update
rr_data=${DDNS_PTR_HOSTNAME-${DDNS_HOSTNAME-${DDNS0_HOSTNAME-${default_hostname}}}}
if [ -n "${rr_data}" ]; then
# Get reverse zone from IP address
local ADDR
IFS='.' read -ra ADDR <<< "$ip_address"
rr_name="${ADDR[3]}.${ADDR[2]}.${ADDR[1]}.${ADDR[0]}.in-addr.arpa"
type="PTR"
server=${DDNS_PTR_SERVER-${DDNS_SERVER}}
tcp=${DDNS_PTR_TCP-${DDNS_TCP:-yes}}
replace="yes"
ttl=${DDNS_PTR_TTL-${DDNS_TTL:=300}}
zone="${ADDR[2]}.${ADDR[1]}.${ADDR[0]}.in-addr.arpa"
gss_tsig=${DDNS_PTR_GSS_TSIG-${DDNS_GSS_TSIG}}
gss_keytab=${DDNS_PTR_GSS_KEYTAB-${DDNS_GSS_KEYTAB}}
gss_principal=${DDNS_PTR_GSS_PRINCIPAL-${DDNS_GSS_PRINCIPAL}}
tsig_file=${DDNS_PTR_TSIG_FILE-${DDNS_TSIG_FILE}}
tsig_key_type=${DDNS_PTR_TSIG_KEY_TYPE-${DDNS_TSIG_KEY_TYPE}}
tsig_key_name=${DDNS_PTR_TSIG_KEY_NAME-${DDNS_TSIG_KEY_NAME}}
tsig_key_secret=${DDNS_PTR_TSIG_KEY_SECRET-${DDNS_TSIG_KEY_SECRET}}
run_nsupdate "${rr_name}" "${ttl}" "${type}" "${rr_data}" "${replace}" "${server}" "${tcp}" "${zone}" "${gss_tsig}" "${gss_keytab}" "${gss_principal}" "${tsig_file}" "${tsig_key_type}" "${tsig_key_name}" "${tsig_key_secret}"
fi
fi
}
function get_all_ifaces() {
echo `ip addr show | sed -nr 's/([0-9]*: )(.*): .*/\2/p'`
return 0
}
function get_iface_ip() {
echo `ip addr show dev ${1} 2>/dev/null | sed -nr 's/.*inet ([^ \/]+).*/\1/p'`
return 0
}
function update_iface() {
local ip_address
[ "x${1}x" == "xlox" ] && return 0
# Unset all DDNS variables except DDNS_DEBUG
local DEBUG=${DDNS_DEBUG}
unset `compgen -v | grep "^DDNS.*"`
DDNS_DEBUG=$DEBUG
# Get address if not supplied
if [ $# -eq 1 ]; then
# Get interface address
ip_address=$(get_iface_ip "${1}")
else
ip_address=${2}
fi
# Skip if no address found
if [ "x${ip_address}x" == "xx" ]; then
return 1
fi
[ -f /etc/sysconfig/network ] && . /etc/sysconfig/network
[ -f /etc/sysconfig/networking/network ] && . /etc/sysconfig/networking/network
# Load interface config
cd /etc/sysconfig/network-scripts
CONFIG="${1}"
need_config ${CONFIG}
source_config >/dev/null 2>&1
if [ "x${DDNS}x" == "xnox" ] ; then
return 0
fi
parse_ddns_config "${ip_address}"
return 0
}
# Show usage if neeaded
for var in "$@"
do
if [ "$var" == "--help" ]; then
cat <<EOF
Usage:
dnsupdate [[interface] [ip]]
--help - Show usage
EOF
fi
done
. /etc/sysconfig/network-scripts/network-functions
. /etc/rc.d/init.d/functions
if [[ $# -eq 1 ]] || [[ $# -eq 2 ]]; then
update_iface "${1}" "${2}"
exit 0
fi
# No parametars - try update all interfaces
if [[ $# -eq 0 ]]; then
for iface in $(get_all_ifaces)
do
update_iface "${iface}"
done
fi

2
dnsupdate.cron Normal file
View File

@@ -0,0 +1,2 @@
# Run dnsupdate every 2 minutes
*/2 * * * * root /usr/bin/dnsupdate > /dev/null 2>&1 || :

63
dnsupdate.spec Normal file
View File

@@ -0,0 +1,63 @@
Summary: Dynamic DNS for ppp and dhclient
Name: dnsupdate
Version: 0.5.2
Release: 1%{?dist}
License: GPLv2+
Group: System Environment/Daemons
URL: http://netst.org/pub/fedora/st/
BuildArch: noarch
Requires: initscripts
Requires: ppp
Requires: bind-utils
Source0: dnsupdate
Source1: dhclient-dnsupdate.sh
Source2: ppp-dnsupdate.sh
Source3: dnsupdate.cron
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
%description
Dynamic DNS for ppp and dhclient.
%install
%{__rm} -rf %{buildroot}
install -dm 755 $RPM_BUILD_ROOT%{_sysconfdir}
install -dm 755 $RPM_BUILD_ROOT%{_sysconfdir}/cron.d
install -dm 755 $RPM_BUILD_ROOT%{_bindir}
install -dm 755 $RPM_BUILD_ROOT%{_sysconfdir}/dhcp/
install -dm 755 $RPM_BUILD_ROOT%{_sysconfdir}/dhcp/dhclient.d
install -dm 755 $RPM_BUILD_ROOT%{_sysconfdir}/ppp
install -dm 755 $RPM_BUILD_ROOT%{_sysconfdir}/ppp/ip-up.d
install -pm 755 %{SOURCE0} $RPM_BUILD_ROOT%{_bindir}/dnsupdate
install -pm 755 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/dhcp/dhclient.d/dnsupdate.sh
install -pm 755 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/ppp/ip-up.d/dnsupdate.sh
install -pm 644 %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/cron.d/dnsupdate
%clean
%{__rm} -rf %{buildroot}
%files
%defattr(-,root,root,-)
%{_bindir}/dnsupdate
%{_sysconfdir}/dhcp/dhclient.d/dnsupdate.sh
%{_sysconfdir}/ppp/ip-up.d/dnsupdate.sh
%{_sysconfdir}/cron.d/dnsupdate
%changelog
* Mon Jul 27 2015 Zoran Pericic <zpericic@netst.org> - 0.5.2-1
- Fix dhcpd script
* Sun Jul 26 2015 Zoran Pericic <zpericic@netst.org> - 0.5.1-1
- Fix cron job and permissions
* Wed Jul 22 2015 Zoran Pericic <zpericic@netst.org> - 0.5.0-1
- Many improvements
* Sun Apr 5 2015 Zoran Pericic <zpericic@netst.org>
- Initial commmit

10
ppp-dnsupdate.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/bash
[ -f "/etc/sysconfig/network-scripts/ifcfg-${6}" ] && . /etc/sysconfig/network-scripts/ifcfg-${6}
if [[ $# -l 6 ]]; then
exit 0
fi
/usr/bin/dnsupdate "${6}" "${4}"