Začínáme bezpečně s FreeBSD (9)

7. 9. 2004
Doba čtení: 11 minut

Sdílet

V předchozích dvou dílech jste si určitě nainstalovali kupu síťových démonů, kteří nyní čekají na příchozí spojení. Samozřejmě si je již umíte vypsat, ale ještě jsme si neřekli nic o pravidlech síťového provozu, filtrování paketů neboli o IPFW, IPFilteru a nově i PF.

Poznámka

IPFilter je vybrán z toho důvodu, že momentálně tento seriál běží na FreeBSD 4.10; FreeBSD 5.x přináší spoustu skvělých zlepšení, včetně asi nejlepšího open-source řešení – PF z OpenBSD. Mimo to IPFilter a PF používají téměř totožnou syntaxi pravidel, takže následný přechod na PF bude snadný.

Jádro a síťové funkce

Ve 4. dílu seriálu, ve kterém jsme se věnovali příznakům souborů ( chflags), jsme při zmínce o bezpečnostní úrovni (securelevel) narazili na pojem sysctl – parametry jádra (sysctl MIB). Změna některých parametrů jádra může změnit funkci/výkon běžícího systému i bez sestavení pozměněného kernelu nebo konfigurace démonů. Tyto parametry můžete prohlédnout:

srot# sysctl -A | head
kern.ostype: FreeBSD
kern.osrelease: 4.10-RELEASE-p2
kern.osrevision: 199506
kern.version: FreeBSD 4.10-RELEASE-p2 #1: Sun Aug 8 18:59:56 CEST 2004
hospodin@srot.blackbox.qc.to: /usr/obj/sources/stable/src/sys/SROT
kern.maxvnodes: 6206
kern.maxproc: 708
kern.maxfiles: 1416
kern.argmax: 65536 

Některé parametry jsou zjevné, některé méně. Celý sysctl MIB strom je rozdělen do větví, např. kern, vm (virtuální pamět), vfs (soubor. systémy) nebo net. Právě některé položky z net větve pracují s TCP/IP stackem a mohou tak změnit síťové chování systému (výkon nebo v našem případě práci s pakety).

srot# sysctl net.inet
net.inet.ip.portrange.lowfirst: 1023
net.inet.ip.portrange.lowlast: 600
net.inet.ip.portrange.first: 1024
net.inet.ip.portrange.last: 5000
...zkraceno... 

Pomocí příkazu sysctl tedy můžeme položky číst nebo nastavovat. Jestliže bychom chtěli permanentní nastavení (tj. i po restartu), můžeme je přidat do /etc/sysctl.conf. Některé položky tedy jsou (hodnotami položek jsou buď řetězce, celá čísla, binární hodnoty [ 0– vypnuto, 1  – zapnuto] nebo hodnoty ve strojovém kódu):

net.inet.ip.forwarding: 1
schopnost jádra předávat pakety z jednoho iface na druhý
net.inet.ip.check_interface: 1
kontrola, zda má iface stejnou adresu, jako je cílová adresa přicházejího paketu
net.inet.ip.stealth: 0
v případě, že zapnute tuto volbu, musíte mít IPSTEALTH v jádře; volba dovoluje stealth fwd, např. při traceroute nebude sníženo TTL
net.inet.icmp.drop_redirect: 1
nepřijímání žádných přesměrovávacích ICMP paketů
net.inet.icmp.icmplim: 200
nastavuje počet paketů za sec, které jádro obslouží, v případě logů po DoS nebo skenu se doporučuje zvýšit
net.inet.tcp.log_in_vain=1
loguje přístupy na porty, na kterých nenaslouchá démon
net.inet.udp.log_in_vain=1
loguje přístupy na porty, na kterých nenaslouchá démon. Jde zapnout i log_in_vain=„YES“ v /etc/rc.conf
net.inet.tcp.blackhole=1
umožňuje, aby byly pakety na neobsazené porty ztraceny
net.inet.udp.blackhole=1
umožňuje, aby byly pakety na neobsazené porty ztraceny. Povolení blackhole pro UDP znemožní traceroute na váš stroj, více man blackhole
net.inet.tcp.syncookies=1
ochrana proti SYN flood

