OpenWrt 5: filtrovani (cenzura) webu

Filtrovani weboveho obsahu (cenzura) je posledni dobou aktualni tema. At uz jde o ACTA, SOPA, nebo hlidani zamestnancu, aby pracovali celych 8 hodin. 🙂
Cilem je filtorovat vybrane domeny (napr. facebook.com) na routeru tak, aby se na ne nedalo z vnitrni site pripojit. V pripade potreby je mozne blokovane domeny pro urcite stroje povolit.
Zakladem bude router s openwrt, ktery jsem popisoval minule. Ten rozsirime o proxy server a jednoduche uzivatelske rozhranni, aby seznam blokovanych domen mohl spravovat i naprosty zacatecnik.
Navod je psany na OpenWrt, samozrejme je mozne ho nasadit na „poradny“ router s beznou linuxovou distribuci (napr. Debian).

Vzhledem k malemu vykonu ruznych kupovanych routeru zapomente na filtrovani 50Mbps pro 100 pocitacu – co taky muzete chtit za 525Kc?

Prihlasime se do nastaveneho routeru na roota a po aktualizaci seznamu balicku nainstalujeme proxy server tinyproxy:

root@OpenWrt:/etc/config# opkg update
Downloading http://downloads.openwrt.org/backfire/10.03/ar71x              
Inflating http://downloads.openwrt.org/backfire/10.03/ar71xx/            
Updated list of available packages in /var/opkg-lists/package
root@OpenWrt:/etc/config# opkg install tinyproxy
Installing tinyproxy (1.8.0-1) to root...
Downloading http://downloads.openwrt.org/backfire/10.03/ar71x                 
root@OpenWrt:/etc/config#

zkontrolujeme, zda se spousti po startu systemu:

root@OpenWrt:/etc/config# ls /etc/rc.d
K50dropbear           S39usb                S60dnsmasq
K90network            S40network            S60ldap
K95luci_fixtime       S45firewall           S65radiusd
K98boot               S50cron               S95done
K99umount             S50dropbear           S96led
S05defconfig          S50tinyproxy          S97watchdog
S05luci_fixtime       S50uhttpd             S99sysctl
S10boot               S59luci_dhcp_migrate
root@OpenWrt:/etc/config#
root@OpenWrt:/etc/config# /etc/init.d/tinyproxy enable
root@OpenWrt:/etc/config#

Uzivatele se nebudou dobrovolne pripojovat na interent pres nas proxy server, proto jim ho musime vnutit. 
Zapomente na nastaveni proxy v uzivatelove prohlizeci!
Takze to budeme resit firewallem. Doinstalujeme tedy vse potrebne k iptables:

root@OpenWrt:/etc# opkg install iptables-mod-extra iptables-mod-nat-extra
Installing iptables-mod-extra (1.4.6-2) to root...
Downloading http://downloads.openwrt.org/backfire/10.03/ar71xx/packages/iptables-mod-extra_1.4.6-2_ar71xx.ipk.
Installing kmod-ipt-extra (2.6.32.10-1) to root...
Downloading http://downloads.openwrt.org/backfire/10.03/ar71xx/packages/kmod-ipt-extra_2.6.32.10-1_ar71xx.ipk.
Configuring kmod-ipt-extra.
Configuring iptables-mod-extra.
root@OpenWrt:/etc#

IP routeru je 192.168.7.1. Vsechny pozadavky na web (port TCP 80) presmerujeme na router na port TCP 8888 – na nem bezi tinyproxy.

root@OpenWrt:/# cat /etc/firewall.user
echo 1 > /proc/sys/net/ipv4/ip_forward

iptables -F
iptables -X

iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

iptables -t nat -A PREROUTING -i br-lan -p tcp --dport 80 -j DNAT --to 192.168.7.1:8888
 # vse z LAN (br-lan) sitovky jdouci na port TCP 80 presmerovat na 192.168.7.1:8888

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -A FORWARD -i eth0 -o br-lan -m state --state=RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -o eth0 -i br-lan -j ACCEPT

iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -m state --state INVALID -j DROP

iptables -A INPUT -p icmp -j ACCEPT

iptables -A INPUT -i br-lan -j ACCEPT
iptables -A OUTPUT -o eth0 -j ACCEPT

iptables -A INPUT -j REJECT --reject-with icmp-admin-prohibited

