Netfilter og iptables

Fra Wikipedia, den frie encyklopedi
Gå til: navigasjon, søk

Netfilter og iptables er infrastrukturen i Linux som gjør det mulig å lage brannmur og gjøre forskjellige operasjoner på nettverkspakker. Netfilter/iptables finnes i versjon 2.4 og seinere av Linux. I Linux versjon 2.2 heter tilsvarende løsning ipchains. ipchains er ikke så fleksibel og mangler en del funksjonalitet som finnes i Netfilter/iptables.

Netfilter er en arkitektur i Linux-kjernen som definerer et sett med tabeller og kjeder der det kan gjøres operasjoner på datapakker. iptables er et brukerverktøy for å manipulere disse strukturene. Denne artikkelen kommer til å omtale systemet under ett som «Netfilter», og selve kommandoen som brukes for «iptables».

Virkemåte[rediger | rediger kilde]

Netfilterarkitekturen legger opp til at nettverkspakker som kommer inn på et nettverksgrensesnitt må passere gjennom et sett med tabeller og kjeder. I hver kjede finnes det et sett med regler som pakkene blir sammenlignet med. Dersom pakkene passer til en regel, kan et sett med operasjoner utføres. Dette kan innebære endring av avsender- eller mottageradresser, aksept, nekt og en mengde andre operasjoner.

Arkitektur[rediger | rediger kilde]

Flow of network packets through Netfilter

Netfilter er bygget opp som tre tabeller, hver med sin tiltenkte funksjon. Disse tre heter «filter», «nat» og «mangle». Hver enkelt tabell har et sett med «kjeder». Hvert kjede inneholder et sett med brukerspesifiserte regler som pakkene blir sammenlignet med i rekkefølge. Dersom pakken samsvarer med regelen kan en operasjon som er gitt i samme regel utføres. I de fleste tilfeller betyr dette at pakken ikke vil sammenlignes med de reglene som kommer etterpå i kjedet.

Vi skal nå se på de forskjellige tabellene hver for seg, og til slutt se på et flytskjema som viser hvordan pakker beveger seg mellom tabellene og kjedene avhengig av hvor den kommer fra og hvor den skal.

Tabeller og kjeder[rediger | rediger kilde]

«Filter»-tabellen[rediger | rediger kilde]

filter er den viktigste tabellen hva angår å sette opp brannmur. filtertabellen inneholder som standard tre forhåndsdefinerte kjeder, som heter «INPUT», «FORWARD» og «OUTPUT». All filtrering av pakker bør skje i denne tabellen.

«Input»-kjedet[rediger | rediger kilde]

«INPUT»-kjedet behandler alle pakker som mottas og som har endelig destinasjon på samme maskin. Det vil si at kun pakker som er ment for selve maskinen som netfilter kjører på blir behandlet i dette kjedet. Pakker som skal videresendes til andre maskiner vil ikke passere her i det hele tatt, men i stedet gjennom «FORWARD»-kjedet.

«Forward»-kjedet[rediger | rediger kilde]

«FORWARD»-kjedet behandler de pakkene som kommer inn via maskinen som kjører Netfilter, men som skal videresendes til andre maskiner, enten på et lokalt eller et eksternt nett.

«Output»-kjedet[rediger | rediger kilde]

«OUTPUT»-kjedet behandler alle pakker som skal sendes fra maskinen som kjører Netfilter, og ut til en annen maskin. Det vil si at pakker som kommer fra et lokalt nett, og passerer gjennom maskinen, ikke vil behandles her, men i «FORWARD»-kjedet. Det er svært viktig å forstå denne forskjellen mellom kjedene i «filter»-tabellen.

«Nat»-tabellen[rediger | rediger kilde]

«Nat»-tabellen er laget for å utføre NAT (Network Address Translation). Hensikten med dette er som oftest å endre mottager- eller avsenderadressen til en pakke. Merk at man IKKE bør utføre filtrering av pakker her, da det kan føre til uventede resultater. nat-tabellen har i likhet med filter-tabellen tre standardkjeder, «PREROUTING», «POSTROUTING» og «OUTPUT». Kjedene har følgende funksjoner:

«Prerouting»-kjedet[rediger | rediger kilde]

«PREROUTING»-kjedet har som funksjon å utføre NAT på pakker før selve IP-stacken bestemmer seg for hvor pakken skal ende opp, derav navnet «PREROUTING». Dette kjedet egner seg derfor godt til å utføre såkalt DNAT, Destionation Network Address Translation. Typisk situasjon er at man vil rute pakker som kommer inn utenfra inn til en maskin på et lokalt nettverk. Merk at pakker som genereres på samme maskin som Netfilter kjører på ikke vil gå gjennom dette kjedet. De vil i stedet gå gjennom «OUTPUT»-kjedet.

«Postrouting»-kjedet[rediger | rediger kilde]

«POSTROUTING»-kjedet endrer på pakker etter at IP-stacken har bestemt seg for hvor den skal rutes, og er også navngitt deretter. Kjedet egner seg godt til å utføre SNAT, Source Network Address Translation. Typisk situasjon er at man vil endre avsenderadressen til en pakke som er på vei ut fra lokalnettet ut på Internett. Det finnes en variant av «SNAT» kalt «MASQUERADE», som fungerer mye på samme måte, men med et par forskjeller vi skal komme tilbake til.

«Output»-kjedet[rediger | rediger kilde]

«OUTPUT»-kjedet brukes til å utføre NAT på pakker som kommer fra den lokale maskinen, altså den samme som Netfilter kjører på. Igjen er det viktig å se forskjellen mellom «PREROUTING» og «OUTPUT», og hvilke pakker som behandles hvor.

«Mangle»-tabellen[rediger | rediger kilde]

«Mangle»-tabellen benyttes til å endre innholdet i pakkehoder. Her skal man være litt forsiktig, det er mulig å gjøre mange ting med datapakker som vil føre til merkelige resultater. «mangle»-tabellen har i likhet med filter-tabellen tre kjeder som heter «INPUT», «OUTPUT» og «FORWARD».

Totalt flytskjema[rediger | rediger kilde]

Netfilter-packet-flow.svg

Det totale flytskjemaet for forhåndsdefinerte tabeller og kjeder ser ut som i figuren. Navnet på tabellen er angitt øverst og navnet på kjeden under.

Pakker kommer inn et av nettverksgrensesnittene (pil) til venstre. Deretter vil de uansett gå gjennom kjedene «PREROUTING» i hhv mangle og nat-tabellene. Deretter skjer det en avgjørelse på hvor pakken skal sendes. Det er to alternativer: I det ene tilfellet skal den videresendes til en annen maskin, og sendes gjennom mangle og filter FORWARD, og deretter gjennom «mangle» og «nat POSTROUTING», så ut på nettverket igjen. I det andre tilfellet skal den til lokal maskin, og sendes dermed via «mangle» og filter «INPUT» til en lokal prosess.