Jemným laděním můžete zlepšit síťové funkce systému a ochránit jej proti různým útokům. Článek, který zmiňuje sysctl MIB, je zde. Některé položky sysctl MIB jsou zapínány také díky nastavením v /etc/rc.conf. Když budete mít v /etc/rc.conf  položku gateway_enable="YES", příslušný síťový skript – /etc/rc.network  – přečte tuto položku z konfiguračního souboru a nastaví sysctl MIB položku net.inet.ip.forwarting na 1 (povoleno), příslušná část z /etc/rc.network:

case ${gateway_enable} in
   [Yy][Ee][Ss])
   echo -n ' IP gateway=YES'
   sysctl net.inet.ip.forwarding=1 >/dev/null
   ;;
   esac

TCP Wrapper

Některé programy jsou zkompilovány s podporou TCP Wrapper – knihovny libwrap. Ta přicházející požadavky na démona zkontroluje vůči svému konfiguračnímu souboru /etc/hosts.allow a pak je případně předá dále příslušnému démonu. V dnešní době s nasazením výkonných fw tento postup trochu ztrácí význam. Dále se takové řešení nachází hlavně v DMZ za kvalitním fw. V případě, že byste přesto chtěli použít libwrap, poskytne vám více informací man 5 hosts_access nebo tato stránka .

IPFilter

Základní úkony

IPFilter je program, který má schopnost filtrovat pakety nebo dělat NAT. Je standardní součástí FreeBSD. Není ovšem součástí jádra GENERIC, můžete jej tam přidat a posléze zkompilovat přidáním následných řádků:

options IPFILTER #ipfilter support
options IPFILTER_LOG #ipfilter logging

nebo můžete použít kernel modul (KLD) – ipl  –nachází se v /modules. Příkaz na načtení modulu je:

srot# kldload -v /modules/ipl.ko
Loaded /modules/ipl.ko, id=5
srot# kldstat -vi 5
Id Refs Address Size Name
5 1 0xc1197000 18000 ipl.ko
Contains modules:
Id Name
215 IP Filter: v3.4.31 

Nyní máte modul načtený včetně informace o jeho verzi. IPFilter obsahuje sadu několika nástrojů, které vám pomohou při testování, logování či přehledu zpracovávaných paketů. Nejdůležitější nástroje jsou:

ipf
načítá seznam pravidel z stdin nebo souboru (defaultně /etc/ipf.rules) a předává je jádru. Může být použito i na smazání pravidel
ipnat
načítá seznam pravidel z stdin nebo souboru (defaultně /etc/ipnat.rules) a předává je jádru. Může být použito i na smazání pravidel
ipmon
čte logované pravidla z /dev/ipl a může je předat na stdout, do souboru nebo logovacímu démonu
ipfstat
statistika procházejících paketů
ipftest
načítá ipf pravidla ze souboru a předává je na testování

Mezi další obslužné programy IPFilteru patří ipsend, ipresend a iptest. Dalším programem je ipf s, který ukládá informace pro NAT a stavovou tabulku. K IPFilteru se váže několik položek pro  /etc/rc.conf:

ipfilter_enable="NO" # Set to YES to enable ipfilter functionality
ipfilter_program="/sbin/ipf" # where the ipfilter program lives
ipfilter_rules="/etc/ipf.rules" # rules definition file for ipfilter, see # /usr/src/contrib/ipfilter/rules for examples
ipfilter_flags="" # additional flags for ipfilter
ipnat_enable="NO" # Set to YES to enable ipnat functionality
ipnat_program="/sbin/ipnat" # where the ipnat program lives
ipnat_rules="/etc/ipnat.rules" # rules definition file for ipnat
ipnat_flags="" # additional flags for ipnat
ipmon_enable="NO" # Set to YES for ipmon; needs ipfilter or ipnat
ipmon_program="/sbin/ipmon" # where the ipfilter monitor program lives
ipmon_flags="-Ds" # typically "-Ds" or "-D /var/log/ipflog"
ipfs_enable="NO" # Set to YES to enable saving and restoring
ipfs_program="/sbin/ipfs" # where the ipfs program lives
ipfs_flags="" # additional flags for ipfs 

Pravidla

Jak již bylo řečeno, pravidla se defaultně ukládají do /etc/ipf.rules. Před samotným psaním pravidel je třeba si ujasnit politiku filtrování. Jinak budou vypadat pravidla, jestliže přesně víme, z jakých IP adres se bude kdo připojovat, a jinak budou vypadat pravidla, jestliže jsou psána např. pro webový server, na který se bude moci připojit kdokoliv.