root@OpenWrt:/#

Firewall je, takze zbyva nastavit tinyproxy:

root@OpenWrt:/# cat  /etc/config/tinyproxy
config tinyproxy
	option enable 1
	option User nobody
	option Group nogroup
	option Port 8888
	option Listen 192.168.7.1
	option Timeout 180
	option ErrorFile_403 "/etc/blok/pristupZakazan.html"
	option DefaultErrorFile "/usr/share/tinyproxy/default.html"
	option StatFile "/usr/share/tinyproxy/stats.html"
	option LogFile "/var/log/tinyproxy.log"
	option LogLevel Info
	option MaxClients 100
	option MinSpareServers 5
	option MaxSpareServers 20
	option StartServers 10
	option MaxRequestsPerChild 0
	list Allow 127.0.0.1
	list Allow 192.168.7.0/24
	option ViaProxyName "tinyproxy"
	option Filter "/etc/blok/zakazaneAdresy.txt"
	# Use POSIX Extended regular expressions rather than basic.
	#option FilterExtended On
	option FilterCaseSensitive Off
	option FilterDefaultDeny No
	list ConnectPort 443
	list ConnectPort 563
	

vse je celkem jasne, zajimave jsou volby:

ErrorFile_403 /etc/blok/pristupZakazan.html pri pristupu na zakazanou stranku se uzivateli zobrazi obsah tohoto souboru
MaxClients 100 maximalni pocet pripojenych klientu – tady hlavne zalezi na vykonu routeru
MinSpareServers 5
MaxSpareServers 20
StartServers 10
to je taky ladeni vykonu, nutno vyzkouset na vasem hardwaru
list Allow 127.0.0.1
list Allow 192.168.7.0/24
pripojeni na proxy povolime pouze z localhost a z vybrane podsite, v pripade potreby je mozne povolovat (vynutit pouziti proxy) pouze pro nektere IP
#FilterExtended On Jak rika manual: „Use POSIX Extended regular expressions rather than basic.“ – tedy vyhodnocovat radky v seznamu blokovanych domen jako regularni vyrazy. 
Jestli neznate, zakomentujte, nebo dejte Off.

Aby uzivatel, ktery dostane spravu blokovani na starost nemusel mit SSH pristup do routeru (bylo by to pro nej slozite a omylem by mohl neco rozbit), pouzijeme pro nastaveni FTP.
Vytvorime noveho uzivatele, ktery bude spravovat seznam a nastavime mu heslo.
Je zbytecne vymyslet slozitosti, do /etc/passwd pridame radek:

blok:*:1000:1000:nogroup:/etc/blok:/bin/false

uzivatel nebude mit pristup k shellu a domovsky adresar bude mit v /etc/blok. Jeste je nutne nastavit heslo!

root@OpenWrt:/etc# cat /etc/passwd
root:!:0:0:root:/root:/bin/ash
ftp:*:55:55:ftp:/home/ftp:/bin/false
network:*:101:101:network:/var:/bin/false
nobody:*:65534:65534:nobody:/var:/bin/false
daemon:*:65534:65534:daemon:/var:/bin/false
blok:*:1000:1000:nogroup:/etc/blok:/bin/false  
root@OpenWrt:/etc#
root@OpenWrt:/etc# passwd blok
Changing password for blok
New password:
Bad password: too short
Retype password:
Password for blok changed by root
root@OpenWrt:/etc# cat /etc/passwd
root:!:0:0:root:/root:/bin/ash
ftp:*:55:55:ftp:/home/ftp:/bin/false
network:*:101:101:network:/var:/bin/false
nobody:*:65534:65534:nobody:/var:/bin/false
daemon:*:65534:65534:daemon:/var:/bin/false
blok:$1$znhigRRX$SoB1IDft6QndpgUYQM95A1:1000:1000:nogroup:/etc/blok:/bin/false  
root@OpenWrt:/etc#

Nyni vytvorime uzivateli domovsky adresar i s potrebnymi soubory. Soubory musi vlastnit uzivatel blok a musi mit pravo cteni pro vsechny! Jen uzivatel blok bude mit pravo zapisu.