Når en pakke kommer fra en lokal prosess følger den alltid samme mønster: Først skjer det en rutingsavgjørelse (som uansett sender pakken samme vei ifht Netfilter). Så går pakken gjennom «mangle», «nat» og «filter OUTPUT», og til slutt gjennom «mangle» og «nat POSTROUTING» og ut på nettverket (og nå kan den gjerne komme inn igjen til samme maskin på venstre side dersom den skal til samme maskin).

Mer om virkemåten til kjeder - «policy»[rediger | rediger kilde]

Hvordan virker så de forskjellige kjedene? Som nevnt har hvert kjede et sett med definerte regler. En pakke som kommer til et kjede vil bli sammenlignet med hver enkelt regel som befinner seg i kjedet helt til den kommer til en regel som passer. Denne regelen kan så gjøre en operasjon på pakken. De vanligste operasjonene er å tillate pakken eller å nekte den. I begge disse tilfeller vil pakken bli tatt ut av kjedet og ikke bli sammenlignet med flere kjeder i samme tabell. Den vil imidlertid fortsatt passere gjennom de andre tabellenes kjeder avhengig av flytskjemaet over!

Det finnes noen operasjoner som lar pakken fortsette gjennom kjedene i samme tabell – de viktigste av disse er «LOG», «ULOG» og «TOS». Disse kommer vi tilbake i et annet avsnitt.

Dersom en pakke kommer til enden av et kjede uten å ha passet med noen regel – blir den behandlet med noe som heter POLICY. Policy er det som skal gjøres med en pakke når den ikke passer til noen regel. I en fornuftig brannmur er policy som regel å droppe pakken og glemme at den eksisterte. I noen tilfeller ønsker man kanskje å si fra til avsender om at pakken ikke er godtatt. I sjeldne tilfeller kan en fornuftig policy være å tillate pakken, det vil si slippe den inn/gjennom.

Altså: For hvert kjede en pakke kommer til, går den gjennom hver enkelt regel fra topp til bunn til den passer inn i en regel. Når den treffer en regel den passer til blir den tatt ut av kjedet og gjort noe med. Hvis pakken kommer til bunnen av kjedet uten å treffe noen regel vil POLICY bli brukt på pakken.

Sette policy for et kjede[rediger | rediger kilde]

For å sette policy på et kjede brukes iptables-kommandoen slik som dette:

# iptables -P INPUT DROP

Her sier vi at policy for «INPUT»-kjedet skal være «DROP». «DROP» angir at pakker skal forkastes uten melding til avsender. Siden vi ikke angir hvilken tabell som skal brukes antar iptables at det er «filter»-tabellen det gjelder. Mer om dette i neste avsnitt.

Regelspesifikasjoner - en liten smaksprøve[rediger | rediger kilde]

Først en liten advarsel: Om du er nybegynner med iptables, skal du aldri redigere på regler uten å ha fysisk tilgang til maskinen iptables kjøres på. Hvis du gjør en feil i en regel kan du fort låse maskinen ute fra alt nett, og da er det kun et lokalt tilkoblet tastatur som kan redde deg.

Noen konvensjoner: Tabeller skrives alltid med små bokstaver, mens forhåndsdefinerte kjeder skrives med store bokstaver. Egendefinerte kjeder skrives som definert. Med et «mål» mener vi heretter en operasjon som kan utføres på en pakke. Et mål kan innebære en handling, som for eksempel akseptans eller nekt, eller et hopp til et annet kjede.

En regel legges alltid i et kjede – ikke i en tabell, siden tabeller kun inneholder kjeder. For å spesifisere en regel som skal settes inn i et kjede bruker vi kommandoen iptables. Faktisk brukes denne kommandoen til alle operasjoner på tabeller og enkeltkjeder. Når vi spesifiserer en regel, antar iptables normalt at det er filter-tabellen vi skal redigere. I motsatt fall må vi angi tabell som skal redigeres.

Den vanligste generelle formen for en iptables-kommando er:

# iptables <kommando> <regelspesifikasjon> <mål>

<kommando> utgjør som oftest en spesifikasjon over hvor ting skal gjøres, og hvordan det skal gjøres. Regler kan legges til, settes inn og slettes. <regelspesifikasjon> består av et sett egenskaper som en pakke skal sammenlignes med. Til slutt sier vi hva som skal gjøres med pakker som passer.

La oss først se på en svært enkel spesifikasjon av en regel med iptables, og se i detalj på hva den gjør:

# iptables -A INPUT -p icmp -j ACCEPT

Her ser vi at det er to ting som gjøres, -A INPUT angir at regelen som kommer skal legges til på slutten av «INPUT»-kjedet (A=append). Husk at «INPUT»-kjedet er for alle pakker som vi har funnet ut skal til den lokale maskinen. Siden vi ikke har angitt hvilken tabell er det filter-tabellen som blir brukt. Etter at vi har angitt kjedet kommer spesifikasjonen av selve regelen. Her består regelen av -p icmp. Det angir at alle pakker som er av protokoll (-p) ICMP passer til regelen. Til slutt kommer operasjonen som skal utføres, -j ACCEPT. Dette betyr at pakker som passer regelen altså skal aksepteres. Kort sagt: Aksepter alle pakker av protokoll icmp som skal til denne maskinen. La oss se på et litt mer avansert eksempel:

# iptables -I INPUT -p tcp --dport 80 -j ACCEPT

Her har vi valgt en litt annen måte å sette regelen inn i «INPUT»-kjedet. I stedet for -A (append) bruker vi -I (insert). Det vil si at regelen blir satt inn først i kjedet. Selve regelen består nå av -p tcp --dport 80. Første del kjenner vi igjen som en angivelse av protokoll. Men i stedet for icmp ser vi nå på TCP-pakker. Siste parameter, --dport angir destinasjonsport, i dette tilfellet port 80, som vi vet normalt brukes til http-trafikk. Som i sted velger vi å akseptere pakken. Husk at når pakken aksepteres, vil den ikke bli sammenlignet med flere regler i samme eller andre kjeder i denne tabellen.

La oss se på et eksempel der vi legger en regel inn i en annen tabell:

# iptables -t nat -A PREROUTING -p tcp --dport 3600 -j DNAT --to 192.168.42.42

Her har vi i begynnelsen angitt tabellen vi skal gjøre en operasjon på. Deretter sier vi at vi skal legge til en regel i «PREROUTING»-kjedet. Regelen er at pakken skal ha protokoll tcp, og skal til port 3600. Så kommer operasjonen som skal utføres, som nå er litt mer komplisert. Husk at vi tidligere har sagt at i denne tabellen (nat) skal vi kun utføre NAT. -j DNAT sier at vi skal utføre «Destination NAT», og her angir vi at mottageradressen skal skrives om til 192.168.42.42. DEt vil si at alle pakker som kommer inn av type tcp, med destinasjonsport 3600, skal skrives om slik at mottageradresse er 192.168.42.42. Siden «PREROUTING»-kjedet i nat-tabellen er FØR ruting-avgjørelsen i flytskjemaet, vil pakken bli rutet videre som en pakke som skal videre inn på et lokalt nettverk (forutsatt såklart at IPen finnes der).

I de neste avsnittene går vi i dybden på hvordan de ulike reglene skrives. Først skal vi se på de ulike operasjonene som kan gjøres på pakker.

