Problem: :global cfDdnsToken liest im Skript-Kontext 'nothing', obwohl /system script environment cfDdnsToken gesetzt ist (53 Zeichen, live verifiziert). Fix: /system script environment get statt :global — scope-unabhängig auf ROS 7.24. Skript importiert als tp10-ddns-bf4, Trigger: DHCP-Client client1 (Lease-Event), kein stündlicher Scheduler nötig (Entscheidung 2026-10-03). Recovery-Lücke dokumentiert: GC-Template rendert kein /system script / /system scheduler — Recovery von null hätte Updater nicht. Co-Authored-By: Claude Code <noreply@anthropic.com>
113 lines
5.3 KiB
Plaintext
113 lines
5.3 KiB
Plaintext
# =============================================================================
|
|
# TP10 — Cloudflare-DDNS-Updater fuer bf4.emsenhuber.net
|
|
# =============================================================================
|
|
# Zweck: der WG-Hub-Endpoint der Spokes (fm/dw) ist bf4.emsenhuber.net. Der
|
|
# A-Record muss der Liwest-Public-IP des Core folgen. Heute manuell gepflegt.
|
|
#
|
|
# BASIS: bajodel/mikrotik-cloudflare-dns (MIT, Copyright (c) 2025 bajodel)
|
|
# https://github.com/bajodel/mikrotik-cloudflare-dns
|
|
# Aenderungen ggue. dem Original (Christoph-Entscheid 2026-10-03):
|
|
# 1. IP kommt aus der DHCP-Lease (client1/vlan100), NICHT von Echo-Diensten.
|
|
# Liwest ist die Quelle, kein Dritter; kein Cloudflare im Pfad.
|
|
# 2. check-certificate=yes (Original-Default war false -> Token ungeprueft).
|
|
# 3. Nur EIN Record (bf4), Konfiguration auf das Noetige reduziert.
|
|
#
|
|
# Token: liegt NICHT hier, sondern als globale Script-Variable `cfDdnsToken`.
|
|
# Einmalig setzen per SSH (siehe docs/teilprojekte.md ### TP10).
|
|
#
|
|
# Installation: /import file=tp10-ddns-cf-updater.rsc
|
|
# danach /system scheduler add ... (siehe unten)
|
|
# =============================================================================
|
|
|
|
# ---- Konfiguration ----------------------------------------------------------
|
|
:local DnsRcName "bf4.emsenhuber.net"
|
|
:local DnsZoneID "1b5bc02fdf61b6b989afde543f3f4134" # CF_ZONE_ID aus mcp/cloudflare/.env
|
|
:local DnsRcrdID "dba9d9ec3b261fdb314c0f83e4e62f0d"
|
|
:local RecordTTL "120" # wie der bestehende Record
|
|
:local RecordProxied "false" # WG-Endpoint: NICHT proxied
|
|
:local VerboseLog false
|
|
:local WanDhcpName "client1"
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# Token aus /system script environment holen (NIE im Skriptkopf, NIE per :global).
|
|
# Grund (2026-10-03): :global cfDdnsToken liest im Skript-Kontext "nothing", obwohl
|
|
# /system script environment cfDdnsToken gesetzt ist. CLI-Scope und Skript-Scope sind
|
|
# auf RouterOS 7.24 unterschiedlich. `/system script environment get` ist scope-unabhaengig.
|
|
:do {
|
|
:local tk ""
|
|
:local found [/system script environment find name=cfDdnsToken]
|
|
:if ([:len $found] > 0) do={
|
|
:set tk [/system script environment get [find name=cfDdnsToken] value]
|
|
}
|
|
:if ([:typeof $tk] = "") do={
|
|
:log error "[tp10-ddns] cfDdnsToken nicht gesetzt - Abbruch"
|
|
:error "cfDdnsToken fehlt"
|
|
}
|
|
:global cfDdnsToken
|
|
:set cfDdnsToken $tk
|
|
} on-error={
|
|
:log error "[tp10-ddns] cfDdnsToken nicht lesbar - Abbruch"
|
|
:error "cfDdnsToken fehlt"
|
|
}
|
|
|
|
# ---- WAN-IPv4 aus der DHCP-Lease (Quelle: Liwest, kein Dritter) ------------
|
|
:local CFWanIP4New ""
|
|
:do {
|
|
:local leaseAddr [/ip dhcp-client get [find name=$WanDhcpName] address]
|
|
:if ([:typeof $leaseAddr] != "nothing") do={
|
|
# "90.146.33.177/24" -> "90.146.33.177"
|
|
:local slashPos [:find $leaseAddr "/"]
|
|
:if ($slashPos >= 0) do={
|
|
:set CFWanIP4New [:pick $leaseAddr 0 $slashPos]
|
|
} else={
|
|
:set CFWanIP4New $leaseAddr
|
|
}
|
|
}
|
|
} on-error={
|
|
:log error "[tp10-ddns] DHCP-Lease nicht lesbar ($WanDhcpName)"
|
|
}
|
|
|
|
:if ($CFWanIP4New = "") do={
|
|
:log warning "[tp10-ddns] Keine WAN-IP aus der Lease, naechster Lauf"
|
|
} else={
|
|
|
|
# ---- Guard: nur oeffentliche IPv4 zulassen --------------------------------
|
|
# Faengt den Fall ab, dass DHCP Muell liefert (privat/CGNAT) -> kein Write.
|
|
:local isPrivate false
|
|
:if ([:pick $CFWanIP4New 0 3] = "10.") do={ :set isPrivate true }
|
|
:if ([:pick $CFWanIP4New 0 8] = "192.168.") do={ :set isPrivate true }
|
|
:if ([:pick $CFWanIP4New 0 7] = "172.16.") do={ :set isPrivate true }
|
|
:if ([:pick $CFWanIP4New 0 8] = "100.64.0") do={ :set isPrivate true } # CGNAT 100.64/10
|
|
:if ($isPrivate) do={
|
|
:log error "[tp10-ddns] Lease liefert nicht-oeffentliche IP ($CFWanIP4New) - ABBRUCH, kein Write"
|
|
} else={
|
|
|
|
# ---- Nur bei Abweichung schreiben (Idempotenz) --------------------------
|
|
:global CFWanIP4Cur
|
|
:if ($CFWanIP4New != $CFWanIP4Cur) do={
|
|
:if ($VerboseLog) do={ :log info "[tp10-ddns] WAN-IP: $CFWanIP4Cur -> $CFWanIP4New" }
|
|
|
|
# Kommentar am Record: Zeit + Geraet, wie im Original
|
|
:local ds [/system clock get date]
|
|
:local ts [/system clock get time]
|
|
:local datetime ([:pick $ds 0 4] . "." . [:pick $ds 5 7] . "." . [:pick $ds 8 10] . "-" . [:pick $ts 0 2] . ":" . [:pick $ts 3 5])
|
|
:local CFComment ("$datetime by crs326-core")
|
|
|
|
:local url "https://api.cloudflare.com/client/v4/zones/$DnsZoneID/dns_records/$DnsRcrdID/"
|
|
:do {
|
|
:local res [/tool fetch http-method=put mode=https url=$url check-certificate=yes output=user as-value http-header-field="Authorization: Bearer $cfDdnsToken,Content-Type: application/json" http-data="{\"type\":\"A\",\"name\":\"$DnsRcName\",\"content\":\"$CFWanIP4New\",\"ttl\":$RecordTTL,\"proxied\":$RecordProxied,\"comment\":\"$CFComment\"}"]
|
|
:if (($res->"status") = "finished") do={
|
|
:log warning "[tp10-ddns] $DnsRcName -> $CFWanIP4New aktualisiert"
|
|
:set CFWanIP4Cur $CFWanIP4New
|
|
} else={
|
|
:log error "[tp10-ddns] Update fehlgeschlagen (status != finished)"
|
|
}
|
|
} on-error={
|
|
:log error "[tp10-ddns] Exception beim Cloudflare-Update - naechster Lauf"
|
|
}
|
|
} else={
|
|
:if ($VerboseLog) do={ :log info "[tp10-ddns] WAN-IP unveraendert ($CFWanIP4New)" }
|
|
}
|
|
}
|
|
}
|