Hlavní navigace

Firewall IPFW ve FreeBSD praktickým pohledem

3. 8. 2017
Doba čtení: 7 minut

Sdílet

Běžný správce Linuxu jistě bude znát iptables. Jsou ale i jiné systémy, kde tento firewall nenajdete. Dnes bych chtěl ukázat jednu z možností v systému FreeBSD – firewall IPFW.

Proč jednu z možností? FreeBSD obsahuje v základu dokonce několik firewallů. Jsou to IPFW, PF a IPFILTER (IPF) a také dva traffic shapery – Dummynet a Altq. My si dnes ukážeme IPFW a Dummynet. Mimochodem – ipfw najdete i v macOS.

Nechci zde uvádět jeden konkrétní kompletní firewall, spíše ukázat, co vše je možné a jak je to proti iptables rozdílné. Zapomeňte na INPUT, OUTPUT, FORWARD, PREPROUTING a MANGLE. To zde nenajdete. Někoho asi napadne, zda se vůbec jedná o stavový firewall. To je samozřejmost, hledejte v manuálu známé výrazy keep-state, established nebo limit. Tím se ale zabývat nebudeme.

Rovnou začneme malou ukázkou, vypíšeme si část pravidel. K tomu slouží program  ipfw:

# ipfw show
00600    94119   131901948 allow ip from 192.168.10.0/24 to me dst-port 25 // omezeni posty
00800        1         219 unreach filter-prohib log ip from 192.168.10.0/24 to any dst-port 25
04900 10352102  1433545773 queue 1 ip from 192.168.10.0/24 to any out xmit bge0
05000 25712581 15251692928 nat 1 ip from any to any via bge0 // nat
05100 11799580 11391415570 queue 2 ip from any to 192.168.10.0/24 in recv bge0
08000 78181717 65955888439 allow ip from any to any via em0 // povolit vse interni
08300       11         440 unreach filter-prohib log logamount 100 ip from any to any out via bge0 // zbytek zakazat
08400 11274800 13008420444 allow tcp from any to any established // navazana tcp pustime
08500      391      224380 allow ip from any to any frag
65535        0           0 allow ip from any to any

Toto není kompletní firewall, ale některé věci si na výpisu vysvětlíme. Pravidla jsou číslovaná a průchod paketu firewallem probíhá v tomto pořadí. Výchozí pravidlo má číslo 65535, není možné jej smazat ani změnit („default to accept“ nebo „default to deny“). Průchod je ukončen po nalezení prvního odpovídajícího pravidla. Druhý sloupec ve výpisu je počet paketů, které pravidlu vyhoví, třetí pak počet bajtů. Pokud nás počítadla (counter) nezajímají, je možné místo show použít slovo list.

Komentáře jsou velmi užitečná vlastnost, zejména u složitých firewallů. Ke každému pravidlu je možné přidat komentář pomocí kombinace //. V našem příkladu je několik komentářů použito. Pozor na to, že za lomítky musí být mezera. Vše za dvěma lomítky až do konce řádku je komentář.

Značení karet

Z výpisu výše může linuxáře překvapit značení síťových karet, nic jako eth0, eth1 zde nenajdete. Síťové karty ve FreeBSD jsou nazývány podle čipu karty:

em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=4209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,VLAN_HWTSO>
        ether 68:05:ca:24:53:ef
        inet 192.168.10.1 netmask 0xffffff00 broadcast 192.168.10.255
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
        media: Ethernet autoselect (100baseTX <full-duplex>)
        status: active
bge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=c009b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,VLAN_HWTSO,LINKSTATE>
        ether c8:cb:b8:cc:39:60
        inet 212.x.z.y netmask 0xfffffffc broadcast 212.x.z.159
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
        media: Ethernet autoselect (100baseTX <full-duplex>)
        status: active

Např. em je karta Intel, pokud takových budete mít víc, další bude mít název em1, em2 a tak dále. Man bge prozradí toto:

bge - Broadcom BCM57xx/BCM590x Gigabit/Fast Ethernet driver

Paket může firewallem procházet i vícekrát – až čtyřikrát. Počet průchodů je dán konfigurací, zdrojem a cílem paketu. Více o tomto se dozvíte v manuálu v části PACKET FLOW. Proto si u pravidel všimněte slovíček via, xmit, recv, in a out. Tím se dá přesně určit průchod:

deny ip from any to any out recv ed0 xmit ed1

Znamená IP paket, který přišel přes kartu ed0 a bude odcházet přes ed1. In a out ještě upřesňuje směry. Recv ed0 out znamená pouze odchozí pakety přijaté přes ed0.

Číslování pravidel

Číslování pravidel hodně usnadňuje práci, je snadné vložit pravidlo kamkoli na požadované místo. V případě, že číslo nezadáte, automaticky se nastaví dle posledního pravidla + 100. Ale i tato hodnota se dá změnit.

Selektivní mazání pravidel není problém:

# ipfw delete 8300 8400

Nemusíme vypisovat nebo mazat jednotlivá pravidla, zkuste třeba

ipfw show 10000-10600

Smazání všech pravidel pak pomoci

ipfw -f flush

Ještě se může hodit třeba vynulování počítadel:

# ipfw zero

nebo

# ipfw zero cislo_pravidla

Obecný zápis pravidla vypadá takto:

[rule_number] [set set_number] [prob match_probability] action
[log [logamount number]] [altq queue] [{tag | untag} number] body

Praktické ukázky

Možností je mnoho, praktické ukázky jsou nad zlato. Ukážeme si přidání pravidla a nějaké logování. Zakážeme třeba port 25 z lan sítě:

# ipfw add 3000 deny tcp from 192.168.1.0/24 to any 25