Mer om operasjoner på kjeder[rediger | rediger kilde]

Regler kan legges til et kjede, eller slettes fra et kjede, på flere måter.

Legge til regler[rediger | rediger kilde]

For å legge til en regel til et kjede, brukes -A eller -I opsjonene. -A står for «Append», og betyr at en regel legges til på slutten av et kjede:

# iptables -A INPUT -p tcp -j ACCEPT

Hvis vi vil sette inn en regel på toppen av et kjede, kan vi bruke -I («Insert»):

# iptables -I INPUT -p tcp -j ACCEPT

Vi kan også sette inn en regel midt i et kjede, hvis vi angir regelnummeret regelen skal få (de andre reglene blir da skjøvet nedover):

# iptables -I INPUT 5 -p tcp -j ACCEPT

Slette regler[rediger | rediger kilde]

Regler kan slettes enten ved å angi hele regelen, eller ved å angi nummeret til regelen. Til dette bruker vi -D opsjonen:

# iptables -D INPUT -p tcp -j ACCEPT

Merk at når vi gjør dette, må vi angi eksakt regel for at den skal finne fram. Det er kun første forekomst som slettes. DEn andre metoden er å angi regelnummer:

# iptables -D INPUT 4

Tømme et kjede («flushing»)[rediger | rediger kilde]

For å tømme et kjede helt for regler kan vi bruke -F (flush) kommandoen:

# iptables -F INPUT

Gjør aldri dette uten lokal tilgang til maskinen! Hvis du tømmer INPUT-tabellen når den har DROP-policy, vil alle forbindelser bli sperret ute! Du kan selvsagt unngå dette ved å sette policy til ACCEPT først, men det er uansett en god regel å aldri tømme kjeder uten lokal tilgang. Strengt tatt bør man ikke redigere brannmursregler i det hele tatt uten lokal tilgang, men må man, så må man.

Egne kjeder[rediger | rediger kilde]

I en del brannmursimplementasjoner blir det utilstrekkelig å bruke kun de forhåndsdefinerte kjedene. Da kan vi opprette våre egne. Det er noen forskjeller på de forshåndsdefinerte og de egendefinerte kjedene. De viktigste er:

  • Egendefinerte kjeder kan ikke ha en egen «policy».
  • Når en pakke har passert en hel egendefinert kjede uten å passe til en regel, går den tilbake til kjedet den kom fra, like under regelen som sendte den ut til det egendefinerte kjedet.

For å opprette et eget kjede kalt «kjede_navn», brukes iptables slik:

#  iptables -t nat -N kjede_navn

Hvis vi ikke angir tabellnavn her, vil kjedet bli laget i «filter»-tabellen. For å slette et egendefinert kjede bruker vi -X kommandoen:

#  iptables -t nat -X kjede_navn

Oversikt over mål[rediger | rediger kilde]

Med et mål menes en operasjon som skal utføres på en pakke som passer til en regel. Dette kan som tidligere nevnt være at pakken sendes til et annet kjede for videre inspeksjon, eller det kan innebære en rekke andre operasjoner som vi skal gå gjennom her.

Drop[rediger | rediger kilde]

Dette er et av de enkleste målene – det betyr rett og slett at pakken droppes på gulvet og aldri mer blir plukket opp igjen. Avsender får aldri noen melding om hva som har skjedd med pakken. For å utføre dette brukes -j DROP på slutten av regelspesifikasjonen:

# iptables -A INPUT -j DROP

Her setter vi inn en regel sist i «INPUT»-kjedet som dropper ALLE pakker (tom regelspesifikasjon betyr at alle pakker passer regelen)

Accept[rediger | rediger kilde]

Dette er også et svært enkelt mål – det betyr rett og slett at pakken aksepteres. Den går dermed ikke gjennom noen andre kjeder i samme tabell (Men den går fortsatt gjennom kjeder i andre tabeller avhengig av hvor den skal rutes!). Utføres med -j ACCEPT:

# iptables -A INPUT -j ACCEPT

Her legger vi til en regel i «INPUT»-kjedet som aksepterer all trafikk (tom regelspesifikasjon).

Reject[rediger | rediger kilde]

«REJECT»-målet er en variant av «DROP». Men i motsetning til «DROP» gir denne oss muligheten til å høflig si fra til avsender at pakken har blitt avvist. Dette gjøres med en spesiell type ICMP-pakke som vi kan spesifisere med en egen opsjon, --reject-with:

# iptables -A INPUT -p tcp --dport 113 -j REJECT --reject-with icmp-host-unreachable

De gyldige opsjonene til --reject-with er:

  • icmp-net-unreachable
  • icmp-host-unreachable
  • icmp-port-unreachable
  • icmp-proto-unreachable
  • icmp-net-prohibited
  • icmp-host-prohibited

Disse er rimelig selvforklarende. Den nysgjerrige leser kan gå i dybden på dette hos IANAs icmp-parameter forklaring

Legg merke til at «REJECT» kun kan brukes i «INPUT», «OUTPUT» og «FORWARD» kjedene. I tillegg bør bruken begrenses til «filter»-tabellen.

Log[rediger | rediger kilde]

«LOG» betyr akkurat det det ser ut til – og brukes til å logge pakker. Til forskjell fra de andre målene vil en logging av en pakke IKKE føre til at pakken slutter å følge kjedet. Istedet fortsetter pakken nedover kjedet etter at loggingen er utført. Når en pakke passer til an LOG-regel vil en del informasjon om pakken bli logget via syslog. For å logge en pakke brukes -j LOG målet. Målet kan brukes alene, eller sammen med et sett opsjoner. Først et enkelt eksempel på logging uten opsjoner:

# iptables -A INPUT -p tcp --syn --dport 123 -j LOG

Her logges alle synpakker på port 123 til syslog. For å få en mer beskrivene tekst i loggen kan vi bruke --log-prefix opsjonen:

# iptables -A INPUT -p tcp --syn --dport 123 -j LOG --log-prefix "tcp syn port 123 mottatt: "

Her legger vi til et prefix til logmeldingen slik at det er lettere å lese ut av loggen hva som skjer.

Vi kan også definere hvilket loggnivå som skal brukes for loggmeldingen. Konsekvensene av å endre dette er avhengig av innstillingene til syslog. For å bruke dette benytter vi --log-level opsjonen. Denne tar som parameter et av følgende loggnivåer:

  • debug
  • info
  • notice
  • warning
  • err
  • crit
  • alert
  • emerg

For eksempel:

# iptables -A INPUT -p tcp --syn --dport 123 -j LOG --log-level info

Det finnes i tillegg opsjoner for å logge utvidet informasjon om tcp-sekvens, tcp-hoder og ip-hoder, disse er som følger:

  • --log-tcp-sequence
  • --log-tcp-options
  • --log-ip-options

Disse opsjonene tar ingen parameter:

# iptables -A INPUT -p tcp --syn --dport 123 -j LOG --log-tcp-options

Dnat[rediger | rediger kilde]

