Hausanschlussraum
Benutzer
- Mitglied seit
- 04. Jan 2016
- Beiträge
- 4
- Punkte für Reaktionen
- 1
- Punkte
- 1
Es klappt jetzt: sowohl IPv4 als auch IPv6 werden aktualisiert, wenn sie sich geändert haben, oder wenn ein Monat vergangen ist.
Das basiert auf dem kostenlosen DDNS-Service von nsupdate.info - ich nutze den schon seit 8 Jahren für die Fritzbox und er war immer stabil. Ich weiß gar nicht mehr, wie ich den damals gefunden habe. Jetzt habe ich noch einen zweiten Host hinzugefügt.
Das war mein erstes größeres Bash-Script. Habe doch sehr viel im oben verlinkten Code geändert; er hatte auch noch einige Bugs. Außerdem habe ich noch einige Sicherungen eingefügt. Leider habe ich auch als Root keinen Zugang zu /var/log auf der DS, weshalb das Script im Nutzerverzeichnis läuft und dort auch seine Logs und Dateien ablegt. Falls Ihr Fehler seht, lasst es mich wissen.
Wer es auch nutzen möchte: einfach ganz am Anfang die eigenen Daten bei DOMAIN und TOKEN eintragen. Datei im Adminverzeichnis speichern als "nsupdate.sh". Dann per SSH auf DS einloggen. Datei ausführbar machen mit "chmod +x nsupdate.sh". Und dann per "./nsupdate.sh" ausführen. Oder für Debug-Output als "bash -x nsupdate.sh" ausführen.
Das ganze muss natürlich noch mit crontab regelmäßig laufen; das sollte aber einfach sein (habe es aber noch nicht gemacht).
Nächste Baustelle: Let's Encrypt...
Das basiert auf dem kostenlosen DDNS-Service von nsupdate.info - ich nutze den schon seit 8 Jahren für die Fritzbox und er war immer stabil. Ich weiß gar nicht mehr, wie ich den damals gefunden habe. Jetzt habe ich noch einen zweiten Host hinzugefügt.
Das war mein erstes größeres Bash-Script. Habe doch sehr viel im oben verlinkten Code geändert; er hatte auch noch einige Bugs. Außerdem habe ich noch einige Sicherungen eingefügt. Leider habe ich auch als Root keinen Zugang zu /var/log auf der DS, weshalb das Script im Nutzerverzeichnis läuft und dort auch seine Logs und Dateien ablegt. Falls Ihr Fehler seht, lasst es mich wissen.
Wer es auch nutzen möchte: einfach ganz am Anfang die eigenen Daten bei DOMAIN und TOKEN eintragen. Datei im Adminverzeichnis speichern als "nsupdate.sh". Dann per SSH auf DS einloggen. Datei ausführbar machen mit "chmod +x nsupdate.sh". Und dann per "./nsupdate.sh" ausführen. Oder für Debug-Output als "bash -x nsupdate.sh" ausführen.
Das ganze muss natürlich noch mit crontab regelmäßig laufen; das sollte aber einfach sein (habe es aber noch nicht gemacht).
Nächste Baustelle: Let's Encrypt...
Bash:
#!/usr/bin/env sh
# Based on script from comment in https://gist.github.com/raphiz/837453f189dca966a69c
# Original Author, 2015-06-05: raphiz
# Additional Author in comment, IPv6 adaptation, 2016-09-23: rosch100
# Updated and improved script below, 2023-01-31: Hausanschlussraum
#Add your domain and token from nsupdate.info
DOMAIN="MYDOMAIN.nsupdate.info"
TOKEN="MYSECRET"
#If IP address did not change, only update after the following number of seconds (should be one month to avoid ban)
TIMEBETWEENFORCEDUPDATES="2628000"
#Files to be used - add path if required
LOGFILE='nsupdate.log'
ERRORLOGFILE='nsupdateerror.log'
TEMPFILE='nsupdate.temp'
LASTCONTACTFILE='lastcontactv4.upd'
LASTCONTACTFILEv6='lastcontactv6.upd'
# Functions to check whether returned variables are roughly valid IP addresses to catch empty or error responses
is_ipv4_address() {
[[ $1 =~ [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]]
}
is_ipv6_address() {
[[ $1 =~ ^([0-9a-fA-F]{0,4}:){0,7}[0-9a-fA-F]{1,4}$ ]]
}
# initialise Force Update variable
FORCEUPDATE="FALSE"
FORCEUPDATEv6="FALSE"
# Store current time
CURRENTDATE=$(date --utc +%FT%T.%3N%Z)
CURRENTTIME=$(date +%s)
CURRENTTIMEv6=$(date +%s)
# Evaluate the current remote IPs and the one that is currently registerd
CURRENT=$(curl -s https://ipv4.nsupdate.info/myip)
CURRENTv6=$(curl -s https://ipv6.nsupdate.info/myip)
SAVED=$(python2 -c "import socket; print socket.gethostbyname('$DOMAIN')")
#Fritzbox DNS appears to filter local IPv6 address for some reason in responses; hence, nslookup specifying Google DNS is used instead
#getaddrinfo would be preferred if it works
#SAVEDv6=$(python2 -c "import socket; print socket.getaddrinfo('$DOMAIN', None, socket.AF_INET6)[0][4][0]")
SAVEDv6=$(nslookup -type=AAAA "$DOMAIN" 8.8.8.8 | awk 'NR==6 {print $2}')
# Write the current date, ip and registered ip into the log file
{
echo '----------------------------'
echo "$CURRENTDATE"
echo "The current external IPv4 is: $CURRENT"
echo "The current external IPv6 is: $CURRENTv6"
echo "The following IPv4 is registered: $SAVED"
echo "The following IPv6 is registered: $SAVEDv6"
} >> "$LOGFILE"
# Read in time of last contact (create and fill file with sensible value if missing or empty)
if [ ! -f "$LASTCONTACTFILE" ]; then
touch "$LASTCONTACTFILE"
fi
if [ ! -s "$LASTCONTACTFILE" ]; then
echo -n "1675124740" > "$LASTCONTACTFILE"
fi
LASTCONTACT=$(< "$LASTCONTACTFILE")
# Same for v6
if [ ! -f "$LASTCONTACTFILEv6" ]; then
touch "$LASTCONTACTFILEv6"
fi
if [ ! -s "$LASTCONTACTFILEv6" ]; then
echo -n "1675124740" > "$LASTCONTACTFILEv6"
fi
LASTCONTACTv6=$(< "$LASTCONTACTFILEv6")
# Correct current time to be at least last contact time plus 5 seconds in case of current time problem
if [ $(("$LASTCONTACT")) -gt $(($"CURRENTTIME")) ]; then
$"CURRENTTIME"=$(("$LASTCONTACT"+5))
echo "$CURRENTDATE Warning: current time or time of last IPv4 contact potentially wrong" >> "$ERRORLOGFILE"
fi
# Same for v6
if [ $(("$LASTCONTACTv6")) -gt $(($"CURRENTTIMEv6")) ]; then
$"CURRENTTIMEv6"=$(("$LASTCONTACTv6"+5))
echo "$CURRENTDATE Warning: current time or time of last IPv6 contact potentially wrong" >> "$ERRORLOGFILE"
fi
# If last contact more than the number of seconds defined above ago, set Force Update variable to TRUE
if [ $(("$LASTCONTACT"+"$TIMEBETWEENFORCEDUPDATES")) -lt $(($"CURRENTTIME")) ]; then
FORCEUPDATE="TRUE"
fi
# Same for v6
if [ $(("$LASTCONTACTv6"+"$TIMEBETWEENFORCEDUPDATES")) -lt $(($"CURRENTTIMEv6")) ]; then
FORCEUPDATEv6="TRUE"
fi
# Check if an update is required - if so, update and verify the response
# If more than required time has passed, update anyway
if ! is_ipv4_address "$CURRENT"; then
echo "Warning: The current external IPv4 adress is not valid. Skipping IPv4 update." >> "$LOGFILE"
echo "$CURRENTDATE Warning: The current external IPv4 adress is not valid. Skipping IPv4 update." >> "$ERRORLOGFILE"
elif ! is_ipv4_address "$SAVED"; then
echo "Warning: The saved IPv4 adress is not valid. Skipping IPv4 update." >> "$LOGFILE"
echo "$CURRENTDATE Warning: The saved IPv4 adress is not valid. Skipping IPv4 update." >> "$ERRORLOGFILE"
elif [ "$CURRENT" != "$SAVED" ] || [ "$FORCEUPDATE" = "TRUE" ]; then
echo "updating IPv4..." >> "$LOGFILE"
RESPONSE=$(curl --user "$DOMAIN":"$TOKEN" https://ipv4.nsupdate.info/nic/update)
START=$(python2 -c "print '$RESPONSE'[:5]")
if [ "$START" = "good " ]; then
echo "Update IPv4 succesful!" >> "$LOGFILE"
echo -n "$CURRENTTIME" > "$LASTCONTACTFILE"
elif [ "$START" = "nochg" ]; then
echo "WARNING: IPv4 has not changed but was updated - watch out for client ban" >> "$LOGFILE"
echo "$CURRENTDATE WARNING: IPv4 has not changed but was updated - watch out for client ban" >> "$ERRORLOGFILE"
echo -n "$CURRENTTIME" > "$LASTCONTACTFILE"
else
echo "ERROR: DDNS Server for IPv4 did not respond or response not as expected" >> "$LOGFILE"
echo "$CURRENTDATE ERROR: DDNS Server for IPv4 did not respond or response not as expected" >> "$ERRORLOGFILE"
fi
else
echo 'no IPv4 update required' >> "$LOGFILE"
fi
# Same for IPv6
if ! is_ipv6_address "$CURRENTv6"; then
echo "Warning: The current external IPv6 adress is not valid. Skipping IPv6 update." >> "$LOGFILE"
echo "$CURRENTDATE Warning: The current external IPv6 adress is not valid. Skipping IPv6 update." >> "$ERRORLOGFILE"
elif ! is_ipv6_address "$SAVEDv6"; then
echo "Warning: The saved IPv6 adress is not valid. Skipping IPv6 update." >> "$LOGFILE"
echo "$CURRENTDATE Warning: The saved IPv6 adress is not valid. Skipping IPv6 update." >> "$ERRORLOGFILE"
elif [ "$CURRENTv6" != "$SAVEDv6" ] || [ "$FORCEUPDATEv6" = "TRUE" ]; then
echo "updating IPv6..." >> "$LOGFILE"
RESPONSE=$(curl --user "$DOMAIN":"$TOKEN" https://ipv6.nsupdate.info/nic/update)
START=$(python2 -c "print '$RESPONSE'[:5]")
if [ "$START" = "good " ]; then
echo "Update IPv6 succesful!" >> "$LOGFILE"
echo -n "$CURRENTTIMEv6" > "$LASTCONTACTFILEv6"
elif [ "$START" = "nochg" ]; then
echo "WARNING: IPv6 has not changed but was updated - watch out for client ban" >> "$LOGFILE"
echo "$CURRENTDATE WARNING: IPv6 has not changed but was updated - watch out for client ban" >> "$ERRORLOGFILE"
echo -n "$CURRENTTIMEv6" > "$LASTCONTACTFILEv6"
else
echo "ERROR: DDNS Server for IPv6 did not respond or response not as expected" >> "$LOGFILE"
echo "$CURRENTDATE ERROR: DDNS Server for IPv6 did not respond or response not as expected" >> "$ERRORLOGFILE"
fi
else
echo 'no IPv6 update required' >> "$LOGFILE"
fi
# Keep the log down to 100,000 lines
cp -R "$LOGFILE" "$TEMPFILE"
tail -n 100000 "$TEMPFILE" > "$LOGFILE"
rm "$TEMPFILE"
[/ICODE]