Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3b563228f | ||
|
|
4e375b130c | ||
|
|
24d23012c5 | ||
|
|
edef3c3303 | ||
|
|
b3a4c05001 |
@@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 1.1.0 - 2026-09-05
|
||||
|
||||
### Added
|
||||
|
||||
- Added optional post-update BIND journal synchronization through `rndc sync -clean`.
|
||||
- Added `DYNDNS_RNDC_SERVER`, `DYNDNS_RNDC_KEY`, and `DYNDNS_RNDC_SYNC_CLEAN` configuration parameters.
|
||||
- Added validation for the RNDC synchronization switch and required RNDC settings when synchronization is enabled.
|
||||
- Added conditional runtime validation for the `rndc` command when post-update journal synchronization is enabled.
|
||||
- Added `nsupdate` diagnostic output to the dynDNS log and preservation of failed update instructions for troubleshooting.
|
||||
|
||||
### Changed
|
||||
|
||||
- Separated RFC 2136 update settings from BIND RNDC control settings.
|
||||
- Updated dynamic update processing to target the authoritative DNS listener instead of a non-authoritative localhost resolver view.
|
||||
- Changed the post-update workflow to synchronize accepted dynamic updates into the primary zone file and clean BIND journal files when explicitly enabled.
|
||||
- Made RNDC synchronization failures non-fatal after a successful `nsupdate` transaction, while retaining a warning in the dynDNS log.
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed unsafe DNSSEC handling that attempted to delete the zone `DNSKEY` RRset before dynamic updates.
|
||||
- Removed the unnecessary `rndc freeze` and `rndc thaw` workflow after RFC 2136 updates.
|
||||
|
||||
## 1.0.0 - 2026-06-20
|
||||
|
||||
### Added
|
||||
|
||||
@@ -32,7 +32,7 @@ This repository contains only the backend components of the dynDNS service: the
|
||||
|
||||
1. Clone the repository.
|
||||
2. Copy `vars.example` to a site-specific vars file.
|
||||
3. Adjust paths, database settings, BIND zone settings, and TSIG key references.
|
||||
3. Adjust paths, database settings, BIND zone settings and TSIG key references.
|
||||
4. Make `dyndns.sh` executable.
|
||||
5. Run the script manually once before automation.
|
||||
|
||||
@@ -87,7 +87,7 @@ GRANT ALL PRIVILEGES ON dyndns.* TO 'dyndnsuser'@'127.0.0.1';
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
This setup allows local access for the dedicated dynDNS user from `localhost`, `127.0.0.1`, and `::1`, and keeps the dynDNS backend user restricted to the `dyndns` database and local connections only.
|
||||
This setup allows local access for the dedicated dynDNS user from `localhost`, `127.0.0.1` and `::1` and keeps the dynDNS backend user restricted to the `dyndns` database and local connections only.
|
||||
|
||||
After database initialization, adjust the matching settings in your vars file:
|
||||
|
||||
@@ -262,8 +262,8 @@ See `LICENSE` for details.
|
||||
|
||||
CB-601 - the open tec Elevator
|
||||
|
||||
- Stephan Düsterhaupt ([XMPP](xmpp:me@jabber.stephanduesterhaupt.de))
|
||||
- Ivo Noack aka Insonic ([XMPP](xmpp:me@jabber.ivonoack.de))
|
||||
- [Stephan Düsterhaupt](xmpp:me@jabber.stephanduesterhaupt.de)
|
||||
- [Ivo Noack](xmpp:me@jabber.ivonoack.de) aka Insonic
|
||||
|
||||
## Project Home
|
||||
|
||||
|
||||
@@ -17,9 +17,12 @@
|
||||
# - Validate database connectivity before command execution
|
||||
# - POSIX-compatible operation for cron and service integration
|
||||
|
||||
# Authors: Stephan Düsterhaupt
|
||||
# Authors: Stephan Düsterhaupt, Ivo Noack aka Insonic
|
||||
# Copyright (c) 2018-2026 CB-601 - the open tec Elevator
|
||||
# License: MIT
|
||||
#
|
||||
# Project Home: https://dev.town-square.de/cb601/dyndns
|
||||
#
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -238,6 +241,19 @@ _vars_source_check() {
|
||||
[ -n "$DYNDNS_BIND_ZONE_DIR" ] || _die "DYNDNS_BIND_ZONE_DIR env-var undefined" 5
|
||||
[ -n "$DYNDNS_BIND_ZONE_FILE" ] || _die "DYNDNS_BIND_ZONE_FILE env-var undefined" 5
|
||||
|
||||
case "$DYNDNS_RNDC_SYNC_CLEAN" in
|
||||
0|1)
|
||||
;;
|
||||
*)
|
||||
_die "DYNDNS_RNDC_SYNC_CLEAN must be either 0 or 1" 5
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$DYNDNS_RNDC_SYNC_CLEAN" = "1" ]; then
|
||||
[ -n "$DYNDNS_RNDC_SERVER" ] || _die "DYNDNS_RNDC_SERVER env-var undefined" 5
|
||||
[ -n "$DYNDNS_RNDC_KEY" ] || _die "DYNDNS_RNDC_KEY env-var undefined" 5
|
||||
fi
|
||||
|
||||
_log "Leave the function '_vars_source_check()'..." 1
|
||||
|
||||
return 0
|
||||
@@ -262,12 +278,15 @@ _verify_runtime_init() {
|
||||
|| command -v "$DYNDNS_DB_PROGRAM" >/dev/null 2>&1 \
|
||||
|| _die "Database client '$DYNDNS_DB_PROGRAM' not available. $help_note" 5
|
||||
|
||||
command -v rndc >/dev/null 2>&1 || _die "rndc not available. $help_note" 5
|
||||
command -v sed >/dev/null 2>&1 || _die "sed not available. $help_note" 5
|
||||
command -v grep >/dev/null 2>&1 || _die "grep not available. $help_note" 5
|
||||
command -v awk >/dev/null 2>&1 || _die "awk not available. $help_note" 5
|
||||
command -v nsupdate >/dev/null 2>&1 || _die "nsupdate not available. $help_note" 5
|
||||
|
||||
if [ "$DYNDNS_RNDC_SYNC_CLEAN" = "1" ]; then
|
||||
command -v rndc >/dev/null 2>&1 || _die "rndc not available. $help_note" 5
|
||||
fi
|
||||
|
||||
_log "Leave the function '_verify_runtime_init()'..." 1
|
||||
return 0
|
||||
} #=> _verify_runtime_init()
|
||||
@@ -368,6 +387,16 @@ _vars_setup() {
|
||||
set_var DYNDNS_BIND_ZONE_FILE_SIGNED "$DYNDNS_BIND_ZONE_DIR/$DYNDNS_BIND_ZONE.zone.signed"
|
||||
set_var DYNDNS_BIND_ZONE_TTL 300
|
||||
|
||||
# RNDC post-update zone synchronization defaults
|
||||
#
|
||||
# The RNDC control interface is separate from the authoritative DNS
|
||||
# listener used by nsupdate. Keep the default disabled so existing
|
||||
# installations do not gain a new administrative post-update action
|
||||
# unless it is explicitly enabled in their vars file.
|
||||
set_var DYNDNS_RNDC_SERVER "127.0.0.1"
|
||||
set_var DYNDNS_RNDC_KEY ""
|
||||
set_var DYNDNS_RNDC_SYNC_CLEAN 0
|
||||
|
||||
# Create a per-run temp directory name. The directory itself may be created
|
||||
# lazily later by dyndns_mktemp().
|
||||
if [ -z "$DYNDNS_TEMP_DIR_session" ]; then
|
||||
@@ -398,7 +427,7 @@ set_var() {
|
||||
|
||||
|
||||
# SDuesterhaupt: 2026-06-18 - Write a message to the dynDNS log file.
|
||||
|
||||
#
|
||||
# Severity levels:
|
||||
# 0 -> OFF
|
||||
# 1 -> DEBUG
|
||||
@@ -406,7 +435,7 @@ set_var() {
|
||||
# 3 -> WARNING
|
||||
# 4 -> ERROR
|
||||
# 5 -> CRITICAL
|
||||
|
||||
#
|
||||
# @param1: Log message.
|
||||
# @param2: Severity level.
|
||||
_log() {
|
||||
@@ -444,7 +473,7 @@ _log() {
|
||||
|
||||
|
||||
# SDuesterhaupt: 2026-06-18 - Check whether DYNDNS_MEMBER_HOSTNAME is a valid hostname
|
||||
|
||||
#
|
||||
# Returns:
|
||||
# 0 if valid
|
||||
# 1 if invalid
|
||||
@@ -1294,26 +1323,11 @@ _zone_updates_apply() {
|
||||
return 1
|
||||
}
|
||||
|
||||
_log "Check the zone '$DYNDNS_BIND_ZONE' for DNSSEC capabilities..." 1
|
||||
if [ -f "$DYNDNS_BIND_ZONE_FILE_SIGNED" ]; then
|
||||
_log "The zone '$DYNDNS_BIND_ZONE' uses DNSSEC..." 1
|
||||
zone_uses_dnssec=1
|
||||
else
|
||||
_log "The zone '$DYNDNS_BIND_ZONE' does not use DNSSEC..." 1
|
||||
zone_uses_dnssec=0
|
||||
fi
|
||||
|
||||
{
|
||||
printf 'debug\n'
|
||||
printf 'server %s\n' "$DYNDNS_BIND_SERVER"
|
||||
printf 'zone %s.\n' "$DYNDNS_BIND_ZONE"
|
||||
|
||||
if [ "$zone_uses_dnssec" -eq 1 ]; then
|
||||
printf '; Move %s from secure to insecure temporarily\n' "$DYNDNS_BIND_ZONE_FILE"
|
||||
printf 'update delete %s. DNSKEY\n' "$DYNDNS_BIND_ZONE"
|
||||
printf 'send\n'
|
||||
fi
|
||||
|
||||
awk -F '\t' -v zone_file="$DYNDNS_BIND_ZONE_FILE" '
|
||||
$1 == "del" {
|
||||
del_owner[++del_count] = $2
|
||||
@@ -1372,9 +1386,20 @@ _zone_updates_apply() {
|
||||
|
||||
cp "$nsupdate_file" "$DYNDNS_LOG_UPDATE_FILE" 2>/dev/null || true
|
||||
|
||||
if ! nsupdate -k "$DYNDNS_BIND_ZONE_KEY" "$nsupdate_file" >/dev/null 2>&1; then
|
||||
nsupdate_output=$(nsupdate -d -k "$DYNDNS_BIND_ZONE_KEY" "$nsupdate_file" 2>&1)
|
||||
nsupdate_rc=$?
|
||||
|
||||
if [ "$nsupdate_rc" -ne 0 ]; then
|
||||
{
|
||||
printf '%s\n' "nsupdate output (exit code: $nsupdate_rc):"
|
||||
printf '%s\n' "$nsupdate_output"
|
||||
} >> "$DYNDNS_LOG_FILE"
|
||||
|
||||
cp "$nsupdate_file" \
|
||||
"$DYNDNS_LOG_UPDATE_FILE.failed" 2>/dev/null || true
|
||||
rm -f "$nsupdate_file"
|
||||
_log "Zone updates could not be applied." 4
|
||||
|
||||
_log "Zone updates could not be applied (nsupdate exit code: $nsupdate_rc)." 4
|
||||
_log "Leave the function '_zone_updates_apply()'..." 1
|
||||
return 1
|
||||
fi
|
||||
@@ -1394,20 +1419,22 @@ _zone_updates_apply() {
|
||||
rm -f "$nsupdate_file"
|
||||
_log "Zone updates were applied successfully." 2
|
||||
|
||||
if command -v rndc >/dev/null 2>&1; then
|
||||
if rndc -s "$DYNDNS_BIND_SERVER" -k "$DYNDNS_BIND_ZONE_KEY" freeze "$DYNDNS_BIND_ZONE" >/dev/null 2>&1; then
|
||||
_log "The zone '$DYNDNS_BIND_ZONE' was frozen." 2
|
||||
if rndc -s "$DYNDNS_BIND_SERVER" -k "$DYNDNS_BIND_ZONE_KEY" thaw "$DYNDNS_BIND_ZONE" >/dev/null 2>&1; then
|
||||
_log "The zone '$DYNDNS_BIND_ZONE' was reloaded." 2
|
||||
# Synchronize dynamic zone journal changes into the master zone file.
|
||||
#
|
||||
# BIND keeps successful RFC 2136 updates in the zone journal until a zone dump
|
||||
# occurs. sync -clean writes the active journal state to the master zone file
|
||||
# and removes the journal after a successful synchronization.
|
||||
#
|
||||
# A synchronization failure is intentionally non-fatal: nsupdate has already
|
||||
# succeeded and named keeps the authoritative runtime state in the journal.
|
||||
if [ "$DYNDNS_RNDC_SYNC_CLEAN" = "1" ]; then
|
||||
if rndc \
|
||||
-s "$DYNDNS_RNDC_SERVER" \
|
||||
-k "$DYNDNS_RNDC_KEY" \
|
||||
sync -clean "$DYNDNS_BIND_ZONE" >/dev/null 2>&1; then
|
||||
_log "The zone '$DYNDNS_BIND_ZONE' was synchronized and journals were cleaned." 2
|
||||
else
|
||||
_log "Couldn't reload the zone '$DYNDNS_BIND_ZONE'." 4
|
||||
_log "Leave the function '_zone_updates_apply()'..." 1
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
_log "Couldn't freeze the zone '$DYNDNS_BIND_ZONE'." 4
|
||||
_log "Leave the function '_zone_updates_apply()'..." 1
|
||||
return 1
|
||||
_log "Zone update succeeded, but rndc sync -clean failed for '$DYNDNS_BIND_ZONE'." 3
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
+40
-4
@@ -69,7 +69,7 @@
|
||||
# Database login credentials.
|
||||
# These are mainly used when DYNDNS_SQL_GROUP is unset/empty.
|
||||
#set_var DYNDNS_SQL_USER "dyndns_user"
|
||||
#set_var DYNDNS_SQL_PASS "strong_passphrase"
|
||||
#set_var DYNDNS_SQL_PASS "<REPLACE_WITH_STRONG_PASSWORD>"
|
||||
|
||||
# Additional database client options, if needed.
|
||||
# Example:
|
||||
@@ -81,7 +81,12 @@
|
||||
# DNS / BIND
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# Authoritative DNS server used for update operations
|
||||
# Authoritative DNS server used for RFC 2136 dynamic update operations.
|
||||
#
|
||||
# This address is used by nsupdate on DNS port 53. It must point to the
|
||||
# authoritative BIND listener and matching view serving DYNDNS_BIND_ZONE.
|
||||
#
|
||||
# Do not use a local recursive-only listener or a non-authoritative view.
|
||||
#set_var DYNDNS_BIND_SERVER "127.0.0.1"
|
||||
|
||||
# Service name used when reloading/reconfiguring the name server
|
||||
@@ -90,7 +95,10 @@
|
||||
# DNS zone handled by dynDNS
|
||||
#set_var DYNDNS_BIND_ZONE "example24.com"
|
||||
|
||||
# TSIG key file or key identifier used for nsupdate access
|
||||
# TSIG key file or key identifier used for nsupdate access.
|
||||
#
|
||||
# This key should be restricted in BIND with update-policy and must not be
|
||||
# confused with the RNDC control key configured below.
|
||||
#set_var DYNDNS_BIND_ZONE_KEY "keyfile"
|
||||
|
||||
# Directory containing the primary zone files
|
||||
@@ -105,6 +113,34 @@
|
||||
# Default TTL for generated/managed records
|
||||
#set_var DYNDNS_BIND_ZONE_TTL 300
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# RNDC POST-UPDATE ZONE SYNCHRONIZATION
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# Local BIND control endpoint used for optional post-update synchronization.
|
||||
#
|
||||
# rndc connects to named's control interface, normally TCP port 953.
|
||||
# This is independent from DYNDNS_BIND_SERVER, which is used by nsupdate
|
||||
# against DNS port 53.
|
||||
#set_var DYNDNS_RNDC_SERVER "127.0.0.1"
|
||||
|
||||
# RNDC control key authorized by the named controls {} configuration.
|
||||
#
|
||||
# This key is intentionally separate from DYNDNS_BIND_ZONE_KEY. The latter is
|
||||
# used by nsupdate for RFC 2136 DNS updates, while this key authorizes BIND
|
||||
# administrative operations such as "rndc sync -clean".
|
||||
#set_var DYNDNS_RNDC_KEY "/etc/named/rndc.key"
|
||||
|
||||
# Synchronize dynamic zone journals after a successful nsupdate request.
|
||||
#
|
||||
# 0 = disabled; named handles zone dumps using its normal maintenance schedule.
|
||||
# 1 = execute "rndc sync -clean <zone>" after a successful DNS update.
|
||||
#
|
||||
# A failed synchronization must be logged as a warning only. The dynamic update
|
||||
# remains successful because named retains the authoritative state in its
|
||||
# journal until the next successful zone dump.
|
||||
#set_var DYNDNS_RNDC_SYNC_CLEAN 0
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# MEMBER DEFAULTS
|
||||
# ------------------------------------------------------------------
|
||||
@@ -119,7 +155,7 @@
|
||||
#set_var DYNDNS_MEMBER_EMAIL "admin@example24.com"
|
||||
|
||||
# Password or shared secret used during member creation/authentication
|
||||
#set_var DYNDNS_MEMBER_PASS "strong_passphrase"
|
||||
#set_var DYNDNS_MEMBER_PASS "<REPLACE_WITH_STRONG_PASSWORD>"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# OPTIONAL COMMAND HOOKS
|
||||
|
||||
Reference in New Issue
Block a user