Mikrotik: Lokale Domain mit Namensauflösung für Clients (FQDN)

Die Namensauflösung von Netzwerkteilnehmern ist bei Mikrotik nicht von Haus aus implementiert. Somit gibt es keine richtige lokale Domain, mit der sich Clients ansprechen lassen. Dennoch liefern die Router alles, was wir benötigen, um für jeden Netzwerkteilnehmer dynamisch einen FQDN (Fully Qualified Domain Name) anzulegen und sie darüber auch im Netzwerk erreichbar zu machen. Dafür nutzen wir ein Script, das zu jedem DHCP-Lease einen statischen DNS-Eintrag anlegt und diesen Eintrag auch von selbst wieder entfernt.

Ich setze in diesem Beitrag voraus, dass euer Router grundsätzlich läuft und mit dem Internet verbunden ist. Damit verbunden gehe ich auch davon aus, dass es einen DHCP-Server bei euch gibt, der seinen Job tut.

Meine Netzwerk-Struktur

Als Router verwende ich ein Mikrotik Routerboard RB2011UAS-RM. Darauf läuft ein DHCP-Server, der allen Netzwerkteilnehmern eine IP-Adresse und den DNS-Server zuweist. Der DNS-Server ist Pi-hole, installiert auf einer virtuellen Maschine mit Debian.

DNS-Anfragen nehmen folgenden Weg: Client -> Pi-hole -> Router -> 8.8.8.8

Als IP-Subnetz verwende ich 192.168.243.0/24, wobei der Router die IP-Adresse .1, und Pi-hole .2 besitzt. Meine lokale Domain soll home.local heißen, sodass mein ioBroker-Server unter dem FQDN srv-iobroker1.home.local erreichbar ist.

Die richtige Domain wählen:
Im Prinzip kann man jeden beliebigen Domain-Namen verwenden, den man möchte. Wenn man also eine private Domain besitzt, die im öffentlichen Internet auch erreichbar ist, z.B. domain.com, dann könnte man Zuhause auch die Domain home.domain.com verwenden. Allerdings ist das nicht ganz ohne, daher nehmen wir hier in diesem Beispiel eine Domain-Endung, die die meisten Systeme als nicht öffentlich klassifizieren: .local.

DNS-Settings

Wir beginnen mit den DNS-Settings im Router. In WinBox navigieren wir zu IP -> DNS und prüfen die Einstellungen.

Mikrotik: DNS-Settings

Mikrotik: DNS-Settings

Relevant sind hier zwei Einstellungen. Unter Servers werden die DNS-Server angegeben, die der Router verwenden soll. Das ist zum einen er selbst (für die lokale Domain) und 8.8.8.8, also der DNS-Server von Google, in dem alle öffentlichen Namen nachgeschlagen werden.

Mit Allow Remote Requests gestatten wir allen Netzwerkteilnehmern, DNS-Anfragen beim Router zu stellen. Das ist auch nötig, da der Router die FQDN aller Netzwerkteilnehmer verwaltet.

Über die Schaltfläche OK schließen wir den Dialog.

DHCP-Server

Im Nächsten Schritt passen wir die Konfiguration des DHCP-Servers an. Dazu navigieren wir in WinBox nach IP -> DHCP-Server -> Networks und öffnen die Einstellungen unseres DHCP-Netzwerks. Hier wird definiert, was die Clients per DHCP zugewiesen bekommen. Unter DNS-Servers tragen wir den Server ein, den die Clients nutzen sollen. In meinem Fall ist das der Pi-hole. Solltet ihr keinen separaten DNS-Server verwenden, sondern möchtet, dass die Clients ihre DNS-Anfragen direkt an den Router stellen, so tragt ihr hier die Router-IP ein. Bei mir wäre das 192.168.243.1.

Mit Domain legen wir die lokale Domain an, die viele Clients auch als Such-Domain anzeigen. Wir nennen sie home.local.

Mikrotik: DHCP-Netzwerk

Mikrotik: DHCP-Netzwerk

Nun gehen wir zu IP -> DHCP-Server -> DHCP und öffnen die Eigenschaften des DHCP-Servers. Im Feld Lease Script tragen wir den Namen des Scripts ein, das wir im nächsten Schritt anlegen werden. Der Name kann frei ausgedacht und gewählt werden.

Mikrotik: DHCP-Server

Mikrotik: DHCP-Server

Lease-Script

Das Lease-Script habe ich im Mikrotik-Forum gefunden und im Prinzip übernimmt es die ganze Arbeit. Unter System -> Scripts legen wir ein neues Script an, geben ihm den Namen, den wir uns gerade ausgedacht haben und kopieren folgenden Code in das Source-Feld:

:local DHCPtag
:set DHCPtag "#DHCP"

:if ( [ :len $leaseActIP ] <= 0 ) do={ :error "empty lease address" }