V našem případě si zavedeme následující politiku (v tomto případě si IP adresy vymyslíme): máme 192.168.17.128 pro venkovní rozhraní a alias na něj s 192.168.17.129­. Budeme uvažovat takto (nyní trochu předběhneme náš seriál), na aliasované IP adrese máme vybudovaný jail (něco jako virtuální subsystém) a do něj povolíme přístup z veškerých IP adres, na druhou stranu do hostitelského systému (hlavního systému) přístup povolíme pouze z jailu a z místní sítě.

Samotný řádek, na kterém, je jedno pravidlo se skládá z několika částí:

akce směr volby protokol zdroj cíl další_volby

Každá část má vyčerpávající možnosti, my se však zaměříme na ty základní, podrobnosti v man 5 ipf  nebo zde.

Základní volby jednotlivých částí pravidla

Tabulka č. 595
akce block
pass
blokuj
povol
směr out
in
ven
dovnitř
volby log
quick


on
logovat
ukončí procházení pravidel tímto pravidlem
určuje síťové rozhraní
protokol $protokol název protokolu z /etc/protocols (např. icmp, tcp, udp...)
zdroj any/IP zdroj paketu
cíl any/IP cíl paketu
další volby with short

with ipopts


keep state


keep frags


flags
příliš krátké pakety
pakety obsahující volby IP protokolu
uloží informaci do stavové tabulky
uloží informaci o fragmetovaných paketech
identifikování podle příznaku paketu

Několik skutečností ohledně pravidel IPFilteru. Některé položky není nutné specifikovat, můžeme některé volby vynechat nebo nahradit all. Dále je nutné vědět, že paket prochází všechna pravidla (pokud není určeno jinak) až do posledního, tzn. že jestliže např. jedno pravidlo vstup zakáže a další povolí, ipf to vyhodnotí jako povoleno. Příklad:

pass in all
block in all
pass in all

I při takto ujeté konstrukci ipf nakonec vezme poslední pravidlo a paket povolí. Řešením je zmiňovaná volba quick, která pročítání pravidel ukončí a provede akci tohoto pravidla.

pass in all
block in all
pass in quick all
block in all

IPFilter dojde až na pravidlo obsahující volbu quick a tam svou činnost pro tento paket ukončí a provede příslušnou akci –povolí vše dovnitř. Nyní si ukážeme jednotlivé kombinace (v rámci popisu):

pass in quick on lnc0 all

Přečte pravidlo, ukončí procházení a povolí veškeré pakety přicházející na síťové rozhraní  lnc0

pass in quick on lnc0 proto tcp all

Viz výše plus pakety musí být TCP protokolu

pass in quick on lnc0 proto tcp from 81.27.192.47 to any 

Předcházející pravidlo bylo obohaceno o požadavek, že paket musí přicházet z uvedené IP adresy

pass in quick on lnc0 proto tcp from 81.27.192.47 to 192.168.17.129 

Přicházející paket musí být rovněž směrován na specifikovanou IP adresu

pass in quick on lnc0 proto tcp from 81.27.192.47 to 192.168.17.129 port = www 

Může specifikovat i cílový port, buď číselně, nebo pomocí zkratky v /etc/services

pass in quick on lnc0 proto tcp from 81.27.192.47 to 192.168.17.129 port = www keep state 

K předešlému pravidla přidáme ještě požadavek na uložení informace do stavové tabulky.

Kombinace jsou rozmanité. Nyní se vrhneme na základní rozdělení pravidel. Různé příklady najdete v  /usr/share/examples/ipfilter.

ict ve školství 24

# odmitneme a logujeme nestandardni odpad, tj. prilis
# kratke pakety a pakety s IP s volbami IP protokolu
block in log quick from any to any with short
block in log quick proto tcp from any to any with ipopts

# na loopbacku vse povoleno, nutne pro funkcnost
# mnoha programu
pass in quick on lo0 all
pass out quick on lo0 all

