DynDNS mit IONOS API - AAAA Record wird nicht aktualsiert

tiermutter

Well-known member
Moin zusammen,

ich wende mich mal an euch, beim IONOS Support sehe ich nach zwei Tagen nicht, dass dieser etwas taugt und zur Lösung beitragen kann...

Ich habe eine Domain über IONOS und möchte den DynDNS nutzen. Dazu habe ich gem. IONOS Docs (https://www.ionos.de/hilfe/domains/...misches-dns-ddns-einrichten-bei-company-name/) die API freigegeben (Schritt 1) und den DDNS Dienst aktiviert (Schritt 2). Das war soweit auch erfolgreich und ich konnte mir die Update URL entsprechend kopieren.

Nun wird mit der Update URL nur der A Record aktualisiert, laut Docs muss für den AAAA Record &ipv4=<ipaddr>&ipv6=<ip6addr> an den Link angefügt werden.
Leider klappt es damit nicht, es wird nichtmal mehr der A Record aktualisiert. Als DDNS Client habe ich die OPNsense eingerichtet (spiel eigentlich keine Rolle). Außerdem habe ich unter verschiedenen OS versucht die Recors mittels curl zu aktualisieren, dabei bekomme ich aber Syntaxfehler (die Update URL ist samt API Key nicht mehr aktiv):

Linux:
Code:
curl -X GET https://ipv4.api.hosting.ionos.com/dns/v1/dyndns?q=ZjA4ZDdhZTAyM2I5NGY0NDlkNzI4YzA4YjJjYTliMGEuMU50RG8zcjd5SEhBUW5XdVlNQzM0VUIwc0xYNTlDN095ZDhsSXp6YXgtS0pOT2JSYXVOemtEX3RiUHpyUFl0X0VHNTNmUEdHM2RWaWRVVFRReGF0Y1E&ipv4=<ipaddr>&ipv6=<ip6addr>

-bash: syntax error near unexpected token `newline'

Windows:
Code:
curl -X GET https://ipv4.api.hosting.ionos.com/dns/v1/dyndns?q=ZjA4ZDdhZTAyM2I5NGY0NDlkNzI4YzA4YjJjYTliMGEuMU50RG8zcjd5SEhBUW5XdVlNQzM0VUIwc0xYNTlDN095ZDhsSXp6YXgtS0pOT2JSYXVOemtEX3RiUHpyUFl0X0VHNTNmUEdHM2RWaWRVVFRReGF0Y1E&ipv4=<ipaddr>&ipv6=<ip6addr>

">&" kann syntaktisch an dieser Stelle nicht verarbeitet werden.

Code:
curl -X GET https://ipv4.api.hosting.ionos.com/dns/v1/dyndns?q=ZjA4ZDdhZTAyM2I5NGY0NDlkNzI4YzA4YjJjYTliMGEuMU50RG8zcjd5SEhBUW5XdVlNQzM0VUIwc0xYNTlDN095ZDhsSXp6YXgtS0pOT2JSYXVOemtEX3RiUHpyUFl0X0VHNTNmUEdHM2RWaWRVVFRReGF0Y1E&ipv6=<ip6addr>

Syntaxfehler.

Hat jemand eine Idee, was hier falsch ist? Der Support bringt mich nicht weiter... der erste Kollege hat mir den AAAA Record einfach nur eingetragen, auf Nachfrage ob und wie das nun mittels DDNS automatisch funktioniert, wurde ich an das API Team verwiesen. Die ernüchternde Rückmeldung enthielt den "passenden" Artikel zum Thema "Domain mit statischer IP verbinden". Großartig.
 
Hast Du den Bash Befehl mit " versucht, also so:
Code:
 curl -X GET "https://ipv4.api.hosting.ionos.com/dns/v1/dyndns?q=ZjA4ZDdhZTAyM2I5NGY0NDlkNzI4YzA4YjJjYTliMGEuMU50RG8zcjd5SEhBUW5XdVlNQzM0VUIwc0xYNTlDN095ZDhsSXp6YXgtS0pOT2JSYXVOemtEX3RiUHpyUFl0X0VHNTNmUEdHM2RWaWRVVFRReGF0Y1E&ipv4=<ipaddr>&ipv6=<ip6addr>"

Dann erhältst Du zwar nicht mehr die "unexpected token" Meldung, aber ob es hilft, kann ich mangels Zugriff nicht testen. ;).

Bei "unexpected token" fehlt meist irgendwo eine Klammer, ein Anführungszeichen oder sonst ein syntaktischer Ausdruck.

Gruss
 
Spontaner Gedanke dazu, kann es sein dass die Fritzbox die Platzhalter ersetzt, man bei direktem Aufruf mittels curl die Daten aber selber eintragen müsste?
 
Ich kenne das nur mit zwei getrennten HTTP Aufrufen. Also über CRON gesteuert einen für IPv4 und einen für IPv6. Man ruft eine URL auf, identifiziert sich mit einem Token-Hash und es wird die IP der Verbindung genutzt. Daher einmal der Aufruf per 4 und 6 ...

Code:
curl -4 -X GET "https://api.hosting.ionos.com/dns/v1/dyndns?q=ZjA4ZDdhZTAyM2I5NGY0NDlkNzI4YzA4YjJjYTliMGEuMU50RG8zcjd5SEhBUW5XdVlNQzM0VUIwc0xYNTlDN095ZDhsSXp6YXgtS0pOT2JSYXVOemtEX3RiUHpyUFl0X0VHNTNmUEdHM2RWaWRVVFRReGF0Y1E"
curl -6 -X GET "https://api.hosting.ionos.com/dns/v1/dyndns?q=ZjA4ZDdhZTAyM2I5NGY0NDlkNzI4YzA4YjJjYTliMGEuMU50RG8zcjd5SEhBUW5XdVlNQzM0VUIwc0xYNTlDN095ZDhsSXp6YXgtS0pOT2JSYXVOemtEX3RiUHpyUFl0X0VHNTNmUEdHM2RWaWRVVFRReGF0Y1E"
 
Hast Du den Bash Befehl mit " versucht, also so:
Gute Idee... so gibt es zwar keinen Fehler, aber es wird dennoch nichts aktualisiert :(
Spontaner Gedanke dazu, kann es sein dass die Fritzbox die Platzhalter ersetzt, man bei direktem Aufruf mittels curl die Daten aber selber eintragen müsste?
Hm, gut möglich, dass das so nur für die Fritte vorgesehen ist... aber selbst kann man ja schlecht etwas ersetzen, was dynamisch ist... :unsure:
Ich kenne das nur mit zwei getrennten HTTP Aufrufen.
curl -4 oder -6 funktioniert zumindest unter Windows nicht... curl: (7) Couldn't connect to server
Auf der Sense mache ich das zwar nicht mit Cron, aber prinzipiell sind es auch getrennte curl Aufrufe, wobei man in den Einstellungen festlegt, ob es v4 oder v6 ist. Allerdings müsste dadurch auch ohne diesen Zusatz der AAAA Record aktualisiert werden, v6 ist ja schließlich gewählt. So funktioniert das auch bei anderen DDNS Providern... Update URL rein, im DDNS Plugin auswählen ob v4 oder v6 aktualisiert werden soll und fertig.
 
Keine Ahnung wie das bei IONOS läuft, aber theoretisch geht sowas schon in einem einzigen Aufruf... Kommt halt auch darauf an, wie die Gegenseite das verarbeitet...
 
Na dann wollen wir doch alle mal, oder? 🤣 Gib dem Onkel mal eine Minute und dann guckste mal in Deine PNs...
 
Soll ich in meine PNs schauen oder in meine Firewall-Logs und mich auf seinen "Gegenangriff" wappnen?! 😈
 
DU noch dieses uralt CMD.EXE nutzt?! <I'm shocked!>
Klar :)
mit curl -6 kommt es grundsätzlich klar, aber nicht mit dem link dazu.
ch hoffe ich habe Deinen DynDNS nicht gerade aus versehen verbogen. Ich habe nämlich aus versehen und erfolgreich das hier gemacht...
Ne, der Link ist leider nicht mehr aktiv... sonst hätte jetzt ich wenigstens sehen können, dass Du es hinbekommst :D
 
Ok, mit der richtigen URL (die IONOS selbst wohl nicht kennt ;) ) funktioniert der Aufruf wenigstens... Aktualisiert wird aber weiterhin nichts. Jetzt ist eh erstmal Pause, zu viel gespielt:

"message":"API rate limit exceeded"
 
Ich habe das nicht weiter verfolgt und verwende die Domain einfach nicht (nutze ich nur für VPN und da ist es mir relativ egal welche Domain ich verwende)...
 
Ich hatte das gleiche Problem und folgende, funktionierende Lösung (macOS) entwickelt:

Dieses Script trägt erfolgreich die Dynamic DNS records bei IONOS ein:


Code:
#!/bin/bash

# API-Token für IONOS
API_TOKEN="MY_API_TOKEN"

# IPv4-Adresse ermitteln (externe IP)
IPV4=$(curl -s https://api.ipify.org)

# IPv6-Adresse ermitteln (externe IPv6)
IPV6=$(curl -s https://api6.ipify.org)

# Update URL zum Aktualisieren der DDNS-Daten
UPDATEURL="https://ipv4.api.hosting.ionos.com/dns/v1/dyndns?q=$API_TOKEN&ipv4=$IPV4&ipv6=$IPV6"


# Ausgabe der ermittelten Adressen
echo "IPv4: $IPV4"
echo "IPv6: $IPV6"
echo "Update URL: $UPDATEURL"

curl -X GET "$UPDATEURL"


Bei MY_API_TOKEN müsste natürlich der API-Token aus Eurer Update-URL eingetragen werden
Viel Spaß damit
 
Ich habe das gleiche Problem gehabt.
Die URL von IONOS sieht ja erstmal nur SO aus:
https://ipv4.api.hosting.ionos.com/dns/v1/dyndns?q=NTExMWMyMGViMD...
Wird diese URL einfach so aufgerufen, nimmt Ionos die IP, von der dieser Befehl aufgerufen wird.
Man hat da aber keinen Einfluss darauf, ob es zufälligerweise eine IPv4 oder IPV6 Adresse ist.
Man kann aber die URL ergänzen.

Im Falle der Fritzbox ist das dann folgendermaßen:
Die Fritzbox benutzt tatsächlich Variablen für die IP Adressen, die an den DynDNS Anbieter übermittelt werden.
Bei den DynDNS Einstellungen wird eine Update-URL erwartet.
Da gibt man dann folgendes ein:
https://ipv4.api.hosting.ionos.com/dns/v1/dyndns?q=DEINAPITOKEN
Parameter werden mit einem "&"-Zeichen initiiert. Was danach kommt, wird an Ionos übermittelt.
Ionos unterstützt dabei die Variablen ipv4 und ipv6, je nachdem, ob der A oder AAAA Eintrag aktualisiert werden soll. Geht auch beides.
<ipaddr> und <ip6addr> dagegen sind Variablen von der Fritzbox, die sie VOR der Übermittlung automatisch entsprechend auflöst.
Um also über die Fritte IPv4 und IPv6 bei Ionos zu aktualisieren, muss die URL so aussehen:
https://ipv4.api.hosting.ionos.com/dns/v1/dyndns?q=DEINAPITOKEN&ipv4=<ipaddr>&ipv6=<ip6addr>
Die Felder Domainname, Benutzername und Kennwort dürfen bei der Fritzbox nicht leer bleiben, Ionos braucht sie aber nicht,
daher kann und muss da einfach irgendwas eintragen, Hauptsache, nicht leer lassen.

Willste vom PC aus die IP aktualisieren, ist der Befehl etwas anders.
Ich habe z.B. das Problem, dass die Dienste, die ich hoste, nichts von CNAME wissen wollen, die wollen eigene A und AAAA Einträge.
Das heißt, ich habe für jeden zickigen Dienst eine eigene Subdomain eingerichtet.
Via DynDNS API werden sie eigenständig aktualisiert.
Dabei ist natürlich die IPv4 Adresse immer die gleiche vom Router,
die IPv6 dagegen ist die globale vom Reverse Proxy (oder beim TURN-Server die des echten Servers).
Das heißt, ich muss im Update-URL für diese Subdomain 2 verschiedene IP-Adressen angeben:
Die IPv4 des Routers (der dann NAT macht) sowie die globale IPv6 des Reverse Proxy.
Musste mir also ein Updateskript bauen, der regelmäßig die gerade aktuelle IP des Rechners ausliest und der Fritzbox.
Bei Änderungen (neuer Präfix z.B.) erfolgt dann ein Update.
Für denjenigen, der dieses Problem ebenfalls hat, hier das Skript (Powershell, also Windows):

Code:
$FritzBoxIP     = "192.168.171.1"
$RemotePCName   = "PROXY"
$Token          = "MEIN_API_TOKEN"

$ScriptName     = [System.IO.Path]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Name)
$CacheFile      = "$PSScriptRoot\$ScriptName.LastIP.json"
$LogFile        = "$PSScriptRoot\$ScriptName.log"
$MaxLogSizeMB   = 16

# ======================
# Logging Setup
# ======================
function Write-Log {
    param(
        [string]$Message,
        [string]$Level = "INFO"
    )
 
    $Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $LogEntry = "$Timestamp`t$Level`t$Message"
 
    switch ($Level) {
        "ERROR"   { Write-Host $LogEntry -ForegroundColor Red }
        "WARNING" { Write-Host $LogEntry -ForegroundColor Yellow }
        "SUCCESS" { Write-Host $LogEntry -ForegroundColor Green }
        default   { Write-Host $LogEntry }
    }
 
    try {
        $LogEntry | Out-File -FilePath $LogFile -Encoding Default -Append -Force
    }
    catch { }
}

# ======================
# Log-Größe begrenzen
# ======================
function Limit-LogSize {
    param([int]$MaxMB = 16)
    if (Test-Path $LogFile) {
        $LogSizeMB = (Get-Item $LogFile).Length / 1MB
        if ($LogSizeMB -gt $MaxMB) {
            Write-Log "Log-Datei zu groß ($([math]::Round($LogSizeMB,2)) MB) ? wird gekürzt" "WARNING"
            try {
                $Content = Get-Content $LogFile -Tail 600 -Encoding Default
                $Content | Out-File -FilePath $LogFile -Encoding Default -Force
                Write-Log "Log-Datei auf letzte 600 Zeilen gekürzt" "INFO"
            }
            catch { }
        }
    }
}

Limit-LogSize -MaxMB $MaxLogSizeMB
Write-Log "=== Skript gestartet ===" "INFO"

# ======================
# Cache laden
# ======================
$LastIPv4 = $null
$LastIPv6 = $null
if (Test-Path $CacheFile) {
    try {
        $cacheContent = Get-Content $CacheFile -Raw | ConvertFrom-Json
        $LastIPv4 = $cacheContent.IPv4
        $LastIPv6 = $cacheContent.IPv6
        Write-Log "Cache geladen - Letzte IPv4: $LastIPv4 | IPv6: $LastIPv6" "INFO"
    }
    catch {
        Write-Log "Cache konnte nicht gelesen werden" "WARNING"
    }
} else {
    Write-Log "Keine Cache-Datei vorhanden (Erststart)" "INFO"
}

# ======================
# 1. IPv4 von der Fritz!Box
# ======================
$IPv4 = $null
try {
    $URL = "http://$FritzBoxIP`:49000/igdupnp/control/WANIPConn1"
    $SOAPBody = @"
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <u:GetExternalIPAddress xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"/>
  </s:Body>
</s:Envelope>
"@

    $response = Invoke-WebRequest -Uri $URL -Method Post -Body $SOAPBody `
        -ContentType 'text/xml; charset=utf-8' `
        -Headers @{'SOAPAction'='urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress'} `
        -UseBasicParsing -ErrorAction Stop

    [xml]$xml = $response.Content
    $IPv4 = $xml.Envelope.Body.GetExternalIPAddressResponse.NewExternalIPAddress
    Write-Log "IPv4 erfolgreich abgerufen: $IPv4" "INFO"
}
catch {
    Write-Log "Fehler beim Abruf der IPv4: $($_.Exception.Message)" "ERROR"
}

# ======================
# 2. IPv6 vom Proxy
# ======================
$IPv6 = $null
try {
    Write-Log "Starte DNS-Auflösung für $RemotePCName (AAAA)" "INFO"
  
    $RawResult = Resolve-DnsName -Name $RemotePCName -Type AAAA -ErrorAction Stop
  
    # Debug-Ausgabe wie im Original
    Write-Log "Resolve-DnsName lieferte $($RawResult.Count) Ergebnisse" "INFO"
    $RawResult | ForEach-Object {
        Write-Log "   Gefunden: $($_.IPAddress)" "INFO"
    }

    # Dein originaler, funktionierender Filter
    $IPv6List = @(
        $RawResult |
        Where-Object {
            $_.IPAddress -and
            $_.IPAddress -match '^[23][0-9A-Fa-f]{3}:'
        } |
        Select-Object -ExpandProperty IPAddress
    )

    Write-Log "Gefilterte globale IPv6-Adressen: $($IPv6List -join ', ')" "INFO"

    if ($IPv6List.Count -gt 0) {
        $IPv6 = $IPv6List[0]
        Write-Log "IPv6 erfolgreich abgerufen: $IPv6" "INFO"
    }
    else {
        Write-Log "Keine globale IPv6-Adresse gefunden" "WARNING"
    }
}
catch {
    Write-Log "Fehler beim Abruf der IPv6: $($_.Exception.Message)" "ERROR"
}

# ======================
# Änderungsprüfung + IONOS Update
# ======================
$UpdateNeeded = $false

if ($IPv4 -and $IPv4 -ne $LastIPv4) {
    $UpdateNeeded = $true
    Write-Log "IPv4 hat sich geändert: $LastIPv4 -> $IPv4" "SUCCESS"
}
if ($IPv6 -and $IPv6 -ne $LastIPv6) {
    $UpdateNeeded = $true
    Write-Log "IPv6 hat sich geändert: $LastIPv6 -> $IPv6" "SUCCESS"
}

if ($UpdateNeeded -and $IPv4) {
    Write-Log "IP-Änderung erkannt ? Starte IONOS Update" "INFO"
 
    $url = "https://ipv4.api.hosting.ionos.com/dns/v1/dyndns?q=$Token&ipv4=$IPv4&ipv6=$IPv6"
 
    try {
        $curlResult = curl.exe -s -w "`n%{http_code}" -o response.txt "$url"
        $httpCode = ($curlResult -split "`n")[-1].Trim()
        $responseBody = Get-Content "response.txt" -Raw -ErrorAction SilentlyContinue
        Remove-Item "response.txt" -Force -ErrorAction SilentlyContinue

        if ($httpCode -match "^2") {
            Write-Log "IONOS DynDNS erfolgreich aktualisiert (HTTP $httpCode)" "SUCCESS"
        }
        else {
            $errorMsg = if ($responseBody) { $responseBody.Trim() } else { "Keine Antwort" }
            if ($errorMsg -match "rate limit" -or $httpCode -eq "429") {
                Write-Log "RATE LIMIT erreicht!" "WARNING"
            }
            elseif ($errorMsg -match "invalid token|authentication") {
                Write-Log "FEHLER: Token ungültig!" "ERROR"
            }
            else {
                Write-Log "IONOS Update fehlgeschlagen - HTTP $httpCode" "ERROR"
            }
        }
    }
    catch {
        Write-Log "Schwerer Fehler beim IONOS-Update: $($_.Exception.Message)" "ERROR"
    }
}
else {
    Write-Log "Keine IP-Änderung erkannt. Kein Update nötig." "INFO"
}

