Wednesday, December 22, 2010

FTP сервер ProFTPd

Использую именно его, т.к. вполне простой и хорошо настраиваемый.
Первый момент - это то, что метод входа в папку на этом сервере - chroot, а значит система следит за правами доступа на файлы. Чтобы не было проблем с удалением файлов и пр., те файлы которые создаются автоматически должны иметь имя/права корректного пользователя. Либо, как делаю я 777, а потом просто разделение политик READ/WRITE настройками самого сервера.
Тут я выложу свой шаблон конфига, точнее, его отличия от дефолтного:


UseIPv6 off
IdentLookups off # Чтобы не искал DNS

ServerType standalone # Не люблю работать через inetd. Множатся сущности.
TimesGMT off # Хорошая опция :) При ней корректно отображается время файлов при просмотре.

Все остальные опции можно легко найти в мануале по Proftpd.

Friday, December 10, 2010

Про защиту астериска.

Защита астериска, особенно, если о стоит на внешнем IP - первоочередная задача. Итак...

1. Настроим сам Астериск

sip.conf
[general]
context=nocontext ; Чтобы неавторизованные/левые звонки никуда не попадали
allowguest=no ; Вообще запретить неавторизованные вызовы
match_auth_username=no
; Честно, не скажу как это влияет на защиту, но пишут, что влияет. Имеет смысл в том случае, если UserID и AuthUserID - разные
alwaysauthreject=yes ; Не выдает доп. информацию при неудачной регистрации. spwar отказывается работать.
useragent=D-Link DVG-1402S ; Или любой другой - найдите в гугле реальное железо. так вы будете меньше привлекать внимание хацкеров которые ищут астериски в инете.

users.conf
[XXX]
...
deny = 0.0.0.0/0.0.0.0

premit = <подсеть, в которой будет этот телефон>/<маска подсети>
; Не дает возможности регистрироваться экстеншенам из левых подсетей

2. Fail2Ban. Банит IP по проваленным попыткам регистрации.

apt-get install fail2ban
cd /etc/fail2ban/filter.d
vi asterisk.conf

# Fail2Ban configuration file
#
#
# $Revision: 250 $
#

[INCLUDES]

# Read common prefixes. If any customizations available -- read them from
# common.local
#before = common.conf


[Definition]

#_daemon = asterisk

# Option: failregex
# Notes.: regex to match the password failures messages in the logfile. The
# host must be matched by a group named "host". The tag "" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P\S+)
# Values: TEXT
#
# HOST надо поместить в <> скобки.
failregex = NOTICE.* .*: Registration from '.*' failed for 'HOST' - Wrong password
NOTICE.* .*: Registration from '.*' failed for 'HOST' - No matching peer found
NOTICE.* .*: Registration from '.*' failed for 'HOST' - Username/auth name mismatch
NOTICE.* .*: Registration from '.*' failed for 'HOST' - Device does not match ACL
NOTICE.* .*: Registration from '.*' failed for 'HOST' - Peer is not supposed to register
NOTICE.* failed to authenticate as '.*'$
NOTICE.* .*: No registration for peer '.*' \(from \)
NOTICE.* .*: Host failed MD5 authentication for '.*' (.*)
NOTICE.* .*: Failed to authenticate user .*@.*


# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =

vi /etc/fail2ban/jail.conf

[asterisk-iptables]

enabled = true
filter = asterisk
action = iptables-allports[name=ASTERISK, protocol=all]
sendmail-whois[name=ASTERISK, dest=root, sender=fail2ban@example.org]
logpath = /var/log/asterisk/messages
maxretry = 5
bantime = 259200

vi /etc/asterisk/logger.conf

[general]

dateformat=%F %T

Monday, October 18, 2010

Про запись разговоров

Тут напишу про шаблон, который постоянно дорабатывается, и которым пользуюсь я.

Это касается записи в очереди, но может быть легко адаптировано к любому случаю

extensions.conf
[macro-QueueRoutine]
exten => s,1,Set(TIMESTAMP=${STRFTIME(${EPOCH},,%T)})
exten => s,n,Set(DATESTAMP=${STRFTIME(${EPOCH},,%Y:%m:%d)})
exten => s,n,Set(DB(${CHANNEL}T)=${TIMESTAMP})
exten => s,n,Set(DB(${CHANNEL}D)=${DATESTAMP})
exten => s,n,Set(MONITOR_FILENAME=${UNIQUEID})
exten => s,n,Set(AUDIOHOOK_INHERIT(MixMonitor)=yes)

