Files
mikeandClaude Sonnet 5 ae415b17b4 Document the sulaco DB copy and netatmocollect/fuw cron hand-off
Separate from the router README since it's not part of narcissus's
router role — it's a copy of the user's personal sulaco server's
databases plus two cron scripts moved over, kept here anyway since
it's simpler than a second repo.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-21 11:10:34 +02:00

326 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# narcissus – Router-Konfiguration
Dieses Repo dokumentiert die Router-Konfiguration des Servers **narcissus**
(narcissus.fhi.mpg.de). Der Server hat zwei Netzwerkinterfaces und übernimmt
für ein kleines internes Netz die Rollen **Router, Default-Gateway,
Nameserver und DHCP-Server**.
Die Dateien unter [`config/`](config/) sind 1:1-Kopien der aktiven
Konfiguration auf dem Server (Stand: siehe Git-Log). Das Repo ist reine
**Dokumentation/Backup** – es gibt kein automatisches Deployment. Änderungen
müssen manuell auf dem Server vorgenommen werden (siehe unten) und sollten
danach hier eingecheckt werden, damit Doku und Realität übereinstimmen.
Statische Host-Einträge (feste IP/DHCP-Reservierung + DNS-Name) werden nicht
mehr von Hand in `dnsmasq.d` gepflegt, sondern über das Tool
[`ipadm`](tools/ipadm/) (`/usr/local/bin/ipadm` auf narcissus), siehe
[tools/ipadm/README.md](tools/ipadm/README.md).
Zusätzlich läuft auf narcissus eine (nicht zur Router-Rolle gehörende)
Kopie von Datenbanken des Servers *sulaco* plus zwei dorthin umgezogene
Cronjobs — siehe [SULACO.md](SULACO.md).
## Netzwerk-Topologie
```
Internet
│
enp3s0 (WAN, öffentlich)
141.14.140.128/20
Gateway: 141.14.128.128
│
┌─────────────────────┐
│ narcissus (Router) │
│ ip_forward=1, NAT │
└─────────────────────┘
│
enp7s0 (LAN)
10.0.0.1/22
│
┌───────────────┼───────────────┬───────────────┐
│ │ │ │
10.0.0.0/24 10.0.1.0/24 10.0.2.0/24 10.0.3.0/24
statisch DHCP-Reserv. dynamischer Reserve
(kein DHCP, (per MAC, DHCP-Pool (unbenutzt)
nur DNS) via ipadm) .10–.250
```
- **WAN**: `enp3s0`, statische öffentliche IP, unverändert wie vorher.
- **LAN**: `enp7s0`, `10.0.0.1/22` (seit 2026-08-21, davor `/24`), Router =
Gateway = DNS für alle Clients im Netz. Details zur Aufteilung in vier
`/24`-Zonen siehe [IP-Adressschema](#ip-adressschema) unten.
## IP-Adressschema
Das LAN ist ein `10.0.0.0/22` (Netzmaske `255.255.252.0`, Adressen
`10.0.0.0`–`10.0.3.255`), aufgeteilt in vier gleich große `/24`-Zonen mit
klar getrennten Zwecken:
| Subnetz | Zweck | Vergabe |
|---|---|---|
| `10.0.0.0/24` | **Statische Adressen** — Geräte, die ihre IP selbst fest eingestellt haben (kein DHCP), bekommen hier nur einen DNS-Eintrag | `ipadm -a <name>` (ohne MAC) |
| `10.0.1.0/24` | **Feste DHCP-Reservierungen** — Geräte, die per DHCP immer dieselbe IP bekommen sollen | `ipadm -a <name> <mac>` |
| `10.0.2.0/24` | **Dynamischer DHCP-Pool** — alle anderen Clients (Laptops, Handys, Gäste) | automatisch von dnsmasq, Bereich `.10`–`.250` |
| `10.0.3.0/24` | **Reserve** — aktuell nicht konfiguriert/genutzt | – |
`10.0.0.1` (Router/Gateway) ist über das gesamte `/22` hinweg reserviert und
kann keinem Host zugewiesen werden.
Das Tool [`ipadm`](tools/ipadm/) kennt diese Regel und wendet sie automatisch
an: Hosts **ohne** MAC-Adresse landen in `10.0.0.0/24`, Hosts **mit**
MAC-Adresse in `10.0.1.0/24`. Die IP wird beim Anlegen automatisch aus dem
passenden Subnetz vergeben, wenn keine explizit angegeben wird; wird
nachträglich eine MAC-Adresse hinzugefügt/entfernt (`ipadm -m`), verschiebt
`ipadm` den Host automatisch in eine freie IP des jetzt passenden Subnetzes.
Details siehe [tools/ipadm/README.md](tools/ipadm/README.md).
Technisch ist das weiterhin **ein** LAN (eine Broadcast-Domain, ein
Interface, eine Netzmaske `/22`) — die vier `/24`-Zonen sind reine
Adress-Konventionen, keine getrennten physischen/VLAN-Netze. dnsmasq braucht
dafür nur einen `dhcp-range` für den dynamischen Pool
(`10.0.2.10,10.0.2.250,255.255.252.0`); `dhcp-host`-Reservierungen außerhalb
dieses Bereichs (z.B. in `10.0.1.0/24`) funktioniert trotzdem, solange sie im
selben `/22` liegen.
## Was wurde eingerichtet
| Bereich | Was | Datei auf dem Server | Kopie in diesem Repo |
|---|---|---|---|
| LAN-Interface | `enp7s0` statisch auf `10.0.0.1/22` | `/etc/network/interfaces` | [`config/network-interfaces`](config/network-interfaces) |
| IP-Forwarding | `net.ipv4.ip_forward=1`, persistent über Reboot | `/etc/sysctl.d/99-router-forwarding.conf` | [`config/sysctl.d/99-router-forwarding.conf`](config/sysctl.d/99-router-forwarding.conf) |
| NAT | Masquerading `10.0.0.0/22` → raus über `enp3s0` | `/etc/nftables.conf` | [`config/nftables.conf`](config/nftables.conf) |
| Port-Forwarding-Include | `/etc/nftables.conf` bindet `/etc/nftables.d/*.conf` ein (dort generiert `ipadm` die Port-Forward-Regeln) | `/etc/nftables.conf` (Zeile am Ende) | [`config/nftables.conf`](config/nftables.conf) |
| DHCP + DNS | dnsmasq: DHCP-Pool, Gateway/DNS-Option, DNS-Forwarding | `/etc/dnsmasq.d/lan.conf` | [`config/dnsmasq.d/lan.conf`](config/dnsmasq.d/lan.conf) |
| DNS-Includes aktiviert | eine Zeile in `/etc/dnsmasq.conf` einkommentiert: `conf-dir=/etc/dnsmasq.d/,*.conf` | `/etc/dnsmasq.conf` | – (Rest der Datei ist Debian-Standard, nicht gespiegelt) |
| DHCP-Logging | `log-dhcp` aktiviert (zeigt DHCPDISCOVER/OFFER/REQUEST/ACK/NAK in `journalctl -u dnsmasq`) — war entscheidend, um am 2026-08-19 einen rogue DHCP-Server im LAN zu finden | `/etc/dnsmasq.d/90-logging.conf` | [`config/dnsmasq.d/90-logging.conf`](config/dnsmasq.d/90-logging.conf) |
| Statische Hosts (DHCP-Reservierung + DNS) | von `ipadm` generiert, **nicht** von Hand editieren | `/etc/dnsmasq.d/hosts.conf` (generiert) + `/etc/ipadm/hosts` (Datenbank) | – (live Daten, siehe [`tools/ipadm/`](tools/ipadm/)) |
| Port-Forwards (WAN → LAN-Host) | von `ipadm` generiert, **nicht** von Hand editieren | `/etc/nftables.d/portforward.conf` (generiert) + `/etc/ipadm/portforwards` (Datenbank) | – (live Daten, siehe [`tools/ipadm/`](tools/ipadm/)) |
| dnsmasq-Resilienz | `Restart=on-failure` (Default war `no`), damit dnsmasq bei einem Boot-Race mit `enp7s0` nicht dauerhaft tot bleibt | `/etc/systemd/system/dnsmasq.service.d/override.conf` | [`config/systemd/dnsmasq.service.d/override.conf`](config/systemd/dnsmasq.service.d/override.conf) |
| SSH-Port | von `22` auf `2234` verlegt (Konvention wie sulaco), Port `22` lauscht gar nicht mehr | `/etc/ssh/sshd_config.d/port.conf` | [`config/ssh/sshd_config.d/port.conf`](config/ssh/sshd_config.d/port.conf) |
Installiertes Paket: `dnsmasq` (übernimmt sowohl DHCP- als auch
DNS-Server-Rolle). `nftables` war bereits installiert, wurde aber aktiviert
(`systemctl enable --now nftables`).
### Details zur dnsmasq-Konfiguration (`config/dnsmasq.d/lan.conf`)
- `interface=enp7s0` + `bind-interfaces` + `except-interface=enp3s0`:
dnsmasq lauscht **ausschließlich** auf dem LAN-Interface. Das ist absichtlich
so restriktiv, damit auf der öffentlichen WAN-Seite kein offener
DNS-Resolver/DHCP-Server erreichbar ist (Missbrauchsrisiko, z.B.
DNS-Amplification).
- `dhcp-range=10.0.2.10,10.0.2.250,255.255.252.0,12h`: dynamischer DHCP-Pool
in `10.0.2.0/24`, 12h Lease. Die Netzmaske `255.255.252.0` (`/22`) sagt
dnsmasq, dass das gesamte LAN ein einziges `/22`-Netz ist — siehe
[IP-Adressschema](#ip-adressschema).
- `dhcp-option=option:router,10.0.0.1` / `dhcp-option=option:dns-server,10.0.0.1`:
Clients bekommen den Router selbst als Gateway und als DNS-Server.
- `domain=fhi.mpg.de` / `server=141.14.128.1` / `no-resolv`: DNS-Anfragen aus
dem LAN werden an den institutseigenen DNS-Server weitergeleitet (gleicher
Resolver wie auf der WAN-Seite), interne `fhi.mpg.de`-Hosts bleiben
auflösbar. `no-resolv` verhindert, dass dnsmasq zusätzlich `/etc/resolv.conf`
als Upstream-Quelle einliest (Eindeutigkeit).
### Details zur nftables-Konfiguration (`config/nftables.conf`)
- `table inet filter`: unverändert (keine Regeln, Policy `accept` auf
`input`/`forward`/`output`) – **die WAN-Seite wurde bewusst nicht
gehärtet/eingeschränkt**, um die bestehende Erreichbarkeit des Servers
nicht zu verändern.
- `table inet nat` / `chain postrouting`: NAT-Masquerading für Traffic aus
`10.0.0.0/22`, der über `enp3s0` rausgeht. Das ist die einzige Regel, die
tatsächlich nötig ist, damit LAN-Clients ins Internet kommen.
## Konfiguration anpassen
Alle Änderungen werden direkt auf dem Server in den Dateien unter `/etc/...`
gemacht (Pfade siehe Tabelle oben), dann der jeweilige Dienst neu geladen
(siehe Befehle unten). Bitte die Änderung danach auch hier ins Repo
übernehmen (Datei in `config/` anpassen + committen), damit die Doku aktuell
bleibt.
### DHCP-Pool / Lease-Zeit ändern
Der dynamische Pool liegt in `10.0.2.0/24`. In `/etc/dnsmasq.d/lan.conf` die
Zeile anpassen, z.B. größerer Pool oder andere Lease-Zeit:
```
dhcp-range=10.0.2.10,10.0.2.250,255.255.252.0,24h
```
Die Netzmaske (`255.255.252.0` = `/22`) nicht verändern, solange das
[IP-Adressschema](#ip-adressschema) mit den vier `/24`-Zonen gilt — sie
definiert, dass dnsmasq das ganze `/22` bedient, nicht nur `10.0.2.0/24`.
Danach: `systemctl restart dnsmasq`
### Statischen Host anlegen (DNS und/oder feste DHCP-Reservierung per MAC)
Immer über `ipadm`, **nicht** von Hand in `dnsmasq.d` eintragen — das Tool
kennt das [IP-Adressschema](#ip-adressschema) und vergibt/prüft die IP im
passenden Subnetz automatisch:
```sh
ipadm -a mein-server # nur DNS, IP aus 10.0.0.0/24 auto-vergeben
ipadm -a mein-server aa:bb:cc:dd:ee:ff # + feste DHCP-Reservierung, IP aus 10.0.1.0/24 auto-vergeben
ipadm -u # anwenden (dnsmasq neu starten)
```
Details, weitere Befehle (IP/MAC nachträglich ändern, Kommentar, Umbenennen,
löschen) siehe [tools/ipadm/README.md](tools/ipadm/README.md).
### DNS-Upstream ändern (z.B. auf öffentliche Resolver)
In `/etc/dnsmasq.d/lan.conf` die `server=`-Zeile anpassen/ergänzen, z.B.:
```
server=9.9.9.9
server=1.1.1.1
```
Mehrere `server=`-Zeilen sind möglich (Round-Robin/Fallback). Danach:
`systemctl restart dnsmasq`
### Lokale Domain / eigene Hostnamen im LAN
dnsmasq kann zusätzlich als einfacher lokaler DNS-Server für das LAN dienen.
Beispiel in `/etc/dnsmasq.d/lan.conf`:
```
address=/server1.lan/10.0.0.10
```
Oder Einträge über `/etc/hosts`-Syntax in einer eigenen Datei einbinden
(`addn-hosts=/etc/dnsmasq.d/lan-hosts`).
### Port-Forwarding (WAN → LAN-Host)
Wird über `ipadm` verwaltet, siehe [tools/ipadm/README.md](tools/ipadm/README.md).
Kurzform: Zielhost muss zuerst als Host in `ipadm` angelegt sein, dann:
```sh
ipadm -pa <hostname> <wan-port> [lan-port] [tcp|udp|both]
ipadm -u # generiert /etc/nftables.d/portforward.conf neu + reloadet nftables
```
Nicht mehr von Hand in `/etc/nftables.conf` eintragen — die Datei bindet
dafür `/etc/nftables.d/*.conf` ein, das ist der von `ipadm` verwaltete Teil.
⚠️ Falls künftig auch der WAN-Eingang gefiltert werden soll (aktuell bewusst
offen gelassen), unbedingt zuerst SSH-Zugriff (und alle anderen aktiv
genutzten Dienste) explizit erlauben, bevor eine restriktive `policy drop`
auf `chain input` gesetzt wird – sonst sperrt man sich ggf. selbst aus.
### LAN-Netz/IP-Bereich komplett ändern (z.B. auf einen anderen Adressraum)
1. `/etc/network/interfaces`: `address` der `enp7s0`-Zeile anpassen.
2. `/etc/dnsmasq.d/lan.conf`: `dhcp-range` und beide `dhcp-option`-Zeilen
(Router/DNS-IP) anpassen.
3. `/etc/nftables.conf`: `ip saddr 10.0.0.0/22` in der NAT-Regel anpassen.
4. Falls sich die Aufteilung der vier `/24`-Zonen ändert (nicht nur die
Basis-Adresse): `ipadm`s Env-Vars `IPADM_STATIC_CIDR`,
`IPADM_RESERVED_CIDR`, `IPADM_GATEWAY_IP` entsprechend über
`/etc/systemd/system/ipadm.env` o.ä. anpassen — siehe
[tools/ipadm/README.md](tools/ipadm/README.md) (Default ist
`10.0.0.0/24` / `10.0.1.0/24` / `10.0.0.1`, fest im Binary einkompiliert
als Fallback).
5. Anwenden: Adresse live setzen (`ip addr change <neue-ip>/<prefix> dev
enp7s0` + alte Adresse mit `ip addr del` entfernen, falls sich die
Präfixlänge ändert — sonst bleiben beide Adressen parallel aktiv),
`systemctl restart dnsmasq` (ein reines `reload` reicht bei
`dhcp-range`-Änderungen **nicht**, siehe Hinweis unten), `nft -f
/etc/nftables.conf`. Alternativ komplett: `ifdown enp7s0 && ifup enp7s0`.
Bestehende `ipadm`-Hosts danach mit `ipadm -i <name> <neue-ip>` einzeln
umziehen und mit `ipadm -u` anwenden.
## Befehle zum Anwenden von Änderungen
```sh
# dnsmasq-Konfig auf Syntaxfehler prüfen, dann neu laden
dnsmasq --test
systemctl restart dnsmasq # NICHT "reload" (SIGHUP) — siehe Hinweis unten
# nftables-Konfig auf Syntaxfehler prüfen, dann neu laden
nft -c -f /etc/nftables.conf
nft -f /etc/nftables.conf
# bzw. systemctl reload nftables (lädt /etc/nftables.conf neu ein)
# Netzwerk-Interface-Änderungen anwenden (ifupdown)
ifdown enp7s0 && ifup enp7s0
# sysctl-Änderungen anwenden
sysctl --system
```
⚠️ **`systemctl reload dnsmasq` (SIGHUP) genügt bei Config-Änderungen nicht.**
dnsmasq liest per SIGHUP nur `/etc/hosts` und einige spezielle
Hosts-Dateien-Optionen neu — **nicht** die `conf-dir`-Dateien
(`/etc/dnsmasq.d/*.conf`, also `lan.conf` und das von `ipadm` generierte
`hosts.conf`). Änderungen dort (`dhcp-range`, `host-record`, `dhcp-host`, …)
brauchen einen echten `systemctl restart dnsmasq`, sonst läuft der alte Stand
unbemerkt weiter. `ipadm -u` macht das seit Version 1.2.0 automatisch
richtig (restart statt reload) — bei manuellen Änderungen selbst dran denken.
## Troubleshooting / nützliche Befehle
```sh
# Aktive nftables-Regeln anzeigen
nft list ruleset
# dnsmasq-Status und Logs
systemctl status dnsmasq
journalctl -u dnsmasq -f
# Wer bekommt gerade welche DHCP-Lease
cat /var/lib/misc/dnsmasq.leases
# DNS-Auflösung über den Router testen
dig @10.0.0.1 www.example.com
# Lauscht dnsmasq wirklich NUR auf enp7s0 (nicht auf der WAN-IP)?
ss -tulpn | grep -E ':53|:67'
# IP-Forwarding aktiv?
sysctl net.ipv4.ip_forward
# Interface-/Carrier-Status (z.B. wenn Kabel nicht erkannt wird)
ip -brief addr
ip link show enp7s0
cat /sys/class/net/enp7s0/carrier
```
### Rogue DHCP-Server erkennen (z.B. "falscher Nameserver"-Symptom)
Am 2026-08-19 kam die Meldung "DHCP liefert falschen Nameserver aus". Ursache
war kein Config-Fehler, sondern ein **zweiter DHCP-Server im LAN** (ein
WLAN-Router, der noch im Router- statt Access-Point-Modus lief und parallel
eigenes DHCP anbot). Erkennbar in `journalctl -u dnsmasq` (braucht `log-dhcp`,
siehe oben) an folgendem Muster:
```
DHCPOFFER(enp7s0) 10.0.0.157 <mac> ← unser Angebot
DHCPREQUEST(enp7s0) 10.0.0.151 <mac> ← Client nimmt eine andere IP an
DHCPNAK(enp7s0) 10.0.0.151 <mac> wrong server-ID ← wir lehnen zu Recht ab
```
Client hat also ein Angebot von einer fremden Quelle angenommen. Gerät mit
aktiver Web-Verwaltung im LAN suchen (z.B. `curl -I http://<verdächtige-ip>/`)
und dessen DHCP-Server deaktivieren / in Access-Point-Modus umschalten —
narcissus soll der einzige DHCP-Server im `10.0.0.0/22`-Netz sein.
## Sicherheitshinweise
- dnsmasq ist bewusst so konfiguriert, dass es **nur** auf `enp7s0` lauscht
(`interface=`, `bind-interfaces`, `except-interface=enp3s0`). Vor jeder
Änderung an dieser Konfiguration prüfen, dass diese Einschränkung erhalten
bleibt – sonst entsteht ein von außen erreichbarer DNS-/DHCP-Dienst.
- Die WAN-Seite (`enp3s0`) wurde absichtlich nicht gefiltert/gehärtet, um
die bestehende Erreichbarkeit nicht zu verändern. Das war eine bewusste
Entscheidung bei der Einrichtung, keine Vergesslichkeit.
- SSH läuft seit 2026-08-21 nur noch auf Port `2234` (nicht mehr `22`), siehe
Tabelle oben. `nftables` filtert `input` weiterhin nicht (Policy `accept`),
die Portverlegung ist reine Verschleierung, kein Ersatz für eine Firewall-
Regel — falls das mal gehärtet werden soll, siehe Warnung zu
Port-Forwarding weiter oben (zuerst SSH auf 2234 explizit erlauben, bevor
`policy drop` auf `chain input` gesetzt wird).