День добрый.
Появилась необходимость в создании HotSpot точки. Как человек, немного знакомый с UNIX, я решил искать софтверные решения. Тем более что покупать специальное железо для этого дела не было возможности. Да и требования были весьма минимальными. А именно организовать раздачу WiFi так, как это сделано, к примеру, в сети McDonnalds. Т.е. пользователь пришел, подключился к сети и спокойной получил свои 30 минут интернета. Либо 15 мегабайт трафика.
Изначально пытался приспособить под это дело ChilliSpot, FreeRadius, EasyHotSpot и прочие решения. У меня это так и не завелось. По этому я продолжил поиски и наткнулся на статью HotSpot у «lissyara». И понял, что это именно то, что надо. Немного подправив скрипты я получил именно то, что мне надо практически штатными средствами FreeBSD.
Я использовал FreeBSD 8.2 и пакеты, установленные из портов, но эта схема будет работать практически на любой другой системе, так как она не использует никаких специфических программ.
И так. Есть компьютер с 2-мя сетевыми картами, есть WiFi точка доступа. Никаких иных требований к железу нет.
На компьютере установлена FreeBSD, apache, PHP, MySQL, ISC-dhcpd.
Во первых вам надо пересобрать ядро, для включения НАТ и пайпов для ограничения скорости.
Как собрать ядро и установить его можно найти в гугле. Тут я приведу параметры, с которыми я собирал ядро:
Далее, после сборки ядра надо установить Apache, PHP и MySQL. Информации по этой теме тоже полно в интернете, по этому тут этот процесс я расписывать не буду.
Прописываем настройки в rc.conf:
Если вы прочитали перед этим статью, на которую я ссылался вначале, то вас ясен принцип работы этой схемы. Если нет — то объясню вкратце. И так, клиент подключаясь к Wi-Fi точке получает по DHCP ip-адрес. Затем, когда он пытается открыть любой сайт его кидает на страницу с приветствием. В вышеупомянутой статье на той странице запрашивается логин и пароль. Я убрал авторизацию, по этому по сути на странице только одна кнопка — «Получить доступ». Реализуется это следующим образом. В правилах файрвола прописано перенаправлять запросы на свой веб-сервер. После посещения страницы и клика по единственной кнопке в правила файрвола добавляется новое, которое разрешает пользователю с указанный ИП получить доступ к Интернету. Каждую минуту демон cron вызывает скрипт, который смотрит сколько времени пользователь в сети и сколько трафика он израсходовал. И в случае превышения одного или другого он удаляет разрешающее правило и при следующем запросе этот пользователь снова будет переадресован на стартовую страницу.
Вот в принципе и вся суть этой схемы. И так, продолжим реализацию.
Далее нам надо настроить файрвол.
Сразу хочу сказать, что тут только основные настройки. Если вы настраиваете машину по SSH, то вам надо добавить правило, которое разрешит вам доступ к этой машине.
Разрешающие правила будут с номер 200 по 600, по этому правило переадресации у нас будет идти под номером 1000.
/etc/firewall.sh:
Для того, что бы абсолютно все запросы попадали на нашу страницу авторизации надо создать в корне директории с сайтом файл ".htaccess" (предварительно разрешив Rewrite в httpd.conf) со следующим содержанием:
Тогда, даже если в строке адреса будет не только сайт (http://habrahabr.ru) но и конкретная страница (http://habrahabr.ru/i/habr.gif), все равно откроется нужная страница.
Теперь остается только создать таблицу в базе данных, в которой будут храниться данные о текущих сессиях, настроить DHCP-server и создать необходимые PHP-скрипты, которые сделают всю основную работу.
Таблица MySQL совершенно простая. Номер правила, время начала сессии.
Далее все файлы, описаные далее должны лежать в директории сайта.
Начнем со страницы настроек config.php:
Далее основная страница, на которую будут переадресовываться пользователи — index.php:
Эта страница определяет, какой адрес был введен изначально, что бы потом переадресовать на него. Это, а так-же добавления правила файрвола делает скрипт open.php:
После этих манипуляций у пользователя появляется полный доступ к сети интернет. Файрвол не блокирует ничего, по этому будут работать и аська, и агент и все остальное. Но с другой стороны это наверно тоже не правильно и надо будет потом настроить файрвол и оставить только нужные порты. Но это уже в зависимости от потребности.
Теперь осталось только отключить пользователей при превышении одного из лимитов и все.
Изначально планировалось трафик считать при помощи trafd, но как оказалось, чем стрелять из пушки по воробьям, лучше работать с тем, что и так уже считает трафик. А именно IPFW. При вызове ipfw show в 3 столбце идет количество байт, которые прошли через файрвол. А так как у нас для каждого пользователя будет отдельное правило, то по номеру правила можно легко подсчитать, сколько этот пользователь трафика использовал.
Это у нас будет делать скрипт cron.php:
Теперь добавляем в crontab запить, и раз в минуту наш скрипт будет проверять, не превысил ли кто лимит:
На этом кажется все.
Естественно пути, названия сетевых карт и некоторые мелочи могут отличаться,
P.S. Чуть не забыл про DHCP. Вот конфиг:
Вот теперь кажется все.
Появилась необходимость в создании HotSpot точки. Как человек, немного знакомый с UNIX, я решил искать софтверные решения. Тем более что покупать специальное железо для этого дела не было возможности. Да и требования были весьма минимальными. А именно организовать раздачу WiFi так, как это сделано, к примеру, в сети McDonnalds. Т.е. пользователь пришел, подключился к сети и спокойной получил свои 30 минут интернета. Либо 15 мегабайт трафика.
Изначально пытался приспособить под это дело ChilliSpot, FreeRadius, EasyHotSpot и прочие решения. У меня это так и не завелось. По этому я продолжил поиски и наткнулся на статью HotSpot у «lissyara». И понял, что это именно то, что надо. Немного подправив скрипты я получил именно то, что мне надо практически штатными средствами FreeBSD.
Я использовал FreeBSD 8.2 и пакеты, установленные из портов, но эта схема будет работать практически на любой другой системе, так как она не использует никаких специфических программ.
И так. Есть компьютер с 2-мя сетевыми картами, есть WiFi точка доступа. Никаких иных требований к железу нет.
На компьютере установлена FreeBSD, apache, PHP, MySQL, ISC-dhcpd.
Во первых вам надо пересобрать ядро, для включения НАТ и пайпов для ограничения скорости.
Как собрать ядро и установить его можно найти в гугле. Тут я приведу параметры, с которыми я собирал ядро:
options IPFIREWALL
options IPFIREWALL_DEFAULT_TO_ACCEPT
options IPFIREWALL_FORWARD
options IPFIREWALL_VERBOSE
options IPFIREWALL_VERBOSE_LIMIT=50
options IPFIREWALL_NAT
options LIBALIAS
options ROUTETABLES=2
options DUMMYNET
options HZ="1000"
Далее, после сборки ядра надо установить Apache, PHP и MySQL. Информации по этой теме тоже полно в интернете, по этому тут этот процесс я расписывать не буду.
Прописываем настройки в rc.conf:
defaultrouter="1.1.1.1" # Шлюз по умолчанию.
gateway_enable="YES" # Наша машина работает как шлюз.
ifconfig_re0="inet 1.1.1.2 netmask 255.255.255.252" # Карточка, которая смотрит в мир.
ifconfig_re1="inet 10.128.1.1 netmask 255.255.255.0" # Карточка, к которой подключена Wi-Fi точка.
inetd_enable="YES"
sshd_enable="YES" #Включаем SSH
sendmail_enable="NO" #Выключаем Sendmail
firewall_enable="YES" # Включаем файрвол
firewall_nat_enable="YES" # Включаем на файрволе НАТ
dummynet_enable="YES" # Dummynet. Будет резать скорость пользователям.
firewall_script="/etc/firewall.sh" # Пусть в скрипту файрвола.
Если вы прочитали перед этим статью, на которую я ссылался вначале, то вас ясен принцип работы этой схемы. Если нет — то объясню вкратце. И так, клиент подключаясь к Wi-Fi точке получает по DHCP ip-адрес. Затем, когда он пытается открыть любой сайт его кидает на страницу с приветствием. В вышеупомянутой статье на той странице запрашивается логин и пароль. Я убрал авторизацию, по этому по сути на странице только одна кнопка — «Получить доступ». Реализуется это следующим образом. В правилах файрвола прописано перенаправлять запросы на свой веб-сервер. После посещения страницы и клика по единственной кнопке в правила файрвола добавляется новое, которое разрешает пользователю с указанный ИП получить доступ к Интернету. Каждую минуту демон cron вызывает скрипт, который смотрит сколько времени пользователь в сети и сколько трафика он израсходовал. И в случае превышения одного или другого он удаляет разрешающее правило и при следующем запросе этот пользователь снова будет переадресован на стартовую страницу.
Вот в принципе и вся суть этой схемы. И так, продолжим реализацию.
Далее нам надо настроить файрвол.
Сразу хочу сказать, что тут только основные настройки. Если вы настраиваете машину по SSH, то вам надо добавить правило, которое разрешит вам доступ к этой машине.
Разрешающие правила будут с номер 200 по 600, по этому правило переадресации у нас будет идти под номером 1000.
/etc/firewall.sh:
ipfw -q flush
ipfw pipe 1 config bw 512Kbit/s mask dst-ip 0x00000001 #Ограничение скорости закачки
ipfw pipe 2 config bw 256Kbit/s mask dst-ip 0x00000001 #Ограничение скорости отдачи
ipfw nat 1 config log if re0 reset same_ports #Включаем НАТ на сетевой карте, которая смотрит в мир.
ipfw add 120 nat 1 ip from 10.128.1.0/24 to any via re0 # НАТим локальную посдеть на выход
ipfw add 121 nat 1 ip from any to 192.168.24.154 via re0 # И на вход.
ipfw add 1000 fwd 10.128.1.1,80 tcp from any to any 80 via re1 # Правило, которое все запросы будет перекидывать на внутренний ВЕБ сервер.
Для того, что бы абсолютно все запросы попадали на нашу страницу авторизации надо создать в корне директории с сайтом файл ".htaccess" (предварительно разрешив Rewrite в httpd.conf) со следующим содержанием:
RewriteEngine on
ErrorDocument 404 10.128.1.1/index.php
Тогда, даже если в строке адреса будет не только сайт (http://habrahabr.ru) но и конкретная страница (http://habrahabr.ru/i/habr.gif), все равно откроется нужная страница.
Теперь остается только создать таблицу в базе данных, в которой будут храниться данные о текущих сессиях, настроить DHCP-server и создать необходимые PHP-скрипты, которые сделают всю основную работу.
Таблица MySQL совершенно простая. Номер правила, время начала сессии.
CREATE TABLE `hotspot` (
`time_begin` timestamp NOT NULL default '0000-00-00 00:00:00',
`rule_num` smallint(5) unsigned NOT NULL,
KEY `rule_num` (`rule_num`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 ;
Далее все файлы, описаные далее должны лежать в директории сайта.
Начнем со страницы настроек config.php:
<?php
//Данные для подключения к базе данных:
define('conf_DB_HOST', 'localhost');
define('conf_DB_USER', 'root');
define('conf_DB_PASS', '');
define('conf_DB_NAME', 'hotspot');
define('RULE_NUM_MIN', 200); //Номер, с которого будут начинаться правила, разрешающие доступ.
define('CLIENTS_TIME', '1800'); //Время для клиента 30 минут (в секундах)
define('CLIENTS_TRAF', '30'); //Лимит трафика в мегабайтах
//Команды, которыми открывается или закрывается доступ к интернету
define('RULE_ADD_IP', '/usr/local/bin/sudo /sbin/ipfw add %s pipe 1 ip from any to %s');
define('RULE_ADD_IP2', '/usr/local/bin/sudo /sbin/ipfw add %s pipe 2 ip from %s to any');
define('RULE_DEL_IP', '/usr/local/bin/sudo /sbin/ipfw delete %s');
define('RULE_DEL_IP2', '/usr/local/bin/sudo /sbin/ipfw delete %s');
//Подключение к базе данных.
$db_link = mysql_connect(conf_DB_HOST, conf_DB_USER, conf_DB_PASS);
if (!$db_link) echo('Connect Error!');
if (!mysql_select_db(conf_DB_NAME, $db_link))
echo('Connect Error');
?>
Далее основная страница, на которую будут переадресовываться пользователи — index.php:
<H1>
Немного бесплатного Wi-Fi каждому!<br>
Вы можете получить 30 минут или 30 мб трафика.
</H1>
<?php
$redir='http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
echo('<form method=GET action="open.php">');
echo("<input type=hidden name=redir value=$redir>");
echo('<input value="В сеть!" type="submit"></form>');
?>
Эта страница определяет, какой адрес был введен изначально, что бы потом переадресовать на него. Это, а так-же добавления правила файрвола делает скрипт open.php:
<?php
require_once('config.php');
$user_ip = $_SERVER['REMOTE_ADDR'];
$current_date = time();
//Тут мы находим первый свободный номер правил файрвола. У нас они начинаются с 200. Это прописано в RULE_NUM_MIN.
$temp = 0;
$sql = 'SELECT rule_num FROM hotspot ORDER BY rule_num';
$res = mysql_query($sql);
if ($res)
{
$t = mysql_fetch_array($res);
if (!$t) $rule_num = RULE_NUM_MIN;
else {
while ($temp = mysql_fetch_array($res))
{
if (($t[0]+1) < $temp[0]) break;
$t = $temp;
}
$rule_num = $t[0]+1
}
} else return false;
//Далее мы добавляем в файвол 2 правила. Первое - "на выход", второе "на вход". Номер второго правила получаем прибавив 200 к первому. Итого наша сеть может принять 200 компов.
$command = sprintf(RULE_ADD_IP, $rule_num, $user_ip);
exec($command);
$command2 = sprintf(RULE_ADD_IP2, $rule_num+200, $user_ip);
exec($command2);
//Записываем в базу номер правила и время начала сессии.
$sql = 'INSERT INTO hotspot (time_begin, rule_num) values (NOW(),'.$rule_num.')';
mysql_query($sql);
//И переадресовываем на ту страницу, которую пользователь хотел получить изначально.
$redir=$_GET['redir'];
header("Location: $redir");
return true;
?>
После этих манипуляций у пользователя появляется полный доступ к сети интернет. Файрвол не блокирует ничего, по этому будут работать и аська, и агент и все остальное. Но с другой стороны это наверно тоже не правильно и надо будет потом настроить файрвол и оставить только нужные порты. Но это уже в зависимости от потребности.
Теперь осталось только отключить пользователей при превышении одного из лимитов и все.
Изначально планировалось трафик считать при помощи trafd, но как оказалось, чем стрелять из пушки по воробьям, лучше работать с тем, что и так уже считает трафик. А именно IPFW. При вызове ipfw show в 3 столбце идет количество байт, которые прошли через файрвол. А так как у нас для каждого пользователя будет отдельное правило, то по номеру правила можно легко подсчитать, сколько этот пользователь трафика использовал.
Это у нас будет делать скрипт cron.php:
<?php
require_once('config.php');
//Тут из базы выбираются те пользователи, у которых привышен лимит по времени, и эти пользователи отключаются от интернета путем удаления их правил из файрвола.
$sql = 'SELECT * FROM hotspot WHERE time_begin > 0 AND (TIME_TO_SEC(TIMEDIFF(NOW(), time_begin)) > '.CLIENTS_TIME.')';
$res = mysql_query($sql);
if ($res)
{
while ($user = mysql_fetch_assoc($res))
{
block($user['rule_num']);
}
}
//Тут мы из данных IPFW вытаскиваем количество принятых данных и сравниваем с лимитом. При превышении лимита пользователь так-же блокируется.
$sql = 'SELECT * FROM hotspot WHERE 1';
$res = mysql_query($sql);
if ($res)
{
while ($user = mysql_fetch_array($res))
{
$rule=$user['rule_num'];
exec("/usr/local/bin/sudo /sbin/ipfw show $rule | awk '{print($3)}'",$ct);
if($ct[0]>=CLIENTS_TRAF*1024*1024) block($rule);
}
}
return true;
//Функция, которая удаляет правило файрвола и удаляет запись из базы.
function block($num)
{
$command = sprintf(RULE_DEL_IP, $num);
exec($command);
$command2 = sprintf(RULE_DEL_IP2, $num+200);
exec($command2);
$sql = 'DELETE FROM hotspot WHERE rule_num='.$num;
mysql_query($sql);
}
?>
Теперь добавляем в crontab запить, и раз в минуту наш скрипт будет проверять, не превысил ли кто лимит:
*/1 * * * * /usr/local/bin/php /var/www/data/cron.php
На этом кажется все.
Естественно пути, названия сетевых карт и некоторые мелочи могут отличаться,
P.S. Чуть не забыл про DHCP. Вот конфиг:
#Имя домена.
option domain-name "hotspot.my";
#ДНС сервер. Я использую ДНС гугла.
option domain-name-servers 8.8.8.8;
#Время выдачи. И максимальное время.
default-lease-time 600;
max-lease-time 7200;
#Собственно подсеть. С увазанием диапазона и шлюза для клиентов.
subnet 10.128.1.0 netmask 255.255.255.0 {
range 10.128.1.20 10.128.1.220;
option routers 10.128.1.1;
}
Вот теперь кажется все.