exten => h,1,StopMixMonitor
exten => h,n,Set(MEMBERINTERFACE=${CUT(MEMBERINTERFACE,/,2)})
exten => h,n,Set(TIMESTAMP=${DB_DELETE(${CHANNEL}T)})
exten => h,n,Set(DATESTAMP=${DB_DELETE(${CHANNEL}D)})
exten => h,n,GotoIf($[ "x${DATESTAMP}${TIMESTAMP}" != "x"]?DatePresent)
exten => h,n,Set(TIMESTAMP=${STRFTIME(${EPOCH},,%T)})
exten => h,n,Set(DATESTAMP=${STRFTIME(${EPOCH},,%Y:%m:%d)})
exten => h,n(DatePresent),GotoIf($[ "x${CALLERID(num)}" != "x" ]?CIDPresent)
exten => h,n,Set(CALLERID(num)=0000)
exten => h,n(CIDPresent),GotoIf($[ "x${MEMBERINTERFACE}" = "x"]?NoRec)
exten => h,n,System(sh /etc/asterisk/bin/rec.sh /home/superuser/RecordCalls ${DATESTAMP} ${TIMESTAMP} ${CALLERID(num)} ${MEMBERINTERFACE} ${UNIQUEID} I)
exten => h,n,System(rm /var/spool/asterisk/monitor/${UNIQUEID}.wav)
exten => h,n(NoRec),Set(CDR(userfield)=${MEMBERINTERFACE})
exten => h,n,Verbose(Call from 0${CALLERID(num)} was answered by ${MEMBERINTERFACE})


Более доработанный вариант скрипта, для более точного определения ответившего можно сделать, использовав описанное тут

И, собсно, сам скрипт преобразования в mp3
/etc/asterisk/bin/rec.sh

#! /bin/sh

# Recording file script. v0.5
# Arg1 - In/Out removed
# Arg1 - Directory Arg2 - who calles, Arg3 - Answered, Arg4 - Time, Arg5 - Date
# Arg1 - Directory, Arg2 - Date, Arg3 - Time, Arg4 - First number, Arg5 - Second number
# Arg1 - Directory, Arg2 - Date, Arg3 - Time, Arg4 - First number, Arg5 - Second number, Arg6 - Time Attribute
# Arg1 - Directory, Arg2 - Date, Arg3 - Time, Arg4 - First number, Arg5 - Second number, Arg6 - FileName, Arg7 - Time Attribute

MAINDIR="$1"
DATESTAMP="$2"
TIMESTAMP="$3"
FIRSTN="$4"
SECONDN="$5"
FILENAME="$6"
TIMEATTR="$7"

mkdir -p $MAINDIR
mkdir -p $MAINDIR/$DATESTAMP
case $TIMEATTR in
'D')
mkdir -p $MAINDIR/$DATESTAMP/$SECONDN
mkdir -p $MAINDIR/$DATESTAMP/$SECONDN/DayTime
lame /var/spool/asterisk/monitor/$FILENAME.wav $MAINDIR/$DATESTAMP/$SECONDN/DayTime/$TIMESTAMP--$FIRSTN.mp3
chmod 777 $TIMESTAMP--$FIRSTN.mp3
;;
*)
mkdir -p $MAINDIR/$DATESTAMP/$SECONDN
lame /var/spool/asterisk/monitor/$FILENAME.wav $MAINDIR/$DATESTAMP/$SECONDN/$TIMESTAMP--$FIRSTN.mp3
chmod 777 $TIMESTAMP--$FIRSTN.mp3
;;
esac

Суть проста, как угол дома. Файл, который пишет MixMonitor имеет формат ${UNIQUEID}.vaw
После разговора фай, в экстешнене h обрабатывается, как то, выяснение того, кто взял трубку, обработка ошибок на предмет того, что некоторых полей может не быть, вызов скрипта, который жмет в mp3 и удаление wav файла. Поле CDR(userfield) устанавливается для того, чтобы выяснить, какой абонент из очереди взял трубку.

Chmod используется, чтобы пользователи могли удалять файлы из ftp-сервера. Саму политику удаления/записи лучше настроить на самом ftp.

UPD: При трансфере отвеченного звонка лучше сделать доработку: Причем при входящем звонке нужно на канале ставить переменную, чтобы при окончании звонка в случае трансфера можно было определить, что звонок были именно входящий.

