LinuxForum.Fans
Тема

Iptables и интернет кафе

Автор: magistr_forever 24 сообщений 3545 просмотров
#249561

Здравствуйте.
Возникла задача создать бесплатное интернет кафе. Т.е. что бы пользователи свободно подключались бес логинов и паролей.
Проблема в том, что нужно для каждого соединения резать трафик и время соединения.
Например 128 кб на полч часа, потом обрыв. И заново подключение.
Можно ли это сделать на Iptables? Или нужны доп. пакеты?

#249591

По идее так:
iptables + shaper (tc) + mlimit тыц

#249754

Squid
Ну и HAVP + ClamAV по желанию

#255250

TC урезало скорость.
А что делать со временем и объемом трафика?

Всем ip назначить лимит и через TC скорость в 0? А обратно.....
Вообще не представляю как сделать....

#255279

Ставь биллинг, который может учитывать время, ну и само собой трафик.
Они специально заточены под эти нужды, тебе меньше гемора и автоматизация этих процессов в одной проге.

#255537

Сделал через прозрачный SQUID.
Написал свой обработчик логов SQUID, с БД MySQL.
Теперь все что угодно можно реализовать.

#255549
"magistr_forever" написал:
Написал свой обработчик логов SQUID, с БД MySQL

Можно глянуть? или под закрытой лицензией ;)

#255580

Как-то так ))
Запуск по крону.

text
<?
print "log squid <br/>";

define('LIMIT_TIME', '2'); //мин define('LIMIT_BYTES', '10485760'); //байты define('LIMIT_TIME_WAIT', '1'); //мин define('LIMIT_LAST_TIME', '5'); //мин

$db = mysql_connect('localhost', 'root', '') or die('connect to database failed'); mysql_set_charset('cp1251'); mysql_select_db('wifi') or die('db not found');

$filename = /tmp/access.log'; $file = fopen($filename, 'r');

while(!feof($file)) { $line = fgets($file, 4096);

$line_array = preg_split("/[\s,]+/", $line); $t1 = preg_split("/[\/]/", $line_array[8]); if ($t1[1] == "127.0.0.1") continue; $t1 = preg_split("/[\/]/", $line_array[8]); if ($t1[1] == "192.168") continue; $t1 = preg_split("/[\/]/", $line_array[3]); if ($t1[0] == "TCP_DENIED") continue; $date = preg_split("/[.]/", $line_array[0]); $peerip = preg_split("/[\/]/", $line_array[8]); mysql_query("INSERT INTO `Traffic` (`date`, `clientip`, `resultcode`, `bytes`, `url`, `peerip`, `mimetype`) VALUES('".$date[0]."', INET_ATON('".$line_array[2]."'), '".$line_array[3]."', '".$line_array[4]."', '".$line_array[4]."', INET_ATON('".$peerip[1]."'), '".$line_array[9]."')"); mysql_query("INSERT INTO `Sessions` SET clientip = INET_ATON('".$line_array[2]."'), time=0, status = 1, bytes=".$line_array[4].", lasttime = '".$date[0]."' ON DUPLICATE KEY UPDATE bytes = bytes + ".$line_array[4].", lasttime = '".$date[0]."'");

} fclose($file);

//увеличиваем счетчик на 1 минуту mysql_query("UPDATE `Sessions` SET time = time + 1");

//проверка статусов mysql_query("UPDATE `Sessions` SET status = 0, time = 0, bytes = 0 WHERE (time > '".LIMIT_TIME."' OR bytes > '".LIMIT_BYTES."') AND status = 1"); mysql_query("UPDATE `Sessions` SET status = 1 WHERE time > '".LIMIT_TIME_WAIT."' AND status = 0");

//формирование листа ip mysql_query("INSERT INTO `DenyList` (`clientip`) SELECT clientip FROM `Sessions` WHERE status = 0"); $time = time(); $lasttime = LIMIT_LAST_TIME*60; mysql_query("DELETE FROM `DenyList` WHERE clientip IN (SELECT clientip FROM `Sessions` WHERE status = 1 OR (".$time." - lasttime) > ".$lasttime.")"); mysql_query("DELETE FROM `Sessions` WHERE (".$time." - lasttime) > ".$lasttime." "); //неактивные соединения

//файл SQUID $result = mysql_query("SELECT clientip FROM `DenyList`"); $denyclient = "";

while($row = mysql_fetch_array($result)) { if ($denyclient != "") $denyclient .= "\n"; $denyclient .= long2ip($row['clientip']); }

$filename = '/etc/squid/deny.ip'; $file = fopen($filename, 'w'); fwrite($file, $denyclient); fclose($file);

mysql_close(); ?>

А трафик через TC в iptables режется...

#255603

Не хилый подход.

#255614

magistr_forever Ваш код работать не будет!
По крайней мере в таком виде.
Потому что в самой первой строке должно быть указанно
не

text
<?

, а

text
<?php
#255622
Vadimsky написал:
magistr_forever Ваш код работать не будет!
По крайней мере в таком виде.
Потому что в самой первой строке должно быть указанно
не
text
<?

, а

text
<?php

Смотря как настроен PHP.

#255624

Vadimsky, short_open_tag=On

#255629

Вот это работает, но с тормозами...

text

#!/bin/sh
rm -f /wifi/tmp/access.log
cp /var/log/squid/access.log /wifi/tmp/access.log
cat /dev/null > /var/log/squid/access.log
php /wifi/scripts/squid-to-mysql.php
echo "lstat for this access.log:"
ls -l /wifi/tmp/access.log
mv  /wifi/tmp/access.log /wifi/tmp/access.log.last
service squid reload
text

