Увод
Пре него што изнесем рецепт, само да кажем да ово није за људе који се не разумеју добро у Линукс, iptables и apache. Да бисте ово извели код своје куће, потребно је да разумете шта радите, не само преписујете јер, у супротном нећете далеко догурати. Овај текст треба да Вам да генералну идеју и да Вас погура у правом правцу, неће урадити све за Вас. Не покушавам да Вас уплашим, само да скренем пажњу да нисам водио много рачуна о детаљима. Такође, ово је текст о Линуксу који ради као рутер и користи iptables и apache, тако да, ако то немате при руци, можете само да читате, али не и да испробате. Наравно, ако сте гуру, вероватно можете постићи сличне резултате и са другим алатима (поред iptables и apache-а), али сте онда сами на своме. Па да кренемо.
КОРИШЋЕЊЕ
Имате Линукс који ради као рутер, и док неким корисницима желите забранити приступ интернету, желите да им прикажете обавештење о о томе. Или желите да забраните приступ одређеним сајтовима, и, уместо жељеног сајта да прикажете Вашу страну са Вашег сервера о томе како корисник није био добар када је ишао на тај и тај сајт, или да је тај сајт забрањен…Свакакве остале идеје које могу одавде да изникну…
ОСНОВНЕ СТВАРИ
ОК, у згради имамо мали сервер који (углавном) служи као рутер за око 20так комшија који деле нет. Сви скупљамо паре и делимо конекцију. Проблем се јавља када неко не жели интернет за следећи месец, или није ту, или заборави да плати…До сада, имали смо просто решење са iptables алатом – REJECT-уј све пакете и дозволи да прођу само пакети са ИП адреса које су платиле за интернет, које би изгледало некако овако:
iptables -I FORWARD -i ext0 -o ext1 -j DROP
iptables -I FORWARD -p ALL -s 192.168.0.XX -j ACCEPT
iptables -I FORWARD -p ALL -d 192.168.0.XX -j ACCEPT
Онда смо комшија и ја дошли на идеју да онај ко није платио за интернет, када посети неки страну, добије страну на којој пише да није платио и сл. До сада му се интернет прегледач куцао при разрешавању ИП адресе хоста (јер ни DNS пакети нису могли да прођу).
Прва идеја која нам је пала на памет је хаковање нашег DNS сервера, али, иако универзално, ово решење је много зајебано за урадити, није проширљиво, тешко се мења и углавном…срање, тако да сам се одлучио за ово друго, изузетно ефикасно решење изложено даље.
Основна идеја је преусмерити све ХТТП захтеве од корисника који нису платили ка нашем серверу и приказати им једноставну страну обавештења. Решење се може поделити на два дела: део са iptables-има и део са apache-ом. Прво нам треба iptables део.
IPTABLES ДЕО
Проста линија која преусмерава одређеног корисника би била:
iptables -t nat -I PREROUTING -s 192.168.0.XX -p tcp --dport 80 -j REDIRECT --to-ports 3001
Објашњење на брзину је да се сви TCP пакети корисника са ИП адресом 192.168.0.XX који су намењени за порт 80 преусмеравају на порт 3001 нашег сервера. Ту ћемо ставити да наш сервер слуша. Овај, чек мало…па ово не ради! Зашто? Просто, када корисник затражи неку страну, на пример http://www.mozilla.com/en-US/firefox, прво треба разрешити ИП адресу, па се тек онда конектовати, тј. пре него што је иједан пакет за порт 80 послат, прво корисник шаље и прима пакете ка DNS серверу. А, ако имамо (као што је горе написано):
iptables -I FORWARD -i ext0 -o ext1 -j DROP
име хоста не може бити разрешено, па неће бити ни HTTP пакета. Дакле, морамо дозволити DNS пакете тамо и овамо са нечим оваквим:
iptables -I FORWARD -s 192.168.0.XX -p udp --dport 53 -j ACCEPT
iptables -I FORWARD -d 192.168.0.XX -p udp --sport 53 -j ACCEPT
iptables -t nat -I PREROUTING -s 192.168.0.XX -p tcp --dport 80 -j REDIRECT --to-ports 3001
Ово је у неку руку trade-off (српски речено: буџење) јер сада наш корисник није комплетно изолован од интернета – има приступ DNS серверима. ОК, први део са преусмеравањем је готов, сада да наместимо apache.
APACHE ДЕО
Све што треба урадити је направити нови виртуелни хост на apache-у. Иако је наша конфигурација жестоко измењена у односу на конфигурацију по инсталацији, све је било јако просто. Можда код Вас овај рецепт неће радити, али додавање следећих линија на крај httpd.conf-а је све што је било потребно:
Listen 192.168.0.1:3001
Listen 127.0.0.1:3001
NameVirtualHost *:3001
ServerName
DocumentRoot /var/www/no_net/
RewriteEngine On
RewriteRule ^.* /index.html
Када сте додали ово на крај, сада само направите нови htdocs корени директоријум (овде је /var/www/no_net/) са index.html-ом који ће садржати обавештење које ћемо приказати корисницима који нису платили интернет. Порт на коме ће овај виртуелни хост слушати (3001) је исти као онај дефинисан код iptables дела. Као што видите, Listen директива је само за localhost и за наш ЛАН, тако да хост није видљив са интернета. Ако погледате пажљиво у VirtualHost директиву, примећите две чудне линије:
RewriteEngine On
RewriteRule ^.* /index.html
Ове линије раде замену свега у УРЛ-у са “/index.html”. Зашто? Па, хајде да претпоставимо да је наш корисник хтео да оде на сајт http://www.mozilla.com/en-US/firefox/. После тога се преусмерава на порт 3001. Одатле, корисников интернет прегледач тражи /en-US/firefox/ страну која, наравно, не постоји код нас. Најједноставније решење овог проблема је са apache-овим mod_rewrite модулом који ће замењивати све GET захтеве. Друга линија ради управо то – уз помоћ регуларних израза, замењује било шта са “/index.html”. Све што Вам је сада преостало да урадите је да направите фину index.html страну и то је то.
Али, чекај, ово је много просто да би било (geek) фенси. Зато ћемо да зачинимо сад мало са мало Bash магије.
НАПРЕДНЕ СТВАРИ
Пошто је наша мрежа на подмрежи 192.168.0.0/24, имамо 253 могућих ИП адреса и око 20 корисника. Генерално, у скрипти за подешавање iptables-а ћемо морати да поновимо 253-20 пута део:
iptables -I FORWARD -s 192.168.0.XX -p udp --dport 53 -j ACCEPT
iptables -I FORWARD -d 192.168.0.XX -p udp --sport 53 -j ACCEPT
iptables -t nat -I PREROUTING -s 192.168.0.XX -p tcp --dport 80 -j REDIRECT --to-ports 3001
и 20 пута део:
iptables -I FORWARD -p ALL -s 192.168.0.XX -j ACCEPT
iptables -I FORWARD -p ALL -d 192.168.0.XX -j ACCEPT
Хух…Или да унајмимо црнца или да научимо Bash.
Дакле, ево како сам то извео. Ово није никакво елеганци решење, али ће Вам дати идеју. Направите фајл /etc/allowed_ips и, у њему, ставите последње октете ИП адреса које имају интернет – један октет по линији. Дакле, ако 192.168.0.12 и 192.168.0.34 имају интернет, овај фајл би изгледао овако некако:
Наша подмрежа има фиксне адресе, и због једноставности, не пишемо целу ИП адресу (зато само последњи октет). Такође, приметите да је у овом фајлу наведен и сâм сервер (који има адресу 192.168.0.1). Сада, направите скрипту ip_allowing (ставите је где год Вам је згодно) са следећим садржајем:
#!/bin/bash
FILE=/etc/allowed_ips
ip_listing=`cat $FILE`
function check_exist {
for i in $ip_listing; do
if [ ${i:0:1} != "#" ]; then
if [ "$i" = "$1" ]; then
return 1
fi
fi
done
return 0
}
for ip in `seq 1 254`; do
check_exist $ip
if [ $? -eq 1 ]; then
#ip exist
iptables -I FORWARD -p ALL -s 192.168.0.$ip -j ACCEPT
iptables -I FORWARD -p ALL -d 192.168.0.$ip -j ACCEPT
echo allowing 192.168.0.$ip
else
#ip doesn't exist
iptables -I FORWARD -s 192.168.0.$ip -p udp --dport 53 -j ACCEPT
iptables -I FORWARD -d 192.168.0.$ip -p udp --sport 53 -j ACCEPT iptables -t nat -I PREROUTING -s 192.168.0.$ip -p tcp --dport 80 -j REDIRECT --to-ports 3001
fi
done
Нема овде никакве вуду магије. Функција check_exist узима број (последњи октет) као први аргумент и проверава да је треба пустити ту ИП адресу и враћа 1 ако је у листингу, 0 ако није. Главни део иде у петљи од 1 до 254 и, или дозвољава приступ DNS серверима и ради преусмеравање, или дозвољава све пакете. Ако сте загледали, можда сте приметили линију:
if [ ${i:0:1} != "#" ]; then
Овом линијом смо дозволили да имамо (нешто што личи на) коментаре у нашем /etc/allowed_ips фајлу и да их игноришемо, тако да овај фајл сад може изгледати нпр. овако:
#server
1
#pera
12
#zika
34
Згодно, зар не. Све што нам је сада остало је да позовемо нашу скрипту (и да јој дамо exec привилегије, али то знате, иначе не бисте читали довде) одакле год да подешавате Ваше iptables-е. Пример би био:
iptables -I FORWARD -i ext0 -o ext1 -j DROP
/etc/rc.d/ip_allowing
Шта даље?
Као прво, ово је просто решење. Има две мане, а то су: корисници имају приступ DNS серверу и друга, ако корисник затражи непостојећу адресу (нпр. www.blabla-tucmuc-nemaovog.com), добиће страну у интернет прегледачу да она не постоји, тј. наше обавештење ће добити само ако је разрешавање успело. Ово су ситнице преко којих ја могу да прођем, а ако Ви не можете – решење лежи у подешавању DNS сервиса на серверу.
Осим ових мана, има много ствари које се могу унапредити. На пример, можда желите да забрањујете кориснике по MAC адреси, не по ИП адресама. Или, ако имате већу subnet маску, ово може бити споро, па треба размислити о томе да Ваше iptables команде раде са ИП опсезима. Или, можда желите да вучете дозвољене ИП адресе из неког другог извора, нпр. LDAP-а или MySQL-а, а не из фајла. Такође, уз избацивање одређених ствари, можете преусмерити кориснике само када траже одређени сајт, тако што би се у iptables команди користила и одредишна ИП адреса (-d), не само изворна. Што се тиче apache дела, приметите да је rewrite директива код виртуелног хоста гладна, тј. гута све и замењује у једну ствар. Ово нам не дозвољава да имамо више страна на том хосту. Ако бисте желели да имате две стране (на пример, index.html и contact.html), морали бисте да се играте са регуларним изразима и да замењујете било шта осим “/contact.html” у /index.html.
Могућности су неограничене. као и са свим у вези Линукса. Само треба да знате шта хоћете и како да то урадите – simple as that.
apache, bash, dns, gnu, iptables, mod_rewrite