13 KiB
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 -Csjekker 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:
- sette trygg shell-modus
- finne repo-path
- source
/opt/firewall/lib.sh - aktivere IPv4 forwarding hvis maskinen skal route trafikk
- lage private chains
- flushe bare egne private chains
- koble egne chains inn i systemets chains
- 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.