# odfiltrujeme odpad odchazejici od nas ven
block out quick on lnc0 from 192.168.1.0/24 to any
block out quick on lnc0 from any to 0.0.0.0/7
block out quick on lnc0 from any to 2.0.0.0/8
block out quick on lnc0 from any to 5.0.0.0/8
block out quick on lnc0 from any to 10.0.0.0/8
block out quick on lnc0 from any to 23.0.0.0/8
block out quick on lnc0 from any to 27.0.0.0/8
block out quick on lnc0 from any to 31.0.0.0/8
block out quick on lnc0 from any to 69.0.0.0/8
block out quick on lnc0 from any to 70.0.0.0/7
block out quick on lnc0 from any to 72.0.0.0/5
block out quick on lnc0 from any to 82.0.0.0/7
block out quick on lnc0 from any to 84.0.0.0/6
block out quick on lnc0 from any to 88.0.0.0/5
block out quick on lnc0 from any to 96.0.0.0/3
block out quick on lnc0 from any to 127.0.0.0/8
block out quick on lnc0 from any to 128.0.0.0/16
block out quick on lnc0 from any to 128.66.0.0/16
block out quick on lnc0 from any to 169.254.0.0/16
block out quick on lnc0 from any to 172.16.0.0/12
block out quick on lnc0 from any to 191.255.0.0/16
block out quick on lnc0 from any to 192.0.0.0/19
block out quick on lnc0 from any to 192.0.48.0/20
block out quick on lnc0 from any to 192.0.64.0/18
block out quick on lnc0 from any to 192.0.128.0/17
# block out quick on lnc0 from any to 192.168.0.0/16
block out quick on lnc0 from any to 197.0.0.0/8
block out quick on lnc0 from any to 201.0.0.0/8
block out quick on lnc0 from any to 204.152.64.0/23
block out quick on lnc0 from any to 206.112.0.0/16
block out quick on lnc0 from any to 224.0.0.0/3

Jedná se o IP adresy privátních sítí a různých neroutovatelných sítí, které by mohly přijít na naše síťové rozhraní.

# povolime odchod vsem paketum ven a ulozeni
# informaci do stavove tabulky
pass out quick on lnc0 from any to any keep state

# odfiltrujeme pakety, ktere bychom nemeli nikdy dostat
block in quick on lnc0 from 0.0.0.0/7 to any
block in quick on lnc0 from 2.0.0.0/8 to any
block in quick on lnc0 from 5.0.0.0/8 to any
block in quick on lnc0 from 10.0.0.0/8 to any
block in quick on lnc0 from 23.0.0.0/8 to any
block in quick on lnc0 from 27.0.0.0/8 to any
block in quick on lnc0 from 31.0.0.0/8 to any
block in quick on lnc0 from 69.0.0.0/8 to any
block in quick on lnc0 from 70.0.0.0/7 to any
block in quick on lnc0 from 72.0.0.0/5 to any
block in quick on lnc0 from 82.0.0.0/7 to any
block in quick on lnc0 from 84.0.0.0/6 to any
block in quick on lnc0 from 88.0.0.0/5 to any
block in quick on lnc0 from 96.0.0.0/3 to any
block in quick on lnc0 from 127.0.0.0/8 to any
block in quick on lnc0 from 128.0.0.0/16 to any
block in quick on lnc0 from 128.66.0.0/16 to any
block in quick on lnc0 from 169.254.0.0/16 to any
block in quick on lnc0 from 172.16.0.0/12 to any
block in quick on lnc0 from 191.255.0.0/16 to any
block in quick on lnc0 from 192.0.0.0/19 to any
block in quick on lnc0 from 192.0.48.0/20 to any
block in quick on lnc0 from 192.0.64.0/18 to any
block in quick on lnc0 from 192.0.128.0/17 to any
# block in quick on lnc0 from 192.168.0.0/16 to any
block in quick on lnc0 from 197.0.0.0/8 to any
block in quick on lnc0 from 201.0.0.0/8 to any
block in quick on lnc0 from 204.152.64.0/23 to any
block in quick on lnc0 from 224.0.0.0/3 to any
# povolime urcite prichazejici pakety
pass in quick on lnc0 proto tcp from any to 192.168.17.129 port = 22 flags S keep frags keep state
pass in quick on lnc0 proto tcp from 192.168.17.0/24 to 192.168.17.128 port = 22 flags S keep frags keep state 
# odfiltrujeme zbytek
block out on lnc0 all
block in log quick on lnc0 all

Závěr

Tato pravidla nejsou v žádném případě zatím optimální. Příště je více vyladíme, řekneme si o skupinách pravidel, nějakých tricích, logování a o PF. Je třeba si uvědomit, že pravidla se píší s ohledem na použití. Proto vaše pravidla mohou vypadat zcela jinak.