«DNAT» står for «Destination Network Address Translation», og brukes dersom vi vil forandre mottageradressen til en pakke. I de fleste tilfeller gjøres dette for å sende all trafikk som kommer inn til en brannmur eller gateway videre til en maskin på et internt nettverk som ikke kan nåes fra Internett. «DNAT» må utføres i «nat»-tabellens «PREROUTING»-kjede.

I tillegg til å skrive om mottageradressen og sende pakken videre til en maskin, vil DNAT-mekanismen også sørge for å fjerne informasjonen om at pakken ble DNATet når svaret skal sendes tilbake til den opprinnelige avsenderen.

Målet som brukes er -j DNAT, og tar som opsjon --to-destination (kortform --to med parameter som er IP-adressen til maskinen som skal motta pakken. Eksempel:

# iptables -t nat -A PREROUTING -p tcp --dport 21 -j DNAT --to 192.168.1.2

Her sender vi all trafikk som kommer til tcp port 21 videre til maskinen som har IP 192.168.1.2. Vi kan også spesifisere en port som pakken skal sendes videre til:

# iptables -t nat -A PREROUTING -p tcp --dport 21 -j DNAT --to 192.168.1.2:121

Til slutt viser vi hvordan vi kan sende en pakke videre til flere maskiner:

# iptables -t nat -A PREROUTING -p tcp --dport 21 -j DNAT --to 192.168.1.2-192.168.1.10

Her sendes pakken videre til en av maskinene fra 192.168.1.2 til 192.168.1.10, i tilfeldig mønster.

«DNAT» kan føre til rar oppførsel på et internt nett. Tenk på følgende situasjon: En brannmur settes opp til å DNAT'e alle forbindelser på tcp port 80 til en vevtjener på intern IP. Dette fungerer flott for forespørsler utenfra. Men hva skjer dersom en annen maskin på det interne nettet spør brannmuren om en forbindelse på tcp port 80? Da vil brannmuren skrive om mottager-IP til den interne vevtjenerens IP, og rute pakken dit. Vevtjeneren mottar så denne pakken, men ser at den kommer fra den interne klienten og sender svaret direkte dit. Men det er slett ikke stedet den interne klienten forventer å få svar fra, så den vil derfor ignorere svaret. Løsningen i dette tilfellet er å i tillegg gjøre SNAT på pakkene som kommer inn til brannmuren på tcp port 80, og sette brannmuren som avsender på pakkene i tillegg. Se neste avsnitt.

Snat[rediger | rediger kilde]

«SNAT» står for «Source Network Address Translation», og brukes når vi vil skrive om avsenderadressen til pakker. Som oftest gjøres dette i forbindelse med ruting av trafikk fra interne nett ut til Internett, siden IP-adresser på interne nett (Se RFC1918) ikke kan brukes på Internett. Man ønsker da å skrive om avsenderadressen til pakker som forlater det interne nettet, slik at mottagere på Internett vet hvor de skal sende svaret. «SNAT»-mekanismen til Netfilter vil så sørge for å holde følge med hvilke pakker som er sendt hvor, og sørge for at svaret, når det kommer tilbake, blir sendt til rett maskin på internt nett.

«SNAT» kan kun gjøres i «nat»-tabellens «POSTROUTING»-kjede, og gjøres med målet -j SNAT fulgt av opsjonen --to-source. La oss si at vi har et internt nett 10.0.0.0/24 som vi vil rute ut på Internett gjennom en brannmur med offentlig IP 129.241.150.176 som skal gjøre SNAT på pakkene. Det lokale nettet er på eth1, og det offentlige nettet er på eth0. Vi skriver da SNAT-regelen slik:

# iptables -t nat -A POSTROUTING -o eth0 -s 10.0.0.0/24 -j SNAT --to-source 129.241.150.176

Vi bruker her -o eth0 for å angi at all trafikk som forlater maskinen på vei ut på Internett, skal DNATes dersom det også kommer fra 10.0.0.0/24 nettet (-s opsjonen).

Ruting av pakker[rediger | rediger kilde]

Vær obs på at dersom brannmuren skal være i stand til å rute pakker mellom forskjellige nett, så må en spesiell sysctl være satt på. Denne heter ip_forward, og settes enklest på med en enkel kommando:

# echo "1" > /proc/sys/net/ipv4/ip_forward

Dersom denne fila inneholder "0", vil pakker IKKE kunne rutes mellom forskjellige nett.

Masquerade[rediger | rediger kilde]

«MASQUERADE» fungerer ganske likt med «SNAT», men med en viktig forskjell. «MASQUERADE» vil inspisere hvilket nettverksgrensesnitt pakkene forlater maskinen på, og automatisk sette korrekt IP-adresse som avsender på alle pakker som går ut. Dette er gjerne brukt i de tilfellene der brannmuren har dynamisk offentlig IP-adresse. I tillegg vil «MASQUERADE» også droppe alle aktive forbindelser dersom det utgående grensesnittet av en eller annen grunn går ned.

Fordelen er at man slipper å tenke på oppdatering av IP-adressen som skal benyttes på utgående forbindelser. Ulempen er at det vil bli gjort oppslag på hver enkelt utgående forbindelse for å finne ut hvilken IP-adresse som skal benyttes som avsenderadresse. «MASQUERADE» kan settes opp som i dette eksempelet:

# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Som i forrige eksempel spesifiserer vi her hvilket grensesnitt som går ut, og også her må regelen plasseres i «POSTROUTING»-kjedet i «nat»-tabellen.

Hopp til andre kjeder[rediger | rediger kilde]

Et mål trenger ikke være til en forhåndsdefinert operasjon eller kjede – man kan også sende pakker til et annet kjede for nærmere inspeksjon. Et typisk eksempel på dette er å sende alle tcp-pakker til et eget tcp-kjede der man kan se nærmere på tcp-flagg og andre egenskaper ved pakkene. Dette gjøres typisk for å gjøre større regelsett mer effektive – straks man har fastslått at en pakke er tcp, kan man sende den til et nytt kjede for å se nærmere på den. Hvis pakken ikke er tcp, kan den gå til neste regel, som kanskje sender udp-pakker til et eget kjede. Slik slipper man at alle pakker må gå gjennom alle regler. Dersom en pakke går gjennom et egendefinert kjede uten at det gjøres noe med den, sendes den tilbake til det avgivende kjedet, og vil der bli sammenlignet med den neste regelen der.

For å sende en pakke til et annet kjede kan vi for eksempel gjøre slik:

# iptables -I INPUT -p tcp -j tcp_packets

Dette forutsetter selvsagt at kjedet tcp_packets eksisterer. Vi kan ikke sende pakker til kjeder i andre tabeller.

Listing av regler[rediger | rediger kilde]

Når man redigerer regler i Netfilter er det viktig å kunne liste ut de reglene som er satt opp. Det gjøres også med iptables-kommandoen:

# iptables -nL -v --line-numbers
Chain INPUT (policy DROP 3758K packets, 539M bytes)
num   pkts bytes target     prot opt in     out     source               destination
1     195M  174G ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           ctstate RELATED,ESTABLISHED
2    15104  915K ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
3    3773K  540M ext_in     all  --  eth0   *       0.0.0.0/0            0.0.0.0/0

Chain FORWARD (policy DROP 18 packets, 864 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy DROP 60 packets, 3952 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1     229M  241G ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           ctstate RELATED,ESTABLISHED
2    15104  915K ACCEPT     all  --  *      lo      0.0.0.0/0            0.0.0.0/0
3     5633 1067K local_out  all  --  *      eth1    0.0.0.0/0            0.0.0.0/0
4     187K   12M ext_out    all  --  *      eth0    0.0.0.0/0            0.0.0.0/0

Når vi ikke angir tabell listes kjeden i «filter»-tabellen med tilhørende regler opp. Vi ser at «INPUT»-kjedet listes først, sammen med sin POLICY og et pakkeantall som har gått gjennom kjedet. -n parameteret angir at iptables ikke skal forsøke å slå opp ip-adressene i DNS. -L betyr at iptables skal liste reglene. -v angir at det skal gies mer info enn standard, og til slutt angir --line-numbers at reglene skal nummereres. Dette kommer til nytte dersom vi skal angi en regel som skal slettes.

For hver regel som listes angis det følgende kolonner:

  • regelnummer (num)
  • antall pakker som har passet regelen (pkts)
  • hvor mye dette utgjør i bytes (bytes)
  • operasjonen som skal gjøres på pakken (target)
  • protokollen regelen angir (prot; all betyr at alle protokoller passer)
  • opsjoner (opt; kan være flere ting, mer om dette senere)
  • Grensesnitt inn (in)
  • Grensesnitt ut (out)
  • Avsenderadresse og nettmaske (source)
  • Mottageradresse og nettmaske (destination)
  • Evt tilleggsflagg

Merk at dersom en skal angi tabell (for eksempel «nat»-tabellen) må dette angies før de andre parameterene:

# iptables -t nat -nL -v --line-numbers

Mer om regelskriving[rediger | rediger kilde]

Nå har vi sett hvordan regler settes inn i og fjernes fra kjeder, men alt dette er lite nyttig uten å kunne skrive mer kompliserte regler. Det skal vi se på i dette avsnittet :)

Generelle regler[rediger | rediger kilde]

En av de enkleste reglene vi kan skrive, undersøker hva slags protokoll en pakke har. Vi angir dette med -p opsjonen. Gyldige parameter til denne opsjonen er navn på protokollen, eller protokollnummer ifølge RFC791 (Se også IANAs liste på http://www.iana.org/assignments/protocol-numbers).

Vi kan foreksempel se på alle pakker som har IGMP som protokoll:

# iptables -I INPUT -p igmp -j ACCEPT

Husker du hva -I gjorde? Bra! Denne regelen vil akseptere alle innkommende igmp-pakker. (Merk: Det er IKKE lurt å droppe igmp-pakker!) Hvordan ville denne regelen sett ut med protokollnummer i stedet for protokollnavn? Slik:

# iptables -I INPUT -p 2 -j ACCEPT

igmp er protokoll nummer to iht. IP-spesifikasjonen. For de nysgjerrige er ICMP protokoll 1, tcp protokoll 6, og udp protokoll 17.

Vi kan også inspisere avsender eller mottageradresse på pakker. Eller begge, for den saks skyld. La oss lage en regel som ser på avsenderadressen til en pakke:

# iptables -A FORWARD -p 17 -s 193.212.1.11 -j DROP

Klarer du å se hva denne kommandoen gjør? Det stemmer. Den lager en regel sist i «FORWARD»-kjedet i filtertabellen som dropper alle udp pakker fra IP adresse 193.212.1.11 som skal videre til en annen maskin. -p 17 angir protokoll udp som forklart over, mens det nye er -s 193.212.1.11. -s er kortform for --source og spesifiserer avsenderens IP-adresse. 193.212.1.11 er forøvrig en av navnetjenerene til Telenor, så det er ikke sikkert det er så lurt å sperre for udp-pakker derfra til lokalnettet sitt ;)

Vi kan også sperre med hensyn på mottageradresse, da bruker vi -d eller --destination opsjonen:

# iptables -I OUTPUT -p 6 -d 193.212.1.11 -j ACCEPT

Leseren bør nå klare å dekode denne regelen på egen hånd ;)

