Netfilter

Fra Wikipedia, den frie encyklopedi.

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

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

Lag din egen brannmur
Innholdsfortegnelse

Virkemåte

Netfilter-arkitekturen legger opp til at nettverkspakker som kommer inn på et nettverksgrensesnitt må passere gjennom et sett med tabeller og kjeder. I hver kjede fins det et sett med regler som pakkene blir sammenliknet med. Dersom pakkene samsvarer med en regel, kan et sett med operasjoner utføres. Dette kan innebære endring av avsender- eller mottakeradresser, aksept, avvisning og en mengde andre operasjoner.

Arkitektur

Netfilter er bygd opp som tre tabeller, hver med sin tiltenkte funksjon. Disse tre heter «filter», «nat» og «mangle». Hver enkelt tabell har et sett med «kjeder». Hver kjede inneholder et sett med brukerspesifiserte regler som pakkene blir sammenliknet 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 sammenliknes med de reglene som kommer etterpå i kjeden.

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

Tabeller og kjeder

«filter»-tabellen

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

«INPUT»-kjeden

«INPUT»-kjeden 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 denne kjeden. Pakker som skal videresendes til andre maskiner, vil ikke passere her i det hele tatt, men i stedet gjennom «FORWARD»-kjeden.

«FORWARD»-kjeden

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

«OUTPUT»-kjeden

«OUTPUT»-kjeden 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»-kjeden. Det er svært viktig å forstå denne forskjellen mellom kjedene i «filter»-tabellen.

«nat»-tabellen

«nat»-tabellen er laget for å utføre NAT (Network Address Translation). Hensikten med dette er som oftest å endre mottaker- 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»-kjeden

«PREROUTING»-kjeden har som funksjon å utføre NAT på pakker før selve IP-stacken bestemmer seg for hvor pakken skal ende opp, derav navnet «PREROUTING». Denne kjeden egner seg derfor godt til å utføre såkalt DNAT (Destination Network Address Translation). En 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 denne kjeden. De vil i stedet gå gjennom «OUTPUT»-kjeden.

«POSTROUTING»-kjeden

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

«OUTPUT»-kjeden

«OUTPUT»-kjeden 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 å merke seg forskjellen mellom «PREROUTING» og «OUTPUT», og hvilke pakker som behandles hvor.

«mangle»-tabellen

«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

Figur 1: Flytskjema for Netfilter
Enlarge
Figur 1: Flytskjema for Netfilter

Det totale flytskjemaet for forhåndsdefinerte tabeller og kjeder er gitt i figur 1. Firkanter med ekstra vertikale streker på sidene representerer kjeder. Navnet på tabellen er angitt øverst og navnet på kjeden under.

Pakker kommer inn fra et av nettverksgrensesnittene (pil) til venstre. Deretter vil de uansett gå gjennom kjedene «PREROUTING» i henholdsvis «mangle»- og «nat»-tabellene. Deretter tas en avgjørelse om 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», deretter gjennom «mangle» og «nat POSTROUTING», og 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 i forholdt til 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

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

Det fins noen operasjoner som lar pakken fortsette gjennom kjedene i samme tabell. De viktigste av disse er «LOG», «ULOG» og «TOS». Disse kommer vi tilbake til senere.

Dersom en pakke kommer til enden av en 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 med 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 hver 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 med, blir den tatt ut av kjeden og gjort noe med. Hvis pakken kommer til bunnen av kjeden uten å treffe noen regel, vil POLICY bli brukt på pakken.

Sette POLICY for en kjede

For å sette POLICY på en kjede, brukes iptables-kommandoen slik som dette:

# iptables -P INPUT DROP

Her sier vi at POLICY for «INPUT»-kjeden 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 som gjelder. Mer om dette i neste avsnitt.

Regelspesifikasjoner – en liten smaksprøve

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 aksept eller avvisning, eller et hopp til en annen kjede.

