Files
oopen-server/roles/ipt-server/README.md
T
chrisandClaude Opus 5.5 402a6c9e89 Role ipt-server: sync with ipt-server repo (93d9af8); adapt extract-fw-host-vars.py.
- Update firewall scripts and shared conf files from firewall/ipt-server
  (HTTP connection limits, IPv6 TCP MSS clamping, ban_ipv6_mask,
  mattermost TCP fallback, rename 'stansard_*' -> 'standard_*').
- New role variables: fw_set_max_new_http_conn_per_ip_per_second,
  fw_max_http_new_conn_per_ip_per_second, fw_set_max_concurrent_http_conn_per_ip,
  fw_max_concurrent_http_conn_per_ip, fw_set_max_new_http_conn_per_second,
  fw_max_new_http_conn_per_second, fw_throttle_tcp6_mss_for_https,
  fw_tcp6_mss_for_https_val, fw_mm_tcp_ports_in, fw_ban_ipv6_mask.
- Split fw_blocked_ips into fw_blocked_ips_v4 / fw_blocked_ips_v6 and
  rename it in host_vars accordingly.
- Restart firewall when scripts or shared conf files change.
- extract-fw-host-vars.py: map new variables, normalize '${var}' and renamed
  bash variables, fall back to IPv6 for shared variables and warn if IPv4
  and IPv6 values differ.
- README.md / MIGRATION.md: document host_vars naming
  (<short-hostname>-ipt-server.yml) and new variables.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 22:01:28 +01:00

231 lines
7.3 KiB
Markdown