Ofte er det aktuelt å filtrere regler med hensyn på hvilket grensesnitt den kommer inn eller skal ut. Vi kan bruke -i eller --in-interface for å angi hvilket grensesnitt pakken kommer inn på, og -o eller --out-interface for å angi hvilket grensesnitt pakken er rutet til å gå ut på. Husk at vi ikke forandrer på pakkene, vi ser bare på hva som allerede er satt. Legg også merke til at det er restriksjoner på hvor disse kan brukes. Innkommende grensesnitt kan bare brukes i «INPUT»-kjedet, mens utgående bare kan spesifiseres i «OUTPUT»-kjedet. Begge kan angies i «FORWARD»-kjedet. La oss se på et par eksempler:

# iptables -A INPUT -i eth0 -j ACCEPT

Vi stoler tydeligvis på eth0, for vi aksepterer alt som kommer inn derfra.

# iptables -A OUTPUT -o eth1 -p tcp -j DROP

Det gjør vi tydeligvis ikke med pakker som skal sendes ut på eth1... :)

Til slutt en titt på en regel i FORWARD, som kan bruke begge:

# iptables -I FORWARD 3 -i eth0 -o eth1 -p tcp -j ACCEPT

Her tillater vi trafikk som kommer inn eth0, og som skal ut eth1, av protokoll tcp, å passere forbi maskinen.

Felles opsjoner for tcp og udp[rediger | rediger kilde]

Det er sjelden nyttig å filtrere kun basert på protokoll. Som oftest vil vi filtrere med utgangspunkt i portnummer. Vi kan både med tcp og udp pakker filtrere med utgangspunkt i portnummer. Dette gjøres med opsjonene --source-port (kortform --sport) og --destination-port (kortform --dport). Et par eksempler:

# iptables -A OUTPUT -p udp --dport 53 -j DROP

Regelen vil droppe utgående udp-pakker som går til port 53 hos mottager.

# iptables -A INPUT -p tcp --sport 80 -j ACCEPT

Regelen aksepterer tcp-pakker som kommer fra port 80 hos avsender.

icmp-pakker har ikke portnummer og kan derfor selvsagt ikke brukes med disse opsjonene.

Regler spesifikke for tcp[rediger | rediger kilde]

Det finnes en rekke regler som er spesifikke for tcp-protokollen. Den viktigste av disse er muligheten til å spesifisere flagg som kan settes i tcp-pakker. Dette gjøres med opsjonen --tcp-flags. Opsjonen tar to parameter: DEn første er en kommaseparert liste med flagg som skal inspiseres, det andre er en kommaseparert liste med flagg som må være PÅ for at pakken skal passe til regelen. Gyldige flagg er SYN, ACK, FIN, RST, URG og PSH. I tillegg kan ALL eller NONE spesifiseres for å angi alle eller ingen av flaggene. Bruken illustreres best med et eksempel: La oss anta at vi vil filtrere pakker som har SYN-flagget satt, men ikke RST eller ACK (populært kalt en SYNpakke). Da må vi i første parameter spesifisere SYN, ACK og RST (flaggene som skal sjekkes), og i andre parameter kun SYN (det flagget som skal være på):