Pokud chcete logovat toto pravidlo do /var/log/security, tak pravidlo rozšíříme:

# ipfw add 3000 deny log tcp from 192.168.1.0/24 to any 25

nebo

# ipfw add 3000 deny log logamount 0 tcp from 192.168.1.0/24 to any 25

Druhý zápis říká, kolik zachycených paketů má logovat, 0 znamená všechny. Předchozí příklad by zde vložil výchozí hodnotu (log logamount 100).

V logu pak vidíme něco podobného. Zde jsem sáhl po jiném logu, a proto akce v logu není deny, ale unreach:

May 30 14:35:14 mail kernel: ipfw: 37400 Unreach 13 UDP 10.112.0.6:123 10.190.22.8:123 in via tun12
May 30 14:38:40 mail kernel: ipfw: 37400 Unreach 13 TCP 10.112.0.6:60315 10.190.22.8:2222 in via tun12
May 30 14:38:49 mail last message repeated 2 times
May 30 14:48:58 mail kernel: ipfw: 37400 Unreach 13 TCP 10.112.0.6:60345 10.190.22.8:49155 in via tun12
May 30 14:49:00 mail kernel: ipfw: 37400 Unreach 13 TCP 10.112.0.6:60346 10.190.22.8:2222 in via tun12
Jun 29 17:05:12 gate kernel: ipfw: limit 100 reached on entry 1700

Poslední záznam logu je zajímavý, upozorňuje, že dále už se logovat nebude. To ale můžeme změnit (bez vymazání počítadel)

# ipfw resetlog 1700

Zde jsme tedy viděli zákaz tvořený pomocí deny (tiché), pak je možné použít třeba unreach s odesláním ICMP odpovědi (třeba filter-prohib). Povolení můžeme provádět slůvkem accept, pass, allow a permit. Je zde ale mnoho dalších zajímavých akcí, zmíním některé.

count – vhodné pro debug v kombinaci s log. Pravidlo dále pokračuje firewallem, pouze se zvyšují počítadla.

skipto – velmi užitečná věc u velkých firewallů, ukázka vysvětlí vše:

# ipfw add skipto 5001 tcp from 192.168.10.99 to any 25
# ipfw add 5000 deny tcp from 192.168.10.0/24 to any 25

Tím jsme udělali výjimku pro IP 192.168.10.99, která teď může mailovat. Pokud by se jako akce u prvního pravidla dalo permit, paket by dále firewallem neprocházel a tím se například nedostal do natu.

divert, nat – ipfw umí i nat. Napřed definice natu s nějakým portforwardem

# ipfw nat 1 config ip VE.RE.JNA.IP same_ports unreg_only redirect_port tcp 192.168.1.1:3389 57463

a pak vlastní pravidlo, re0 je síťová karta do internetu:

# ipfw add 30000 nat 1 all from any to any via re0 // nat

I zde je mnoho možností, zmíním jen starší variantu natu – ipdivert. Ta ale běží v userlandu, takže je zde mnohem větší režie než s novějším kernel-natem výše.

setdscp – umožňuje nastavit nebo změnit hodnotu DSCP v hlavičce paketu. Po nastavení paket neopouští firewall, ale pokračuje dalšími pravidly.

setfib – v systému můžete mít třeba více cest do internetu a i více rotovacích tabulek. Tímto můžete určit FIB (routovací tabulku), která

bude použita. O tom už jsem kdysi napsal v článku Využití dvou internetových připojení (ve FreeBSD).

tee – můžete si udělat kopii paketu a tu si poslat kam chcete, původní paket jde dál firewallem.

Tím jsme probrali pouze část akcí, které je možné s daty dělat. Na závěr jsem si nechal pipe a queue. To už je součást Dummynetu, tedy traffic shaping a packet scheduler.

Pipe a Queue

Můžeme si definovat pipe (vlastně linku) o různé šířce, zpomalení a dokonce packet loss a uživatelská data do nich strkat:

# ipfw pipe 20 config bw 39000Kbit/s
# ipfw add pipe 10 ip from 192.168.1.1 to any via em0

Tím jsme IP provoz adresy 192.168.1.1 prohnali přes pipe o šířce 39 Mbitů.

Queue se pak předřazují před pipe a každá má svou váhu. Velmi pěkné použití je třeba takto pro základní fair user policy:

# ipfw pipe 1 config bw 70Mbit/s
# ipfw queue 1 config pipe 1 mask src-ip 0xffffffff weight 1 queue 256KBytes
# ipfw add queue 1 ip from 192.168.3.0/24 to any out xmit em0

Provoz každé IP v síti 192.168.3.0/24 získá vlastní dynamickou frontu se stejnou prioritou a délkou a všechny jsou navázané na pipe 1. Pokud chceme kontrolovat obě strany, je nutné udělat i pipe a queue pro opačný směr.

Můžete samozřejmě omezovat nebo prioritizovat i na úrovni jednotlivých služeb. Jde si snadno nasimulovat i například úzkou, pomalou a zároveň chybující linku.

CS24_early

# ipfw pipe 1 config loss-level 0.5 delay 250ms bw 1Mbit/s

Ještě malé upozornění – ve výchozí konfiguraci je akce pipe považována za accept a paket opouští firewall. To je ale ve spoustě konfigurací nežádoucí a po omezení jej chceme dále zpracovávat. Je tedy nutné toto chování vypnout:

# ipfw disable one_pass

ipfw -f flush

Byl pro vás článek přínosný?

Autor článku

Petr Macek studoval aplikovanou informatiku na Jihočeské univerzitě, pracuje jako síťový specialista ve firmě Kostax, s. r. o. Baví ho především FreeBSD, sítě a monitoring Cacti.