# ======================
# Cache aktualisieren
# ======================
$cacheObject = @{
    IPv4       = $IPv4
    IPv6       = $IPv6
    LastUpdate = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
    LastRun    = (Get-Date).ToString("o")
} | ConvertTo-Json

$cacheObject | Out-File -FilePath $CacheFile -Encoding UTF8 -Force
Write-Log "Cache-Datei aktualisiert" "INFO"

Write-Log "=== Skript beendet ===" "INFO"

pause

Der PAUSE Befehl am Ende muss natürlich entfernt werden, wenn das über die Aufgabenplanung laufen soll.
Bei mir wird das Skript alle 10 Sekunden ausgeführt, damit ich möglichst wenig Downtime habe, falls die IP wechselt.
Am Ende des Skripts ruft das Skript das nächste auf, so dass alle schön brav NACHEINANDER laufen (separate API Token).
Es wird aber geprüft, ob sich die Adresse auch GEÄNDERT hat, ansonsten wird kein Update gemacht (Gefahr von "API request rate limit exceeded").

Im Übrigen war ich kein Freund davon, für die IP-Ermittlung der Fritzbox einen EXTERNEN Dienst abzufragen.
Wenn man einen VPN benutzt, würde das ohnehin zu Problemen führen.
Ich lese die Fritzbox per uPnP direkt lokal aus. Geht ohne Kennwort.
 
Zuletzt bearbeitet:

Letzte Anleitungen

Statistik des Forums

Themen
8.073
Beiträge
79.545
Mitglieder
8.789
Neuestes Mitglied
eddane
Zurück
Oben