# ipt-server — Ansible Role
Verwaltet die iptables/ip6tables-basierte Firewall (`ipt-firewall-server` /
`ip6t-firewall-server`) auf Debian-Hosts.
Die Rolle ist die **einzige** autorisierte Stelle für Firewall-Änderungen. Direkte
Edits in `/etc/ipt-firewall/` auf dem Host werden beim nächsten Ansible-Run
überschrieben, sobald `fw_manage_config: true` gesetzt ist.
---
## Verzeichnisstruktur
```
roles/ipt-server/
├── defaults/main.yml # Alle Variablen mit Defaults
├── files/
│ ├── etc/ipt-firewall/ # Geteilte Conf-Dateien (nicht host-spezifisch)
│ │ ├── default_settings.conf
│ │ ├── include_functions.conf
│ │ ├── logging_ipv4.conf
│ │ ├── logging_ipv6.conf
│ │ ├── post_declarations.conf
│ │ ├── ban_ipv4.list.sample
│ │ └── ban_ipv6.list.sample
│ ├── etc/systemd/system/
│ │ ├── ipt-firewall.service
│ │ └── ip6t-firewall.service
│ └── usr/local/sbin/
│ ├── ipt-firewall-server # IPv4-Firewall-Skript
│ └── ip6t-firewall-server # IPv6-Firewall-Skript
├── handlers/main.yml
├── tasks/main.yml
└── templates/
└── etc/ipt-firewall/
├── interfaces_ipv4.conf.j2 # Host-spezifisch: Interfaces + IPs
├── interfaces_ipv6.conf.j2
├── main_ipv4.conf.j2 # Host-spezifisch: Dienste, Regeln
└── main_ipv6.conf.j2
```
Host-spezifische Konfiguration liegt ausschließlich in:
```
host_vars/${HOSTNAME}/${HOSTNAME%.*.*}-ipt-server.yml
```
Der Dateiname beginnt mit dem Hostnamen ohne Domain, z.B.
`host_vars/a.mx.oopen.de/a.mx-ipt-server.yml` oder
`host_vars/backup.oopen.de/backup-ipt-server.yml`
(`${HOSTNAME%.*.*}` schneidet die letzten zwei Labels ab).
---
## Neuen Host aufnehmen
### Voraussetzungen
- Host ist im Ansible-Inventory (`hosts`) eingetragen.
- SSH-Zugang mit `sudo`-Rechten ist vorhanden.
### Schritt 1 — host_vars anlegen
```bash
cd /path/to/ansible/oopen-server
HOSTNAME=<hostname>
mkdir -p host_vars/${HOSTNAME}
cat > host_vars/${HOSTNAME}/${HOSTNAME%.*.*}-ipt-server.yml << 'EOF'
---
fw_manage_config: true
# --- Netzwerk
fw_ext_interfaces:
- "eth0"
fw_ext_ips_v4:
- "1.2.3.4"
fw_ext_ips_v6:
- "2001:db8::1"
EOF
```
Alle weiteren Variablen sind optional — sie greifen auf die Defaults in
`defaults/main.yml` zurück. Nur abweichende Werte müssen gesetzt werden.
Für eine vollständige Variablenreferenz: `defaults/main.yml`.
### Schritt 2 — Dry-run
```bash
HOSTNAME=<hostname>
ansible-playbook ipt-server.yml --limit ${HOSTNAME} --check --diff
```
Der Diff zeigt genau, welche Dateien angelegt und welche Config-Werte gesetzt
werden. Prüfen, ob Interfaces, IPs und Dienste stimmen.
### Schritt 3 — Scharf stellen
```bash
ansible-playbook ipt-server.yml --limit ${HOSTNAME}
```
Was passiert:
- Firewall-Skripte werden nach `/usr/local/sbin/` kopiert.
- Geteilte Conf-Dateien werden nach `/etc/ipt-firewall/` kopiert.
- Systemd-Units werden installiert, Dienste werden aktiviert und gestartet.
- Config-Dateien (`interfaces_*.conf`, `main_*.conf`) werden aus den Templates
erzeugt und die Firewall wird gestartet.
---
## Konfiguration ändern
Alle Änderungen erfolgen ausschließlich in der host_vars-Datei des Hosts:
```
host_vars/${HOSTNAME}/${HOSTNAME%.*.*}-ipt-server.yml
```
Danach:
```bash
HOSTNAME=<hostname>
# Vorschau:
ansible-playbook ipt-server.yml --limit ${HOSTNAME} --check --diff
# Anwenden (ändert Config, startet Firewall bei Änderungen neu):
ansible-playbook ipt-server.yml --limit ${HOSTNAME}
```
Ansible erkennt automatisch, ob sich eine Config-Datei geändert hat. Nur bei
tatsächlichen Änderungen wird die Firewall neu gestartet.
### Beispiel: HTTP-Server aktivieren
```yaml
# host_vars/${HOSTNAME}/${HOSTNAME%.*.*}-ipt-server.yml
fw_http_server_ips: "$ext_ips" # oder konkrete IP
```
### Beispiel: SSH auf bestimmten Port einschränken
```yaml
fw_ssh_ports: "2222"
```
### Beispiel: LXC-Gäste eintragen
```yaml
fw_lxc_guest_ips_v4:
- "10.0.3.10"
- "10.0.3.11"
fw_lxc_guest_ips_v6:
- "fd00::10"
- "fd00::11"
```
---
## Firewall-Skripte aktualisieren
Wenn `ipt-firewall-server` oder `ip6t-firewall-server` im `ipt-server`-Repository
aktualisiert werden, müssen die neuen Versionen manuell in die Rolle übernommen
werden:
```bash
SRC=/path/to/ipt-server
DST=roles/ipt-server/files/usr/local/sbin
cp $SRC/ipt-firewall-server $DST/
cp $SRC/ip6t-firewall-server $DST/
chmod 750 $DST/ipt-firewall-server $DST/ip6t-firewall-server
```
Ebenso für geteilte Conf-Dateien in `roles/ipt-server/files/etc/ipt-firewall/`.
Kommen dabei neue Variablen in `main_ipv4.conf.sample` / `main_ipv6.conf.sample`
hinzu, müssen sie zusätzlich nachgezogen werden in:
- `defaults/main.yml` (als `fw_*`-Variable mit Default),
- `templates/etc/ipt-firewall/main_ipv{4,6}.conf.j2`,
- `extract-fw-host-vars.py` (`DEFAULTS`, `MAIN_SHARED` bzw. `MAIN_V4_ONLY`/`MAIN_V6_ONLY`,
Sektion in `render_yaml`).
Nach dem Commit werden die neuen Skripte beim nächsten Ansible-Run auf alle
Hosts deployed. Geänderte Skripte oder geteilte Conf-Dateien lösen einen
Neustart der Firewall aus.
---
## Wichtige Variablen
| Variable | Default | Bedeutung |
|---|---|---|
| `fw_manage_config` | `false` | `true` = Ansible verwaltet Config-Dateien vollständig |
| `fw_ext_interfaces` | `[]` | Externe Netzwerk-Interfaces, z.B. `["eth0"]` |
| `fw_ext_ips_v4` | `[]` | Externe IPv4-Adressen |
| `fw_ext_ips_v6` | `[]` | Externe IPv6-Adressen |
| `fw_ssh_server_ips` | `"$ext_ips"` | IPs auf denen SSH erlaubt ist |
| `fw_ssh_ports` | `"$standard_ssh_port"` | SSH-Port(s) |
| `fw_http_server_ips` | `""` | IPs auf denen HTTP/HTTPS erlaubt ist |
| `fw_set_max_new_http_conn_per_ip_per_second` | `true` | Neue HTTP(S)-Verbindungen/s pro Quell-IP begrenzen |
| `fw_max_http_new_conn_per_ip_per_second` | `"$default_max_http_new_conn_per_ip_per_second"` | Limit dazu |
| `fw_set_max_concurrent_http_conn_per_ip` | `true` | Gleichzeitige HTTP(S)-Verbindungen pro Quell-IP begrenzen |
| `fw_max_concurrent_http_conn_per_ip` | `"$default_max_concurrent_http_conn_per_ip"` | Limit dazu |
| `fw_set_max_new_http_conn_per_second` | `true` | SYN-Rate auf 80/443 insgesamt begrenzen |
| `fw_max_new_http_conn_per_second` | `"$default_max_new_http_conn_per_second"` | Limit dazu |
| `fw_throttle_tcp6_mss_for_https` | `false` | Nur IPv6: MSS eingehender HTTPS-SYNs clampen |
| `fw_tcp6_mss_for_https_val` | `"$min_tcp6_mss_for_https_val"` | Nur IPv6: MSS-Wert (z.B. `1360`) |
| `fw_mm_tcp_ports_in` | `"$standard_mattermost_tcp_ports_in"` | Mattermost TCP-Fallback (STUN) |
| `fw_ban_ipv6_mask` | `"$default_ban_ipv6_mask"` | Nur IPv6: Präfixlänge für `ban_ipv6.list`-Einträge ohne Maske |
| `munin_remote_ipv4` | `""` | Munin-Server IPv4 |
| `munin_remote_ipv6` | `""` | Munin-Server IPv6 |
Alle Variablen mit Beschreibung und Defaults: `defaults/main.yml`.
Variablen die mit `$` beginnen (z.B. `$ext_ips`, `$standard_ssh_port`) sind
Bash-Variablen — sie werden nicht von Ansible aufgelöst, sondern zur Laufzeit
vom Firewall-Skript expandiert.
---
## Ban-Listen
`/etc/ipt-firewall/ban_ipv4.list` und `ban_ipv6.list` werden beim ersten
Ausrollen aus den Beispiel-Dateien der Rolle erzeugt und danach **nicht mehr
durch Ansible angefasst** — sie können auf dem Host direkt bearbeitet werden.