Port 22 no longer listens; matches sulaco's existing convention. Firewall policy on input is still accept, so this is obscurity only, not a real access control — noted in the security section. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
322 lines
16 KiB
Markdown
322 lines
16 KiB
Markdown
# 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).
|
||
|
||
## 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).
|