# iptables -A INPUT -p tcp --tcp-flags SYN,ACK,RST SYN -j DROP

Her angir vi altså at syn-pakker skal droppes. I praksis vil dette si å avvise alle forsøk på å starte en tcp-tilkobling. Fra ipchains har man beholdt en bakkompatibilitetsopsjon som heter --syn. Det vil si at regelen over kan spesifiseres på denne måten i tillegg:

# iptables -A INPUT -p tcp --syn -j DROP

I tillegg til flagg kan tcp-pakker ha et sett med opsjoner spesifisert i hodet. Å gå inn på detaljene i dette er utenfor rekkevidden til denne artikkelen, men de nysgjerrige kan se på IANAs spesifikasjon på adresse http://www.iana.org/assignments/tcp-parameters. Følgende iptables-kommando ser etter tcp-pakker med opsjon 16 (desimal) satt:

# iptables -I FORWARD -p tcp --tcp-option 16 -j DROP

Regler for icmp[rediger | rediger kilde]

icmp-pakker er takknemlige å ha med å gjøre, siden de bare har en opsjon i iptables – og det er --icmp-type. En liste over icmp-typer er ikke i denne artikkelens formål, men som vanlig har IANA en fin liste på denne adressen: http://www.iana.org/assignments/icmp-parameters. icmp er den protokollen som brukes til såkalte ping – en pingforespørsel kalles ICMP echo-request, mens svaret kalles ICMP echo-reply. Disse har icmp typer henholdsvis 8 og 0. Hvis vi vil blokke innkommende icmp-echo request gjør vi det på denne måten:

# iptables -I INPUT -p icmp --icmp-type 8 -j DROP

Forøvrig bør ikke de andre typene icmp-pakker filtreres for hardt, en del av icmp-typene blir brukt til å sende kontrollinformasjon og metainformasjon om nettverksstatus – se RFC792 for mer info om dette.

Negasjon av regler[rediger | rediger kilde]

Det er på tide å spørre om det er mulig å "snu" betydningen av regler. Kan vi for eksempel filtrere alle pakker som IKKE passer en opsjon, for eksempel at den er av protokoll tcp? Det kan vi såklart – og løsningen er å prefikse opsjonen med et utropstegn, «!». Hvis vi vil filtrere alle pakker som IKKE er tcp, gjøres det slik:

# iptables -A INPUT -p ! tcp -j ACCEPT

Merk mellomrommet mellom utropstegnet og regelspesifikasjonen. Utropstegnet berører bare den første regelen som kommer etter, så dersom vi vil filtrere alle pakker som IKKE er av type tcp og som IKKE kommer fra 127.0.0.1, gjør vi det slik:

# iptables -A INPUT -p ! tcp -s ! 127.0.0.1 -j ACCEPT

Utropstegnet kan brukes for å snu betydningen av de fleste parameter.

Øvrige regler[rediger | rediger kilde]

I tillegg til opsjonene som er nevnt over finnes det et lite knippe andre muligheter, som vi lister her:

Begrensning av regler - limit[rediger | rediger kilde]

Det er mulig å forandre hvordan filtreringen av pakker skjer med såkalt «limit matching». Dette er nyttig dersom vi for eks vil tillate maksimalt N antall tilkoblinger per minutt, eller kanskje vil begrense logging av en bestemt type trafikk når volumet overstiger en grense. «limit-matching» må settes på eksplisitt med opsjonen -m limit fulgt av en videre spesifikasjon av hvordan begrensningen skal skje.

«limit»-filtrering fungerer i all hovedsak som et «token-bucket» filter. Virkemåten kan best sammenlignes med en bøtte som har et antall esker i seg som innkommende pakker som passer regelen kan legges i. En pakke vil kun passe til regelen dersom det er tomme esker i bøtta. Tomme esker fylles på med X antall esker per tidsenhet, angitt med --limit opsjonen, forutsatt at det er plass til flere esker i den. Størrelsen til bøtta er angitt med --limit-burst opsjonen. Når en regel tas ut av bøtta fjernes også eska.

Så hvis vi har spesifisert en bøtte som fylles på med 3 esker per minutt, og som rommer maks 10 esker, kan vi tenke oss følgende eksempel:

Det ankommer 10 pakker samtidig. Alle eskene i bøtta fylles da opp, og inspiseres umiddelbart mot regelen. Bøtta er da tom. Nye pakker som ankommer like etterpå vil derfor ikke bli inspisert, og går videre til neste regel i kjedet. Etter 20 sekunder legges det en ny tom eske i bøtta, og det er da plass til en ny pakke i bøtta. Dersom det ankommer en ny pakke innen neste tomme eske legges ned i bøtta (etter ytterligere 20 sekunder) blir bøtta på ny tom. Når det ikke kommer pakker på en stund vil bøtta sakte men sikkert fylles opp med tomme esker igjen

Parameterene til --limit angis enten som et tall, eller som et tall/tidsenhet. Tidsenheten kan være sekunder («second»), minutter («minute»), time («hour») eller dag («day»). Standardvalg er 3/time, altså 3/hour.

La oss illustrere dette med et eksempel. Si at vi vil begrense antallet nye tcp-tilkoblinger til 5 per sekund, men at vi kan tillate topper på 20 pakker per sekund. Dette kan gjøres slik:

# iptables -I INPUT -p tcp --syn -m limit --limit 5/second --limit-burst 20 -j ACCEPT

Legg merke til at --limit-burst også har en maksimumsangivelse per tidsenhet, men denne er implisitt satt til samme tidsenhet som --limit.

Filtrering på MAC-adresse[rediger | rediger kilde]

Vi kan også filtrere pakker basert på avsenders MAC-adresse. Til dette brukes opsjonen -m mac fulgt av --mac-source opsjonen med parameter som er en mac-adresse. Nyttig for å gjøre bestemte ting med pakker fra et gitt nettverkskort. Eksempel:

# iptables -A INPUT -p tcp -m mac --mac-source 00:00:00:00:00:01 -j DROP

Her sperrer vi effektivt ut alle pakker fra den gitte mac-adressen.

Merkede pakker[rediger | rediger kilde]

Netfilter er i stand til å merke pakker (se eget avsnitt under). Når en pakke først har blitt merket, kan senere regler gjøre operasjoner på pakken. For å kjenne igjen en merket pakke, brukes -m mark fulgt av --mark N der N er et heltall («unsigned int» for de implementasjonsinteresserte). Som oftest blir dette brukt i «mangle»-tabellen i forbindelse med båndbreddebegrensning QoS eller endring av TOS flagg. Eksempel:

# iptables -t mangle -A INPUT -m mark --mark 1 -j marked_1_packets

Legg merke til at vi sender den merkede pakken til et egendefinert kjede – marked_1_packets.

Mark-verdiene er interne for Netfilter, og vil IKKE bli sendt videre til andre maskiner. Du kan altså ikke merke pakker som skal sendes videre siden merket vil forsvinne underveis

