# 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](../../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](../../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: `nameipmaccomment`, `mac` ist `-` wenn nicht gesetzt) als Datenbank für statische Hosts, und `/etc/ipadm/portforwards` (`wanportprotohostlanport`) 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 -u` generiert daraus zwei Dateien und wendet die zugehörigen Dienste neu an: - `/etc/dnsmasq.d/hosts.conf` (pro Host ein `host-record=` für DNS, plus `dhcp-host=` für Hosts mit MAC-Adresse für die DHCP-Reservierung), validiert mit `dnsmasq --test`, danach `systemctl restart dnsmasq`. **Bewusst `restart`, nicht `reload`**: dnsmasqs SIGHUP-Handler liest nur `/etc/hosts` neu, nicht die `conf-dir`-Dateien, in denen `hosts.conf` liegt — ein reines `reload` würde die Änderung nicht anwenden. - `/etc/nftables.d/portforward.conf` (eine eigene `table inet portforward` mit einer `dnat`-Regel pro Port-Forward, referenzierte Host-IP wird zum Generierungszeitpunkt aus der Host-DB aufgelöst), validiert mit `nft -c -f /etc/nftables.conf` (dafür bindet `/etc/nftables.conf` bereits `include "/etc/nftables.d/*.conf"` ein), danach `systemctl reload nftables` (dessen `reload` liest 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/24` ohne MAC, `10.0.1.0/24` mit MAC) und dürfen weder die Netz-/Broadcast-Adresse noch die Gateway-Adresse `10.0.0.1` sein. - Wird bei `-a` keine IP angegeben, vergibt `ipadm` automatisch die nächste freie IP im passenden Subnetz. - Wird bei `-m` eine MAC-Adresse hinzugefügt oder entfernt und der Host liegt dadurch im falschen Subnetz, verschiebt `ipadm` ihn automatisch auf eine freie IP im jetzt passenden Subnetz (mit Hinweis in der Ausgabe). `-i` dagegen 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 via `meta l4proto { tcp, udp }`) kollidiert dabei mit einem einzelnen `tcp`- oder `udp`-Eintrag auf demselben Port. ## Usage ``` ipadm add/edit host (interactive) ipadm -l list hosts ipadm -a [-f] [ip address] [mac address] add host (IP auto-assigned if omitted) ipadm -c set comment ipadm -i change ip address ipadm -m change mac address ipadm -r rename host ipadm -d delete host ipadm -pa [-f] [lan-port] [tcp|udp|both] add port-forward to a known host ipadm -pl list port-forwards ipadm -pd [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: ```sh 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 ```sh 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: ```sh 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/22` erweitert, Subnetz-Zonen eingeführt (`IPADM_STATIC_CIDR`/`IPADM_RESERVED_CIDR` statt `IPADM_LAN_CIDR`/`IPADM_POOL_START`/`IPADM_POOL_END`), automatische IP-Vergabe bei `-a`, automatisches Umziehen bei MAC-Änderung (`-m`), dnsmasq-Anwendung von `reload` auf `restart` korrigiert (siehe oben). - **v1.1.0**: Port-Forwarding-Verwaltung (`-pa`/`-pl`/`-pd`) ergänzt, komplett auf Englisch übersetzt, Hilfetext-Ausrichtung korrigiert.