понедельник, 14 сентября 2009 г.

Ищем обнаглевших пользователей в организации

Возникла небольшая задача: найти пользователя, который качает большой файл и напрочь забил нам канал. Ситуация придуманная, но основана на реальных событиях =). Итак, логинимся на наш шлюз и устнанавливаем пакет netdiag[в данный пакет входят следующие утилиты: trafshow,strobe,netwatch,statnet,tcpspray,tcpblast]
# apt-get install netdiag
Далее, запускам trafshow на интерфейсе, подключенном к Интернету.
# trafshow -i eth1
И наблюдаем, кто выжирает трафик. Идем к этому пользователю и даем ему по шапке =))

среда, 9 сентября 2009 г.

Защита ssh в debian с помощью denyhosts

Denyhosts - это скрипт, написанный на Python для защиты[в основном] SSH серверов от переборов паролей[брутфорса].Скрипт отслеживает логи системы о неудачных авторизациях и после того, как N-раз был неверно введена связка "логин-пароль" блокирует IP-адрес, с которого производилась атака[Банально вносит IP-адрес в /etc/hosts.deny].

Я покажу как за несколько минут защитить сервер от подбора паролей[знаю, что тема избитая, но решил написать для людей, кому не интересно долго ковыряться в настройках]. Итак, у вас уже должен быть установлен python. Если нет то устанавливаем:
apt-get install python
Скачиваем сам скрипт [На момент написания заметки версия 2.6].
wget http://sourceforge.net/projects/denyhosts/files/denyhosts/2.6/DenyHosts-2.6.tar.gz/download
Дальше распаковываем архив, заходим в него и запускаем процесс установки[из под root]:
$ tar xvfz DenyHosts-2.6.tar.gz
$ cd ./DenyHosts-2.6
# python setup.py install
После этого необходимо скопировать конфигурационный файл в каталог /etc:
cp ./denyhosts.cfg-dist /etc/denyhosts.cfg
А также файл daemon-control-dist в /usr/sbin/daemon-control:
cp ./daemon-control-dist /usr/sbin/daemon-control
После того как все удачно завершилось переходим к конфигурированию /etc/denyhosts.cfg. Т.к. статья расчитана на "немного ленивых админов"[сам из таких =)], то я сразу прикладываю нужный вам конфиг:
debian:/# cat ./denyhosts.cfg
SECURE_LOG = /var/log/auth.log
HOSTS_DENY = /etc/hosts.deny
PURGE_DENY =
BLOCK_SERVICE = sshd
DENY_THRESHOLD_INVALID = 5
DENY_THRESHOLD_VALID = 10
DENY_THRESHOLD_ROOT = 1
DENY_THRESHOLD_RESTRICTED = 1
WORK_DIR = /usr/share/denyhosts/data
SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS=YES
HOSTNAME_LOOKUP=YES
LOCK_FILE = /var/run/denyhosts.pid
AGE_RESET_VALID=5d
AGE_RESET_ROOT=25d
AGE_RESET_RESTRICTED=25d
AGE_RESET_INVALID=10d
DAEMON_LOG = /var/log/denyhosts
DAEMON_SLEEP = 30s
DAEMON_PURGE = 1h
Далее нужно открыть файл на редактирование /usr/sbin/daemon-control и внести изменение в несколько первых строк:
DENYHOSTS_BIN = "/usr/bin/denyhosts.py"
DENYHOSTS_LOCK = "/var/run/denyhosts.pid"
DENYHOSTS_CFG = "/etc/denyhosts.cfg"
PYTHON_BIN = "/usr/bin/env python"
Теперь просто стартуем наш denyhosts следующей командой и прописать эту же команду в автозагрузку например в /etc/rc.local:
/usr/sbin/daemon-control start > /dev/hull &
Через некоторое время у вас в файле начнут появляться заблокированные IP-адреса, с которых 5 раз[параметр DENY_THRESHOLD_INVALID = 5] был введены логин с паролем.

Замечательная автошкола приглашает всех желающих пройти курсы вождения.

вторник, 1 сентября 2009 г.

Биллинг для asterisk 1.6

Сразу оговорюсь, что данная статья предополагает что опыт внедрения asterisk у вас уже был. В нашей компании необходимо было внедрить небольшой call-центр, который бы включал в себя следующие функции:
1. Голосовое меню[Приветствие, выбор отдела или конкретного сотрудника, авторизация по pin-коду].После авторизации необходимо проверить наличие средств на лицевом счете и перевести звонок на ответственного сотрудника. В случае если средств не достаточно перевести на секретаря, который поможет пополнить[выписать] счет.
2. После разговора провести списание средств.

Поскольку при установке сторонних биллингов требуется учитывать множество нюансов - я решил написать биллинг сам.