Multiport-spesifikasjoner[rediger | rediger kilde]

Det er mulig å spesifisere flere porter i en og samme regel. Lenger oppe har vi gjort dette ved å spesifisere en kontinuerlig rekke porter, for eks vha --dport 6889:6991. Hva gjør vi når vi skal prøve å filtrere pakker på flere porter som ikke er i rekkefølge? -m multiport redder dagen. Denne opsjonen kan settes foran både --dport og --sport. Eksempel:

# iptables -A INPUT -p tcp -m multiport --dport 20,53,80 -j ACCEPT

I tillegg til --dport og --sport kan også --port brukes sammen med -m multiport. Da vil en regel sammenligne både avsender- og mottagerport, slik at begge må stemme:

# iptables -A INPUT -p tcp -m multiport --port 20,53,80 -j ACCEPT

Filtrering på pakkens eier[rediger | rediger kilde]

Netfilter kan filtrere pakker basert på hvor pakken kommer fra – både med hensyn på bruker som eier prosessen som sender pakken, hvilken gruppe denne brukeren er i, prosessens id, eller til og med sesjons-id til prosessen som sender pakken. Merk at denne funksjonen KUN fungerer for «OUTPUT»-kjedet, siden vi ikke kan vite noe om prosess- og/eller bruker-id på andre maskiner.

Vi ser først på filtrering basert på avgivende prosess sin «user-id», eller kort «uid». Dette gjøres med -m owner --uid-owner:

# iptables -A OUTPUT -p tcp -m owner --uid-owner 501 -j DROP

Her nekter vi pakker som kommer fra prosesser eid av brukerid 501 å slippe ut. På denne måten kan vi faktisk styre i detalj hva ulike brukere på maskinen kan gjøre.

Tilsvarende kan vi filtrere på gruppe-id:

# iptables -A OUTPUT -p tcp -m owner --gid-owner 0 -j DROP

Videre kan vi filtrere på prosess-id, noe som er litt mer komplisert, siden prosessider tildeles fortløpende. Dette er mest aktuelt for systemer der aktive script går gjennom prosesser og oppdaterer iptables fortløpende. Aktuell opsjon til -m owner er Et eksempel kan være:

# iptables -A OUTPUT -p tcp -m owner --pid-owner 65 -j ACCEPT

Tilslutt kan vi også spesifisere sesjons-id, det vil i praksis si prosess-id til prosessen som eier en prosess for flertrådede prosesser (for eksempel apache):

# iptables -A OUTPUT -p tcp -m owner --sid-owner 100 -j ACCEPT

Filtrering basert på TOS og TTL flagg[rediger | rediger kilde]

De siste «vanlige» mulighetene til filtrering vi skal se på er filtrering basert på de såkalte «TOS» og «TTL» flaggene i pakker. Begge har begrenset nytteverdi for brannmursformål, men kan førstnevnte er av og til brukt i forbindelse med QoS – ofte kalt båndbreddestyring.

For å finne pakker med en bestemt TOS-type, brukes -m tos opsjonen fulgt av --tos 0xNN der NN er en tosifret heksadesimal angivelse av TOS-verdi. For mer informasjon om TOS- og TTL-verdier se http://www.iana.org/assignments/ip-parameters. Eksempel:

# iptables -A OUTPUT -m tos --tos 0x10 -j MARK --set-mark 1

Her merker vi en pakke som har TOS-verdi heksadesimalt 0x10 (desimalt 16).

TTL fungerer tilsvarende:

# iptables -A OUTPUT -m ttl --ttl 30 -j MARK --set-mark 1

Også her merker vi pakker, i dette tilfellet de som har TTL 30. Nytteverdien av dette er begrenset, men dersom behovet skulle oppstå burde eksemplet vise hvordan dette gjøres :)

Tilstandsovervåkning, connection tracking[rediger | rediger kilde]

En av de viktigste forbedringene som ble introdusert med Netfilter og iptables er muligheten til å gjøre sporing av forbindelser. Dette gjør det mulig å finne ut om en pakke tilhører en eksisterende forbindelse, om den er relatert til denne, eller om den er ny eller ugyldig. Før dette konseptet ble introdusert måtte man skrive lange kjeder med regler for å lage en god brannmur som var i stand til å skille pakker som ikke hørte sammen.

I Netfilter som har «connection tracking» slått på (dvs at modulen er lastet eller kompilert inn i kjerna) deles alle pakker inn i fire kategorier eller tilstander, som heter «NEW», «INVALID», «RELATED» og «ESTABLISHED». Selve klassifiseringen av pakker gjøres av en egen kjernemodul som kalles «nf_conntrack». Denne kan gjerne være kompilert statisk inn i kjerna. All klassifisering av pakker skjer enten i «PREROUTING»-kjedet eller «OUTPUT»-kjedet til nat-tabellen. Som et kontrollspørsmål bør leseren spørre seg selv hvilke pakker som går gjennom hvilket av disse to kjedene (Hint: Hvor kommer pakkene fra, og hvor skal de?).

Forklaring av tilstandene[rediger | rediger kilde]

La oss først se på hva de ulike tilstandene innebærer.

«New»[rediger | rediger kilde]

En pakke som blir klassifisert som «NEW» vil være den første pakken som sees i en forbindelse. Typisk eksempel på dette er syn-pakken som blir sendt for å starte en tcp-forbindelse.

«Invalid»[rediger | rediger kilde]

Dette betyr at pakken ikke kan identifiseres eller at den ikke har noen klassifisering. Som oftest skyldes dette en eller annen feil. Normalt vil det være en god ide å ikke tillate slike pakker.

«Established»[rediger | rediger kilde]

En pakke som blir klassifisert som «ESTABLISHED» tilhører en forbindelse som allerede har sett trafikk i begge retninger. Videre pakker som tilhører samme forbindelse vil da bli klassifisert som «ESTABLISHED».

«Related»[rediger | rediger kilde]

Dette er kanskje den mest kompliserte klassifikasjonen, og kanskje også den mest nyttige. For at en pakke skal klassifiseres som «RELATED» kreves det at den tilhører en annen forbindelse som er klassifisert som «ESTABLISHED». Typiske eksempler på dette er dcc-kommunikasjon som tilhører en irc-klient som allerede har opprettet en forbindelse, eller ftp-data som tilhører en opprettet ftp-kontrollforbindelse.I disse tilfellene kreves det at man laster noen hjelpermoduler til kjerna for at man skal kunne bruke «connection-tracking».

Tcp-forbindelser[rediger | rediger kilde]

tcp er en «kontrollert» protokoll – begge sider holder til enhver tid styr på hvilke pakker som er sendt og mottatt. tcp-pakker blir utstyrt med sekvensnummer som gjør at de kan settes sammen rett selv om de kommer fram i feil rekkefølge. En tcp-forbindelse åpnes alltid med noe som kalles treveis håndhilsing. Dette fungerer omtrent som følger:

  1. ene parten ber om å få opprette en forbindelse med en såkalt syn-pakke
  2. motparten svarer positivt med en syn-ack-pakke
  3. avsender kvitterer med en ack-pakke.

