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
akce |
block |
blokuj |
směr |
out |
ven |
volby |
log |
logovat |
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 |
příliš krátké pakety |
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
.
# 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.