# 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.