Gelegentlich ist es eine gute Idee, einen Server zu Hause einzurichten und ihn dann aus dem Internet erreichbar zu machen. Das nennt sich "Home-Server".
Hat man seinen Internetzugang bei der Telekom oder bei 1und1, dann ist das mit einem DynDNS-Account ganz einfach zu realisieren. Komplizierter wird es, wenn man seinen Internetzugang bei Unitymedia hat.
Mit einem Internetzugang von Unitymedia, bei dem man eine Fritz!Box bekommen hat, benötigt man einen DynDNS-Anbieter, der IPv6 unterstützt.
deutsche DynDNS-Anbieter:
Achtung: ddclient ist ziemlich buggy, wenn Cloudflare als DNS zum Einsatz kommt, empfehle ich das selbstgeschriebene Skript weiter unten (Stand ddclient 3.9.1)
daemon=0 syslog=yes pid=@runstatedir@/ddclient.pid ssl=yes ipv6=no login=E-MAIL password=API-KEY-TOKEN use=cmd, cmd='curl --ipv4 http://checkip.dyndns.org/', cmd-skip='Current IP Address: ' #use=web, web='http://checkip.dyndns.org/', web-skip='Current IP Address: ' protocol=cloudflare, zone=EXAMPLE.COM, ttl=1, EXAMPLE.COM
daemon=0 syslog=yes pid=@runstatedir@/ddclient.pid ssl=yes ipv6=yes login=E-MAIL password=API-KEY-TOKEN use=cmd, cmd='curl --ipv6 http://checkipv6.dyndns.org/', cmd-skip='Current IP Address: ' #use=web, web='http://checkipv6.dyndns.org/', web-skip='Current IP Address: ' protocol=cloudflare, zone=EXAMPLE.COM, ttl=1, EXAMPLE.COM
daemon=0 syslog=yes pid=@runstatedir@/ddclient.pid ssl=yes ipv6=yes login=E-MAIL password=API-KEY-TOKEN ### usev6 only works with debian's patched version in apt repos usev6=if, if='eth0', if-skip='inet6 ' protocol=cloudflare, zone=EXAMPLE.COM, ttl=1, EXAMPLE.COM
Aufruf (IPv4 & IPv6):
ddclient -daemon 0 -file /etc/ddclient/ddclientv4.conf -force && ddclient -daemon 0 -file /etc/ddclient/ddclientv6.conf -force
Debuggen (IPv4 & IPv6)
ddclient -daemon=0 -file /etc/ddclient/ddclientv4.conf -force -debug -noquiet -verbose && ddclient -daemon 0 -file /etc/ddclient/ddclientv6.conf -force -debug -noquiet -verbose
ddclient soll stündlich statt täglich ausgeführt werden
mv /usr/local/etc/periodic/daily/ddclient_force /usr/local/etc/periodic/hourly/
alternativ: nur den einzelnen Befehl in crontab hinzufügen
0 * * * * ddclient -daemon 0 -file /etc/ddclient/ddclientv4.conf -force && ddclient -daemon 0 -file /etc/ddclient/ddclientv6.conf -force
neuste Version auf GitHub: https://github.com/masterflitzer/cloudflare-ddns.git
Abhängigkeiten: links und jq
Cron:
@reboot root cloudflare-ddns.sh > /var/log/cloudflare-ddns.log 2>&1 @hourly root cloudflare-ddns.sh > /var/log/cloudflare-ddns.log 2>&1
> apt install links curl jq
API_TOKEN=1234567893feefc5f0q5000bfo0c38d90bbeb ZONE_NAME=example.com
#!/bin/bash ##### Variables CONFIG_FILE="$(dirname "$0")/$(basename -- "$0" .sh).ini" INTERVAL="5" COUNTER="10" # boolean # if "true" the dns record for the root domain will be updated UPDATE_ROOT_DOMAIN="true" # multiple record names (subdomains) to be updated # separated by space, e.g. "www mail smtp" RECORD_NAME_V4="" RECORD_NAME_V6="" TTL="1" PROXIED="false" # stable base URL for all Version 4 HTTPS endpoints API_ENDPOINT="https://api.cloudflare.com/client/v4" # custom API-Token (not global API-Key) # permissions needed: #dns_records:edit API_TOKEN="$(cat "$CONFIG_FILE" | grep -E "^API_TOKEN=" | head -1 | cut -d "=" -f2)" # when you want to update "www.example.com", "www" is the RECORD_NAME and "example.com" is the ZONE_NAME ZONE_NAME="$(cat "$CONFIG_FILE" | grep -E "^ZONE_NAME=" | head -1 | cut -d "=" -f2)" COUNTER_V4="$COUNTER" COUNTER_V6="$COUNTER" ##### Functions links_IPv4() { IP_V4="$(links -dump http://checkip.dyndns.org/ | tr -s '[ :]' '\n' | egrep '[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+')" #IPv4="1.1.1.1" } links_IPv6() { IP_V6="$(links -dump http://checkipv6.dyndns.org/ | tr -s ' ' '\n' | egrep '[0-9a-f]+[:]+[0-9a-f]+[:]*')" #IPv6="2606:4700:4700::1111" } ##### Script ### Get IPs printf "\n#==============================================================================#\n\n" echo -n "Determining IPv4 address" links_IPv4 while test -z "$IP_V4" -a "$COUNTER_V4" -gt "0" do echo -n '.' COUNTER_V4="$(echo "$COUNTER_V4"|awk '{print $1-1}')" sleep $INTERVAL links_IPv4 done echo echo -n "Determining IPv6 address" links_IPv6 while test -z "$IP_V6" -a "$COUNTER_V6" -gt "0" do echo -n '.' COUNTER_V6="$(echo "$COUNTER_V6"|awk '{print $1-1}')" sleep $INTERVAL links_IPv6 done echo echo "IPv4: $IP_V4" echo "IPv6: $IP_V6" printf "\n#==============================================================================#\n\n" ### Get Zone ID ZONE_ID="$(curl -s -X GET "${API_ENDPOINT}/zones" -H "Authorization: Bearer ${API_TOKEN}" -H "Content-Type: application/json" 2>/dev/null | jq -r ".result[] | select(.name == \"${ZONE_NAME}\") | .id")" ### Get Record ID (IPv4) RECORD_ID_V4="$(curl -s -X GET "${API_ENDPOINT}/zones/${ZONE_ID}/dns_records" -H "Authorization: Bearer ${API_TOKEN}" -H "Content-Type: application/json" 2>/dev/null | jq -r ".result[] | select((.name == \"${ZONE_NAME}\") and (.type == \"A\")) | .id")" ### Get Record ID (IPv6) RECORD_ID_V6="$(curl -s -X GET "${API_ENDPOINT}/zones/${ZONE_ID}/dns_records" -H "Authorization: Bearer ${API_TOKEN}" -H "Content-Type: application/json" 2>/dev/null | jq -r ".result[] | select((.name == \"${ZONE_NAME}\") and (.type == \"AAAA\")) | .id")" echo "Record Name = $ZONE_NAME" echo "ZONE_ID = $ZONE_ID" echo "Record ID (IPv4) = $RECORD_ID_V4" echo "Record ID (IPv6) = $RECORD_ID_V6" ### Set IP printf "\n#==============================================================================#\n\n" if test $UPDATE_ROOT_DOMAIN == "true" then echo "IPv4: Updating DNS Record to '$IP_V4'" curl -s -X PUT "${API_ENDPOINT}/zones/${ZONE_ID}/dns_records/${RECORD_ID_V4}" -H "Authorization: Bearer ${API_TOKEN}" -H "Content-Type: application/json" --data "{\"type\":\"A\",\"name\":\"${ZONE_NAME}\",\"content\":\"${IP_V4}\",\"ttl\":${TTL},\"proxied\":${PROXIED}}"; echo printf "\n#------------------------------------------------------------------------------#\n\n" echo "IPv6: Updating DNS Record to '$IP_V6'" curl -s -X PUT "${API_ENDPOINT}/zones/${ZONE_ID}/dns_records/${RECORD_ID_V6}" -H "Authorization: Bearer ${API_TOKEN}" -H "Content-Type: application/json" --data "{\"type\":\"AAAA\",\"name\":\"${ZONE_NAME}\",\"content\":\"${IP_V6}\",\"ttl\":${TTL},\"proxied\":${PROXIED}}"; echo fi ### Set IP for Record Names printf "\n#==============================================================================#\n\n" if test ! -z "${RECORD_NAME_V4// }"; then printf "IPv4: Subdomains\n\n"; fi COUNTER="0" for RECORD_NAME in $RECORD_NAME_V4 do if test $COUNTER -gt 0; then printf "\n#------------------------------------------------------------------------------#\n\n"; fi RECORD_ID="$(curl -s -X GET "${API_ENDPOINT}/zones/${ZONE_ID}/dns_records" -H "Authorization: Bearer ${API_TOKEN}" -H "Content-Type: application/json" 2>/dev/null | jq -r ".result[] | select((.name == \"${RECORD_NAME}.${ZONE_NAME}\") and (.type == \"A\")) | .id")" echo "Record Name = $RECORD_NAME.$ZONE_NAME" echo "Record ID = $RECORD_ID" echo "Updating DNS Record to '$IP_V4'" curl -s -X PUT "${API_ENDPOINT}/zones/${ZONE_ID}/dns_records/${RECORD_ID}" -H "Authorization: Bearer ${API_TOKEN}" -H "Content-Type: application/json" --data "{\"type\":\"A\",\"name\":\"${RECORD_NAME}.${ZONE_NAME}\",\"content\":\"${IP_V4}\",\"ttl\":${TTL},\"proxied\":${PROXIED}}"; echo let "COUNTER += 1" done if test $COUNTER -gt 0; then printf "#==============================================================================#\n\n" fi if test ! -z "${RECORD_NAME_V6// }"; then printf "IPv6: Subdomains\n\n"; fi COUNTER="0" for RECORD_NAME in $RECORD_NAME_V6 do if test $COUNTER -gt 0; then printf "\n#------------------------------------------------------------------------------#\n\n"; fi RECORD_ID="$(curl -s -X GET "${API_ENDPOINT}/zones/${ZONE_ID}/dns_records" -H "Authorization: Bearer ${API_TOKEN}" -H "Content-Type: application/json" 2>/dev/null | jq -r ".result[] | select((.name == \"${RECORD_NAME}.${ZONE_NAME}\") and (.type == \"AAAA\")) | .id")" echo "Record Name = $RECORD_NAME.$ZONE_NAME" echo "Record ID = $RECORD_ID" echo "Updating DNS Record to '${IP_V6}'" curl -s -X PUT "${API_ENDPOINT}/zones/${ZONE_ID}/dns_records/${RECORD_ID}" -H "Authorization: Bearer ${API_TOKEN}" -H "Content-Type: application/json" --data "{\"type\":\"AAAA\",\"name\":\"${RECORD_NAME}.${ZONE_NAME}\",\"content\":\"${IP_V6}\",\"ttl\":${TTL},\"proxied\":${PROXIED}}"; echo let "COUNTER += 1" done if test $COUNTER -gt 0; then printf "#==============================================================================#\n\n" fi
Wird dagegen der Internetzugang per Horizon-Box bereitgestellt, dann kann man dort keinen DynDNS-Account eintragen und muss sich einen DynDNS-Client selber bauen.
hierfür sind folgende Schritte abzuarbeiten:
FORTGESCHRITTEN / Weiterleitung eine Port-Weiterleitung eingerichtet werden, z.B.:| 80 | 192.168.0.2 | 80 | TCP |links -dump http://3075846:geheim@carol.selfhost.de/nic/update?myip=$(links -dump http://www.meine-aktuelle-ip.de/ | awk '/Ihre aktuelle IP Adresse:/{print $NF}')crontab eintragen und einmal am Tag ausführen lassen, damit wäre der selbst gebaute DynDNS-Client fertig;hier noch ein paar alternative Kommandozeilenaufrufe für Linux, die theoretisch alle das gleiche bewirken sollten:
links -dump http://3075846:geheim@carol.selfhost.de/nic/update?myip=$(links -dump http://www.ip-secrets.info/ | awk '/Ihre aktuelle IP-Adresse:/{print $NF}')
links -dump http://3075846:geheim@carol.selfhost.de/nic/update?myip=$(links -dump http://www.wieistmeineip.de/ | sed -n '/Ihre IP-Adresse lautet:/,/[0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*/p' | awk '/[0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*/{print $NF}')
links -dump http://3075846:geheim@carol.selfhost.de/nic/update?myip=$(links -dump http://www.meine-aktuelle-ip.de/ | awk '/Ihre aktuelle IP Adresse:/{print $NF}')
links -dump http://3075846:geheim@carol.selfhost.de/nic/update?myip=$(links -dump http://www.meineip.de/ | sed -n '/Meine IP-Adresse lautet:/,/[0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*/p' | awk '/[0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*/{print $NF}')
links -dump http://3075846:geheim@carol.selfhost.de/nic/update?myip=$(links -dump http://meineipadresse.de/ | fgrep 'Meine o:ffentliche' | tr -s ' ' '\n' | awk '/[0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*/{print $NF}')
links -dump http://3075846:geheim@carol.selfhost.de/nic/update?myip=$(links -dump http://www.heise.de/netze/tools/meine-ip-adresse/ | awk '/Ihre Anfrage kommt von der IP-Adresse:/{print $NF}')
Statt "3075846" und "geheim" sind die eigenen Zugangsdaten für den DynDNS-Account anzugeben.
Und nicht vergessen!
Es muss unbedingt der PATH angegeben werden, denn sonst kann der CRON-Dienst das Programm links nicht finden.
Da diese Kommandos mit Linux und FreeBSD funktionieren sollen, kann ich hier den absoluten Pfad nicht angeben. Denn der links-Pfad ist bei Linux und FreeBSD unterschiedlich.