Splits the LAN into four /24 zones: 10.0.0.0/24 static (no DHCP, DNS only), 10.0.1.0/24 fixed DHCP reservations by MAC, 10.0.2.0/24 dynamic DHCP pool, 10.0.3.0/24 spare/unused. ipadm now derives the required subnet from whether a host has a MAC, auto-assigns free IPs, and auto-migrates a host's IP when its MAC is added/removed. Migrated the existing archerc80 reservation from 10.0.0.2 to 10.0.1.2. Also fixes a latent bug found while doing this: dnsmasq's SIGHUP (`systemctl reload`) only re-reads /etc/hosts, not the conf-dir files ipadm writes to, so config changes were silently not applied on reload. ipadm now restarts dnsmasq instead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
7.9 KiB
ipadm
Kleines Go-CLI-Tool zur Verwaltung statischer Hosts (DHCP-Reservierung +
DNS-Eintrag) und WAN→LAN-Port-Forwards für den dnsmasq/nftables-Router auf
narcissus. Ersetzt/lehnt sich an das Original-Tool ipadm (dhcp/bind
management, mwx'2021) an, arbeitet aber gegen unseren dnsmasq/nftables-Stack
statt isc-dhcp-server/bind9 (siehe ../../README.md).
Installiert auf dem Server unter /usr/local/bin/ipadm.
IP-Adressschema
Das LAN ist ein 10.0.0.0/22, aufgeteilt in vier /24-Zonen (Details siehe
../../README.md#ip-adressschema):
10.0.0.0/24— statische Adressen (kein DHCP, nur DNS), für Hosts ohne MAC-Adresse in der ipadm-Datenbank.10.0.1.0/24— feste DHCP-Reservierungen (per MAC), für Hosts mit MAC-Adresse in der ipadm-Datenbank.10.0.2.0/24— dynamischer DHCP-Pool (nicht von ipadm verwaltet).10.0.3.0/24— Reserve, unbenutzt.
ipadm wendet diese Regel bei jeder IP-Zuweisung automatisch an: welches
Subnetz erlaubt ist, entscheidet allein, ob der Host eine MAC-Adresse hat
oder nicht — nicht der Nutzer. Details siehe unten.
Funktionsweise
-
Pflegt eine flache Textdatei
/etc/ipadm/hosts(eine Zeile pro Host:name<TAB>ip<TAB>mac<TAB>comment,macist-wenn nicht gesetzt) als Datenbank für statische Hosts, und/etc/ipadm/portforwards(wanport<TAB>proto<TAB>host<TAB>lanport) für Port-Forwards. Ein Port-Forward referenziert einen Hostnamen aus der Host-Datenbank statt einer festen IP, damit er automatisch der aktuellen IP des Hosts folgt. -
ipadm -ugeneriert daraus zwei Dateien und wendet die zugehörigen Dienste neu an:/etc/dnsmasq.d/hosts.conf(pro Host einhost-record=für DNS, plusdhcp-host=für Hosts mit MAC-Adresse für die DHCP-Reservierung), validiert mitdnsmasq --test, danachsystemctl restart dnsmasq. Bewusstrestart, nichtreload: dnsmasqs SIGHUP-Handler liest nur/etc/hostsneu, nicht dieconf-dir-Dateien, in denenhosts.confliegt — ein reinesreloadwürde die Änderung nicht anwenden./etc/nftables.d/portforward.conf(eine eigenetable inet portforwardmit einerdnat-Regel pro Port-Forward, referenzierte Host-IP wird zum Generierungszeitpunkt aus der Host-DB aufgelöst), validiert mitnft -c -f /etc/nftables.conf(dafür bindet/etc/nftables.confbereitsinclude "/etc/nftables.d/*.conf"ein), danachsystemctl reload nftables(dessenreloadliest die komplette Config neu ein, das ist hier unproblematisch).
Schlägt die jeweilige Validierung fehl, wird die vorherige generierte Datei automatisch wiederhergestellt und der betroffene Dienst nicht neu angewendet. Referenziert ein Port-Forward einen mittlerweile gelöschten Host, wird er beim Generieren übersprungen und als Warnung ausgegeben, statt den ganzen Lauf abzubrechen.
-
IP-Adressen werden bei
-a/-i/im interaktiven Modus geprüft: müssen im zur MAC-Adresse passenden Subnetz liegen (10.0.0.0/24ohne MAC,10.0.1.0/24mit MAC) und dürfen weder die Netz-/Broadcast-Adresse noch die Gateway-Adresse10.0.0.1sein. -
Wird bei
-akeine IP angegeben, vergibtipadmautomatisch die nächste freie IP im passenden Subnetz. -
Wird bei
-meine MAC-Adresse hinzugefügt oder entfernt und der Host liegt dadurch im falschen Subnetz, verschiebtipadmihn automatisch auf eine freie IP im jetzt passenden Subnetz (mit Hinweis in der Ausgabe).-idagegen validiert nur — eine manuell angegebene IP muss bereits zum (unveränderten) MAC-Status des Hosts passen. -
Port-Forwards werden über
(wan-port, protokoll)eindeutig identifiziert;both(= tcp+udp in einer Regel viameta l4proto { tcp, udp }) kollidiert dabei mit einem einzelnentcp- oderudp-Eintrag auf demselben Port.
Usage
ipadm <hostname> add/edit host (interactive)
ipadm -l list hosts
ipadm -a [-f] <hostname> [ip address] [mac address] add host (IP auto-assigned if omitted)
ipadm -c <hostname> <comment> set comment
ipadm -i <hostname> <ip address> change ip address
ipadm -m <hostname> <mac address> change mac address
ipadm -r <old hostname> <new hostname> rename host
ipadm -d <hostname> delete host
ipadm -pa [-f] <hostname> <wan-port> [lan-port] [tcp|udp|both]
add port-forward to a known host
ipadm -pl list port-forwards
ipadm -pd <wan-port> [tcp|udp|both] delete port-forward
ipadm -u update (regenerate dnsmasq+nftables config, reload)
ipadm -h this help
(Output/messages of the tool itself are English; this README stays German like the rest of the repo.)
Beispiele:
ipadm -a webserver # Host ohne MAC anlegen, IP aus 10.0.0.0/24 auto-vergeben
ipadm -a heizung aa:bb:cc:dd:ee:ff # Host mit MAC anlegen, IP aus 10.0.1.0/24 auto-vergeben
ipadm -a fixip 10.0.0.42 # Host mit expliziter IP (muss zum Subnetz passen)
ipadm -pa webserver 443 tcp # WAN-Port 443/tcp -> webserver:443
ipadm -pa webserver 8080 80 tcp # WAN-Port 8080/tcp -> webserver:80
ipadm -u # anwenden (dnsmasq + nftables)
Bei -a sind IP-Adresse und MAC-Adresse optional und in beliebiger
Reihenfolge angebbar — das Tool erkennt selbst, welches Token eine IP und
welches eine MAC ist. Fehlt die IP, wird automatisch die nächste freie IP im
zur MAC passenden Subnetz vergeben.
lan-port und Protokoll bei -pa sind optional und ebenfalls in beliebiger
Reihenfolge angebbar (Default lan-port = wan-port, Default Protokoll
tcp) — das Tool erkennt selbst, ob ein Token eine Portnummer oder
tcp/udp/both ist.
Nach jeder Änderung an der Host- oder Port-Forward-DB (-a, -c, -i,
-m, -r, -d, -pa, -pd, interaktiv) muss ipadm -u ausgeführt
werden, damit dnsmasq/nftables die Änderung tatsächlich übernehmen — das
Tool weist nach jeder Änderung selbst darauf hin.
Bauen / Installieren
cd tools/ipadm
go build -o ipadm .
install -m 0755 -o root -g root ipadm /usr/local/bin/ipadm
Testen ohne die echte Server-Konfiguration anzufassen
Alle Pfade und das IP-Adressschema sind über Umgebungsvariablen überschreibbar:
export IPADM_DB=/tmp/test-hosts
export IPADM_PORTFWD_DB=/tmp/test-portforwards
export IPADM_DNSMASQ_HOSTS=/tmp/test-hosts.conf
export IPADM_NFT_PORTFWD=/tmp/test-portforward.conf
export IPADM_STATIC_CIDR=10.0.0.0/24
export IPADM_RESERVED_CIDR=10.0.1.0/24
export IPADM_GATEWAY_IP=10.0.0.1
export IPADM_WAN_IFACE=enp3s0
./ipadm -a testhost aa:bb:cc:dd:ee:ff
./ipadm -l
Achtung: ipadm -u ruft trotzdem dnsmasq --test bzw.
nft -c -f /etc/nftables.conf auf (prüft die echte System-Konfiguration)
und bei Erfolg systemctl restart dnsmasq/systemctl reload nftables, auch
im Testmodus — das ist beabsichtigt (validiert, dass die generierte Datei
mit der echten Umgebung zusammenspielt), aber es wendet die echten
laufenden Dienste an (inkl. eines kurzen dnsmasq-Neustarts). IPADM_NFT_PORTFWD
nur auf einen Pfad außerhalb von /etc/nftables.d/ zeigen lassen, sonst
landet die Testdatei im echten Include und wird real aktiv.
Änderungshistorie (Kurzfassung)
- v1.2.0 (2026-08-21): LAN auf
10.0.0.0/22erweitert, Subnetz-Zonen eingeführt (IPADM_STATIC_CIDR/IPADM_RESERVED_CIDRstattIPADM_LAN_CIDR/IPADM_POOL_START/IPADM_POOL_END), automatische IP-Vergabe bei-a, automatisches Umziehen bei MAC-Änderung (-m), dnsmasq-Anwendung vonreloadaufrestartkorrigiert (siehe oben). - v1.1.0: Port-Forwarding-Verwaltung (
-pa/-pl/-pd) ergänzt, komplett auf Englisch übersetzt, Hilfetext-Ausrichtung korrigiert.