root@OpenWrt:/# mkdir /etc/blok
root@OpenWrt:/# cd /etc/blok/
root@OpenWrt:/etc/blok# touch pristupZakazan.html
root@OpenWrt:/etc/blok# touch zakazaneAdresy.txt
root@OpenWrt:/etc/blok# chown blok:root *
root@OpenWrt:/etc/blok# ls -lh
-rw-r--r--    1 blok     root            0 Sep 18 13:35 pristupZakazan.html
-rw-r--r--    1 blok     root            0 Sep 18 13:35 zakazaneAdresy.txt
root@OpenWrt:/etc/blok#

Uzivatel bude provadet editaci zakazanych domen upravou TXT souboru. Ten bude nejjednodussi zpistupnit pres FTP.

root@OpenWrt:/etc/config# opkg install vsftpd
root@OpenWrt:/# cat /etc/vsftpd.conf
background=YES
listen=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
check_shell=NO
dirmessage_enable=YES
ftpd_banner=Muj OpenWrt server :-)
session_support=NO
idle_session_timeout=600
chroot_local_user=YES

root@OpenWrt:/# /etc/init.d/vsftpd enable
root@OpenWrt:/#

vsftpd, je dobra volba. Bezi na nem napr. fedora, suse, debian, kernel.org a mnohe dalsi.

anonymous_enable=NO neni povolen pristup anonymnim uzivatelum
local_enable=YES naopak lokalnim ano
write_enable=YES je povolen zapis
check_shell=NO vsftpd neoveruje platny shell (blok ma /bin/false)
idle_session_timeout=600 timeout pro automaticke odpojeni v sekundach
chroot_local_user=YES uvezni uzivatele v jeho domovskem adresari, aby nemohl prochazet disk (blok bude uveznen v /etc/blok)

 

Router musi byt schopen zjisit, ze uzivatel upravil seznam blokovanych domen. Vypomuzeme si pravidelne spoustenym skriptem, ktery bude porovnavat MD5 soucet. Kontrolovat budeme kazdou 1 minutu. Slo (a bylo by lepsi) to resit cronem.

root@OpenWrt:/etc/blok# cat .zjistit-zmeny.sh
#!/bin/sh

cd /etc/blok/

while [ 1 ]; do

	AKTUALNI=`md5sum zakazaneAdresy.txt | sed 's/  / /'`

	if [ "$AKTUALNI" = "`cat /tmp/.zakazaneAdresy.md5 | sed 's/  / /'`" ] ; then
		echo "Zadna zmena"
	else
		echo "Nalezena zmena"
		echo $AKTUALNI > /tmp/.zakazaneAdresy.md5
		/etc/init.d/tinyproxy restart
	fi
	
	sleep 60
done
root@OpenWrt:/etc/blok#           # STAHNOUT SKRIPT

Kazdou minutu se spocita MD5 soucet souboru zakazaneAdresy.txt (ten upravuje uzivatel) a porovna se s minulym souctem.
Jestlize se lisi, ulozime si aktualni soucet jako vychozi pro pristi kontrolu a restartuje tinyproxy, aby si obnovil seznam.

root@OpenWrt:/etc/blok# chown root:root .zjistit-zmeny.sh
root@OpenWrt:/etc/blok# chmod +x .zjistit-zmeny.sh

Soubor bude vlastnit root a bude mit pravo spusteni. Pravo zapisu musi mit pouze root!
a zajistime automaticke spusteni kontroly po startu systemu:

root@OpenWrt:/# cat /etc/rc.local
/etc/blok/.zjistit-zmeny.sh &
exit 0
root@OpenWrt:/#

 

Do souboru /etc/pristupZakazan.html je mozne umistit libovolnou HTML stranku. Ta se uzivateli zobrazi pri pristupu na blokovanou stranku. 
Jestli uzivatel, ktery bude mit spravu blokovanych adres na starosti nebude umet HTML, je mozne pouzit i „Ulozit jako HTML“ ve Wordu, nebo v OpenOffice.

Jenoducha stranka muze vypadat napriklad takto:

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">  
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">  
<head> 
<title>403 Filtered</title> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
</head>  
<body> 
 
<h1 style="color: red; font-size: 250%; font-weight: bold; text-align: center;">Pristup zakazan !!!</h1>  
<p>403 Filtered - The request you made has been filtered</p>  
<hr />  
<p><em>Generated by <a href="https://www.banu.com/tinyproxy/">tinyproxy</a> version 1.8.0.</em></p> 
 