#!/usr/bin/php
<?php
define('LIMIT_TIME', '5'); //30 min
define('LIMIT_BYTES', '31457280'); //bytes (30 MB)
define('LIMIT_TIME_WAIT', '1'); //1 min
define('LIMIT_LAST_TIME', '20'); //5 min

$db = mysql_connect('', '', '') or die('connect to database failed'); #mysql_set_charset('cp1251'); mysql_select_db('') or die('db not found');

$filename = '/wifi/tmp/access.log'; $file = fopen($filename, 'r');

while(!feof($file)) { $line = fgets($file, 4096);

$line_array = preg_split("/[\s,]+/", $line); $t1 = preg_split("/[\/]/", $line_array[8]); if ($t1[1] == "127.0.0.1") continue; $t1 = preg_split("/[\/]/", $line_array[8]); if ($t1[1] == "192.168") continue; $t1 = preg_split("/[\/]/", $line_array[3]); if ($t1[0] == "TCP_DENIED") continue; $date = preg_split("/[.]/", $line_array[0]); $peerip = preg_split("/[\/]/", $line_array[8]); mysql_query("INSERT INTO `Traffic` (`date`, `clientip`, `resultcode`, `bytes`, `url`, `peerip`, `mimetype`) VALUES('".$date[0]."', INET_ATON('".$line_array[2]."'), '".$line_array[3]."', '".$line_array[4]."', '".$line_array[4]."', INET_ATON('".$peerip[1]."'), '".$line_array[9]."')"); mysql_query("INSERT INTO `Sessions` SET clientip = INET_ATON('".$line_array[2]."'), time=0, status = 1, bytes=".$line_array[4].", lasttime = '".$date[0]."' ON DUPLICATE KEY UPDATE bytes = bytes + ".$line_array[4].", lasttime = '".$date[0]."'");

} fclose($file);

mysql_query("UPDATE `Sessions` SET time = time + 1"); mysql_query("UPDATE `Sessions` SET status = 0, time = 0, bytes = 0 WHERE (time > '".LIMIT_TIME."' OR bytes > '".LIMIT_BYTES."') AND status = 1"); mysql_query("UPDATE `Sessions` SET status = 1 WHERE time > '".LIMIT_TIME_WAIT."' AND status = 0"); mysql_query("INSERT INTO `DenyList` (`clientip`) SELECT clientip FROM `Sessions` WHERE status = 0"); $time = time(); $lasttime = LIMIT_LAST_TIME*60; mysql_query("DELETE FROM `DenyList` WHERE clientip IN (SELECT clientip FROM `Sessions` WHERE status = 1 OR (".$time." - lasttime) > ".$lasttime.")"); mysql_query("DELETE FROM `Sessions` WHERE (".$time." - lasttime) > ".$lasttime." ");

//SQUID $result = mysql_query("SELECT clientip FROM `DenyList`"); $denyclient = ""; while($row = mysql_fetch_array($result)) { if ($denyclient != "") $denyclient .= "\n"; $denyclient .= long2ip($row['clientip']); }

$filename = '/etc/squid/deny.ip'; $file = fopen($filename, 'w'); fwrite($file, $denyclient); fclose($file); mysql_close(); ?>

#255633

magistr_foreverНу а так вообщем ничего, если не считать, что при первом запуске скрипта сквид упал ;)
Хотя таких реализаций много, но мне кажется этому делу тоже нужно дать ход.
Например, можно дамп для мускула, а то в первый раз базу создавать много руками тыкать - не каждый поймёт.
И таки написать инструкцию, как в крон добавить, что в какой последовательности. Запаковать в архивчик и присвоить номер релиза.
Как Вам идея?
Так и начинаются велики дела ;)
P.S. Можно ещё вебморду прикрутить. Джае готовую взять.

#255645
"Kettler" написал:
Смотря как настроен PHP.

У меня по умолчанию. И думаю, чем перенастраивать каждый раз движёк - правильне скрипт привести к нужному формату.

#255744

Нужен демон который будет откидывать клиентов по IP или как-то squid заставить в БД смотреть.
С перезагрузкой squid ничего хорошего не вышло )))

#255747
"magistr_forever" написал:
откидывать клиентов по IP или как-то squid заставить в БД смотреть

Так это же у вас указано:

"magistr_forever" написал:
text
$filename = '/etc/squid/deny.ip';

Только в конфиг сквида добавить что то типа:

text

acl sites_BAN dstdomain "/etc/squid/deny.ip"
http_access deny sites_BAN

И делать squid -k reconfigure по какому-либо событию или по крону.
Кстати, перезагружать сквид вовсе не обязательно ;)

#255749
"Vadimsky" написал:
И делать squid -k reconfigure по какому-либо событию или по крону.

Соединение не обрывает

#255750

Мне кажется через вот это нужно...

external_acl_type check %SRC check.py

#255754
"magistr_forever" написал:
Соединение не обрывает

А нужно что бы обрывало?
squid -k reconfigure заставляет сквид перечитать файл конфигурации. Естественно, что все запущенные процессы останутся.
Мне кажется добавлением чего угодно в конфигу не добится что бы он рвал соединения. ИМХО, это уже явно нужно делать, либо перезапуском сетевого интенрфейса, либо правилами iptables

Войдите или зарегистрируйтесь, чтобы ответить.