Итак, в этой статье я не буду рассказывать как заставить писать логи asterisk в mysql базу. В интернете достаточно информации на эту тему [http://www.voip-info.org/wiki/view/Asterisk+cdr+mysql].

После успешного подключения связки Asterisk+cdr+mysql нам необходимо в этой же базе, куда пишутся логи, создать 2 новые таблицы[назовем ее "organizations" и "tariff"] со следующими полями:
organizations{
id int(11) auto_increment // ID организации
name text // Наименование организации
pin varchar(20) // Пин-код[необходмо обеспечить уникальность]
time int(11) // Оставшееся время
id_tarif int(11) // ID тарифа
}

tariff{
id int(11) auto_increment // ID тарифа
name varchar(50) // Название тарифа
price int(11) // Цена за минуту
descr varchar(300) // Описание
}


Конечно, вы можете добавить свои поля, если видите в этом необходимость. Далее качаете phpagi c официального сайта[http://phpagi.sourceforge.net/]. Распаковывайте файлы в папку /var/lib/asterisk/agi-bin. И в этом же каталоге создаете файл-скрипт с именем auth.php со следующим содержанием[сразу оговорюсь, что скрипт далек от совершенства :)]:
#!/usr/bin/php -q
require('phpagi.php');
function auth($agii)
{
// Определяем номера телефонов. Если абонент недоступен - идет переадресация на сотовый телефон.
$phones = array(
"79110071250" => "000", // Менеждер 1
"79217519838" => "001", // Менеждер 2
...................................................
"79216497787" => "505" // Менежер 505
);
$buffer='';
$dtmfwait=3000;
$result=$agii->fastpass_get_data($buffer,"hello",$dtmfwait,3);
$digits=$result['result'];
//Набран внутренний номер
if(strlen($digits)==3)
{
$agii->exec('Dial',"SIP/$digits");
foreach ($phones as $phone_1 => $phone_2) {
if($phone_2==$digits)
{
$agii->stream_file("net_na_meste");
$agii->exec('Set',"_NUMBER=$phone_1");
$agii->exec('Dial','H323/9999999@prov,,M(bubble),m');
}
}
}
if(strlen($digits)==1)
{
//Соединение с горячей линией 1С [тут авторизация по пин коду]
if($digits=='1')
{
for($i=1;$i<=3;$i++)
{
$agii->stream_file('pin_code');
$result = $agii->get_data('beep', 8000,6);
$code=$result['result'];
if($code=='0')
{
$agii->exec('Dial','SIP/000');
}
else {
$result = mysql_query("select time,id from organizations where pin='$code';");

if (mysql_num_rows($result)==1)
{
while ($row = mysql_fetch_array($result)) {
if($row[0]<=0) //если баланc <0
{
$agii->stream_file("balans_minus");
$agii->exec('Dial','SIP/000');
}
else
{
$agii->exec("Set CDR(userfield)=$row[1]");
mkdir('/home/shares/asterisk/'.$row[1]);
$path='/home/shares/asterisk/'.$row[1].'/'.date("d.m.y.H.i").'.wav';
$agii->exec('MixMonitor',$path.',b');
$agii->exec('Dial','SIP/302,20,tm');
$agii->exec('Dial','SIP/401&SIP/405&SIP/000,,tm');
}
}
}
//даем на ввод пин кода 3 попытки
else
{
$tries=3-$i;
$agii->stream_file('error_pin_code');
if($tries==0)
{
$agii->stream_file('3_error_pin_code');
$agii->exec('Dial','SIP/000');
}
}
}
}
}
//Техподдержка
if($digits=='2')
$agii->exec('Dial','SIP/405');
//Контроль качества
if($digits=='3')
$agii->exec('Dial','SIP/007');
//Секретарь
if($digits=='0')
$agii->exec('Dial','SIP/000');
}
if(strlen($digits)==0) $agii->exec('Dial','SIP/000');
$agii->stream_file("bye");
$agii->exec('Hangup');
return 0;
}

$link = mysql_connect("localhost", "asterisk", "password") or die("Could not connect: " . mysql_error());
mysql_select_db('asterisk', $link) or die ('Can\'t use database : ' . mysql_error());
$agi = new AGI();
$agi->answer();
$agi->exec('NoOp','Starting main module AGI script');
//Запуск основного модуля
auth($agi);
mysql_close($link);
?>

Далее в extensions.conf прописываем что при звонке с внешней линии - идет выполнение скрипта auth.php. [Если будут вопросы как это сделать - спрашивайте в комментах].

Теперь самый интересный вопрос: каким образом произойдет списание средств после разговора? Я очень долго искал информацию как можно выполнить свой скрипт после того как на одной из сторон кладется тубка, но ничего не нашел. А решение оказалось более чем простым. Для реализации списания средств со счета абонента, я использовал crontab. В /etc/crontab добавляется строка:
*/5 * * * * root /var/lib/asterisk/agi-bin/auth-pay.agi

Данной строкой мы каждые 5 минут запускам скрипт auth-pay.agi:
#!/usr/bin/php -q
$link = mysql_connect("localhost", "asterisk", "password") or die("Could not connect: " . mysql_error());
mysql_select_db('asterisk', $link) or die ('Can\'t use database : ' . mysql_error());
$result = mysql_query("SELECT userfield,billsec FROM cdr WHERE UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(calldate) <=300 AND userfield!=''") or die(mysql_error());

if (mysql_num_rows($result)>0)
{
while ($row = mysql_fetch_array($result)) {
mysql_query("UPDATE organizations SET time=time-$row[1] WHERE id=$row[0]");
}
}
$user =mysql_num_rows($result);
if ($user==1) {echo "$user User online";} else {echo "$user Users online";}
mysql_close($link);
?>


Данным скриптом мы выбераем все id организации, разговаривавших за последние 5 минут. Берем время разговора и вычитаем из поля time таблицы organizations.

Вот и все! Мини-биллинг готов. Такую схему можно перенести и на другие возможности астериска: например для ограничения звонков не с внешней линией, а с ваших абонентов.