exten => h,1,StopMixMonitor
exten => h,n,GoToIf($[ "${LEN(${MONITOR_FILENAME})}" = "0"]?MixMonitorPresent)
exten => h,n,Set(FileName=${MONITOR_FILENAME})
exten => h,n(MixMonitorPresent),GoToIf($[ "${LEN(${SIPREFERREDBYHDR})}" = "0"]?NoTransferDetected)
exten => h,n,Set(FileName=${UNIQUEID})
exten => h,n(NoTransferDetected),Set(AnsweredPeer=${CUT(BRIDGEPEER,/,2)})
exten => h,n,Set(AnsweredPeer=${CUT(AnsweredPeer,-,1)})
exten => h,n,Set(MEMBERINTERFACE=${CUT(MEMBERINTERFACE,/,2)})
exten => h,n,Set(TIMESTAMP=${DB_DELETE(${CHANNEL}T)})
exten => h,n,GotoIf($[ "x${TIMESTAMP}" != "x"]?TimePresent)
exten => h,n,Set(TIMESTAMP=${STRFTIME(${EPOCH},,%T)})
exten => h,n(TimePresent),Set(DATESTAMP=${DB_DELETE(${CHANNEL}D)})
exten => h,n,GotoIf($[ "x${DATESTAMP}" != "x"]?DatePresent)
exten => h,n,Set(DATESTAMP=${STRFTIME(${EPOCH},,%Y:%m:%d)})
exten => h,n(DatePresent),GotoIf($[ "x${CALLERID(num)}" != "x" ]?CIDPresent)
exten => h,n,Set(CALLERID(num)=0000)
exten => h,n(CIDPresent),GotoIf($[ "x${MEMBERINTERFACE}" != "x"]?CheckPickup)
exten => h,n,Set(MEMBERINTERFACE=${DIALEDPEERNUMBER})
exten => h,n(CheckPickup),GotoIf($[ "${MEMBERINTERFACE}" = "${AnsweredPeer}"]?GoRec)
exten => h,n,GoToIf($[ "${LEN(${AnsweredPeer})}" != "3" ]?GoRec)
exten => h,n,Set(MEMBERINTERFACE=${AnsweredPeer})
exten => h,n(GoRec),System(sh /etc/asterisk/bin/rec.sh /home/record  ${DATESTAMP} ${TIMESTAMP} ${CALLERID(num)} ${MEMBERINTERFACE} ${FileName} Q)
exten => h,n(NoRec),System(rm /var/spool/asterisk/monitor/${FileName}.wav)
exten => h,n,Set(CDR(userfield)=${MEMBERINTERFACE})

Thursday, September 2, 2010

Про установку простенького биллинга

Опишу тут установку простенького биллинга на базе ams (Asterisk Management System).
Находится данный проект по адресу www.ampex.ru (или тут)
Итак, для начала установим на сервер с Asterisk связку apache+php+mysql. Все команды далее для Debian 5

#aptitude install mysql-server mysql-client apache2 php5 libapache2-mod-php5 php5 php5-mysql php5-gd php5-ps libmysqlclient15-dev



#/etc/init.d/apache2 restart


Да, часть модулей можно убрать, но я не настолько глубоко разбираюсь в php.
Разбирать установку ams я тут особо не буду, просто пара советов себе на будущее.
- читай файлы INSTALL и README
- для биллинга необходим ams_cdr_mysql
- Необходимо дать вебморде права на доступ и запись в /etc/asterisk
- после установки отредактировать файл /etc/asterisk/ams.conf
- Сокет mysql - =/var/run/mysqld/mysqld.sock

Если морда при установке не может прицепиться к mysql, то лучше создать базу руками:

mysql -u root -p
> CREATE DATABASE ams;
> GRANT ALL PRIVILEGES ON ams.* TO ams@localhost IDENTIFIED BY 'some_pass';
> FLUSH PRIVILEGES;

После, в вебморде в админке поправить необходимые модули.

Monday, July 26, 2010

Про сборку asterisk на свежеустановленном Debian Lenny 5.0/6.0

Что касается необходимых пакетов:

apt-get install zlib1g-dev libnewt-dev bison ncurses-dev procps flex automake build-essential autoconf libtool libssl-dev libncurses5-dev linux-headers-$(uname -r) libxml2-dev libsqlite3-dev


Сборка и установка:

Dahdi:
tar -xvf dahdi-linux-complete-XXX.tar.gz
cd dahdi-linux-complete-XXX

make (возможно надо указать make MODULES_EXTRA=dahdi_dummy)
make install
make config


Asterisk:
tar -xvf asterisk-XXX.tar.gz
cd asterisk-XXX
./configure
make menuselect
make
make install
make samples

make config

Астериск теперь на виртуальной консоли 9 (Ctrl+Alt+F9)

UPD: Примечание для Ubuntu. В скрипте safe_asterisk надо поменять #! /bin/sh на #! /bin/bash

Tuesday, July 6, 2010

Некоторый опыт по поводу настройки SIP-trunk через роутер.

Ситуация такая - есть во внутренней сети Астериск, в интернете - провайдер, который дает транк. Роутер - Polycom V2IU 4350T. В целом хорошая штука, но частенько капризничает. Так вот, по уверениям создателей она умеет корректно пробрасывать SIP трафик без дыр во внешней защите. Таки умеет, но почему-то только на 7.х версии прошивке. 9-я какая-то странная. В один прекрасный момент вырубилась функция h323 гейткипера, sip вообще перестал работать. В общем, даунгрейд помог. Теперь крайне простая схема:
SIP Server - указываем адрес нашего провайдера
SIP trunk - указываем адрес нашего Астера
Default inbound rule - на наш сервер.
В роутере - все.
Но есть хитрость. Почему-то он отказывется пропускать трафик, если перед этим не было REGISTER, посему лучше выпросить у провайдера логин и пароль.
Кстати, в самом астере надо реристрироваться и заводить транк так, если бы сам роутер был провайдером и не указывать ему в настройках external ip. Т.е. звоним и регистрируемся мы на роутере. Вот такая умная железка.

Monday, May 17, 2010

Asterisk + Polycom MWI

Итак, я таки заставил их работать вместе.
Что для этого надо:
1. Asterisk (я настроил на 1.4.30, думаю, с другими особо проблем не возникнет)
2. Собсно, телефон Polycom (настраивал на 301 - ужас, что там нету спикерфона, проверено на 501)
3. Boot Server (обычный FTP, думаю, тот, кто работал с телефонами Polycom знает, что это за зверь)

Итак... На примере номера 604 и имени Igor
Настройки самого Астера:
users.conf
[604]
FullName = XXXX
secret = XXXX
notifyringing=yes
call-limit=100
limitonpeers=yes
hasvoicemail = yes
mailbox = 604@TestVoiceMail

voicemail.conf
[TestVoiceMail]
604 => 1111,Igor
Пароль - произвольный, он не нужен, разве что пользоваться родным приложением VoiceMail, но оно мне показалось неудобным.

Настройки на Boot Server
<mac-адрес телефона>-phone.cfg

Что-то тут совсем плохо можно вставлять XML код
В общем, в теге PHONE_CONFIG есть опция OVERRIDES. В нем необходимо добавить следующее: msg.mwi.1.subscribe="604" up.mwiVisible="1"

Параметр up.mwiVisible="1" можно указать и в sip.cfg (sip_316.cfg в моем случае). Вообще, чтобы не сильно копаться в XML структуре, легче указывать необходимые опции через этот файл. Но это для штучной работы. Естественно, телефон необходимо перегрузить.

Соответственно, чтобы зажглась лампочка необходимо создать файл msg0000.txt в папке /var/spool/asterisk/voicemail/TestVoiceMail/604/INBOX Через секунду-две загорается лампочка.

Некоторые полезные ссылки (будут добавляться по мере нахождения и прочей полезности)

http://lynks.ru - Записки по триксбоксу
http://igorg.ru/ - Блог по VoIP
http://asteriskpbx.ru/ - Тоже информация по Asterisk
http://erlyvideo.org/ - Стриминг сервер, аналог (в чем-то) Woowza
http://tamkovich.com/ - Еще один блог по IP/Телекому
http://max.ptm-s.ru/blogs/ - Здесь можно почитать, как прикрутить chan_datacard и OSLEC
http://asteriskpbx.ru - База знаний от PBXWare.ru
http://wapo-spb.livejournal.com/ - Решения некоторых хитрых задач

Sunday, May 9, 2010

Первая запись :)

Итак, для чего, собственно, создается этот блог. Исключительно для поста какой-либо технической информации, которая оказалось полезной для меня.
Как то скрипты, ссылки и прочее.