From d14abc70413e3196cebb003a3e9ce5ad87d36537 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 10 May 2026 13:15:32 +0200 Subject: [PATCH] first --- .gitignore | 3 + README.md | 837 +++++++++++++++++++++++++++++++++++++++++++++++++ lib.sh | 38 +++ load-chains.sh | 7 + 4 files changed, 885 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100755 lib.sh create mode 100755 load-chains.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..29bdfc7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +hooks +chains + diff --git a/README.md b/README.md new file mode 100644 index 0000000..d1e9689 --- /dev/null +++ b/README.md @@ -0,0 +1,837 @@ +# Firewall-oppsett for `/opt/firewall` + +Dette repoet inneholder firewall-logikk for en Linux-host med `iptables`, Docker og eventuelt WireGuard. + +Målet er at firewall-reglene skal være: + +- lesbare +- flyttbare +- enkle å ta backup av +- mulige å versjonskontrollere med Git +- trygge å laste inn flere ganger +- adskilt fra systemets egne chains +- mulig å laste automatisk ved boot med systemd + +Repoet ligger her: + +```text +/opt/firewall +``` + +--- + +## 1. Hvorfor dette oppsettet finnes + +Firewall-regler som skrives direkte i terminalen med `iptables`, finnes bare aktivt i kernel mens maskinen kjører. + +Eksempel: + +```bash +sudo iptables -A FORWARD -j ACCEPT +``` + +Dette er ikke nok som varig dokumentasjon eller drift. + +Hvis maskinen rebooter, eller hvis reglene endres senere, er det lett å miste oversikt. + +Derfor ligger firewall-logikken som filer i: + +```text +/opt/firewall +``` + +Da kan reglene: + +- leses +- endres +- kjøres på nytt +- legges i Git +- kopieres til en annen maskin +- lastes automatisk med systemd + +--- + +## 2. Filstruktur + +Dette oppsettet bruker denne strukturen: + +```text +/opt/firewall +├── README.md +├── lib.sh +├── load-chains.sh +├── chains/ +└── hooks/ +``` + +Forklaring: + +```text +/opt/firewall/README.md +``` + +Dokumentasjon for hvordan firewall-oppsettet fungerer. + +```text +/opt/firewall/lib.sh +``` + +Felles hjelpefunksjoner som kan brukes av flere firewall-script. + +Typiske funksjoner i `lib.sh` kan være: + +- sjekke om en chain finnes +- lage en chain hvis den mangler +- flushe egne chains +- legge til regler uten duplikater +- koble chains sammen + +```text +/opt/firewall/load-chains.sh +``` + +Hovedscriptet som laster firewall-reglene. + +Dette er scriptet systemd bør kjøre ved boot. + +```text +/opt/firewall/chains/ +``` + +Mappe for egne chain-filer. + +Eksempel: + +```text +/opt/firewall/chains/wg-admin.sh +/opt/firewall/chains/wg-guest.sh +/opt/firewall/chains/docker-filter.sh +``` + +```text +/opt/firewall/hooks/ +``` + +Mappe for scripts som kan brukes av andre tjenester, for eksempel WireGuard `PostUp`, `PostDown`, eller egne systemd-hooks. + +--- + +## 3. Hovedprinsipp + +Systemet har egne chains med store bokstaver: + +```text +INPUT +OUTPUT +FORWARD +DOCKER +DOCKER-USER +``` + +Egne private chains bør bruke små bokstaver: + +```text +custom-forward +wg-admin +wg-guest +docker-filter +``` + +Dette gjør det lett å se forskjell på: + +- systemets egne chains +- Docker sine chains +- egne firewall-chains + +--- + +## 4. Hvorfor bruke egne chains + +Man bør ikke legge all logikk direkte i `FORWARD`. + +Ryddigere prinsipp: + +```text +FORWARD + -> custom-forward + -> wg-admin + -> wg-guest +``` + +For Docker: + +```text +DOCKER-USER + -> docker-filter +``` + +Da kan egne chains ryddes og lastes inn på nytt uten å flushe hele systemets firewall. + +Dette er spesielt viktig på maskiner som bruker: + +- Docker +- WireGuard +- SSH +- Caddy +- Pi-hole +- andre nettverkstjenester + +--- + +## 5. Idempotente regler + +Firewall-script bør kunne kjøres flere ganger uten å lage duplikate regler. + +Ikke gjør dette ukritisk: + +```bash +iptables -A FORWARD -j custom-forward +``` + +Hvis scriptet kjøres fem ganger, får du fem like regler. + +Bruk heller denne logikken: + +```bash +iptables -C FORWARD -j custom-forward 2>/dev/null || iptables -A FORWARD -j custom-forward +``` + +Forklaring: + +- `iptables -C` sjekker om regelen finnes +- hvis den ikke finnes, legges den inn med `iptables -A` +- da kan scriptet kjøres flere ganger trygt + +--- + +## 6. Rolle til `lib.sh` + +`lib.sh` bør inneholde felles funksjoner. + +Eksempel på typiske funksjoner: + +```bash +chain_exists() { + local chain="$1" + iptables -L "$chain" -n >/dev/null 2>&1 +} + +ensure_chain() { + local chain="$1" + + if ! chain_exists "$chain"; then + iptables -N "$chain" + fi +} + +flush_chain() { + local chain="$1" + + if chain_exists "$chain"; then + iptables -F "$chain" + fi +} + +ensure_rule() { + local chain="$1" + shift + + if ! iptables -C "$chain" "$@" >/dev/null 2>&1; then + iptables -A "$chain" "$@" + fi +} + +ensure_jump() { + local from_chain="$1" + local to_chain="$2" + shift 2 + + if ! iptables -C "$from_chain" "$@" -j "$to_chain" >/dev/null 2>&1; then + iptables -A "$from_chain" "$@" -j "$to_chain" + fi +} +``` + +Poenget med `lib.sh` er at chain-script slipper å gjenta samme hjelpefunksjoner. + +--- + +## 7. Rolle til `load-chains.sh` + +`load-chains.sh` er hovedscriptet. + +Det bør gjøre omtrent dette: + +1. sette trygg shell-modus +2. finne repo-path +3. source `/opt/firewall/lib.sh` +4. aktivere IPv4 forwarding hvis maskinen skal route trafikk +5. lage private chains +6. flushe bare egne private chains +7. koble egne chains inn i systemets chains +8. laste regler fra `/opt/firewall/chains/` + +Eksempel på start: + +```bash +#!/usr/bin/env bash +set -euo pipefail + +BASE_DIR="/opt/firewall" + +source "$BASE_DIR/lib.sh" + +sysctl -w net.ipv4.ip_forward=1 >/dev/null +``` + +`load-chains.sh` bør være scriptet systemd kjører. + +--- + +## 8. Eksempel på private chains + +Vanlige private chains kan være: + +```text +custom-forward +wg-admin +wg-guest +docker-filter +``` + +Eksempel på oppretting: + +```bash +ensure_chain custom-forward +ensure_chain wg-admin +ensure_chain wg-guest +ensure_chain docker-filter +``` + +Eksempel på rydding: + +```bash +flush_chain custom-forward +flush_chain wg-admin +flush_chain wg-guest +flush_chain docker-filter +``` + +Viktig: + +Bare egne chains bør flushes. + +Ikke flush disse ukritisk: + +```text +INPUT +OUTPUT +FORWARD +DOCKER +DOCKER-USER +``` + +--- + +## 9. WireGuard-logikk + +Eksempelnett: + +```text +wg-admin: 10.10.10.0/24 +wg-guest: 10.10.11.0/24 +``` + +Typisk logikk: + +```text +wg-admin: + - får full forward-tilgang + +wg-guest: + - får begrenset tilgang + - kan eventuelt få DNS + - resten avvises +``` + +Eksempel: + +```bash +ensure_jump custom-forward wg-admin -s 10.10.10.0/24 +ensure_jump custom-forward wg-guest -s 10.10.11.0/24 + +ensure_rule wg-admin -j ACCEPT + +ensure_rule wg-guest -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +ensure_rule wg-guest -p udp -d 10.10.11.1 --dport 53 -j ACCEPT +ensure_rule wg-guest -p tcp -d 10.10.11.1 --dport 53 -j ACCEPT +ensure_rule wg-guest -j REJECT +``` + +Tilpass IP-adresser til eget oppsett. + +--- + +## 10. Docker-logikk + +Docker lager egne chains automatisk. + +Vanlige Docker-chains: + +```text +DOCKER +DOCKER-USER +DOCKER-ISOLATION-STAGE-1 +DOCKER-ISOLATION-STAGE-2 +``` + +Egne Docker-regler bør normalt kobles inn via: + +```text +DOCKER-USER +``` + +Eksempel: + +```bash +ensure_jump DOCKER-USER docker-filter +``` + +I `docker-filter` kan du legge egne regler. + +Eksempel: + +```bash +ensure_rule docker-filter -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN +ensure_rule docker-filter -s 10.10.10.0/24 -j RETURN +ensure_rule docker-filter -j RETURN +``` + +`RETURN` betyr at trafikken går tilbake til Docker sin normale behandling. + +--- + +## 11. Pi-hole og Docker + +Hvis Pi-hole kjører i Docker bridge-nettverk, kan Pi-hole ofte se Docker gateway eller container-IP som klient, ikke ekte klient-IP. + +For å se ekte klient-IP kan man vurdere: + +- host network +- macvlan +- kjøre Pi-hole direkte på host +- bruke routing der klientens kilde-IP bevares + +Dette README-et handler primært om firewall-logikken, ikke selve Pi-hole-oppsettet. + +--- + +## 12. Manuell lasting av firewall + +Kjør: + +```bash +sudo /opt/firewall/load-chains.sh +``` + +Hvis scriptet ikke er kjørbart: + +```bash +sudo chmod +x /opt/firewall/load-chains.sh +``` + +Kjør med debug: + +```bash +sudo bash -x /opt/firewall/load-chains.sh +``` + +--- + +## 13. Se aktive regler + +Vis regler som kommandoer: + +```bash +sudo iptables -S +``` + +Vis regler med tellere: + +```bash +sudo iptables -L -n -v +``` + +Vis NAT-regler: + +```bash +sudo iptables -t nat -S +``` + +Vis Docker sin user-chain: + +```bash +sudo iptables -S DOCKER-USER +``` + +--- + +## 14. Systemd-tjeneste + +Systemd kan brukes til å laste firewall-reglene automatisk ved boot. + +Tjenesten bør ligge her: + +```text +/etc/systemd/system/custom-firewall.service +``` + +Innhold: + +```ini +[Unit] +Description=Custom firewall rules from /opt/firewall +Documentation=file:/opt/firewall/README.md +Wants=network-online.target +After=network-online.target docker.service + +[Service] +Type=oneshot +ExecStart=/opt/firewall/load-chains.sh +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target +``` + +--- + +## 15. Lage systemd-tjenesten manuelt + +Lag filen: + +```bash +sudo nano /etc/systemd/system/custom-firewall.service +``` + +Lim inn: + +```ini +[Unit] +Description=Custom firewall rules from /opt/firewall +Documentation=file:/opt/firewall/README.md +Wants=network-online.target +After=network-online.target docker.service + +[Service] +Type=oneshot +ExecStart=/opt/firewall/load-chains.sh +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target +``` + +Lagre filen. + +Deretter: + +```bash +sudo chmod +x /opt/firewall/load-chains.sh +sudo systemctl daemon-reload +sudo systemctl enable custom-firewall.service +sudo systemctl start custom-firewall.service +``` + +--- + +## 16. Forklaring av systemd-filen + +```ini +Description=Custom firewall rules from /opt/firewall +``` + +Beskrivelse av tjenesten. + +```ini +Documentation=file:/opt/firewall/README.md +``` + +Peker til denne dokumentasjonen. + +```ini +Wants=network-online.target +After=network-online.target docker.service +``` + +Tjenesten starter etter at nettverk er oppe. + +Hvis Docker finnes, starter firewall-oppsettet etter Docker. Dette er nyttig fordi Docker lager `DOCKER-USER`. + +```ini +Type=oneshot +``` + +Scriptet kjøres én gang og avsluttes. + +```ini +ExecStart=/opt/firewall/load-chains.sh +``` + +Dette scriptet laster firewall-reglene. + +```ini +RemainAfterExit=yes +``` + +Systemd markerer tjenesten som aktiv etter at scriptet er ferdig. + +Dette gir mening fordi reglene fortsatt ligger aktive i kernel. + +```ini +WantedBy=multi-user.target +``` + +Gjør at tjenesten kan aktiveres ved vanlig boot. + +--- + +## 17. Hvis firewall må starte før WireGuard + +Hvis firewall-reglene må være klare før `wg0` starter, kan man legge til: + +```ini +Before=wg-quick@wg0.service +``` + +Da blir unit-filen: + +```ini +[Unit] +Description=Custom firewall rules from /opt/firewall +Documentation=file:/opt/firewall/README.md +Wants=network-online.target +After=network-online.target docker.service +Before=wg-quick@wg0.service + +[Service] +Type=oneshot +ExecStart=/opt/firewall/load-chains.sh +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target +``` + +Ikke bruk `Before=wg-quick@wg0.service` hvis du ikke trenger det. + +For mange oppsett holder det at firewall-reglene lastes etter nettverk og Docker. + +--- + +## 18. Aktivere tjenesten + +Etter at filen er laget: + +```bash +sudo systemctl daemon-reload +sudo systemctl enable custom-firewall.service +sudo systemctl start custom-firewall.service +``` + +Sjekk status: + +```bash +systemctl status custom-firewall.service +``` + +--- + +## 19. Etter endringer + +Hvis du endrer script: + +```bash +sudo systemctl restart custom-firewall.service +``` + +Hvis du endrer systemd-filen: + +```bash +sudo systemctl daemon-reload +sudo systemctl restart custom-firewall.service +``` + +--- + +## 20. Stoppe tjenesten + +```bash +sudo systemctl stop custom-firewall.service +``` + +Viktig: + +Dette fjerner ikke nødvendigvis firewall-reglene fra kernel. + +Siden tjenesten er `Type=oneshot`, betyr `stop` hovedsakelig at systemd ikke lenger markerer tjenesten som aktiv. + +Hvis du vil fjerne regler, må du lage eget cleanup-script eller rydde egne chains manuelt. + +Eksempel: + +```bash +sudo iptables -F custom-forward +sudo iptables -F wg-admin +sudo iptables -F wg-guest +sudo iptables -F docker-filter +``` + +Ikke flush hele firewall-oppsettet ukritisk på en server du er koblet til over SSH. + +--- + +## 21. Feilsøking + +Sjekk status: + +```bash +systemctl status custom-firewall.service +``` + +Se logger: + +```bash +journalctl -u custom-firewall.service -xe +``` + +Se logger fra siste boot: + +```bash +journalctl -b -u custom-firewall.service +``` + +Kjør script direkte: + +```bash +sudo /opt/firewall/load-chains.sh +``` + +Kjør script med debug: + +```bash +sudo bash -x /opt/firewall/load-chains.sh +``` + +Sjekk om en chain finnes: + +```bash +sudo iptables -L custom-forward -n -v +``` + +Sjekk om en regel finnes: + +```bash +sudo iptables -C FORWARD -j custom-forward +``` + +Sjekk Docker-chain: + +```bash +sudo iptables -L DOCKER-USER -n -v +``` + +--- + +## 22. Backup + +Ta backup av aktiv iptables-state: + +```bash +sudo iptables-save > /opt/firewall/iptables-backup.rules +``` + +Men viktigste backup er selve repoet: + +```text +/opt/firewall/README.md +/opt/firewall/lib.sh +/opt/firewall/load-chains.sh +/opt/firewall/chains/ +/opt/firewall/hooks/ +``` + +Hvis `/opt/firewall` ligger i Git, kan oppsettet flyttes og reproduseres. + +--- + +## 23. Flytte til annen maskin + +Kopier repoet til: + +```text +/opt/firewall +``` + +Gjør scriptet kjørbart: + +```bash +sudo chmod +x /opt/firewall/load-chains.sh +``` + +Lag systemd-tjenesten: + +```bash +sudo nano /etc/systemd/system/custom-firewall.service +``` + +Lim inn: + +```ini +[Unit] +Description=Custom firewall rules from /opt/firewall +Documentation=file:/opt/firewall/README.md +Wants=network-online.target +After=network-online.target docker.service + +[Service] +Type=oneshot +ExecStart=/opt/firewall/load-chains.sh +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target +``` + +Aktiver: + +```bash +sudo systemctl daemon-reload +sudo systemctl enable custom-firewall.service +sudo systemctl start custom-firewall.service +``` + +Sjekk: + +```bash +systemctl status custom-firewall.service +sudo iptables -S +``` + +--- + +## 24. Viktige regler + +Ikke flush hele `iptables` ukritisk. + +Ikke slett Docker sine chains manuelt. + +Ikke legg permanente regler bare manuelt i terminalen. + +Ikke bland admin-nett, guest-nett og Docker-regler uten tydelige chains. + +Bruk egne chains for egen logikk. + +La `/opt/firewall/load-chains.sh` være kilden til sannheten. + +La systemd laste firewall-reglene ved boot. diff --git a/lib.sh b/lib.sh new file mode 100755 index 0000000..9598fdc --- /dev/null +++ b/lib.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -euo pipefail + +IPTABLES=${IPTABLES:-/usr/sbin/iptables} + +# ---------- filter/default table ---------- + +ipt() { + "$IPTABLES" "$@" +} + +ensure_chain() { + local chain="$1" + ipt -N "$chain" 2>/dev/null || true +} + +add_rule() { + local chain="$1" + shift + ipt -C "$chain" "$@" 2>/dev/null || ipt -A "$chain" "$@" +} + +# ---------- nat table ---------- + +ipt_nat() { + "$IPTABLES" -t nat "$@" +} + +ensure_nat_chain() { + local chain="$1" + ipt_nat -N "$chain" 2>/dev/null || true +} + +add_nat_rule() { + local chain="$1" + shift + ipt_nat -C "$chain" "$@" 2>/dev/null || ipt_nat -A "$chain" "$@" +} diff --git a/load-chains.sh b/load-chains.sh new file mode 100755 index 0000000..fded71c --- /dev/null +++ b/load-chains.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -euo pipefail + +for file in /opt/firewall/chains/*.sh; do + [ -e "$file" ] || continue + bash "$file" +done