:if ( $leaseBound = 1 ) do=\
{
    :local ttl
    :local domain
    :local hostname
    :local fqdn
    :local leaseId
    :local comment

    /ip dhcp-server
    :set ttl [ get [ find name=$leaseServerName ] lease-time ]
    network 
    :set domain [ get [ find $leaseActIP in address ] domain ]

    .. lease
    :set leaseId [ find address=$leaseActIP ]

    # Check for multiple active leases for the same IP address. It's weird and it shouldn't be, but just in case.

    :if ( [ :len $leaseId ] != 1) do={
        :log info "DHCP2DNS: not registering domain name for address $leaseActIP because of multiple active leases for $leaseActIP"
        :error "multiple active leases for $leaseActIP"
    }  

    :set hostname [ get $leaseId host-name ]
    :set comment [ get $leaseId comment ]
    /

    :if ( [ :len $hostname ] <= 0 ) do={ :set hostname $comment }

    :if ( [ :len $hostname ] <= 0 ) do={
        :log error "DHCP2DNS: not registering domain name for address $leaseActIP because of empty lease host-name or comment"
        :error "empty lease host-name or comment"
    }
    :if ( [ :len $domain ] <= 0 ) do={
        :log error "DHCP2DNS: not registering domain name for address $leaseActIP because of empty network domain name"
        :error "empty network domain name"
    }

    :set fqdn "$hostname.$domain"

    /ip dns static
    :if ( [ :len [ find name=$fqdn and address=$leaseActIP and disabled=no ] ] = 0 ) do={
        :log info "DHCP2DNS: registering static domain name $fqdn for address $leaseActIP with ttl $ttl"
        add address=$leaseActIP name=$fqdn ttl=$ttl comment=$DHCPtag disabled=no
    } else={
        :log error "DHCP2DNS: not registering domain name $fqdn for address $leaseActIP because of existing active static DNS entry with this name or address"
    }
    /
} else={
    /ip dns static
    :local dnsDhcpId
    :set dnsDhcpId [ find address=$leaseActIP and comment=$DHCPtag ]
    :if ( [ :len $dnsDhcpId ] > 0 ) do={
        :log info "DHCP2DNS: removing static domain name(s) for address $leaseActIP"
        remove $dnsDhcpId
    }
    /
}

Funktionsweise des Scripts:

Das Script erzeugt einen statischen DNS-Eintrag mit dem FQDN, sobald ein DHCP-Lease vergeben wird und entfernt diesen Eintrag wieder, sobald das Lease abläuft. Der Eintrag setzt sich aus zwei Teilen zusammen:

  1. Der Host-Name des Netzwerkteilnehmers. Sollte der leer sein, dann wird der Kommentar des DHCP-Lease-Eintrages (IP -> DHCP-Server -> Leases) genutzt.
  2. Der festgelegten Domain. Bei uns ist das home.local.

Für meinen ioBroker-Server wäre das also srv-iobroker1.home.local.

Für ungültige FQDN wird kein Eintrag angelegt. Ebenso wird keiner angelegt, wenn es die IP-Adresse oder den FQDN schon gibt. Alle durch das Script angelegten Einträge erhalten den Kommentar #DHCP, damit man sie von den manuell angelegten unterscheiden kann. Die Gültigkeitsdauer der DNS-Träge entspricht der der DHCP-Leases (in Standardeinstellungen 1d). Das Script loggt verschiedene Fehler und Informationen mit dem Tag DHCP2DNS.

Mikrotik: Lease-Script

Mikrotik: Lease-Script

Mit OK speichern wir das Script und die Arbeit ist getan.

Ergebnis

Wenn wir alles korrekt eingestellt haben, dann sollten nun statische DNS-Einträge angelegt werden, sobald sich ein Gerät im Netzwerk anmeldet und seine IP-Adresse per DHCP bezieht. Zu sehen sind die Einträge unter IP -> DNS -> Static. Wenn euch das zu lange dauert, bis hier etwas passiert, könnt ihr ja auch mal das Netzwerkkabel eines Gerätes ziehen, oder das WLAN kurz ab- und wieder einschalten.

Mikrotik: statische DNS-Einträge

Mikrotik: statische DNS-Einträge

Die Netzwerkteilnehmer, für die ein statischer DNS-Eintrag angelegt wurde, sind nun unter ihrem FQDN erreichbar. Prüfen kann man das beispielsweise mittels Ping:

Ping per FQDN oder Host-Name

Ping per FQDN oder Host-Name

Wenn euer Computer die Such-Domain richtig übernimmt, werden Hostnamen automatisch zu FQDNs aufgelöst, wie man im Screenshot beim zweiten Ping gut erkennen kann.

Angepasstes Lease-Script

Ich habe das Script nochmal ein wenig angepasst. Einige meiner Netzwerkgeräte haben einfach unmögliche Hostnamen, die sich auch nicht ändern lassen. Andere Hostnamen sind doppelt vorhanden, weil der gleiche China-WiFi-Chip eingebaut ist.

Dieses nun angepasste Script arbeitet genauso, wie das originale, jedoch wird zur Bildung des FQDN zuerst der Kommentar des Leases verwendet. Wenn der leer ist, dann wird der Hostname genutzt. Sollten Sonder- oder Leerzeichen im Kommentar vorhanden sein, so werden die nicht in den FQDN übernommen.

