Blokování provozu podle zemí s firewallem a ipset

23. 9. 2016
Doba čtení: 3 minuty

Sdílet

Valí se vám do sítě nechtěný provoz a vy chcete zablokovat jednotlivé země nebo nechat naopak procházet jen pakety z českých adres? Přichází čas nasadit těžký kalibr s ipset.

V jedné síti s několika desítkami serverů jsem řešil problém s intenzivními útoky z konkrétních zemí (čti Čína a Rusko). Bylo potřeba na firewallu zakázat řadu adresních rozsahů, ze kterých stejně nemohou přicházet legitimní uživatelé. U některých kritických služeb jsme se rozhodli pro opačný postup – pustit dovnitř jen uživatele z českých rozsahů. Krásně se k tomu hodí linuxový firewall s module ipset.

O ipset se na Rootu už psalo, přesto připomenu to podstatné: jedná se o modul do iptables, který dovoluje do paměti ukládat sady různých informací (IP, MAC, port…) do hashovacích tabulek. V těch je pak možné velmi rychle vyhledávat a pomocí několika málo pravidel ve firewallu třeba porovnávat provoz proti tisícům adres. Na rozdíl od tisíců jednotlivých záznamů v iptables je tohle řešení výrazně efektivnější, škálovatelné a dobře se s ním pracuje.

Získání adres

IP adresy jednotlivých regionů je možné získat na webu IPdeny.com. Naleznete tam jednotlivé soubory rozdělené podle zemí pro IPv4IPv6. My si pro ukázku stáhneme soubor cn.zone (Čína).

Další možností je třeba služba ip2location.com, kde je možné si ve webovém rozhraní naklikat jednotlivé regiony, vybrat protokol a následně si stáhnout vygenerovaný konfigurační soubor. Doporučuji nestahovat ten pro iptables, protože ten jen sype pravidla přímo do firewallu. Stáhněte si formát CIDR, který je shodný s tím na IPdeny.

Je možné použít libovolné další seznamy adres, třeba ty z I-Blocklist nebo seznamy objevených útočníků zveřejňuje i projekt Turris. Je na vás, co pak s takto vyfiltrovaným provozem uděláte. Nemusíte ho rovnou blokovat, můžete ho třeba jen monitorovat, omezit počty paketů nebo zablokovat potenciálně rizikové příchozí porty, na které by mohl být veden útok.

Pro další účely budeme potřebovat soubor ve stejném formátu, jaký nabízí IPdeny – tedy jeden rozsah na jeden řádek.

1.0.1.0/24
1.0.2.0/23
1.0.8.0/21
1.0.32.0/19
…

Instalace ipset

Pro zprovoznění budete na firewallu potřebovat jádro 2.6.39 nebo novější. To vyšlo v roce 2011, čili postačí jakákoliv rozumně aktuální distribuce. Musí v něm být zapnutá podpora ipsetu, který je součástí netfilteru.

Obvykle ještě bude potřeba doinstalovat balíček ipset, který obsahuje utilitu pro správu setů. Já jsem instaloval v Debianu, takže stačí prosté:

# apt-get install ipset

a vše je připraveno k vytvoření a naplnění sady adres.

Tvoříme set

Nyní je potřeba vytvořit sadu adres a vložit do ní získané rozsahy. Budeme potřebovat set typu hash:net, který slouží k ukládání adresních rozsahů. Ten založíme jednoduše příkazem:

# ipset create cina hash:net

Poté jej naplníme adresami z našeho seznamu:

# while read line; do ipset add cina $line; done < cn.zone

Můžeme provést kontrolu tím, že si vypíšeme obsah setu:

# ipset list cina
Name: cina
Type: hash:net
Revision: 5
Header: family inet hashsize 2048 maxelem 65536
Size in memory: 118424
References: 0
Members:
59.77.0.0/16
103.223.172.0/22
119.2.0.0/19
…

Pokud budeme chtít vytvořit set také pro IPv6 rozsahy, musíme to utilitě explicitně sdělit:

# ipset create cina6 hash:net family inet6

Zbytek postupu je pak už stejný, jen budeme muset pamatovat na to, že máme dva sety: jeden s názvem cina pro IPv4 a druhý cina6 pro IPv6.

Blokujeme provoz

Nyní stačí už jen přidat do firewallu pravidlo podle našich potřeb. Můžeme třeba provoz z vybraných rozsahů úplně blokovat:

# iptables -I INPUT -m set --match-set cina src -j DROP

Podobně je možné třeba pustit jen české adresy a podobně. Výhodou je, že můžeme v budoucnu libovolně měnit set, aniž bychom museli zasahovat do iptables. Změny se projeví okamžitě.

Výjimky

Nakonec ještě jedna poznámka k výjimkám. Pokud byste potřebovali z rozsahů některou adresu vyjmout, nemusíte pro ni zavádět speciální pravidlo do iptables, ale stačí do setu adresu vložit s parametrem nomatch, který zajistí, že konkrétní adresa (či rozsah) testu na přítomnost nevyhoví:

bitcoin_skoleni

# ipset add cina 59.77.10.0/24 nomatch

V setu je pak vidět jak původní větší rozsah, tak i výjimka:

…
Members:
59.77.0.0/16
103.223.172.0/22
119.2.0.0/19
…
59.77.10.0/24 nomatch
…

Snadno je pak možné položit dotaz na konkrétní adresu:

# ipset test cina 59.77.1.1
59.77.1.1 is in set cina.
# ipset test cina 59.77.10.1
59.77.10.1 is NOT in set cina.

Autor článku

Petr Krčmář pracuje jako šéfredaktor serveru Root.cz. Studoval počítače a média, takže je rozpolcen mezi dva obory. Snaží se dělat obojí, jak nejlépe umí.