2026-05-10 13:27:00 +02:00
2026-05-10 13:27:00 +02:00
2026-05-10 13:27:00 +02:00
2026-05-10 13:15:32 +02:00
2026-05-10 13:15:32 +02:00
2026-05-10 13:15:32 +02:00
2026-05-10 13:15:32 +02:00

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:

/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:

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:

/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:

/opt/firewall
├── README.md
├── lib.sh
├── load-chains.sh
├── chains/
└── hooks/

Forklaring:

/opt/firewall/README.md

Dokumentasjon for hvordan firewall-oppsettet fungerer.

/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
/opt/firewall/load-chains.sh

Hovedscriptet som laster firewall-reglene.

Dette er scriptet systemd bør kjøre ved boot.

/opt/firewall/chains/

Mappe for egne chain-filer.

Eksempel:

/opt/firewall/chains/wg-admin.sh
/opt/firewall/chains/wg-guest.sh
/opt/firewall/chains/docker-filter.sh
/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:

INPUT
OUTPUT
FORWARD
DOCKER
DOCKER-USER

Egne private chains bør bruke små bokstaver:

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:

FORWARD
  -> custom-forward
       -> wg-admin
       -> wg-guest

For Docker:

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:

iptables -A FORWARD -j custom-forward

Hvis scriptet kjøres fem ganger, får du fem like regler.

Bruk heller denne logikken:

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:

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:

#!/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:

custom-forward
wg-admin
wg-guest
docker-filter

Eksempel på oppretting:

ensure_chain custom-forward
ensure_chain wg-admin
ensure_chain wg-guest
ensure_chain docker-filter

Eksempel på rydding:

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:

INPUT
OUTPUT
FORWARD
DOCKER
DOCKER-USER

9. WireGuard-logikk

Eksempelnett:

wg-admin: 10.10.10.0/24
wg-guest: 10.10.11.0/24

Typisk logikk:

wg-admin:
  - får full forward-tilgang

wg-guest:
  - får begrenset tilgang
  - kan eventuelt få DNS
  - resten avvises

Eksempel:

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:

DOCKER
DOCKER-USER
DOCKER-ISOLATION-STAGE-1
DOCKER-ISOLATION-STAGE-2

Egne Docker-regler bør normalt kobles inn via:

DOCKER-USER

Eksempel:

ensure_jump DOCKER-USER docker-filter

I docker-filter kan du legge egne regler.

Eksempel:

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:

sudo /opt/firewall/load-chains.sh

Hvis scriptet ikke er kjørbart:

sudo chmod +x /opt/firewall/load-chains.sh

Kjør med debug:

sudo bash -x /opt/firewall/load-chains.sh

13. Se aktive regler

Vis regler som kommandoer:

sudo iptables -S

Vis regler med tellere:

sudo iptables -L -n -v

Vis NAT-regler:

sudo iptables -t nat -S

Vis Docker sin user-chain:

sudo iptables -S DOCKER-USER

14. Systemd-tjeneste

Systemd kan brukes til å laste firewall-reglene automatisk ved boot.

Tjenesten bør ligge her:

/etc/systemd/system/custom-firewall.service

Innhold:

[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:

sudo nano /etc/systemd/system/custom-firewall.service

Lim inn:

[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:

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

Description=Custom firewall rules from /opt/firewall

Beskrivelse av tjenesten.

Documentation=file:/opt/firewall/README.md

Peker til denne dokumentasjonen.

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.

Type=oneshot

Scriptet kjøres én gang og avsluttes.

ExecStart=/opt/firewall/load-chains.sh

Dette scriptet laster firewall-reglene.

RemainAfterExit=yes

Systemd markerer tjenesten som aktiv etter at scriptet er ferdig.

Dette gir mening fordi reglene fortsatt ligger aktive i kernel.

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:

Before=wg-quick@wg0.service

Da blir unit-filen:

[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:

sudo systemctl daemon-reload
sudo systemctl enable custom-firewall.service
sudo systemctl start custom-firewall.service

Sjekk status:

systemctl status custom-firewall.service

19. Etter endringer

Hvis du endrer script:

sudo systemctl restart custom-firewall.service

Hvis du endrer systemd-filen:

sudo systemctl daemon-reload
sudo systemctl restart custom-firewall.service

20. Stoppe tjenesten

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:

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:

systemctl status custom-firewall.service

Se logger:

journalctl -u custom-firewall.service -xe

Se logger fra siste boot:

journalctl -b -u custom-firewall.service

Kjør script direkte:

sudo /opt/firewall/load-chains.sh

Kjør script med debug:

sudo bash -x /opt/firewall/load-chains.sh

Sjekk om en chain finnes:

sudo iptables -L custom-forward -n -v

Sjekk om en regel finnes:

sudo iptables -C FORWARD -j custom-forward

Sjekk Docker-chain:

sudo iptables -L DOCKER-USER -n -v

22. Backup

Ta backup av aktiv iptables-state:

sudo iptables-save > /opt/firewall/iptables-backup.rules

Men viktigste backup er selve repoet:

/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:

/opt/firewall

Gjør scriptet kjørbart:

sudo chmod +x /opt/firewall/load-chains.sh

Lag systemd-tjenesten:

sudo nano /etc/systemd/system/custom-firewall.service

Lim inn:

[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:

sudo systemctl daemon-reload
sudo systemctl enable custom-firewall.service
sudo systemctl start custom-firewall.service

Sjekk:

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.

Description
Setting up a custom firewall on linux with systemd.
Readme MIT 35 KiB
Languages
Shell 100%