Hvis vi antar at første avsender her kjører en brannmur med «connection tracking», vil den første syn-pakken bli markert som «NEW» i «nat»-tabellens OUTPUT-kjede. Når så svaret kommer i form av en syn-ack pakke, vil forbindelsen ha sett trafikk i begge retninger. Siden innkommende pakker blir klassifisert i «nat»-tabellens PREROUTING-kjede vil denne pakken føre til at forbindelsen blir klassifisert som «ESTABLISHED» før syn-ack pakken kommer til «filter»-tabellen. Dermed har vi et glimrende verktøy for å slippe inn trafikk som noen på innsiden har bedt om!

Vær obs på at det slettes ikke bare er forbindelser på utsiden som kan føre til problemer – forbindelser som har sin opprinnelse på innsiden kan også kompromittere brannmuren eller nettverket ditt. Vær nøye med hva du tillater også av utgående forbindelser, og av inngående forbindelser som er «RELATED» eller «ESTABLISHED»

Merk at tcp-forbindelser også avsluttes eksplisitt, ved hjelp av FIN/ACK pakker (som motpart vil svare på med en ACK-pakke). Forbindelsen mister da sin «ESTABLISHED»-tilstand og går over til en tilstand som er intern for kjernen, «CLOSED».

Kjernen har en begrenset tabell for å holde rede på klassifikasjoner, noe som potensielt kan bli et problem for brannmurer som holder rede på mange forbindelser. Hvor stor denne tabellen er avhenger av mengde RAM på brannmuren. med 128MB RAM kan man maks holde rede på 8192 forbindelser i gangen. Innstillingene kan justeres med en sysctl som heter nf_conntrack_max eller via /proc/sys/net/netfilter/nf_conntrack_max filen.

Udp-forbindelser[rediger | rediger kilde]

udp er en tilstandsløs protokoll, det vil si at det ikke føres noen kontroll med hvilke pakker som kommer fram, og det er ikke noen kvittering på mottak. Det er heller ikke noen sekvenskontroll på udp. Netfilter kan likevel føre kontroll med trafikken og klassifisere pakker basert på avsender og mottager.

Icmp-trafikk[rediger | rediger kilde]

icmp er en protokoll helt uten kontroll, slik at det egentlig er feil å kalle den en forbindelse. Det finnes imidlertid fire typer icmp-pakker som vil generere returtrafikk. Disse kan også Netfilter holde rede på. Disse typene er som følger:

  • icmp-echo-request og -reply
  • icmp-timestamp-request og -reply
  • icmp-information-request og -reply
  • icmp-address-mask-request og -reply

Førstnevnte er den mest brukte av de fire (ping). Timestamp er utdatert og kan i de aller fleste tilfeller droppes.

Husk at icmp-pakker kan brukes for å fortelle en avsender at det er oppstått feil. For eksempel kan en icmp-net-unreachable komme i retur fra en ruter på veien dersom det ikke er mulig å nå nettet en sendt pakke skal fram til. I slike tilfeller vil icmp-pakken som kommer i retur bli merket som «RELATED», og dermed vil bruken av «connection-tracking» også kunne sørge for at slike potensielt viktige pakker kommer fram. Dette er noe man bør ha i bakhodet når man lager en brannmur. Husk også at uten korrekt bruk av «connection-tracking» kan filtrering av icmp føre til at potensielt viktige pakker ikke slippes inn av brannmuren.

Praktisk bruk[rediger | rediger kilde]

Vi bruker -m conntrack fulgt av --ctstate <tilstand> for å angi tilstandsregler. Dersom vi forutsetter at alle utgående forbindelser som er aktuelle slippes ut (Ellers vil det heller aldri komme noen syn-ack ;), kan vi slippe inn returtrafikk (både syn-ack og senere trafikk) på denne måten:

# iptables -I INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

Enkelt, ikke sant? «ESTABLISHED» vil sørge for å slippe inn direkte returtrafikk, mens «RELATED» vi slippe inn andre forbindelser som er relatert til allerede «ESTABLISHED» forbindelser. Dette kan for eks være icmp-pakker med informasjon om at nett ikke kan nåes eller dcc-trafikk i forbindelse med en etablert irc-sesjon.

Med en liten regel har vi sørget for at alle forbindelser som er forespurt internt slippes inn når det kommer svar. Dersom man kjører en brannmur for et lokalt nett må selvsagt en slik regel legges i «FORWARD»-kjedet til «filter»-tabellen. Legg også merke til at vi brukte -I for å sørge for at regelen ble lagt til først i relevant kjede. Da er vi sikret at ikke andre regler dropper pakken før den kommer til --ctstate testen.

Spesielle protokoller - irc og ftp[rediger | rediger kilde]

Det er to protokoller som krever litt spesiell omtale. irc (Internet relay chat) og ftp (file transfer protocol) fungerer på måter som gjør det ekstra vanskelig å drive med «connection tracking» (Vi skal ikke gå i detalj på dette her). Derfor finnes det et sett med ekstra moduler til kjernen som hjelper den med å klassifisere pakker som er relatert til disse protokollene. For ftp heter modulene nf_conntrack_ftp og nf_nat_ftp, og for irc heter de nf_conntrack_irc og nf_nat_irc. Dersom du lager en brannmur som skal gjøre «connection tracking» med disse protokollene må disse modulene lastes.

Lagre og hente fram igjen tabeller[rediger | rediger kilde]

iptables kommer med et par nyttige verktøy for å lagre og hente fram igjen oppsettet. Disse kommandoene heter iptables-save og iptables-restore. Disse kommandoene bruker hhv stdout og stdin som kilde. For å lagre iptables-oppsettet vårt til en fil omdirigerer vi derfor utputt fra kommandoen til en fil:

# iptables-save > iptables_save_info

For å lese inn igjen oppsettet fra samme fil:

# iptables-restore < iptables_save_info

Hva må man så gjøre for å nullstille hele oppsettet? Det er faktisk litt mer komplisert – det finnes ikke noen enkel kommando i iptables for å nullstille alt. Kort fortalt er fremgangsmåten slik:

For hver av tabellene «nat», «mangle» og «filter»: Sett policy for alle forhåndsdefinerte kjeder til ACCEPT. Tøm alle kjeder, inkludert brukerdefinerte. Slett til slutt alle brukerdefinerte kjeder.

Det er ikke noen komplisert sak å skrive et skallskript som gjør dette. Imidlertid kommer de aller fleste Linux-distribusjoner med et såkalt initscript som kan gjøre operasjonene over for deg. Implementasjonen for disse varierer noe, men det vanligste er at man kaller initscriptet med et parameter, normalt start, stop og save. Start leser da inn alle lagrede regler, stop tømmer alt og setter policy til accept, og save lagrer det nåværende regelsettet.

Noen distribusjoner har til og med et «panic»-parameter til initscriptet som stenger ned for alle forbindelser :)

Eksempler[rediger | rediger kilde]

  • Gjennomsiktig mellomtjener (transparent proxy) – få alle klientene til å bruke en mellomtjener uavhengig av klientens oppsett.

Eksterne lenker[rediger | rediger kilde]