Et åpent, men strengt bevoktet trådløst nettverk med authpf

Som så ofte ellers, ser vi at det er andre måter å konfigurere sikkerheten i det trådløse nettverket enn det vi akkurat har sett på. Det lille grann av beskyttelse som WEP-kryptering gir er de fleste med noe innsikt i IT-sikkerhet enige om stort sett bare er nyttig som et signal til angripere om at du ikke har tenkt å la alle og enhver bruke nettverksressursene dine.

En helt annen tilnærming dukket opp en dag i eposten min i en melding fra min venn Vegard Engen, som fortalte at han hadde satt opp authpf. authpf er et skall du tildeler brukere, som så gir deg mulighet til å laste PF-regler tilpasset den enkelte brukeren. Dermed får du potensielt ganske finkornet kontroll over hvem som får lov til å gjøre hva.

Hvis du vil bruke authpf, må du opprette brukere som har programmet authpf som skall. For å få adgang til nettverket logger så brukeren inn på gatewayen med ssh. Når brukeren er ferdig autentisert over ssh, laster authpf de reglene du har definert for den aktuelle brukeren eller den klassen av brukere som brukeren tilhører.

Disse reglene, som da gjelder for den IP-adressen som brukeren er logget inn fra, forblir aktive så lenge brukeren er innlogget via ssh-forbindelsen. Når forbindelsen brytes, blir reglene fjernet, og i de aller fleste scenarier blir alt annet enn ssh-trafikk fra brukerens IP-adresse sperret. Med et fornuftig oppsett vil bare trafikk som stammer fra autentiserte brukere bli sluppet gjennom.

Vegards konfigurasjon med kommentarer følger nedenfor. Hans trådløse nettverk er konfigurert uten WEP-kryptering, siden han foretrekker å håndtere sikkerheten via PF og authpf:

Start med en tom /etc/authpf/authpf.conf. Filen må eksistere for at authpf skal virke, men den trenger ikke å ha noe innhold.

De relevante delene av /etc/pf.conf følger. Først grensesnitt-makroene:

int_if="sis1"
ext_if="sis0"
wi_if = "wi0"

Hva denne adressen brukes til vil bli klart senere:

auth_web="192.168.27.20"

Den tradisjonelle authpf-tabellen

table <authpf_users> persist 

Vi kunne lagt NAT-delen i authpf.rules, men det skader ikke å beholde den i selve pf.conf:

nat on $ext_if from $wi_if:network to any -> ($ext_if)

Omdirigeringer for å å slippe gjennom trafikk til servere på det interne nettet. Disse kunne vi også lagt inn i authpf.rules, men siden de ikke faktisk gir noen tilgang uten pass-regler, skader det ikke å beholde dem her.

rdr on $wi_if proto tcp from any to $myaddr port $tcp_in -> $server
rdr on $wi_if proto udp from any to $myaddr port $udp_in -> $server

Den neste omdirigeringen sender all web-trafikk fra brukere som ikke er autentiserte, til port 80 på $auth_web. I Vegards oppsett er dette en web-server som viser kontaktinfo til de som måtte komme over det trådløse nettet ved en tilfeldighet. I mer kommersielle sammenhenger ville dette vært stedet du plasserte noe som kunne håndtere kredittkort og opprette brukere.

rdr on $wi_if proto tcp from ! <authpf_users> to any \
 port 80 -> $auth_web

Dette for å aktivere nat, binat eller omdirigeringer i authpf

nat-anchor "authpf/*"
binat-anchor "authpf/*"
rdr-anchor "authpf/*"

Videre til filtreringsreglene, og vi tar et fornuftig utgangspunkt

block all

Andre globale, brukeruavhengige regler kommer her. Så kommer authpf-ankeret, der vi sørger for at ikke autentiserte brukere som kobler seg til det trådløse grensesnittet blir omdirigert til $auth_web

anchor "authpf/*" in on wi0

pass in on $wi_if inet proto tcp from any to $auth_web \
 port 80 keep state

Det er tre ting vi uansett ønsker oss på det trådløse grensesnittet: Navnetjeneste (DNS), DHCP og SSH inn til gatewayen. Disse tre reglene sørger for det

pass in on $wi_if inet proto udp from any port 53 keep state

pass in on $wi_if inet proto udp from any to $wi_if port 67

pass in on $wi_if inet proto tcp from any to $wi_if \
 port 22 keep state

Det neste vi gjør, er å definere regler som blir lastet for alle brukere som logger inn med /usr/sbin/authpf som skall. Disse reglene går i /etc/authpf/authpf.rules,

int_if = "sis1"
ext_if = "sis0"
wi_if = "wi0"
server = "192.168.27.15"
myaddr = "213.187.n.m"

# Tjenester som lever på det interne nettet 
# og trenger å være tilgjengelige
tcp_services = "{ 22, 25, 53, 80, 110, 113, 995 }"
udp_services = "{ 53 }"
tcp_in = " { 22, 25, 53, 80, 993, 2317, pop3}"
udp_in = "{ 53 }"

# Slipp gjennom trafikk til andre steder, altså verden utenfor
pass in on $wi_if inet from <authpf_users> to ! $int_if:network \
   keep state

# La autentiserte brukere bruke tjenester på 
# det interne nettverket.

pass in on $wi_if inet proto tcp from <authpf_users> to $server \
  port $tcp_in keep state
pass in on $wi_if inet proto udp from <authpf_users> to $server \
  port $udp_in keep state

# Slipp også gjennom til ekstern adresse.  Dette betyr at du kan nå 
# interne tjenester på eksterne addesser.

pass in on $wi_if inet proto tcp from <authpf_users> to $myaddr \
    port $tcp_in keep state
pass in on $wi_if inet proto udp from <authpf_users> to $myaddr \
    port $udp_in keep state

Da har vi kommet så langt at vi har et åpent nett der alle kan koble seg til og få en IP-adresse fra DHCP. Alle HTTP-forespørsler fra brukere som ikke er autentisert blir omdirigert til port 80 på 192.168.27.20, som er en server på det interne nettet der alle forespørsler besvares med den samme siden, som viser kontaktinfo i tilfelle du ønsker å bli registrert og få tillatelse til å bruke nettet.

Du får lov til å bruke ssh inn til gatewayen. Brukere med gyldig bruker-ID og passord får lastet regelsett med passende pass-regler for den IP-adressen de har blitt tildelt.

Vi kan finjustere dette enda mer ved å lage brukerspesifikke regler i /etc/authpf/users/$bruker/authpf.rules. Brukerspesifikke regler kan bruke makroen $user_ip som står for brukerens IP-adresse. Hvis jeg for eksempel ønsker å gi meg selv ubegrenset tilgang, lager jeg en /etc/authpf/users/vegard/authpf.rules som ser slik ut:

wi_if="wi0"
pass in on $wi_if from $user_ip to any keep state