:local DHCPtag
:set DHCPtag "#DHCP"

:if ( [ :len $leaseActIP ] <= 0 ) do={ :error "empty lease address" }

:if ( $leaseBound = 1 ) do={
    :local ttl
    :local domain
    :local hostname
    :local dnsname
    :local fqdn
    :local leaseId
    :local comment
    :local devicename
    :local convert ({})
    :local validChars "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-"

    /ip dhcp-server
    :set ttl [ get [ find name=$leaseServerName ] lease-time ]
    network 
    :set domain [ get [ find $leaseActIP in address ] domain ]

    .. lease
    :set leaseId [ find address=$leaseActIP ]

    # Check for multiple active leases for the same IP address. It's weird and it shouldn't be, but just in case.
    :if ( [ :len $leaseId ] != 1) do={
        :log info "DHCP2DNS: not registering domain name for address $leaseActIP because of multiple active leases for $leaseActIP"
        :error "multiple active leases for $leaseActIP"
    }

    :set hostname [ get $leaseId host-name ]
    :set comment [ get $leaseId comment ]
    /

    # Namen für Gerät ermittlen
    :set devicename $comment
    :if ( [ :len $devicename ] <= 0 ) do={
        :set devicename $hostname
    }

    # Gerätenamen auf ungültige Zeichen prüfen
    :for validCharsIndex from=0 to=([:len $validChars] - 1) do={
        :local validChar [:pick $validChars $validCharsIndex]
        :set ($convert->($validChar)) ($validChar)
    }
    :set ($convert->("_")) ("-")
    :set ($convert->(" ")) ("-")

    :for i from=0 to=([:len $devicename] - 1) do={
        :local char [:pick $devicename $i]
        :local converted ($convert->"$char")
        :local convertedType [:typeof $converted]

        :if ($convertedType = "str") do={
            :set $char $converted
        } else={
            :set $char ""
        }
        :set dnsname ($dnsname.$char)
    }

    # FQDN festlegen
    :if ( [ :len $dnsname ] <= 0 ) do={
        :log error "DHCP2DNS: not registering domain name for address $leaseActIP because of empty lease host-name or comment"
        :error "empty lease host-name or comment"
    }
    :if ( [ :len $domain ] <= 0 ) do={
        :log error "DHCP2DNS: not registering domain name for address $leaseActIP because of empty network domain name"
        :error "empty network domain name"
    }

    :set fqdn "$dnsname.$domain"

    /ip dns static
    :if ( [ :len [ find name=$fqdn and address=$leaseActIP and disabled=no ] ] = 0 ) do={
        :log info "DHCP2DNS: registering static domain name $fqdn for address $leaseActIP with ttl $ttl"
        add address=$leaseActIP name=$fqdn ttl=$ttl comment=$DHCPtag disabled=no
    } else={
        :log error "DHCP2DNS: not registering domain name $fqdn for address $leaseActIP because of existing active static DNS entry with this name or address"
    }
    /
} else={
    /ip dns static
    :local dnsDhcpId
    :set dnsDhcpId [ find address=$leaseActIP and comment=$DHCPtag ]

    :if ( [ :len $dnsDhcpId ] > 0 ) do={
        :log info "DHCP2DNS: removing static domain name(s) for address $leaseActIP"
        remove $dnsDhcpId
    }
    /
}

Sebastian

...ist staatlich geprüfter Techniker für Elektrotechnik, Schwerpunkt Prozessautomatisierung und Energietechnik. Die Themen Automatisierung und Programmierung haben es ihm besonders angetan.
Außerdem ist er für jede technische Spielerei zu haben 😉
Sebastian

4 Comments

  1. Avatar
    Antworten Christia

    Hi Sebastian!
    Vielen Dank für die Anleitung, nach einigen Schwierigkeiten habe ich das nun auch hingekriegt 😀

    Dazu hab ich noch eine Frage:
    Kann ich das Script dahingehend anpassen, dass auch ein Static-Eintrag für nur den Hostnamen anlegen kann? An welchen Stellen müsste ich dein angepasstes Lease-Script ändern?

    Vielen Dank und Grüße!
    Christian

    • Sebastian
      Antworten Sebastian

      Ja, das geht. Aber ob das Ergebnis brauchbar sein wird, weiß ich nicht.

      Im originalen Script musst du:
      – Zeile 9 löschen
      – Zeilen 17 & 18 löschen
      – Zeilen 40-43 löschen
      – auf Zeile 45 .$domain entfernen

      Im zweiten Script sind es die gleichen Einträge, die bearbeitet werden müssen, nur die Zeilennummern sind andere.

      Das ganze habe ich allerdings nicht getestet, weil ja die Suchdomain der Betriebssysteme dafür sorgt, dass ich jedes Gerät auch nur mit dem Hostnamen ansprechen kann und die Domain nicht hinschreiben muss.

  2. Avatar
    Antworten Ardian

    Servus.
    Sauber arbeit Respekt. Eine Frage wie kann ich Mikrotik in Windows Domain Controller Einbinden?
    Danke Voraus.
    Viele Grüße
    Ardian

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.