</body> 
</html> 

Ukazka stranky s upozornenim o blokovani

 

Kdyz bude uzivatel chtit upravit seznam, prihlasi se na FTP a v poznamkovem bloku provede upravy. Co jeden radek, to zaznam pro 1 domenu.
Pristup na router pres FTP
 

Je potreba vyzkouset, co vse bude blokovano.
Uvedenim slova linux zablokujete vsechny domeny, ktere obsahuji slovo linux. Naopak cesty na serveru (to za lomitkem) se to nedotkne:

Do souboru /etc/blok/zakazaneAdresy.txt dame treba:

facebook.com
linux
microsoft
www.seznam.cz

Tim zablokujeme facebook.com, linuxexpres.cz, www.linux.cz, microsoft.cz, microsoft.com, atd.

 

Jedna se pouze o jeden z mnoha moznych zpusobu, jak cenzuru resit.
Je dulezite si uvedomit, ze kdyz nektery uzivatel bude chtit, vzdy se pres blokovani dostane. 

 

Zkousel jsem to asi pred pul rokem, takze jsou mozna nekde chyby. Kdyztak napiste komentar.

 

Oprava 23. cervna 2012 22:10: opraven skript zjistit-zmeny.sh. Puvodni verze zapisovala do /etc na flash, cimz by se flash pri castem meneni seznamu bokovanych adres brzy znicila. Nyni se soubor s md5 souctem zapisuje do /tmp (ramdisk).
 

