====== Home-Server ======
===== DynDNS =====
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 [[http://www.telekom.de|Telekom]] oder bei [[http://www.1und1.de|1und1]], dann ist das mit einem [[http://selfhost.de/|DynDNS-Account]] ganz einfach zu realisieren.
Komplizierter wird es, wenn man seinen Internetzugang bei [[http://www.unitymedia.de/|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:
* [[http://selfhost.de/]] - der beste, kann aber kein IPv6
* [[http://spdns.de/]] - kann IPv6
===== ddclient =====
**Achtung: ddclient ist ziemlich buggy, wenn Cloudflare als DNS zum Einsatz kommt, empfehle ich das selbstgeschriebene Skript weiter unten (Stand ddclient 3.9.1)**
* [[https://github.com/ddclient/ddclient]] - originale Konfigurationsvorlage findet man im repo unter dem Namen: **ddclient.conf.in**
* IPv6 und manche DNS Anbieter (z.B. Cloudflare) brauchen noch weitere Abhängigkeiten. Siehe [[https://github.com/ddclient/ddclient#installation|Installation]].
==== Konfigurationsdateien ====
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
=== IPv6 auf der von Debian gepatchten Version (z.B. Ubuntu) ===
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
==== Benutzung ====
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
===== DynDNS-Client selbst gebaut =====
==== Cloudflare ====
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
=== Skript ===
> 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
==== Selfhost ====
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:
- Home-Server mit fester IP im LAN (z.B. 192.168.0.2) konfigurieren, der Server darf keine DHCP-Adresse bekommen, da sich diese u.u. ändern kann;
- in der Horizon-//Box// muss unter ''FORTGESCHRITTEN / Weiterleitung'' eine Port-Weiterleitung eingerichtet werden, z.B.:
* ''| 80 | 192.168.0.2 | 80 | TCP |''
- sinnvoll wäre auch ein Portweiterleitung für den Port 443 aber natürlich nur, wenn man seine Web-Seite SSL-verschlüsselt hat
- jetzt wird ein DynDNS-Zugang benötigt, den kann man u.a. bei [[http://www.selfhost.de|selfhost]] bekommen;
- beim DynDNS-Anbieter eine Umleitung einrichten und das vergebene Passwort merken, man kann sich bei [[http://www.selfhost.de|selfhost]] auch schon eine Update-URL generieren, von der nur die IP entsprechend jedesmal angepasst werden muss;
- beispielsweise sieht das bei [[https://secure.selfhost.de/cgi-bin/selfhost?p=faq&show=59|selfhost]] so aus:
* ''http://3075846:geheim@carol.selfhost.de/nic/update?myip=139.110.183.137''
- man kann es auch automatisieren, dann würde der Kommandozeilenaufruf von Linux aus so aussehen:
* ''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}')''
- die Kommandozeile kann man dann in die ''crontab'' eintragen und einmal am Tag ausführen lassen, damit wäre der selbst gebaute DynDNS-Client fertig;
- **Wichtig ist hierbei noch, dass er nicht zu oft ausgeführt wird, da einige Anbieter nur ein IP-Update pro Tag zulassen!**
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.