En regel legges alltid i en kjede – ikke i en tabell, siden tabeller kun inneholder kjeder. For å spesifisere en regel som skal settes inn i en 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 tabellen 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 og hvordan ting skal gjøres. Regler kan legges til, settes inn og slettes. regelspesifikasjon består av et sett egenskaper som en pakke skal sammenliknes 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»-kjeden (A = «append»). Husk at «INPUT»-kjeden er for alle pakker som vi har funnet ut skal til den lokale maskinen. Siden vi ikke har angitt tabellen, er det «filter»-tabellen som blir brukt. Etter at vi har angitt kjeden, kommer spesifikasjonen av selve regelen. Her består regelen av -p icmp. Det angir at alle pakker som er av protokollen (-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 protokollen 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»-kjeden på. I stedet for -A («append») bruker vi -I («insert»). Det vil si at regelen blir satt inn først i kjeden. Selve regelen består nå av -p tcp --dport 80. Første del kjenner vi igjen som en angivelse av protokollen. 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 tidligere velger vi å akseptere pakken. Husk at når pakken aksepteres, vil den ikke bli sammenliknet 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»-kjeden. Regelen er at pakken skal ha protokollen 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 DNAT (Destination NAT), og her angir vi at mottakeradressen 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 mottakeradresse er 192.168.42.42. Siden «PREROUTING»-kjeden i «nat»-tabellen er før rutingsavgjørelsen i flytskjemaet, vil pakken bli rutet videre som en pakke som skal videre inn på et lokalt nettverk (forutsatt, så klart, at IP-en fins 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

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

Legge til regler

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

# iptables -A INPUT -p tcp -j ACCEPT

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

# iptables -I INPUT -p tcp -j ACCEPT

Vi kan også sette inn en regel midt i en 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

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 den eksakte regelen for at iptables skal finne fram. Det er kun første forekomst som slettes. Den andre metoden er å angi regelnummer:

# iptables -D INPUT 4

Tømme en kjede («flushing»)

For å tømme en kjede helt for regler, kan vi bruke kommandoen -F («flush»):

# 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 brannmurregler i det hele tatt uten lokal tilgang (men må man, så må man ...).

Egne kjeder

I en del brannmurimplementasjoner 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 med en regel, går den tilbake til kjeden den kom fra, like under regelen som sendte den ut til den egendefinerte kjeden.

For å opprette en egen kjede kalt «kjede_navn», brukes iptables slik:

#  iptables -t nat -N kjede_navn

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

#  iptables -t nat -X kjede_navn

Oversikt over mål

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

DROP

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 som dropper alle pakker (tom regelspesifikasjon betyr at alle pakker passer regelen) sist i «INPUT»-kjeden.

ACCEPT

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!). Dette utføres med -j ACCEPT:

# iptables -A INPUT -j ACCEPT

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

REJECT

«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 oversikt over ICMP-typer (http://www.iana.org/assignments/icmp-parameters).

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

LOG

«LOG» betyr akkurat det det ser ut til – den 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 kjeden. I stedet fortsetter pakken nedover kjeden etter at loggingen er utført. Når en pakke passer til en 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 prefiks til loggmeldingen 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 fins 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

REDIRECT

«REDIRECT» brukes når en vil omdirigere trafikk som kommer inn på en port til en annen port. Dette er typisk i forbindelse med oppsett av gjennomsiktig mellomtjener eller at tjenester kjøres på ikke-standard porter. Eksempel:

# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080

DNAT

DNAT står for Destination Network Address Translation, og brukes dersom en vil forandre mottakeradressen 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ås fra Internett. DNAT må utføres i «nat»-tabellens «PREROUTING»-kjede.

I tillegg til å skrive om mottakeradressen og sende pakken videre til en maskin, vil DNAT-mekanismen også sørge for å fjerne informasjonen om at pakken ble DNAT'et 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 IP-adressen til maskinen som skal motta pakken som parameter. 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-en 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 mottaker-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.

For øvrig kan man definere hvilket grensesnitt forespørselen kommer på:

# iptables -t nat -A PREROUTING -p tcp -i <eksternt interface> --dport 21 -j DNAT --to <ip>

SNAT

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 RFC 1918 (http://www.faqs.org/rfcs/rfc1918.html)) ikke kan brukes på Internett. Man ønsker da å skrive om avsenderadressen til pakker som forlater det interne nettet slik at mottakere 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 når svaret kommer tilbake, blir det 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 DNAT'es dersom det også kommer fra 10.0.0.0/24-nettet (-s-opsjonen).

Ruting av pakker

Vær oppmerksom på at dersom brannmuren skal være i stand til å rute pakker mellom forskjellige nett, 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

«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»-kjeden i «nat»-tabellen.

Hopp til andre kjeder

Et mål trenger ikke være til en forhåndsdefinert operasjon eller kjede – man kan også sende pakker til en annen kjede for nærmere inspeksjon. Et typisk eksempel på dette er å sende alle TCP-pakker til en egen 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 en ny kjede for å se nærmere på den. Hvis pakken ikke er TCP, kan den gå til neste regel, som kanskje sender UDP-pakker til en egen kjede. Slik slipper man at alle pakker må gå gjennom alle regler. Dersom en pakke går gjennom en egendefinert kjede uten at det gjøres noe med den, sendes den tilbake til den avgivende kjeden, og vil der bli sammenliknet med den neste regelen.

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

# iptables -I INPUT -p tcp -j tcp_packets

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

Listing av regler

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           state 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           state 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»-kjeden listes først, sammen med sin POLICY og et pakkeantall som har gått gjennom kjeden. -n-parameteren 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 gis mer informasjon 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 med 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)
  • Mottakeradresse og nettmaske (destination)
  • Eventuelle tilleggsflagg

Merk at dersom en skal angi tabell (for eksempel «nat»-tabellen), må denne angis før de andre parametrene:

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

Mer om regelskriving

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å her!

Generelle regler

En av de enkleste reglene vi kan skrive undersøker hva slags protokoll en pakke har. Vi angir dette med -p-opsjonen. Gyldige parametre til denne opsjonen er navn på protokollen, eller protokollnummeret ifølge RFC 791 (se også IANAs oversikt over protokollnumre (http://www.iana.org/assignments/protocol-numbers)).

Vi kan for eksempel 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 i henhold til IP-spesifikasjonen. For de nysgjerrige er ICMP protokoll 1, TCP protokoll 6 og UDP protokoll 17.

Vi kan også inspisere avsender eller mottakeradresse 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»-kjeden i filtertabellen som dropper alle UDP-pakker som skal videre til en annen maskin fra IP-adressen 193.212.1.11. -p 17 angir protokollen 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 til mottakeradresse. Da bruker vi -d- eller --destination-opsjonene:

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

Leseren bør nå klare å dekryptere denne regelen på egen hånd!

Filtrering på grensesnitt

Ofte er det aktuelt å filtrere regler med hensyn til hvilket grensesnitt en pakke 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 bare ser 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»-kjeden, mens utgående bare kan spesifiseres i «OUTPUT»-kjeden. Begge kan angis i «FORWARD»-kjeden. 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, som skal ut eth1 og som er av protokollen TCP å passere forbi maskinen.

Felles opsjoner for TCP og UDP

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 mottaker.

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

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

Siden ICMP-pakker ikke har portnummer, kan de selvsagt ikke brukes med disse opsjonene.

Regler spesifikke for TCP

Det fins 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 parametre: Den første er en kommaseparert liste med flagg som skal inspiseres, det andre er en kommaseparert liste med flagg som må være for at pakken skal passe med 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 SYN-pakke). 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 bakoverkompatibilitetsopsjon 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 oversikt over TCP-opsjoner (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

ICMP-pakker er greie å ha med å gjøre, siden de bare har én opsjon i iptables – og det er --icmp-type. En liste over ICMP-typer er ikke denne artikkelens formål, se heller IANAs oversikt over ICMP-typer (http://www.iana.org/assignments/icmp-parameters). ICMP er den protokollen som brukes til såkalt ping – en ping-forespørsel kalles «icmp echo-request», mens svaret kalles «icmp echo-reply». Disse har henholdsvis ICMP-typene 8 og 0. Hvis vi vil blokkere 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 mye, da en del av ICMP-typene blir brukt til å sende kontrollinformasjon og metainformasjon om nettverksstatus – se RFC 792 (http://www.faqs.org/rfcs/rfc792.html) for mer informasjon om dette.

Negasjon av regler

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 å utstyre opsjonen med prefikset «!». Hvis vi vil filtrere alle pakker som ikke er TCP, gjøres det slik:

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

Legg merke til 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 parametre.

Øvrige regler

I tillegg til opsjonene som er nevnt over, fins det et lite knippe andre muligheter som vi ramser opp her:

Begrensning av regler – limit

Det er mulig å forandre hvordan filtreringen av pakker skjer med såkalt «limit matching». Dette er nyttig dersom vi for eksempel 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 sammenliknes med en bøtte som har et antall esker i seg som innkommende pakker som passer med regelen kan legges i. En pakke vil kun passe med regelen dersom det er tomme esker i bøtta. Bøtta 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 opsjonen --limit-burst. Når en regel tas ut av bøtta, fjernes også esken.

Så hvis vi har spesifisert en bøtte som det 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 kjeden. 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.

Parametrene 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

Vi kan også filtrere pakker basert på avsenders MAC-adresse. Til dette brukes opsjonen -m mac fulgt av --mac-source-opsjonen med MAC-adressen som parameter. Dette er 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 for alle pakker fra den gitte MAC-adressen.

Merkede pakker

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 en 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

Det er mulig å spesifisere flere porter i en og samme regel. Lenger oppe har vi gjort dette ved å spesifisere en kontinuerlig rekke porter, for eksempel ved hjelp av --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 sammenlikne både avsender- og mottakerport, slik at begge må stemme:

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

Filtrering på pakkens eier

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

Vi ser først på filtrering basert på den avgivende prosessens «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 bruker-ID 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 prosess-ID-er tildeles fortløpende. Dette er mest aktuelt for systemer der aktive skript går gjennom prosesser og oppdaterer iptables fortløpende. Aktuell opsjon til -m owner er:

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

Til slutt kan vi også spesifisere økt-ID, som i praksis vil si prosess-ID-en 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

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 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 IANAs oversikt over IP-parametre (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 dem 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»)

En av de viktigste forbedringene som ble introdusert med Netfilter og iptables, er muligheten til å foreta sporing av forbindelser. Dette gjør det mulig å finne ut om en pakke tilhører en eksisterende forbindelse, og om den er relatert til denne, om den er ny eller om den er 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 en Netfilter-konfigurasjon hvor «connection tracking» er slått på (dvs. at modulen er lastet eller kompilert inn i kjernen), 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 «ip_conntrack». Denne kan gjerne være kompilert statisk inn i kjernen. All klassifisering av pakker skjer enten i «PREROUTING»-kjeden eller «OUTPUT»-kjeden til «nat»-tabellen. Som et kontrollspørsmål bør leseren spørre seg selv hvilke pakker som går gjennom hvilken kjede av disse to (hint: Hvor kommer pakkene fra, og hvor skal de?).

Forklaring av tilstandene

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

«NEW»

En pakke som blir klassifisert som «NEW», vil være den første pakken som ses i en forbindelse. Et typisk eksempel på dette er SYN-pakken som blir sendt for å starte en TCP-forbindelse.

«INVALID»

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 idé å ikke tillate slike pakker.

«ESTABLISHED»

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»

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 til 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 kjernen for at man skal kunne bruke «connection-tracking».

TCP-forbindelser

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. Den 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 svaret så 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 oppmerksom på at det 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 motparten 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 128 MB RAM kan man maks holde rede på 8 192 forbindelser om gangen. Innstillingene kan justeres med en sysctl som heter ip_conntrack_max eller i filen /proc/sys/net/ipv4/ip_conntrack_max.

UDP-forbindelser

UDP er en tilstandsløs protokoll, som vil si at det ikke føres noen kontroll med hvilke pakker som kommer fram, og at det ikke er 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 mottaker.

ICMP-trafikk

ICMP er en protokoll helt uten kontroll, slik at det egentlig er feil å kalle den en forbindelse. Det fins imidlertid fire typer ICMP-pakker som vil generere returtrafikk. Disse kan også Netfilter holde rede på. 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

Vi bruker -m state fulgt av --state <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 state --state 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 forbindelser som allerede er «ESTABLISHED». Dette kan for eksempel være ICMP-pakker med informasjon om at et nett ikke kan nåes eller DCC-trafikk i forbindelse med en etablert IRC-økt.

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»-kjeden 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 --state-testen.

Spesielle protokoller – IRC og FTP

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 fins det et sett med ekstra moduler til kjernen som hjelper den med å klassifisere pakker som er relatert til disse protokollene. For FTP heter modulene ip_conntrack_ftp og ip_nat_ftp, og for IRC heter de ip_conntrack_irc og ip_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

iptables kommer med et par nyttige verktøy for å lagre og hente fram igjen oppsettet. Disse kommandoene heter iptables-save og iptables-restore, og bruker henholdsvis stdout og stdin som kilde. For å lagre iptables-oppsettet vårt, 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 fins 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 initskript som kan gjøre operasjonene over for deg. Implementasjonen for disse varierer noe, men det vanligste er at man kaller initskriptet med en 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 en «panic»-parameter til initskriptet som stenger ned for alle forbindelser!

Eksempler

Se også

Eksterne ressurser


Personal tools