6 komentářů u „OpenWrt 5: filtrovani (cenzura) webu

  1. AsciiWolf
    Uf, opravdu myslíš, že je dobrý nápad nechat ten script zapisovat každou minutu data (md5 součet) na FLASHku?
    Proč nepoužít /tmp, který je pro zápis dočasných (temporary) dat určen?
  2. tuxmartin Autor příspěvku

    Neni to dobry napad. Ani nevim, proc jsem tam takovou blbost napsal.
    Diky za upozorneni 🙂

    Nyni uz je to spravne. Presunul jsem soubor s MD5 souctem do /tmp. I kdyz se zapisuje pouze po startu systemu a pri zmene souboru s blokovanymi adresami, je to takhle lepsi.

  3. peter
    Ahoj Martine,
    mas zkusenosti s filtrovanim https obsahu? Na facebooku maji uzivatele moznost nastavit prohlizeni pres https a pak je tinyproxy neodfiltruje (a podle vseho tinyproxy na openwrt neni zkompilovany s podporou https). Nevis jak to resit?
    Diky
  4. tuxmartin Autor příspěvku
    Ahoj,

    filtrovani https je uz z principu problem. Da dost prace zjistit, co tam tece za data.

    Muzes pouzit vlastni DNS server, ktery bude pro domenu facebook.com vracet tvoji vlastni IP adresu. Na te muze bezet webserver s oznamenim o zakazu. Snadno se da pouzit treba unbound, sam ho pouzivam. Zde se muzes podivat na ukazove nastaveni. Tebe zajimaji tyto dva radky:

    local-zone: „facebook.com“ redirect
    local-data: „facebook.com A 192.168.1.1“

    Jenze narazis na problem – uzivatele nejsou blby 🙂
    Mohou chodit na facebook pres IP adresu. Nejjednodussi zpusob spociva v zakazani IP adresy facebook na firewallu:

    iptables -A OUTPUT -p tcp -d http://www.facebook.com -j DROP

    To ma jeden zasadni problem – facebook ma hodne IP adres. Iptables si vyse uvedenym prikazem prelozi domenu a vyslednou IP adresu prida do pravidla. Pouze jednu IP adresu. Iptables neumi domenova jmena, pouze IP adresy. Proto je dobre si sehnat seznam vsech IP facebooku a zakazat je vsechny. Muzes googlit, nebo se podivej primo do registru IANA/ARIN na pridelene IP. Maji jich mnohem vic, zkus RIPE a hlavne google.

    Dokonaly zpusob je zkoumat certifikat. Ty si nemuzes cist data, ktera tecou HTTPS tunelem, ale muzes si zjistit informace o tunelu pri jeho sestavovani.

    Takhle funguje spojenie klienta a serveru pres https:

    1. Klient posle pozadavek serveru (Client Hello)
    2. Server posle odpoved klietovi (Server Hello)
    3. a ted tecou data….

    Nyni se dostanes k velkemu problemu HTTPS:

    1. Klient se spoji se serverem a vytvori sifrovane spojeni
    2. V sifrovanem tunelu pomoci standardni HTTP protokolu posle „Host“ hlavicku a tim rekne, ktery web ho zajima

    Takze informace o domene jde az v sifrovanem tunelu => mas problem.

    Kdyz mas stesti, tak klient pouzije SNI. Muzes tak hned zjistit, co ho zajima za domenu a spojeni zlikvidovat.

    Uspesnost vysoka, ale ne 100%. Jesti chces mi 100% jistotu, musis pouzit dokonale, neprustrelne reseni 🙂
    Jak jsem psal vyse, u standardniho HTTPS bez SNI rozsireni funguje komunikace nasledovne:

    1. Klient posle pozadavek serveru (Client Hello)
    2. Server posle odpoved klietovi (Server Hello)
    3. a ted tecou data…

    V odpovedi server hello posila server klientovi svuj certifikat, aby si ho klient mohl zkontrolovat. Tak klientovi pomuzes a zkontrolujes ho jeste pred nim 😉 Vytahnes si z HTTPS spojeni certifikat a overis, pro kterou domenu je vydany (commonName).

    No a kdyz uvidis CN na domenu facebook, spojeni zase zlikvidujes :-) 
    Takhle si muzes overit, ze to jde:

    Takhle to resi i ZyXEL u svych firewallu. Byl jsem na jejich prednasce a jejich clovek to vychvaloval az do nebe 😉
    Jedina podstatna nevyhoda je vykon – takovato hloubkova kontrola je strasne narocna na vykon (to pan ze ZyXELu zapomnel zminit, po dotazu to ale priznal 😉 )

    Taky si over legalitu, na ni ja nejsem expert. Prece jenom ale ctes cizi spojeni…

    Podrobnejsi navod ti ted bohuzel dat nemuzu. Kontrolou certifikatu jsem v praxi nikdy nenastavoval a prave mam zkouskove a vubec nestiham 🙁
    Zkus se ale podivat na tyto odkazy, treba nejaky pomuze:
    http://blog.onoh.info/linux-tinyproxy-filter
    http://wiki.squid-cache.org/Features/BumpSslServerFirst

    A na tinyproxy muzes asi zapomenout: 🙁
    HTTPS support: Tinyproxy allows forwarding of HTTPS connections without modifying traffic in any way.

    Kdyz se ti neco podari, podel se prosim o navod. Moc me dane tema zajima 🙂

    Preji hodne stesti,
    Martin

  5. Lukas
    Dobry den,
    mel bych na vas otazku jako na odbornika. Slo by nejak nastavit KOMPLETNI blokovani obsahu pro konkretni MAC, nebo IP ?
    Dcera ( 6let ) bude mit netbook a ja chci povolit JEN par vybranych webu. Prevazne takove ty detske hry a podobne. Zbytek webu zatim nepotrebuje.
    Pripadne pokud mate nejake jine doporuceni, budu rad za kazdou radu.
  6. tuxmartin Autor příspěvku

    Dobry den, 
    blokovani se samozrejme udelat da pouze pro konkretni PC.

    Otazka je, kolik penez do toho hodlate investovat a jak moc musi byt blokovani spolehlive. Pokud dcera bude chtit, vzdy si nejaky zpusob najde

    Pokud povolite treba Google.cz a nic jineho, stejne to bude k nicemu – nepujde se dostat na vysledky vyhledavani. Take si dejte pozor, kdyz povolite treba jenom urcite weby – dost casto si stahuji ruzne JavaScriptove knihovny z jinych serveru, bez kterych stranka nebude fungovat.

    Pro zacatek bych Vam doporucil zkusit softwarove reseni. Treba ve Windows, nebo v antiviru. Myslim, ze rodicovskou ochranu ma AVG i Avast a dalsi.

    Druha cesta je pomoci dodatecneho hardwaru. Napr. TP-Link WiFi routery maji funkci rodicovske ochrany. Zde je ukazka nataveni pro TP-LINK TL-WR841ND. V menu zvolte „Parental Control“ a kliknete na tlacitko „Add new“:

     

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *