Introduktion till Zero Trust-arkitektur
Den gamla säkerhetsmodellen var i grunden ganska enkel: bygg en stark perimeter och lita på allt som finns innanför. Men ärligt talat — i en värld med distribuerade molntjänster, containerbaserade mikrotjänster och medarbetare som jobbar hemifrån i pyjamas, fungerar det inte längre. Zero Trust vänder upp och ner på hela tänket med sin grundprincip: "lita aldrig, verifiera alltid".
Zero Trust-arkitektur (ZTA) utgår från att intrång redan har skett, eller att de kommer att ske. Varje begäran om åtkomst ska autentiseras, auktoriseras och krypteras — oavsett om den kommer inifrån eller utifrån nätverket.
Under 2026 har detta blivit en absolut nödvändighet för Linux-infrastruktur. Och det är inte så konstigt — majoriteten av alla servrar i molnet och datacenter kör ju trots allt Linux.
Varför räcker inte perimetersäkerhet längre? Jo, det finns flera uppenbara anledningar:
- Lateral rörelse: En angripare som tar sig in via en enda komprometterad tjänst kan röra sig fritt i ett platt nätverk. Det räcker med ett enda svagt led.
- Insider-hot: Interna aktörer eller komprometterade konton har redan tillgång bakom brandväggen — perimetern hjälper inte alls här.
- Molnintegration: Hybridmiljöer med både on-premise och molnresurser gör det i princip omöjligt att definiera en tydlig perimeter.
- Mikrotjänstarkitektur: Hundratals tjänster som kommunicerar med varandra, och varje kommunikationsväg utgör en potentiell attackyta.
Så, låt oss dyka in. I den här guiden går vi igenom hur du praktiskt implementerar Zero Trust på Linux-system med verktyg som nftables, WireGuard, SPIFFE/SPIRE, eBPF och moderna övervakningsverktyg. Fokus ligger på konkreta konfigurationer du kan börja använda direkt.
Grundprinciper för Zero Trust på Linux
Innan vi kastar oss in i de tekniska detaljerna behöver vi förstå de fem grundpelarna i en Zero Trust-arkitektur anpassad för Linux-infrastruktur.
1. Identitetsverifiering
Varje användare, tjänst och arbetsbelastning (workload) måste ha en kryptografiskt verifierbar identitet. På Linux innebär det att vi använder certifikatbaserad autentisering istället för IP-baserade tillitszoner. SPIFFE (Secure Production Identity Framework for Everyone) har blivit standarden för att tilldela identiteter till arbetsbelastningar.
2. Minsta möjliga behörighet (Least Privilege)
Varje process, användare och tjänst ska enbart ha de behörigheter som krävs för att utföra sin uppgift — inget mer. På Linux implementeras detta genom en kombination av SELinux/AppArmor-profiler, Linux capabilities, namespace-isolering och nätverkspolicyer som begränsar vilka tjänster som får prata med varandra.
3. Mikrosegmentering
Nätverket delas upp i små, isolerade zoner där kommunikation mellan zonerna kräver explicit tillåtelse. Istället för ett platt nätverk där alla servrar kan nå varandra skapar vi finkorniga policyer som reglerar vilken trafik som tillåts mellan enskilda tjänster.
4. Kontinuerlig verifiering
Autentisering sker inte bara vid inloggning — den pågår hela tiden. Sessioner har kort livslängd, certifikat roteras regelbundet och beteendeanalys används för att upptäcka anomalier i realtid.
5. Enhets- och arbetsbelastningsattest
Innan en arbetsbelastning får kommunicera med andra tjänster måste den bevisa sin integritet. Det kan innebära verifiering av operativsystemets tillstånd, kontroll av att binärer inte har manipulerats, eller validering genom TPM-baserad attest.
Nätverksmikrosegmentering med nftables
nftables är den moderna ersättaren för iptables och utgör grunden för brandväggshantering i Linux-kärnan sedan version 3.13. I en Zero Trust-kontext använder vi nftables för att implementera mikrosegmentering — strikta regler för vilken trafik som tillåts mellan tjänster på samma nätverk.
Grundläggande zonbaserad policy
Vi börjar med att definiera en nftables-konfiguration som följer Zero Trust-principen: neka allt som standard och sedan explicit tillåta de kommunikationsvägar som faktiskt behövs.
#!/usr/sbin/nft -f
# Rensa alla befintliga regler
flush ruleset
# Definiera variabler för tjänstezoner
define webservrar = { 10.10.1.10, 10.10.1.11 }
define appservrar = { 10.10.2.10, 10.10.2.11, 10.10.2.12 }
define databasservrar = { 10.10.3.10, 10.10.3.11 }
define overvakningsserver = { 10.10.4.10 }
table inet zero_trust {
# Kedja för inkommande trafik
chain input {
type filter hook input priority 0; policy drop;
# Tillåt etablerade och relaterade anslutningar
ct state established,related accept
# Tillåt loopback
iif lo accept
# Tillåt ICMP för diagnostik (begränsat)
ip protocol icmp icmp type { echo-request, echo-reply } \
limit rate 5/second accept
# SSH enbart från bastion-host
tcp dport 22 ip saddr 10.10.0.5 accept
# Logga och neka allt annat
log prefix "ZT-INPUT-DROP: " limit rate 10/minute
drop
}
# Kedja för vidarebefordran (east-west trafik)
chain forward {
type filter hook forward priority 0; policy drop;
ct state established,related accept
# Webservrar -> Appservrar (enbart HTTP)
ip saddr $webservrar ip daddr $appservrar tcp dport 8080 accept
# Appservrar -> Databasservrar (enbart PostgreSQL)
ip saddr $appservrar ip daddr $databasservrar tcp dport 5432 accept
# Alla zoner -> Övervakningsserver (metrics)
ip daddr $overvakningsserver tcp dport { 9090, 9100 } accept
# Logga nekad east-west trafik
log prefix "ZT-FORWARD-DROP: " limit rate 10/minute
drop
}
chain output {
type filter hook output priority 0; policy drop;
ct state established,related accept
oif lo accept
# Tillåt DNS
tcp dport 53 accept
udp dport 53 accept
# Tillåt NTP
udp dport 123 accept
# Tillåt utgående trafik till definierade zoner
ip daddr $overvakningsserver tcp dport { 9090, 9100 } accept
log prefix "ZT-OUTPUT-DROP: " limit rate 10/minute
drop
}
}
Tjänstespecifik mikrosegmentering
För ännu mer finkornig kontroll kan vi använda nftables sets och maps för att definiera exakt vilka tjänster som får kommunicera med vilka portar. Det här är faktiskt ganska elegant:
# Skapa en namngiven map för tjänst-till-tjänst-kommunikation
table inet mikrosegment {
# Set för tillåtna tjänstekombinationer
set tillaten_api_trafik {
type ipv4_addr . inet_service
elements = {
10.10.2.10 . 8080,
10.10.2.11 . 8080,
10.10.2.12 . 8080
}
}
set tillaten_db_trafik {
type ipv4_addr . inet_service
elements = {
10.10.3.10 . 5432,
10.10.3.11 . 5432
}
}
chain begrans_tjanster {
type filter hook forward priority 10; policy drop;
ct state established,related accept
# Kontrollera mot tillåtna sets
ip saddr 10.10.1.0/24 ip daddr . tcp dport @tillaten_api_trafik accept
ip saddr 10.10.2.0/24 ip daddr . tcp dport @tillaten_db_trafik accept
# Neka all annan east-west trafik
log prefix "MIKROSEG-DROP: " counter drop
}
}
Hastighetsbegränsning per tjänst
Zero Trust handlar också om att begränsa mängden trafik en tjänst kan skicka. Även om en tjänst blir komprometterad vill vi minimera skadan:
table inet rate_limiting {
chain limit_tjanster {
type filter hook forward priority 5; policy accept;
# Begränsa databasanslutningar till 100 nya per minut per käll-IP
ip daddr 10.10.3.0/24 tcp dport 5432 ct state new \
meter db_limit { ip saddr limit rate 100/minute } accept
ip daddr 10.10.3.0/24 tcp dport 5432 ct state new \
log prefix "DB-RATE-LIMIT: " drop
}
}
Spara konfigurationen och aktivera den vid systemstart:
# Spara konfigurationen
sudo nft list ruleset > /etc/nftables.conf
# Aktivera nftables-tjänsten
sudo systemctl enable nftables
sudo systemctl start nftables
# Verifiera att reglerna är aktiva
sudo nft list ruleset
WireGuard som Zero Trust-nätverkslager
WireGuard är ett modernt VPN-protokoll som är inbyggt i Linux-kärnan sedan version 5.6. Det passar utmärkt för Zero Trust-arkitekturer tack vare sin design som bygger på kryptografiskt verifierade peer-to-peer-tunnlar med cryptokey routing. Varje peer identifieras genom sin publika nyckel — inte genom IP-adresser. Och det är precis så det ska vara i en Zero Trust-värld.
Grundläggande WireGuard-konfiguration mellan servrar
Vi börjar med att skapa en krypterad tunnel mellan en appserver och en databasserver:
# På båda servrarna: installera WireGuard
sudo apt install wireguard
# Generera nyckelpar på appservern
wg genkey | tee /etc/wireguard/privkey_app | wg pubkey > /etc/wireguard/pubkey_app
chmod 600 /etc/wireguard/privkey_app
# Generera nyckelpar på databasservern
wg genkey | tee /etc/wireguard/privkey_db | wg pubkey > /etc/wireguard/pubkey_db
chmod 600 /etc/wireguard/privkey_db
Konfigurera WireGuard-gränssnittet på appservern (10.10.2.10):
# /etc/wireguard/wg0.conf på appservern
[Interface]
Address = 172.16.0.1/32
PrivateKey = <appserverns_privata_nyckel>
ListenPort = 51820
# Enbart trafik till databasservern routas genom tunneln
PostUp = nft add rule inet zero_trust input udp dport 51820 accept
PostDown = nft delete rule inet zero_trust input udp dport 51820 accept
[Peer]
# Databasservern
PublicKey = <databasserverns_publika_nyckel>
AllowedIPs = 172.16.0.2/32
Endpoint = 10.10.3.10:51820
PersistentKeepalive = 25
Konfigurera WireGuard på databasservern (10.10.3.10):
# /etc/wireguard/wg0.conf på databasservern
[Interface]
Address = 172.16.0.2/32
PrivateKey = <databasserverns_privata_nyckel>
ListenPort = 51820
# Tillåt enbart PostgreSQL-trafik genom WireGuard-tunneln
PostUp = nft add rule inet zero_trust input iifname wg0 tcp dport 5432 accept
PostDown = nft delete rule inet zero_trust input iifname wg0 tcp dport 5432 accept
[Peer]
# Appservern
PublicKey = <appserverns_publika_nyckel>
AllowedIPs = 172.16.0.1/32
Endpoint = 10.10.2.10:51820
PersistentKeepalive = 25
# Starta WireGuard på båda servrarna
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
# Verifiera tunnelstatus
sudo wg show
Cryptokey routing och Zero Trust
WireGuards design stödjer Zero Trust på flera intressanta sätt:
- Obligatorisk ömsesidig autentisering: Båda parter måste ha varandras publika nycklar konfigurerade. Ingen anonym kommunikation tillåts.
- Cryptokey routing: IP-paket mappas direkt till kryptografiska identiteter. Parametern
AllowedIPsdefinierar exakt vilka IP-adresser en peer tillåts använda — det fungerar som en inbyggd brandväggsregel. - Perfekt framåtsekretess: Varje handskakningscykel använder efemära nycklar, vilket innebär att komprometterade sessionsnycklar inte avslöjar tidigare eller framtida trafik.
- Minimal attackyta: WireGuard har cirka 4 000 rader kod jämfört med OpenVPN:s över 100 000. Det är en enorm skillnad som drastiskt minskar risken för sårbarheter.
Automatiserade mesh-nätverk med NetBird och Netmaker
Att manuellt hantera WireGuard-konfigurationer i stor skala blir snabbt ohållbart — och det är inget man vill lägga sin tid på i onödan. Verktyg som NetBird och Netmaker automatiserar skapandet av WireGuard-baserade mesh-nätverk med Zero Trust-policyer.
NetBird erbjuder ett agentbaserat system där varje nod automatiskt upprättar peer-to-peer WireGuard-tunnlar baserat på centralt definierade åtkomstpolicyer:
# Installera NetBird-agenten
curl -fsSL https://pkgs.netbird.io/install.sh | sh
# Anslut till NetBird-kontrollplanet
sudo netbird up --setup-key <din_setup_nyckel>
# Visa nätverksstatus
sudo netbird status
I NetBirds administrationsgränssnitt eller via API kan du sedan definiera åtkomstpolicyer:
# Exempel: NetBird Access Control Policy via API
# Tillåt enbart webservrar att nå appservrar på port 8080
{
"name": "web-till-app",
"description": "Tillat webservrar att na appservrar",
"rules": [
{
"name": "http-access",
"sources": ["grupp-webservrar"],
"destinations": ["grupp-appservrar"],
"bidirectional": false,
"protocol": "tcp",
"ports": ["8080"]
}
]
}
Netmaker erbjuder liknande funktionalitet men med stöd för mer avancerade nätverkstopologier:
# Installera Netmaker-klienten
curl -sL 'https://apt.netmaker.org/gpg.key' | sudo tee /etc/apt/trusted.gpg.d/netclient.asc
sudo apt install netclient
# Gå med i Netmaker-nätverket
sudo netclient join -t <anslutnings_token>
# Visa WireGuard-peers som hanteras av Netmaker
sudo wg show
Båda verktygen hanterar automatiskt nyckelrotation, peer-discovery och NAT-traversering. Det gör det praktiskt att driva WireGuard-baserade Zero Trust-nätverk med hundratals noder utan att drunkna i manuell konfigurationshantering.
Identitetsbaserad åtkomst med SPIFFE och SPIRE
I en Zero Trust-arkitektur är identitet den nya perimetern. Det är ett av de viktigaste koncepten att internalisera. SPIFFE (Secure Production Identity Framework for Everyone) definierar en standard för arbetsbelastningsidentiteter, och SPIRE (SPIFFE Runtime Environment) är referensimplementationen som utfärdar och hanterar dessa identiteter.
Förstå SPIFFE-identiteter
Varje arbetsbelastning tilldelas en SPIFFE ID i form av en URI:
spiffe://foretag.se/webb/frontend
spiffe://foretag.se/api/betalning
spiffe://foretag.se/databas/postgres
Dessa identiteter representeras som SVIDs (SPIFFE Verifiable Identity Documents) — kortlivade X.509-certifikat eller JWT-tokens som automatiskt roteras. En SVID har typiskt en livslängd på mellan 1 och 24 timmar, vilket begränsar skadan rejält om nycklar skulle komprometteras.
Installera och konfigurera SPIRE Server
# Ladda ner och installera SPIRE
curl -s -N -L https://github.com/spiffe/spire/releases/download/v1.11.0/spire-1.11.0-linux-amd64-musl.tar.gz | \
tar xz -C /opt/
# Skapa konfigurationskatalog
sudo mkdir -p /etc/spire/server
sudo mkdir -p /var/lib/spire/server
Skapa SPIRE Server-konfigurationen:
# /etc/spire/server/server.conf
server {
bind_address = "0.0.0.0"
bind_port = "8081"
trust_domain = "foretag.se"
data_dir = "/var/lib/spire/server"
log_level = "INFO"
# SVID-livslängd (1 timme)
default_x509_svid_ttl = "1h"
ca_ttl = "24h"
# JWT-utfärdarkonfiguration
jwt_issuer = "https://spire.foretag.se"
}
plugins {
DataStore "sql" {
plugin_data {
database_type = "sqlite3"
connection_string = "/var/lib/spire/server/datastore.sqlite3"
}
}
NodeAttestor "join_token" {
plugin_data {}
}
KeyManager "disk" {
plugin_data {
keys_path = "/var/lib/spire/server/keys.json"
}
}
UpstreamAuthority "disk" {
plugin_data {
key_file_path = "/etc/spire/server/dummy_upstream_ca.key"
cert_file_path = "/etc/spire/server/dummy_upstream_ca.crt"
}
}
}
Konfigurera SPIRE Agent
SPIRE Agent körs på varje nod och tillhandahåller identiteter till lokala arbetsbelastningar via en Unix Domain Socket:
# /etc/spire/agent/agent.conf
agent {
data_dir = "/var/lib/spire/agent"
log_level = "INFO"
server_address = "spire-server.foretag.se"
server_port = "8081"
trust_domain = "foretag.se"
socket_path = "/run/spire/agent/sockets/agent.sock"
}
plugins {
NodeAttestor "join_token" {
plugin_data {}
}
KeyManager "disk" {
plugin_data {
directory = "/var/lib/spire/agent"
}
}
WorkloadAttestor "unix" {
plugin_data {
discover_workload_path = true
}
}
}
Registrera arbetsbelastningar
Innan en arbetsbelastning kan få en SVID måste den registreras med specifika attestregler. Här är några exempel:
# Registrera webbtjänsten (identifieras via Unix-process UID)
spire-server entry create \
-spiffeID spiffe://foretag.se/webb/frontend \
-parentID spiffe://foretag.se/agent/webbserver-01 \
-selector unix:uid:1001
# Registrera API-tjänsten
spire-server entry create \
-spiffeID spiffe://foretag.se/api/betalning \
-parentID spiffe://foretag.se/agent/appserver-01 \
-selector unix:uid:1002 \
-selector unix:path:/usr/local/bin/betalning-api
# Registrera databasarbetsbelastning
spire-server entry create \
-spiffeID spiffe://foretag.se/databas/postgres \
-parentID spiffe://foretag.se/agent/dbserver-01 \
-selector unix:uid:999
Implementera mTLS mellan tjänster
Med SPIRE på plats kan vi konfigurera ömsesidig TLS (mTLS) mellan tjänster. Här är ett exempel i Go som visar hur en tjänst hämtar sin SVID och upprättar en mTLS-anslutning:
// Exempel: Go-klient som använder SPIFFE Workload API
package main
import (
"context"
"fmt"
"net/http"
"github.com/spiffe/go-spiffe/v2/spiffeid"
"github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig"
"github.com/spiffe/go-spiffe/v2/workloadapi"
)
func main() {
ctx := context.Background()
// Anslut till SPIRE Agent Workload API
source, err := workloadapi.NewX509Source(
ctx,
workloadapi.WithClientOptions(
workloadapi.WithAddr("unix:///run/spire/agent/sockets/agent.sock"),
),
)
if err != nil {
panic(fmt.Sprintf("Kunde inte skapa X509-källa: %v", err))
}
defer source.Close()
// Definiera vilken SPIFFE-ID vi litar på
betroddID := spiffeid.RequireFromString("spiffe://foretag.se/api/betalning")
// Skapa TLS-konfiguration med mTLS
tlsConfig := tlsconfig.MTLSClientConfig(source, source, tlsconfig.AuthorizeID(betroddID))
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
},
}
// Anropa API-tjänsten med mTLS
resp, err := client.Get("https://api-betalning.intern:8443/halsokontroll")
if err != nil {
panic(fmt.Sprintf("Begäran misslyckades: %v", err))
}
defer resp.Body.Close()
fmt.Printf("Svar: %d\n", resp.StatusCode)
}
Den här lösningen ger oss flera viktiga Zero Trust-fördelar:
- Identiteter är kryptografiskt verifierbara och inte beroende av nätverksposition
- Certifikat roteras automatiskt (standard varje timme)
- Arbetsbelastningsattest säkerställer att enbart rätt processer får rätt identiteter
- mTLS ger ömsesidig autentisering — både klient och server verifierar varandras identitet
eBPF-baserad policyhantering
eBPF (extended Berkeley Packet Filter) har ärligt talat revolutionerat hur vi implementerar säkerhetspolicyer på Linux. Genom att köra sandboxade program direkt i kärnan kan eBPF fatta beslut om nätverkstrafik, systemanrop och filåtkomst med minimal prestandapåverkan — ofta storleksordningar snabbare än traditionella iptables-kedjor.
Varför eBPF överträffar iptables för Zero Trust
Traditionella iptables-regler har betydande begränsningar i en Zero Trust-kontext:
- Linjär regelutvärdering: iptables utvärderar regler sekventiellt, så prestanda försämras med antalet regler. I mikrosegmenterade miljöer med tusentals regler blir det en rejäl flaskhals.
- Begränsad kontextmedvetenhet: iptables arbetar primärt med L3/L4-information (IP-adresser och portar). eBPF kan inspektera L7-data och fatta beslut baserat på applikationsprotokoll.
- Statisk natur: iptables-regler kräver omladdning vid ändringar. eBPF-program kan uppdateras atomiskt utan avbrott.
Cilium för nätverkspolicy i Kubernetes
Cilium är det ledande eBPF-baserade nätverksverktyget för Kubernetes och Linux. Det ersätter kube-proxy och implementerar nätverkspolicyer direkt i kärnan:
# Installera Cilium med Helm
helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium --version 1.16.5 \
--namespace kube-system \
--set kubeProxyReplacement=true \
--set hubble.enabled=true \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true
Definiera en Zero Trust-nätverkspolicy med Cilium:
# cilium-zero-trust-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "betalning-api-policy"
namespace: "produktion"
spec:
description: "Zero Trust-policy for betalnings-API"
endpointSelector:
matchLabels:
app: betalning-api
# Inkommande regler - vem får nå betalnings-API:et?
ingress:
- fromEndpoints:
- matchLabels:
app: webb-frontend
miljö: produktion
toPorts:
- ports:
- port: "8443"
protocol: TCP
rules:
http:
- method: "POST"
path: "/api/v1/betalningar"
- method: "GET"
path: "/api/v1/betalningar/[0-9]+"
- method: "GET"
path: "/halsokontroll"
# Utgående regler - vad får betalnings-API:et kommunicera med?
egress:
- toEndpoints:
- matchLabels:
app: postgres
roll: primär
toPorts:
- ports:
- port: "5432"
protocol: TCP
- toEndpoints:
- matchLabels:
app: redis
toPorts:
- ports:
- port: "6379"
protocol: TCP
# Tillåt DNS-uppslagning
- toEndpoints:
- matchLabels:
"k8s:io.kubernetes.pod.namespace": kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
rules:
dns:
- matchPattern: "*.produktion.svc.cluster.local"
Den här policyn demonstrerar L7-medveten Zero Trust: vi begränsar inte bara vilka tjänster som får kommunicera, utan även vilka HTTP-metoder och URL-sökvägar som är tillåtna. Ganska kraftfullt.
Tetragon för körtidssäkerhet
Tetragon är Ciliums kompanjonprojekt för körtidssäkerhet (runtime security). Det använder eBPF för att övervaka och upprätthålla policyer på processnivå, filåtkomst och nätverkskommunikation:
# Installera Tetragon
helm install tetragon cilium/tetragon \
--namespace kube-system \
--set tetragon.enablePolicyFilter=true
Definiera en TracingPolicy som förhindrar obehörig filåtkomst:
# tetragon-fil-policy.yaml
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: "skydda-hemligheter"
spec:
kprobes:
- call: "fd_install"
syscall: false
args:
- index: 0
type: "int"
- index: 1
type: "file"
selectors:
- matchArgs:
- index: 1
operator: "Prefix"
values:
- "/etc/shadow"
- "/etc/ssl/private"
- "/var/lib/spire"
matchActions:
- action: Sigkill
rateLimit: "1m"
- action: Post
rateLimit: "1m"
- call: "sys_execve"
syscall: true
args:
- index: 0
type: "string"
selectors:
- matchArgs:
- index: 0
operator: "NotIn"
values:
- "/usr/local/bin/betalning-api"
- "/usr/bin/node"
- "/bin/sh"
matchNamespaces:
- namespace: Pid
operator: NotIn
values:
- "host_ns"
matchActions:
- action: Sigkill
Tetragon kan även övervaka nätverksanslutningar på kärnnivå och avsluta processer som försöker upprätta otillåtna anslutningar. Det är en riktigt kraftfull mekanism för att förhindra lateral rörelse i realtid.
eBPF på icke-Kubernetes-system
Kör du Linux-servrar utan Kubernetes? Inga problem. Du kan använda bpftool och libbpf för att implementera eBPF-baserade policyer direkt:
# Visa laddade eBPF-program
sudo bpftool prog list
# Visa eBPF-kartor (maps) som används för policydata
sudo bpftool map list
# Fäst ett eBPF-program vid ett nätverksgränssnitt med tc
sudo tc filter add dev eth0 ingress bpf da obj zero_trust_filter.o sec ingress
# Inspektera eBPF-programstatistik
sudo bpftool prog show id 42 --json | jq '.run_cnt, .run_time_ns'
Kontinuerlig verifiering och övervakning
Zero Trust kräver att vi inte bara sätter upp policyer en gång och sen glömmer dem. Vi måste kontinuerligt verifiera att policyerna efterlevs och att inga avvikelser förekommer. Tre verktyg är särskilt effektiva för detta på Linux: Falco, Osquery och Wazuh.
Falco för körtidsdetektering
Falco övervakar systemanrop med eBPF och genererar varningar vid misstänkt beteende:
# Installera Falco
curl -fsSL https://falco.org/repo/falcosecurity-packages.asc | \
sudo gpg --dearmor -o /usr/share/keyrings/falco-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] \
https://download.falco.org/packages/deb stable main" | \
sudo tee /etc/apt/sources.list.d/falcosecurity.list
sudo apt update && sudo apt install falco
Skapa anpassade Falco-regler för Zero Trust-övervakning:
# /etc/falco/rules.d/zero_trust.yaml
# Detektera otillåtna nätverksanslutningar
- rule: Ej godkänd utgående anslutning
desc: >
Detekterar när en tjänst försöker ansluta till en destination
som inte finns i den godkända listan.
condition: >
evt.type in (connect) and
evt.dir = < and
fd.typechar = 4 and
not fd.sip in (10.10.1.0/24, 10.10.2.0/24, 10.10.3.0/24, 10.10.4.0/24) and
not fd.sport in (53, 123) and
container.id != host
output: >
Otillåten utgående anslutning detekterad
(process=%proc.name pid=%proc.pid användare=%user.name
anslutning=%fd.name container=%container.name
bild=%container.image.repository)
priority: WARNING
tags: [zero_trust, nätverk, lateral_rörelse]
# Detektera försök att läsa känsliga filer
- rule: Obehörig åtkomst till certifikatfiler
desc: Detekterar processer som läser SPIRE-certifikat utan behörighet
condition: >
open_read and
fd.name startswith /var/lib/spire/ and
not proc.name in (spire-agent, spire-server) and
not user.name = root
output: >
Obehörig läsning av SPIRE-certifikat
(fil=%fd.name process=%proc.name användare=%user.name)
priority: CRITICAL
tags: [zero_trust, identitet, certifikat]
# Detektera oväntade processer som lyssnar på nätverksportar
- rule: Oväntad nätverkslyssnare
desc: Detekterar processer som öppnar serverportar utanför godkänd lista
condition: >
evt.type = listen and
not proc.name in (nginx, node, betalning-api, postgres, prometheus)
output: >
Oväntad process lyssnar på nätverksport
(process=%proc.name port=%fd.sport pid=%proc.pid)
priority: ERROR
tags: [zero_trust, nätverk, obehörig_tjänst]
Osquery för kontinuerlig inventering
Osquery låter oss ställa SQL-frågor mot systemets tillstånd och kontinuerligt övervaka förändringar. Det här är ovärderligt i en Zero Trust-miljö där vi behöver verifiera att systemen faktiskt är i det tillstånd vi förväntar oss:
# /etc/osquery/osquery.conf
{
"options": {
"config_plugin": "filesystem",
"logger_plugin": "filesystem",
"schedule_splay_percent": 10
},
"schedule": {
"zt_oppna_portar": {
"query": "SELECT pid, name, local_address, local_port, remote_address, remote_port, state FROM process_open_sockets WHERE state = 'LISTEN' OR state = 'ESTABLISHED';",
"interval": 60,
"description": "Övervaka alla öppna nätverksanslutningar"
},
"zt_wireguard_status": {
"query": "SELECT interface, public_key, allowed_ips, latest_handshake, transfer_rx, transfer_tx FROM wireguard_peers;",
"interval": 300,
"description": "Kontrollera WireGuard-tunnelstatus"
},
"zt_kernel_moduler": {
"query": "SELECT name, size, status FROM kernel_modules WHERE status = 'Live';",
"interval": 3600,
"description": "Inventera laddade kärnmoduler"
},
"zt_obehaviga_suid": {
"query": "SELECT path, username, permissions FROM suid_bin WHERE path NOT IN ('/usr/bin/sudo', '/usr/bin/passwd', '/usr/bin/newgrp', '/usr/bin/chsh', '/usr/bin/chfn');",
"interval": 1800,
"description": "Hitta oväntade SUID-binärer"
},
"zt_certifikat_utgangsdatum": {
"query": "SELECT path, common_name, issuer, not_valid_after, CAST((JULIANDAY(not_valid_after) - JULIANDAY('now')) AS INTEGER) AS dagar_kvar FROM certificates WHERE path LIKE '/etc/ssl/%' AND dagar_kvar < 30;",
"interval": 86400,
"description": "Varna för certifikat som snart löper ut"
}
},
"packs": {
"incident-response": "/usr/share/osquery/packs/incident-response.conf"
}
}
Wazuh för centraliserad övervakning
Wazuh fungerar som det centrala navet för Zero Trust-övervakning. Det samlar in data från Falco, Osquery och systemloggar för att skapa en sammanhängande helhetsvy:
# /var/ossec/etc/ossec.conf (relevant utdrag)
<ossec_config>
<!-- Integrera med Falco -->
<localfile>
<log_format>json</log_format>
<location>/var/log/falco/falco.json</location>
</localfile>
<!-- Övervaka nftables-ändringar -->
<localfile>
<log_format>syslog</log_format>
<location>/var/log/kern.log</location>
</localfile>
<!-- Integritetsövervakning av kritiska filer -->
<syscheck>
<frequency>600</frequency>
<directories check_all="yes" realtime="yes">
/etc/nftables.conf,
/etc/wireguard,
/etc/spire
</directories>
<directories check_all="yes">
/usr/local/bin
</directories>
</syscheck>
<!-- Anpassade regler för Zero Trust-händelser -->
<rule id="100100" level="12">
<if_sid>86601</if_sid>
<field name="rule.tags">lateral_rörelse</field>
<description>Zero Trust: Möjlig lateral rörelse detekterad via Falco</description>
<group>zero_trust,</group>
</rule>
<rule id="100101" level="14">
<if_sid>550</if_sid>
<match>/etc/wireguard|/etc/nftables.conf</match>
<description>Zero Trust: Kritisk säkerhetskonfiguration ändrad</description>
<group>zero_trust,config_ändring,</group>
</rule>
</ossec_config>
Genom att kombinera dessa tre verktyg skapar vi ett övervakningsekosystem som ger:
- Realtidsdetektering av policyöverträdelser (Falco)
- Kontinuerlig inventering av systemtillstånd (Osquery)
- Centraliserad korrelering och varning (Wazuh)
- Historisk spårning för forensisk analys
Praktisk implementeringsplan
Att implementera Zero Trust på befintlig Linux-infrastruktur är ett stegvist arbete. Mitt starkaste råd: försök inte göra allt på en gång. Börja smått, mät effekterna och expandera gradvis.
Fas 1: Kartläggning och synlighet (vecka 1–4)
- Kartlägg alla kommunikationsvägar: Använd verktyg som
ss,conntrackoch nätverksövervakning för att dokumentera vilka tjänster som kommunicerar med varandra. - Installera övervakningsverktyg: Sätt upp Osquery och Falco i övervakningsläge (utan blockering) på alla servrar.
- Skapa en inventering: Dokumentera alla tjänster, deras beroendekedjan och vilka portar och protokoll de använder.
- Definiera zoner: Gruppera tjänster i logiska zoner baserat på funktion och säkerhetskrav.
# Kartlägg aktiva anslutningar
ss -tulnp | sort -k5
# Visa etablerade anslutningar med processinformation
ss -tnp state established
# Exportera conntrack-tabell för analys
sudo conntrack -L -o extended > /tmp/anslutningar_$(date +%Y%m%d).log
Fas 2: Grundläggande segmentering (vecka 5–8)
- Implementera nftables-policyer: Börja med generösa regler som loggar men inte blockerar (
logutandrop), och strama åt gradvis. - Sätt upp WireGuard-tunnlar: Börja med de mest kritiska kommunikationsvägarna, till exempel mellan appservrar och databaser.
- Konfigurera bastion-host: Centralisera all SSH-åtkomst genom en enda bastion-host med strikt loggning.
# Steg 1: Starta i loggningsläge
# Byt "drop" mot "log" i din nftables-policy under testperioden
chain forward {
type filter hook forward priority 0; policy accept;
# Logga trafik som SKULLE blockeras
ip saddr 10.10.2.0/24 ip daddr 10.10.3.0/24 tcp dport != 5432 \
log prefix "ZT-SKULLE-BLOCKERA: " counter
# Efter verifiering, aktivera blockering
# ip saddr 10.10.2.0/24 ip daddr 10.10.3.0/24 tcp dport != 5432 drop
}
Fas 3: Identitetsbaserad åtkomst (vecka 9–14)
- Installera SPIRE: Driftsätt SPIRE Server och Agents på alla noder.
- Registrera arbetsbelastningar: Skapa SPIFFE-identiteter för alla tjänster med lämpliga attestregler.
- Migrera till mTLS: Ersätt gradvis nätverksbaserad tillit med certifikatbaserad mTLS mellan tjänster.
- Implementera auktorisering: Skapa policyer som bestämmer vilka SPIFFE-identiteter som får kommunicera med vilka.
Fas 4: Avancerad policyhantering (vecka 15–20)
- Implementera eBPF-policyer: Lägg till Cilium eller Tetragon för finkornig L7-policyhantering.
- Automatisera policyhantering: Använd GitOps-arbetsflöden för att hantera alla policyer som kod.
- Integrera med CI/CD: Se till att nya tjänster automatiskt får identiteter och policyer vid driftsättning.
Fas 5: Kontinuerlig förbättring (pågående)
- Regelbundna penetrationstester: Testa att policyerna faktiskt förhindrar lateral rörelse.
- Automatiserad efterlevnadskontroll: Använd Osquery-scheman och Wazuh-regler för att kontinuerligt verifiera att alla system följer policyn.
- Incidentövningar: Simulera intrång och mät hur snabbt det upptäcks och begränsas. Du vill inte att första gången du testar din respons ska vara under ett riktigt angrepp.
Vanliga misstag och bästa praxis
Misstag att undvika
Misstag 1: Allt-eller-inget-mentalitet. Att försöka implementera fullständig Zero Trust på hela infrastrukturen samtidigt leder nästan alltid till misslyckande. Jag har sett det hända mer än en gång. Börja med de mest kritiska tjänsterna och expandera stegvis.
Misstag 2: Att ignorera befintliga beroenden. Innan du inför strikta mikrosegmenteringsregler måste du ha fullständig synlighet över alla tjänsters kommunikationsmönster. En oväntad blockering av en kritisk kommunikationsväg kan orsaka produktionsavbrott — och det är ingen rolig fredagskväll.
Misstag 3: Att förlita sig enbart på nätverkssegmentering. Mikrosegmentering med nftables är ett viktigt lager, men utan identitetsbaserad åtkomst och kontinuerlig verifiering har du inte en fullständig Zero Trust-arkitektur. Alla tre komponenterna behövs.
Misstag 4: Otillräcklig loggning. Zero Trust utan fullständig loggning och övervakning är som att ha lås på dörrarna men inga fönster att se igenom. Varje åtkomstbeslut — både godkända och nekade — måste loggas.
Misstag 5: Statiska åtkomstpolicyer. Zero Trust kräver dynamiska policyer som anpassar sig efter kontext. Att enbart ha statiska brandväggsregler som aldrig ändras uppfyller inte kravet på kontinuerlig verifiering.
Bästa praxis
Följande riktlinjer har visat sig vara avgörande för framgångsrika Zero Trust-implementationer på Linux:
- Behandla policyer som kod: Alla nftables-konfigurationer, WireGuard-konfigurationer, SPIRE-registreringar och Cilium-policyer ska versionshanteras i Git. Använd pull requests och kodgranskning för alla policyändringar.
# Exempel på katalogstruktur för Zero Trust-policyer zero-trust-policyer/ ├── nftables/ │ ├── bas.conf │ ├── webzon.conf │ └── databaszon.conf ├── wireguard/ │ ├── appserver-01.conf │ └── dbserver-01.conf ├── spire/ │ ├── registreringar/ │ │ ├── webbfrontend.sh │ │ └── betalning-api.sh │ └── server.conf ├── cilium/ │ ├── betalning-policy.yaml │ └── default-deny.yaml └── falco/ └── zero_trust_regler.yaml - Implementera break-glass-procedurer: Ha dokumenterade och testade nödprocedurer för att tillfälligt utöka åtkomst vid kritiska incidenter. Dessa procedurer ska kräva godkännande och loggas fullständigt.
# Exempel: Nödåtkomstskript med tidsbegränsning och loggning #!/bin/bash # break-glass.sh - Tillfällig utökad åtkomst OPERATÖR=$(whoami) ANLEDNING="$1" VARAKTIGHET="${2:-3600}" # Standard: 1 timme logger -t BREAK-GLASS "Nödåtkomst aktiverad av $OPERATÖR: $ANLEDNING" # Öppna tillfällig åtkomst nft add rule inet zero_trust forward ip saddr 10.10.0.0/16 \ ip daddr 10.10.0.0/16 accept comment \"BREAK-GLASS: $OPERATÖR\" # Schemalägg återställning at now + $((VARAKTIGHET / 60)) minutes <<SLUT nft delete rule inet zero_trust forward handle \ \$(nft -a list chain inet zero_trust forward | grep BREAK-GLASS | awk '{print \$NF}') logger -t BREAK-GLASS "Nödåtkomst avslutad för $OPERATÖR" SLUT echo "Nödåtkomst aktiverad i $VARAKTIGHET sekunder." - Automatisera certifikatrotation: Använd SPIRE:s automatiska certifikatrotation och se till att alla tjänster hanterar certifikatförnyelse utan avbrott. Övervaka certifikatens livslängd och varna proaktivt.
- Testa blockeringarna regelbundet: Använd automatiserade tester som verifierar att mikrosegmenteringsreglerna faktiskt fungerar:
# Automatiserat test av mikrosegmentering #!/bin/bash # test_mikrosegmentering.sh MISSLYCKADE=0 # Test 1: Webbserver SKA kunna nå appserver if timeout 3 bash -c "echo > /dev/tcp/10.10.2.10/8080" 2>/dev/null; then echo "[OK] Webb -> App: Tillåten trafik fungerar" else echo "[FEL] Webb -> App: Tillåten trafik blockeras!" ((MISSLYCKADE++)) fi # Test 2: Webbserver SKA INTE kunna nå databas direkt if timeout 3 bash -c "echo > /dev/tcp/10.10.3.10/5432" 2>/dev/null; then echo "[FEL] Webb -> DB: Otillåten trafik tillåts!" ((MISSLYCKADE++)) else echo "[OK] Webb -> DB: Otillåten trafik blockeras" fi # Test 3: Appserver SKA kunna nå databas if timeout 3 bash -c "echo > /dev/tcp/10.10.3.10/5432" 2>/dev/null; then echo "[OK] App -> DB: Tillåten trafik fungerar" else echo "[FEL] App -> DB: Tillåten trafik blockeras!" ((MISSLYCKADE++)) fi if [ $MISSLYCKADE -gt 0 ]; then echo "" echo "VARNING: $MISSLYCKADE test misslyckades!" exit 1 else echo "" echo "Alla mikrosegmenteringstest godkända." exit 0 fi - Övervaka WireGuard-handskakningar: En WireGuard-peer som inte har genomfört en handskakningscykel på längre tid kan indikera problem. Integrera detta i din övervakning:
# Prometheus-metrik för WireGuard-övervakning # Använd prometheus-wireguard-exporter sudo wg show all dump | awk '{ if (NR > 1) { peer=$2; senaste_handskak=$6; rx=$7; tx=$8; if (senaste_handskak > 0) { alder = systime() - senaste_handskak; if (alder > 300) { print "VARNING: Peer " peer " senaste handskakningcykel: " alder "s sedan"; } } } }' - Implementera gradvis och mät: Inför varje ny policyändring, mät baslinjeprestanda och övervaka att ingen legitim trafik påverkas. Använd Ciliums Hubble eller nftables-räknare för att kvantifiera trafikmönster.
Sammanfattning
Zero Trust på Linux är ingen enskild produkt utan en arkitekturfilosofi som implementeras genom samverkan mellan flera verktyg och tekniker. Genom att kombinera nftables för mikrosegmentering, WireGuard för krypterad kommunikation, SPIFFE/SPIRE för identitetshantering, eBPF/Cilium/Tetragon för finkornig policyhantering och Falco/Osquery/Wazuh för kontinuerlig övervakning skapar du en robust försvarsarkitektur med försvar på djupet.
Det viktigaste att ta med sig? Zero Trust är en resa, inte en destination. Börja med att förstå din nuvarande miljö, implementera grundläggande segmentering och bygg stegvis vidare mot full identitetsbaserad åtkomst och kontinuerlig verifiering. Varje steg du tar minskar attackytan och ökar din förmåga att upptäcka och begränsa intrång.
I takt med att hotlandskapet fortsätter att utvecklas under 2026 och framåt är Zero Trust inte längre ett alternativ — det är ett krav för alla som tar Linux-säkerhet på allvar.