Новости
3CX поглощает Elastix. (22. Dec 2016)
Объявлено о слиянии Elastix и 3CX. Версия MT закрыта для скачивания. Elastix 5 будет разрабатываться в партнерстве с 3CX и распространяться по коммерческой лицензии.
Объявлено о слиянии Elastix и 3CX. Версия MT закрыта для скачивания. Elastix 5 будет разрабатываться в партнерстве с 3CX и распространяться по коммерческой лицензии.
Объявлено о слиянии Elastix и 3CX. Версия MT закрыта для скачивания. Elastix 5 будет разрабатываться в партнерстве с 3CX и распространяться по коммерческой лицензии.
Trunk Name
sipnet
PEER Details
type=friend secret=PASSWORD qualify=yes nat=force_rport,comedia insecure=invite host=sipnet.ru fromuser=SIP_ID fromdomain=sipnet.ru dtmfmode=info disallow=all defaultuser=SIP_ID allow=alaw allow=ulaw allow=g729
Register String
userID:PASSWORD@sipnet.ru
Connectivity > Add SIP (chan_pjsip) Trunk
pjsip.aor.conf
[sipnet.ru] type=aor qualify_frequency=60 contact=sip:SIP_ID@sipnet.ru:5060
pjsip.auth.conf
[sipnet.ru] type=auth auth_type=userpass password=PASSWORD username=SIP_ID
pjsip.endpoint_custom.conf
[sipnet.ru] type=endpoint transport=0.0.0.0-udp context=from-pstn disallow=all allow=ulaw,alaw outbound_auth=sipnet.ru aors=sipnet.ru
pjsip.identify_custom.conf
[sipnet.ru] type=identify endpoint=sipnet.ru match=sipnet.ru
pjsip.registration_custom.conf
[sipnet.ru] type=registration transport=0.0.0.0-udp outbound_auth=sipnet.ru retry_interval=60 expiration=3600 auth_rejection_permanent=yes server_uri=sip:sipnet.ru:5060 client_uri=sip:SIP_ID@sipnet.ru:5060
pjsip.transports.conf
[0.0.0.0-udp] type=transport protocol=udp bind=0.0.0.0:5060 external_media_address=195.144.244.52 external_signaling_address=195.144.244.52 local_net=192.168.0.0/24
ubuntu*CLI> pjsip show endpoints Endpoint: <Endpoint/CID.....................................> <State.....> <Channels.> I/OAuth: <AuthId/UserName...........................................................> Aor: <Aor............................................> <MaxContact> Contact: <Aor/ContactUri...............................> <Status....> <RTT(ms)..> Transport: <TransportId........> <Type> <cos> <tos> <BindAddress..................> Identify: <MatchList.................................................................> Channel: <ChannelId......................................> <State.....> <Time(sec)> Exten: <DialedExten...........> CLCID: <ConnectedLineCID.......> ========================================================================================= Endpoint: sipnet.ru Not in use 0 of inf OutAuth: sipnet.ru/SIP_ID Aor: SIP_ID 0 Contact: sipnet.ru/sip:SIP_ID@sipnet.ru:5060 Avail 23.398 Transport: 0.0.0.0-udp udp 0 0 0.0.0.0:5060 Identify: 212.53.40.40/32,2a02:2f8:2:3::40/128
Connectivity > Outbound Routes
Пример данных провайдера
Asterisk 13.4.0 / FreePBX 13 (FreePBX Framework 13.0.1beta3.54)
asterisk*CLI> pjsip show registrations<Registration/ServerURI..............................> <Auth..........> <Status.......> ========================================================================================= pjsip_test/sip:sip.sprovider.ru:5060 pjsip_test Registered
asterisk*CLI> pjsip show endpoint pjsip_test Endpoint: <Endpoint/CID.....................................> <State.....> <Channels.> I/OAuth: <AuthId/UserName...........................................................> Aor: <Aor............................................> <MaxContact> Contact: <Aor/ContactUri...............................> <Status....> <RTT(ms)..> Transport: <TransportId........> <Type> <cos> <tos> <BindAddress..................> Identify: <Identify/Endpoint.........................................................> Match: <ip/cidr.........................> Channel: <ChannelId......................................> <State.....> <Time(sec)> Exten: <DialedExten...........> CLCID: <ConnectedLineCID.......> ========================================================================================= Endpoint: pjsip_test Not in use 0 of inf OutAuth: pjsip_test/1234567 Aor: pjsip_test 0 Contact: pjsip_test/sip:12345670@sip.sprovider.ru:5060 Avail 78.715 Transport: 0.0.0.0-udp udp 0 0 0.0.0.0:5077 Identify: pjsip_test/pjsip_test Match: 123.123.123.123/32 ParameterName : ParameterValue ===================================================== 100rel : yes accountcode : aggregate_mwi : true allow : (g729|alaw|ulaw|g726) allow_subscribe : true allow_transfer : true aors : pjsip_test auth : call_group : callerid : <unknown> callerid_privacy : allowed_not_screened callerid_tag : connected_line_method : invite context : from-sprovider ......
<spoiler>
Simple/Advanced |
v |
60 |
3600 |
10 |
10 |
60 |
0.0.0.0-udp |
ulaw |
alaw |
g722 |
Группа екстеншенов для приема звонков. Используйте там, где не требуется функционал Queues
ring group dialplan - extensions_additional.conf
ring group dialplan - extensions_additional.conf
В отличии от очереди (queue), в Asterisk нет такого объекта или модуля, как Ring Group.
Для вызова группы, данным модулем, генерируется соответствующий диалплан.
[ext-group] include => ext-group-custom exten => 666,1,GotoIf($["${__RINGINGSENT}" = "TRUE"]?cid) exten => 666,n,Playtones(ring) exten => 666,n,Progress exten => 666,n(cid),Macro(user-callerid,) exten => 666,n,Macro(blkvm-setifempty,) exten => 666,n,GotoIf($["${GOSUB_RETVAL}" = "TRUE"]?skipov) exten => 666,n,Macro(blkvm-set,reset) exten => 666,n,Set(__NODEST=) exten => 666,n(skipov),Set(RRNODEST=${NODEST}) exten => 666,n(skipvmblk),Set(__NODEST=${EXTEN}) exten => 666,n,GosubIf($[${DB_EXISTS(RINGGROUP/666/changecid)} = 1 & "${DB(RINGGROUP/666/changecid)}" != "default" & "${DB(RINGGROUP/666/changecid)}" != ""]?sub-rgsetcid,s,1()) exten => 666,n,Gosub(sub-record-check,s,1(rg,666,dontcare)) exten => 666,n,Set(RingGroupMethod=ringall) exten => 666,n(DIALGRP),Macro(dial,20,${DIAL_OPTIONS},5000-5001-5002) exten => 666,n,Gosub(sub-record-cancel,s,1()) exten => 666,n,Set(RingGroupMethod=) exten => 666,n,GotoIf($["foo${RRNODEST}" != "foo"]?nodest) exten => 666,n,Set(__NODEST=) exten => 666,n,Macro(blkvm-clr,) exten => 666,n,Goto(app-blackhole,hangup,1) exten => 666,n(nodest),Noop(SKIPPING DEST, CALL CAME FROM Q/RG: ${RRNODEST}) exten => h,1,Macro(hangupcall,) ;--== end of [ext-group] ==--;
Обратите внимание на инклюд: include ⇒ ext-group-custom
Это значит, что вы можете написать собственный алгоритм вызова группы номеров с блек джеком и шлюхамии использовать его как ринг группу freepbx.
Номер группы вызываемый в диалплане.
Описание группы.
Понятное название для группы вызова. Используется для идентификации в других модулях FreePBX.
Стратегия вызова пользователей групы.
(max 300 sec) Время в секундах в течение которого телефоны будут звонить. Для всех стратегий вызова серийного искания, это время звонка для каждого шага стратегии вызова.
Список внутренних номеров группы по одному в каждой строке. Вы можете добавить внешний номер или номер удаленной системы. Чтобы обозначить такие екстеншены, добавьте в конец решетку #. Чтобы группа могла вызвать внешний номер, его формат должен совпадать с шаблоном набора из модуля Outbound Routes. Также добавляйте решетку, если в качестве екстеншенов используются такие объекты freepbx, как Queues или Follow-Me.
Выбор участников группы из списка существующих.
Приветствие:Сообщение, которое будет воспроизведено для входящего респондента, прежде чем пойдет звонок в эту группу.Для создания такого приветствия используйте раздел меню System Recordings
Использовать Музыку в ожидании? Если выбран класс Музыки в ожидании вместо простого сигнала вызова (КПВ), то позвонивший будет слушать музыку, пока кто-то не поднимет трубку.
Префикс ИД имени: Опционально, можно использовать какой-то префикс для звонка в эту группу. Например, если это группа «Sales:», то, установив такой префикс для этой группы, можно видеть, если звонит John Doe, то мы увидим на дисплее Sales:John Doe.
Дополнительная информация ALERT_INFO добавляет указанное значение в SIP header Alert-Info. Если телефон поддерживает, будет выведено на дисплей
Отправлять прогресс вызова в вызывающий канал.
YesNo
Игнорировать установки предустановленной переадресации звонков (CF). Если отмечено, форвардинг звонка будет игнорироваться. Это относится к общим установкам CF, форвардингу на Занято и при Неответе. Внутренний номер, набранный с '#' на конце, например для доступа к опции Следуйте сюда, может не сработать.
YesNo
Пропускать занятых операторов. Если отмечено, оператор на вызове будет пропущен и линия возвратит статус Занято. Это служит для тех случаев, когда используются мультиканальные телефоны и телефоны с опцией ожидания второго вызова, которые не верно отрабатывают в различных стратегиях звонков с серийным исканием, таким образом звонок перейдёт следующему члену группы дозвона.
YesNo
Включить перехват вызова в группе. Это даёт возможность прямого перехвата входящего вызова используя номер группы. Если не отмечено, то отдельные внутренние номера, являющиеся членами группы, могут перехватывать вызовы, используя сервисный код прямого перехвата, который будет работать вне зависимости включен пикап здесь или нет.
YesNo
Подтверждение звонков. Используйте это, если звонок идёт на внешний номер, который нуждается в подтверждении. Например, мобильный телефон может включить голосовую почту, которая перехватит этот вызов. Нажатием на 1 можно заблокировать такие действия. Опция действительна только при стратегии вызова ringall (звонят-все).
YesNo
Объявление пользователю принимающему вызов: Сообщение воспроизводится для принявшего этот звонок, если включена опция Call Confirm (Подтверждение звонков). Для создания такого приветствия используйте модуль System recordings.
Сообщение Уже-поздно: Сообщение воспроизводится для принявшего этот звонок, если звонок уже принят прежде чем он успел нажать 1. Для создания такого сообщения используйте модуль System Recordings .
Фиксированное значение Caller ID:</b><br><span>Фиксированное значение для замены Caller ID в зависимости от одного из режимов выше. Должен быть только в цифровом формате, или опционально - в формате Е164 с использованием «+» впереди номера.
Записывать вызовы. Можно выбрать из следующих возможностей: всегда записывать соединения, никогда не записывать соединения, или записывать по запросу во время разговора. Если включена опция не записывать соединения, то запись по запросу также невозможна.
ForceDont CareNever
Везде где возможен вызов екстеншена, во FreePBX добавлена опция включения записи. Если, например, требуется записывать все входящие и исходящие вызовы, достаточно включить запись в модулях Inbound Routesи Outbound Routes, соответственно.
Назначение, если никто не ответил. В выпадающем списке, выберете модуль FreePBX, который вы хотите использовать для failover
~~
Направление исходящей связи можно реализовать определением короткого кода доступа (например '9'), или определить полностью шаблон набираемых номеров.
[international] ignorepat => 9 exten => _9810.,1,Dial(DAHDI/g2/${EXTEN:1}) exten => _9810.,2,Congestion include => longdistance [longdistance] ignorepat => 9 exten => _98[02-9]XXXXXXXXX,1,Dial(DAHDI/g2/${EXTEN:1}) exten => _98[02-9]XXXXXXXXX,2,Congestion include => local [local] ignorepat => 9 exten => _9[02-9]XXXXXX,1,Dial(DAHDI/g2/${EXTEN:1}) exten => _9[02-9]XXXXXX,2,Congestion include => default
В этом примере рассматриваются 3 контекста с различными правами доступа к Телефонной сети Общего Пользования .
Конструкция 'ignorepat ⇒ 9 ' говорит Астериску не отключать тон готовности после набора заданной цифры.
Переменная ${EXTEN:1} удаляет префикс:
${123456789:1} - возвращает строку 23456789 ${123456789:-4} - возвращает строку 6789 ${123456789:0:3} - возвращает строку 123 ${123456789:2:3} - возвращает строку 345 ${123456789:-4:3} - возвращает строку 678
Сохранение CDR в mysql и просмотр данных о звонках FreeSWITCH при помощи веб интерфейса - CDR-Viewer.
Предполагается, что сервер mysql (mariadb) установлен.
yum install -y mysql-connector-odbc unixODBC unixODBC-devel
# Driver from the mysql-connector-odbc package # Setup from the unixODBC package [MySQL] Description = ODBC for MySQL Driver = /usr/lib/libmyodbc5.so Setup = /usr/lib/libodbcmyS.so Driver64 = /usr/lib64/libmyodbc5.so Setup64 = /usr/lib64/libodbcmyS.so FileUsage = 1
[freeswitch] Driver=MySQL SERVER=localhost PORT=3306 DATABASE=freeswitchcdr USER=DB_USER PASSWORD=DB_PASSWORD
echo "select 1" | isql -v freeswitch
+---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ SQL> select 1 +---------------------+ | 1 | +---------------------+ | 1 | +---------------------+ SQLRowCount returns 1 1 rows fetched
Создайте файл, например:
touch freeswitchcdr.sql
И скопируйте в него структуру таблицы БД:
CREATE TABLE cdr ( calldate datetime NOT NULL default '0000-00-00 00:00:00', clid varchar(80) NOT NULL default '', src varchar(80) NOT NULL default '', dst varchar(80) NOT NULL default '', dcontext varchar(80) NOT NULL default '', channel varchar(80) NOT NULL default '', dstchannel varchar(80) NOT NULL default '', lastapp varchar(80) NOT NULL default '', lastdata varchar(80) NOT NULL default '', duration int(11) NOT NULL default '0', billsec int(11) NOT NULL default '0', disposition varchar(45) NOT NULL default '', amaflags int(11) NOT NULL default '0', accountcode varchar(20) NOT NULL default '', uniqueid varchar(32) NOT NULL default '', userfield varchar(255) NOT NULL default '', did varchar(50) NOT NULL default '', recordingfile varchar(255) NOT NULL default '', KEY `calldate` (`calldate`), KEY `dst` (`dst`), KEY `accountcode` (`accountcode`), KEY `uniqueid` (`uniqueid`) );
mysqladmin create freeswitchcdr
mysql asteriskcdrdb < freeswitchcdr.sql
mysql> GRANT ALL PRIVILEGES ON freeswitchcdr.* TO DB_USER@localhost IDENTIFIED BY 'DB_PASSWORD'; flush privileges; \q
Расскомментируйте строку event_handlers/mod_odbc_cdrв файле исходников FS ../freeswitch/modules.conf
и выполните make && make install.
По окончании компиляции скопируйте файл odbc_cdr.conf.xml из исходников в директорию, где установлен FS.
В моем примере это /usr/local/src/freeswitchи /usr/local/freeswitchсоответственно
cp /usr/local/src/freeswitch/src/mod/event_handlers/mod_odbc_cdr/conf/autoload_configs/odbc_cdr.conf.xml /usr/local/freeswitch/conf/autoload_configs/odbc_cdr.conf.xml
И заполните файл следующим содержанием, где параметры БД (odbc-dsn), данные определенные нами в odbc.ini:
<configuration name="odbc_cdr.conf" description="ODBC CDR Configuration"><settings><!-- <param name="odbc-dsn" value="freeswitchcdr:DB_USER:DB_PASSWORD"/> --><param name="odbc-dsn" value="odbc://freeswitch"/><!-- global value can be "a-leg", "b-leg", "both" (default is "both") --><param name="log-leg" value="both"/><!-- value can be "always", "never", "on-db-fail" --><param name="write-csv" value="on-db-fail"/><!-- location to store csv copy of CDR --><param name="csv-path" value="/usr/local/freeswitch/log/odbc_cdr"/><!-- if "csv-path-on-fail" is set, failed INSERTs will be placed here as CSV files otherwise they will be placed in "csv-path" --><param name="csv-path-on-fail" value="/usr/local/freeswitch/log/odbc_cdr/failed"/><!-- dump SQL statement after leg ends --><param name="debug-sql" value="true"/></settings><tables><!-- only a-legs will be inserted into this table --><table name="cdr" log-leg="a-leg"><field name="calldate" chan-var-name="start_stamp"/><field name="clid" chan-var-name="caller_id_name"/><field name="src" chan-var-name="caller_id_number"/><field name="dst" chan-var-name="destination_number"/><field name="dcontext" chan-var-name=""/><field name="channel" chan-var-name="channel_name"/><field name="dstchannel" chan-var-name="bridge_channel"/><field name="lastapp" chan-var-name="hangup_cause"/><field name="lastdata" chan-var-name="sip_hangup_disposition"/><field name="duration" chan-var-name="duration"/><field name="billsec" chan-var-name="billsec"/><field name="disposition" chan-var-name="hangup_cause"/><field name="lastapp" chan-var-name="current_application"/><field name="amaflags" chan-var-name="amaflags"/><field name="uniqueid" chan-var-name="uuid"/><field name="recordingfile" chan-var-name="recordingfile"/><field name="userfield" chan-var-name=""/></table></tables></configuration>
fs_cli
load mod_odbc_cdr
Если в дальнейшем вы будете вносить изменения в файл odbc_cdr.conf.xmlих можно применить командой:
reload mod_odbc_cdr
reload mod_odbc_cdr
reload mod_odbc_cdr
freeswitch@internal> reload mod_odbc_cdr +OK Reloading XML +OK module unloaded +OK module loaded 2016-07-21 18:58:05.585312 [CONSOLE] switch_loadable_module.c:2008 Stopping: mod_odbc_cdr 2016-07-21 18:58:05.585312 [DEBUG] mod_odbc_cdr.c:542 Destroying table cdr 2016-07-21 18:58:05.585312 [CONSOLE] switch_loadable_module.c:2028 mod_odbc_cdr unloaded. 2016-07-21 18:58:05.585312 [INFO] mod_enum.c:880 ENUM Reloaded 2016-07-21 18:58:05.585312 [DEBUG] mod_odbc_cdr.c:396 Set odbc-dsn [odbc://freeswitch] 2016-07-21 18:58:05.585312 [DEBUG] mod_odbc_cdr.c:405 Set debug-sql [true] 2016-07-21 18:58:05.585312 [DEBUG] mod_odbc_cdr.c:425 Set log-leg [both] 2016-07-21 18:58:05.585312 [DEBUG] mod_odbc_cdr.c:436 Set csv-path [/usr/local/freeswitch/log/odbc_cdr/] 2016-07-21 18:58:05.585312 [DEBUG] mod_odbc_cdr.c:437 Set csv-path-on-fail [/usr/local/freeswitch/log/odbc_cdr/failed/] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:113 Found table [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:117 Set table [cdr] to log A-legs only 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:128 Adding fields to table [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [calldate] (start_stamp) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [clid] (caller_id_name) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [src] (caller_id_number) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [dst] (destination_number) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [channel] (channel_name) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [dstchannel] (bridge_channel) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [lastapp] (hangup_cause) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [lastdata] (sip_hangup_disposition) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [duration] (duration) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [billsec] (billsec) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [disposition] (hangup_cause) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [lastapp] (current_application) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [amaflags] (amaflags) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [uniqueid] (uuid) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [recordingfile] (recordingfile) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] mod_odbc_cdr.c:139 Field [userfield] (branch) added to [cdr] 2016-07-21 18:58:05.585312 [INFO] switch_time.c:1415 Timezone reloaded 1781 definitions 2016-07-21 18:58:05.595283 [CONSOLE] switch_loadable_module.c:1538 Successfully Loaded [mod_odbc_cdr]
cd /var/www/html
git clone https://github.com/g613/asterisk-cdr-viewer.git cd asterisk-cdr-viewer/include
$db_type = 'mysql'; $db_host = 'localhost'; $db_port = '3306'; $db_user = 'DB_USER'; $db_pass = 'DB_PASSWORD'; $db_name = 'freeswitchcdrdb'; $db_table_name = 'cdr'; $db_options = array();
Если все сделано правильно в Asterisk-CDR-Viewer будут отображаться свежие данные о вызовах:
Для того, чтобы работала сортировка по статусу вызова надо отредактировать файл ../asterisk-cdr-viewer/templates/form.tpl.phpзаменив секцию:
<td nowrap=""nowrap><input <?php if ( isset($_REQUEST['disposition_neg'] ) && $_REQUEST['disposition_neg'] == 'true' ) { echo 'checked="checked"'; } ?> type="checkbox" name="disposition_neg" value="true" /> not<select name="disposition" id="disposition"><option <?php if (empty($_REQUEST['disposition']) || $_REQUEST['disposition'] == 'all') { echo 'selected="selected"'; } ?> value="all">All Dispositions</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'ANSWERED') { echo 'selected="selected"'; } ?> value="ANSWERED">Answered</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'BUSY') { echo 'selected="selected"'; } ?> value="BUSY">Busy</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'FAILED') { echo 'selected="selected"'; } ?> value="FAILED">Failed</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'NO ANSWER') { echo 'selected="selected"'; } ?> value="NO ANSWER">No Answer</option></select></td>
на следующий код:
<td nowrap=""nowrap><input <?php if ( isset($_REQUEST['disposition_neg'] ) && $_REQUEST['disposition_neg'] == 'true' ) { echo 'checked="checked"'; } ?> type="checkbox" name="disposition_neg" value="true" /> not<select name="disposition" id="disposition"><option <?php if (empty($_REQUEST['disposition']) || $_REQUEST['disposition'] == 'all') { echo 'selected="selected"'; } ?> value="all">All Dispositions</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'NORMAL_CLEARING') { echo 'selected="selected"'; } ?> value="NORMAL_CLEARING">Answer</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'USER_BUSY') { echo 'selected="selected"'; } ?> value="USER_BUSY">Busy</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'UNALLOCATED_NUMBER') { echo 'selected="selected"'; } ?> value="UNALLOCATED_NUMBER">No Number</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'NO_ROUTE_DESTINATION') { echo 'selected="selected"'; } ?> value="NO_ROUTE_DESTINATION">No Route</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'ORIGINATOR_CANCEL') { echo 'selected="selected"'; } ?> value="ORIGINATOR_CANCEL">No Answer</option></select></td>
Follow Me - настройка предустановленной переадресации вызова - Следуй За Мной.
Конфигурационный файл /etc/asterisk/followme.confиспользуется для назначения глобальных параметров generalи уникальных адресатов followmeid, которые могут выполняться из диалплана приложением Follow Me
Приоритет может быть использован только один раз, т.е. в одной строке, но не в разных (для одного пользователя).
Отдельные строки с одинаковым приоритетом будут игнорироваться.
Параллельные вызовы на разные номера (два и больше), должны описываться в одной строке при помощи оператора '&'.
[имя или номер] используется для вызова приложением FollowMe
context ⇒ <context name> - контекст, из которого будут вызываться заданные номера folowme
number ⇒ <number>,[<timeout>],[<priority>] - адресат, время посылки вызова, приоритет
[followmeid_simple] context=from-internal number => 9981138,15 number => 1234,20 number => 3216111,45
Сперва вызывается номер 9981138 в течении 15-ти секунд, затем номер -1234 в течении 20 секунд и после номер 3216111 в течении 45 секунд.
[followmeid_sorted] context=from-internal number => 9981138,35,2 number => 1234,20,1 number => 3216111,50,3
Сначала вызывается номер 1234 (приоритет 1), затем 9981138 (2) и последним 3216111 (3) .
[followmeid_parallel] context=full_outbound_access number => 1234&9981138,35,1 number => 3216111,50,2
Сперва вызываются номера 1234 и 9981138 одновременно, затем 3216111.
Убедитесь, что app_followme.so загружен.
*CLI> module load app_followme.so Loaded app_followme.so == Parsing '/etc/asterisk/followme.conf': Found followme.conf == Registered application 'FollowMe' Loaded app_followme.so => (Find-Me/Follow-Me Application)
Глобальные параметры folowme
featuredigittimeout=>5000
Время в миллисекундах, в течении которого система будет ждать подтверждения принять вызов, вводом DTMF кода, от вызываемого абонента.
enable_callee_prompt=>true
Включить голосовое объявление вызываемому абоненту, с предложением принять или отказаться от переадресованного вызова.
По умолчанию - включено.
takecall=>1
Общее, по умолчанию '1', значение DTMF кода, подтверждения приема вызова.
Может состоять из одной или нескольких цифр.
declinecall=>2
Общее, по умолчанию '2', значение DTMF кода, отказа от ответа на вызов.
call_from_prompt=>followme/call-from
Общее, по умолчанию, сообщение «Входящий вызов от».
norecording_prompt=>followme/no-recording
Общее, по умолчанию, сообщение «Входящий вызов», если вызывающий выбрал опцию, не записывать свое имя.
options_prompt=>followme/options
Общее, по умолчанию, сообщение - «Нажмите 1 чтобы принять вызов или 2 чтобы отказаться».
pls_hold_prompt=>followme/pls-hold-while-try
Общее сообщение: «Оставайтесь на линии, мы вас соединяем».
status_prompt=>followme/status
Общее сообщение: «Вызываемый абонент не на рабочем месте»
sorry_prompt=>followme/sorry
Общее сообщение: «Местонахождение абонента не установлено»
Конфигурация уникального идентификатора для вызова приложением FollowME
musicclass=>default
Класс Музыки на Удержании для воспроизведения ожидающему абоненту.
context=>default
Контекст для вызова адресатов followme
number=>01233456,25
Адресат followme.
Формат:
number⇒ <number to call[&2nd #[&…]]>[,<таймаут в секундахs>[,<порядок выбора адресатов>]]
enable_callee_prompt=>true
Включить приглашение вызывающему абоненту активировать followme.
По умолчанию действует глобальная установка из раздела [general].
takecall=>1
Общее, по умолчанию '1', значение DTMF кода, подтверждения приема вызова.
Может состоять из одной или нескольких цифр. По умолчанию действует глобальная установка из раздела [general].
declinecall=>2
Общее, по умолчанию '2', значение DTMF кода, отказа от ответа на вызов. По умолчанию, как задано в [general].
Назначить сообщения отличные от заданных по умолчанию в [general]
call_from_prompt=>followme/call-from
norecording_prompt=>followme/no-recording
options_prompt=>followme/options
pls_hold_prompt=>followme/pls-hold-while-try
status_prompt=>followme/status
sorry_prompt=>followme/sorry
Приложение диалплана Asterisk для «умной» предустановленной переадресации вызова.
Данное приложение позволяет перевести вызывающего абонента на указанные номера. Команда ссылается на профили <followmeid> заданные в followme.conf. Если указанный <followmeid> не найден, приложение возвращает вызов и диалплан выполняется со следующего приоритета.
Возвращает '-1' при отбое.
FollowMe(followmeid[,options])
пример 1
extensions.conf: exten => _4411,1,Answer exten => _4411,2,Dial(SIP/${EXTEN},12,t) exten => _4411,3,GotoIf($["${DIALSTATUS}" = "NOANSWER"]?:4:5) exten => _4411,4,Followme(${EXTEN}) exten => _4411,5,VoiceMail(u${EXTEN}) exten => _4411,6,Hangup
followme.conf:
[4411] context => default number => 4410,30 number => 4420,30
пример 2:
extensions.conf:
exten => 1111,1,Dial(PJSIP/1111,15,tr) exten => 1111,n,FollowMe(4444) exten => 1111,n,Wait(1) exten => 1111,n,Playback(beep) exten => 1111,n,Goto(1) exten => 2222,1,Dial(PJSIP/2222},15,tr) exten => 2222,n,FollowMe(UserTest,san) exten => 2222,n,Goto(4444,1) exten => 4444,1,Dial(PJSIP/4444,15,tr) exten => 4444,n,FollowMe(${EXTEN},s) exten => 4444,n,Voicemail(UserTest) exten => 4444,n,Hangup
followme.conf:
[4444] music => default context => default number => 1965751234,5 number => 17182025678,20 number => 1234 number => 5678 [UserTest] number => 09876&210,40,2 ; вызываются одновременно 09876 и 210 в течении 40-ка секунд. number => 543,30,1 ; но сначала вызывается 543 в течении 30 секунд.
Пример 3: Follow-me без использования приложения app_followme
[incoming] exten => 300,1,Answer() exten => 300,2,Dial(DAHDI/1,30,grM(call-screening^${CALLERIDNUM}^${CONTEXT}^${EXTEN}^${PRIORITY})) exten => 300,3,Hangup() exten => 300,103,NoOp(${EXTEN}::${PRIORITY}) exten => 300,104,VoiceMail(u${EXTEN}@default) exten => 300,105,Hangup() exten => t,1,Playback(connection-timed-out) exten => t,2,Playback(goodbye) exten => t,3,Hangup()
[macro-call-screening] exten => s,1,NoOp(${ARG2}::${ARG3}::${ARG4}::) exten => s,2,Playback(vm-youhave) exten => s,3,Playback(letters/a) exten => s,4,Playback(call) exten => s,5,Playback(from) exten => s,6,SayDigits(${ARG1}) exten => s,7,Read(ACCEPTCALL|1-yes-2-no|1) ; (repeatoptions) exten => s,8,GotoIf($["${ACCEPTCALL}" = ""] ?t,1) exten => s,9,GotoIf($[${ACCEPTCALL} = 2] ?s,11) exten => s,10,GotoIf($[${ACCEPTCALL} = 1] ?s,14:s,2) exten => s,11,Set(NEWPRIORITY=$[${ARG4} + 101]) exten => s,12,Set(MACRO_RESULT=GOTO:${ARG2}^${ARG3}^${NEWPRIORITY}) exten => s,13,Goto(s,16); exten => s,14,Playback(auth-thankyou) exten => s,15,Set(MACRO_RESULT=) exten => s,16,NoOp(End of macro) exten => t,1,Playback(connection-timed-out) exten => t,2,Goto(s,2)
см. также
Услуги по установке, настройке и обслуживанию Asterisk и FreeSwitch. Нами реализовано более 200 проектов, учитывая только Asterisk.
За годы работы, наши специалисты накопили большой опыт внедрения различных телекоммуникационных платформ,
что позволяет, предлагать клиентам оптимальные решения и лучшее оборудование.
Для внедрения IP АТС небольшой емкости (до 100 абонентов), прекрасно подходит программная АТС Asterisk с веб интерфейсом FreePBX. Русскоязычный, простой и интуитивно понятный веб интерфейс позволит вам, в дальнейшем, обслуживать АТС без дополнительных затрат. Все используемое ПО является свободно распространяемым и вы платите только за пусконаладку. Приобретая базовую установку Asterisk вы гарантировано получаете:
Программное обеспечение и функционал:
Базовая настройка IP АТС Asterisk:
Варианты установки:
Базовая настройка Asterisk при помощи веб-интерфейса предоставляет большие возможности, намного превосходящие возможности традиционных АТС, но, отнюдь не полностью реализующие возможности Asterisk. Для систем большой емкости и самых продвинутых запросов мы предлагаем расширенную настройку. Полностью описать возможности и способы применения не под силу сжатому описанию, поэтому перечислим основные:
Под реалтайм в Asterisk подразумевается взаимодействие с базами данных и другими типами хранилищ в режиме реального времени. Поддерживается статическое хранение настроек Asterisk в БД и собственно реалтайм взаимодействие. -В первом случае, настройки получаются из хранилища в момент загрузки модуля или ядра АТС, так же как и при использовании конфигурационных файлов. -Во втором (реалтайм) настройки не требуют применения и доступны сразу, после внесения изменений. Также в Asterisk имеется большой набор команд и функций, для взаимодействия с реалтайм хранилищами в момент обработки вызова. В каких случаях применяется Реалтайм Архитектура?
Поддерживаются следующие типы хранилищ: MySQL, PostgreSQL, SQLite, LDAP, нативно и через ODBC, а также прием и передача данных при помощи cURL. Предлагаем любые реализации реалтайм архитектуры Asterisk.
Asterisk имеет три интерфейса (4-ре вместе Command Line Interface) для взаимодействия с другими приложениями:
Сами по себе интерфейсы в установленном Asterisk готовы к работе и не требуют серьезной настройки. Предлагаем консультации по работе с APIи ПО под нужды клиентов.
Для подключения внешних пользователей к корпоративной телефонной сети, часто используется шифрование голосового трафика. Asterisk поддерживает шифрование протоколом SRTP с методом обмена ключами SDES через SDP. Предлагаем настройку защищенных телекоммуникационных систем.
Предлагаем построение распределенных телефонных систем, интеграцию с другими АТС через VoIP и ISDN протоколы связи, с единым номерным планом и централизованным управлением. Построение VPN сетей под нужды телефонии. На нашем счету проекты объединяющие по 50 филиалов в единую телефонную сеть. Наши специалисты подберут оптимальное оборудование, зарекомендовавшее себя в других проектах.
«Там, где пехота не пройдет…»
Кросс-платформенная много-пользовательская программная АТС FreeSWITCH
зарекомендовала себя системой повышенной производительности.
Более сложный в настройке и обслуживании, чем Asterisk, тем не менее,
FS показывает вчетверо большую производительность, при потреблении равных ресурсов.
Если абонентская емкость превышает 200 номеров, имеет смысл рассмотреть FreeSWITCH
в качестве альтернативы.
Мы предлагаем установку и настройку IP АТС FreeSWITCH в любой из указанных ролей.
В базовую настройку входит установка и настройка отказоустойчивой системы FreeSWITCH,
с использованием СУБД PostgreSQL в качестве базы данных ядра и регистраций,
а также MySQL - для отчетов о звонках, с веб-интерфейсом поиска и прослушивания записей.
Диалплан - XML .
Для систем автообзвона, предлагаем установку и настройку Newfies-diаler + FreeSWITCH на Debian 8.
Для систем биллинга и маршрутизации - ASTPP billing.
wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm && wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm && rpm -Uvh remi-release-6*.rpm epel-release-6*.rpm
yum install fail2ban
yum install phyton iptables
устаревшее
устаревшее
Создадим правила фильтрации
touch /etc/fail2ban/filter.d/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 "<HOST>" can # be used for standard IP/hostname matching and is only an alias for # (?:::f{4,6}:)?(?P<host>\S+) # Values: TEXT # 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.* <HOST> failed to authenticate as '.*'$ NOTICE.* .*: No registration for peer '.*' \(from <HOST>\) NOTICE.* .*: Host <HOST> failed MD5 authentication for '.*' (.*) NOTICE.* .*: Failed to authenticate user .*@<HOST>.* # Option: ignoreregex # Notes.: regex to ignore. If this regex matches, the line is ignored. # Values: TEXT # ignoreregex =
Синтаксис для Asterisk 1.6 отличается отсутствием номера порта '<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.* <HOST> failed to authenticate as '.*'$ NOTICE.* .*: No registration for peer '.*' \(from <HOST>\) NOTICE.* .*: Host <HOST> failed MD5 authentication for '.*' (.*) NOTICE.* .*: Failed to authenticate user .*@<HOST>.*
/etc/fail2ban/filter.d/asterisk.conf
# Fail2Ban filter for asterisk authentication failures # [INCLUDES] # Read common prefixes. If any customizations available -- read them from # common.local before = common.conf [Definition] _daemon = asterisk __pid_re = (?:\[\d+\]) # All Asterisk log messages begin like this: log_prefix= (?:NOTICE|SECURITY)%(__pid_re)s:?(?:\[C-[\da-f]*\])? \S+:\d*( in \w+:)? failregex = ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - (Wrong password|Username/auth name mismatch|No matching peer found|Not a local domain|Device does not match ACL|Peer is not su$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Call from '[^']*' \(<HOST>:\d+\) to extension '\d+' rejected because extension not found in context 'default'\.$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host <HOST> failed to authenticate as '[^']*'$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s No registration for peer '[^']*' \(from <HOST>\)$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host <HOST> failed MD5 authentication for '[^']*' \([^)]+\)$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Failed to authenticate (user|device) [^@]+@<HOST>\S*$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s (?:handle_request_subscribe: )?Sending fake auth rejection for (device|user) \d*<sip:[^@]+@<HOST>>;tag=\w+\S*$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s SecurityEvent="(FailedACL|InvalidAccountID|ChallengeResponseFailed|InvalidPassword)",EventTV="[\d-]+",Severity="[\w]+",Service="[\w]+",EventVersion="\d+",AccountID="\d*",SessionID="$ ^(%(__prefix_line)s|\[\]\s*WARNING%(__pid_re)s:?(?:\[C-[\da-f]*\])? )Ext\. s: "Rejecting unknown SIP connection from <HOST>"$ ignoreregex = # Author: Xavier Devlamynck / Daniel Black # # General log format - main/logger.c:ast_log # Address format - ast_sockaddr_stringify # # First regex: channels/chan_sip.c # # main/logger.c:ast_log_vsyslog - "in {functionname}:" only occurs in syslog
устаревшее pjsip
устаревшее pjsip
Fail2ban PjSIP
# Fail2Ban filter for asterisk authentication failures # [INCLUDES] # Read common prefixes. If any customizations available -- read them from # common.local before = common.conf [Definition] _daemon = asterisk __pid_re = (?:\[\d+\]) # All Asterisk log messages begin like this: log_prefix= (?:NOTICE|SECURITY)%(__pid_re)s:?(?:\[C-[\da-f]*\])? \S+:\d*( in \w+:)? failregex = ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - (Wrong password|Username/auth name mismatch|No matching peer found|Not a local domain|Device does not match ACL|Peer is not supposed to register|ACL error \(permit/deny\)|Not a local domain)$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Call from '[^']*' \(<HOST>:\d+\) to extension '\d+' rejected because extension not found in context 'default'\.$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host <HOST> failed to authenticate as '[^']*'$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s No registration for peer '[^']*' \(from <HOST>\)$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host <HOST> failed MD5 authentication for '[^']*' \([^)]+\)$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Failed to authenticate (user|device) [^@]+@<HOST>\S*$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s (?:handle_request_subscribe: )?Sending fake auth rejection for (device|user) \d*<sip:[^@]+@<HOST>>;tag=\w+\S*$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s SecurityEvent="(FailedACL|InvalidAccountID|ChallengeResponseFailed|InvalidPassword)",EventTV="[\d-]+",Severity="[\w]+",Service="[\w]+",EventVersion="\d+",AccountID="\d*",SessionID="0x[\da-f]+",LocalAddress="IPV[46]/(UD|TC)P/[\da-fA-F:.]+/\d+",RemoteAddress="IPV[46]/(UD|TC)P/<HOST>/\d+"(,Challenge="\w+",ReceivedChallenge="\w+")?(,ReceivedHash="[\da-f]+")?(,ACLName="\w+")?$ ^(%(__prefix_line)s|\[\]\s*WARNING%(__pid_re)s:?(?:\[C-[\da-f]*\])? )Ext\. s: "Rejecting unknown SIP connection from <HOST>"$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Request from '.*' failed for '<HOST>(:[0-9]{1,5})?' (.*) - (No matching endpoint found)$ ignoreregex = # Author: Xavier Devlamynck / Daniel Black # # General log format - main/logger.c:ast_log # Address format - ast_sockaddr_stringify # # First regex: channels/chan_sip.c # # main/logger.c:ast_log_vsyslog - "in {functionname}:" only occurs in syslog
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Request from '.*' failed for '<HOST>(:[0-9]{1,5})?' (.*) - (No matching endpoint found)$
[asterisk] enabled = true filter = asterisk action = iptables-multiport[name=asterisk-tcp, port="5060,5061", protocol=tcp] iptables-multiport[name=asterisk-udp, port="5060,5061", protocol=udp] sendmail-whois[name=Asterisk, dest=root@localhost, sender=fail2ban@localhost] logpath = /var/log/asterisk/messages maxretry = 3 bantime = 259200
Или jail.local
[asterisk-iptables] enabled = true filter = asterisk action = iptables-allports[name=SIP, protocol=all] sendmail[name=SIP, dest=root@localhost, sender=root@localhost] logpath = /var/log/asterisk/messages maxretry = 5 bantime = 1800
<spoiler|устаревшее>
/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@asterisk] logpath = /var/log/asterisk/messages maxretry = 3 bantime = 259200
</spoiler>
/etc/asterisk/logger_logfiles_custom.conf
messages => notice,warning,error
# asterisk -rx "logger rotate"
/etc/init.d/fail2ban start /etc/init.d/iptables start
chkconfig iptables on chkconfig fail2ban on
sipsak -U -s sip:s@192.168.0.1:5060 sipsak -U -s sip:s@192.168.0.1:5060 sipsak -U -s sip:s@192.168.0.1:5060
iptables -L
Chain fail2ban-ASTERISK (1 references) target prot opt source destination DROP all -- 192.168.0.22 anywhere RETURN all -- anywhere anywhere
fail2ban-client status asterisk-iptables
Status for the jail: asterisk-iptables |- filter | |- File list: /var/log/asterisk/secure | |- Currently failed: 0 | `- Total failed: 3 `- action |- Currently banned: 1 | `- IP list: 192.168.0.22 `- Total banned: 1
удалить правило из iptables
iptables -D fail2ban-ASTERISK 1
Блокировка пакетов средствами IPtables по названию сканера
iptables -I INPUT -p udp --dport 5060 -m string --string "friendly-scanner" --algo bm -j DROP iptables -I INPUT -p udp --dport 5060 -m string --string "sip-scan" --algo bm -j DROP iptables -I INPUT -p udp --dport 5060 -m string --string "sundayddr" --algo bm -j DROP iptables -I INPUT -p udp --dport 5060 -m string --string "iWar" --algo bm -j DROP iptables -I INPUT -p udp --dport 5060 -m string --string "sipsak" --algo bm -j DROP iptables -I INPUT -p udp --dport 5060 -m string --string "sipvicious" --algo bm -j DROP
banned examples
banned examples
Chain fail2ban-asterisk-udp (1 references) target prot opt source destination REJECT all -- ns304512.ip-94-23-212.eu anywhere reject-with icmp-port-unreachable REJECT all -- 69.30.254.10 anywhere reject-with icmp-port-unreachable REJECT all -- 178.32.131.44 anywhere reject-with icmp-port-unreachable REJECT all -- s18080713.onlinehome-server.info anywhere reject-with icmp-port-unreachable REJECT all -- 192.187.109.154 anywhere reject-with icmp-port-unreachable REJECT all -- 46.165.251.197 anywhere reject-with icmp-port-unreachable REJECT all -- 212-129-55-216.rev.poneytelecom.eu anywhere reject-with icmp-port-unreachable REJECT all -- static-ip-188-138-120-135.inaddr.ip-pool.com anywhere reject-with icmp-port-unreachable REJECT all -- s18081076.onlinehome-server.info anywhere reject-with icmp-port-unreachable REJECT all -- 212-129-54-198.rev.poneytelecom.eu anywhere reject-with icmp-port-unreachable REJECT all -- 62-210-148-71.rev.poneytelecom.eu anywhere reject-with icmp-port-unreachable REJECT all -- 195-154-34-157.rev.poneytelecom.eu anywhere reject-with icmp-port-unreachable REJECT all -- 107.150.61.186 anywhere reject-with icmp-port-unreachable REJECT all -- h31-3-236-162.host.redstation.co.uk anywhere reject-with icmp-port-unreachable REJECT all -- 107.150.52.234 anywhere reject-with icmp-port-unreachable REJECT all -- 95.211.117.10 anywhere reject-with icmp-port-unreachable RETURN all -- anywhere anywhere
Нажмите, чтобы отобразить
Нажмите, чтобы скрыть
Fail2Ban: This is a pretty simple implementation, and can be done quickly. I have already setup an email relay on my Asterisk box to email me, so you may need to do that before hand or modify the settings slightly. I really enjoy being able to know by email what bad things are happening. First, modify Asterisk to spit out errors in a separate log file: Edit /etc/asterisk/logger.conf and: – Un-comment the first dateformat line under [general]: 1 dateformat=%F %T ; ISO 8601 date format – Then, modify the messages line near the bottom and add security: 1 messages => security,notice,warning,error Restart the Asterisk logger module to make the changes take effect: sudo asterisk -rx "logger reload" Now, install fail2ban: sudo apt-get -y install fail2ban Add the folowing to the end of /etc/fail2ban/jail.conf: [asterisk-iptables] # if more than 4 attempts are made within 6 hours, ban for 24 hours enabled = true filter = asterisk action = iptables-allports[name=ASTERISK, protocol=all] sendmail[name=ASTERISK, dest=dest@email.here, sender=fail2ban@address.here] logpath = /var/log/asterisk/security maxretry = 4 findtime = 21600 bantime = 86400 Then, move the existing asterisk.conf in filter.d to a backup in the directory below (or wherever else you would like): cd /etc/fail2ban/filter.d sudo mv asterisk.conf ../asterisk.conf.orig Create a new asterisk.conf in filter.d and add the following: # Fail2Ban configuration file # # # $Revision: 251 $ # [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 "<HOST>" can # be used for standard IP/hostname matching and is only an alias for # (?:::f{4,6}:)?(?P<host>\S+) # Values: TEXT # # Asterisk 1.8 uses Host:Port format which is reflected here 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>:.*' - 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.* .*: Registration from '.*' failed for '<HOST>:.*' - ACL error (permit/deny) NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Device does not match ACL NOTICE.* .*: Registration from '\".*\".*' failed for '<HOST>:.*' - No matching peer found NOTICE.* .*: Registration from '\".*\".*' failed for '<HOST>:.*' - Wrong password NOTICE.* <HOST> failed to authenticate as '.*'$ NOTICE.* .*: No registration for peer '.*' \(from <HOST>\) NOTICE.* .*: Host <HOST> failed MD5 authentication for '.*' (.*) NOTICE.* .*: Failed to authenticate user .*@<HOST>.* NOTICE.* .*: <HOST> failed to authenticate as '.*' NOTICE.* .*: <HOST> tried to authenticate with nonexistent user '.*' VERBOSE.*SIP/<HOST>-.*Received incoming SIP connection from unknown peer # Option: ignoreregex # Notes.: regex to ignore. If this regex matches, the line is ignored. # Values: TEXT # ignoreregex = Restart fail2ban: 1 sudo service fail2ban restart
Приложение устанавливается в три клика, как локальный модуль FreePBX.
В отличии от стандартного CDR группирует вызовы по внутренним абонентам,
а также по входящим и исходящим вызовам.
Скачать Asternic CDR Reports
После загрузки модуля необходимо войти в FreePBX, выберите Admin - Module Admin, а затем выберите опцию «Upload module». Вы должны выбрать файл, который вы только что скачали с вашего жесткого диска и нажмите кнопку «Upload».
После загрузки, нажмите на ссылку Manage Local Modules, прокрутите страницу вниз до раздела Отчеты, а затем нажмите на кнопку Asternic CDR Reports. После этого установите переключатель Installи, наконец, нажмите кнопку Proceedв самом низу страницы.
Данная модификация включает отображение записей разговоров FreePBX
в модуле Asterisk CDR Reports
Скачать asternic_cdr-1.5.1.tgz исправленный
Скачать asternic_cdr-1.5.1.tgz исправленный
Данная модификация включает отображение записей разговоров FreePBX
в модуле Asterisk CDR Reports
Скачать asternic_cdr-1.5.1.tgz исправленный
Скачать asternic_cdr-1.5.1.tgz исправленный
Замените файл:
/var/www/html/admin/modules/asternic_cdr/functions.inc.phpмодуля Asternic.
на файл именем с модифицированным кодом:
[root@localhost asternic_cdr]# ls -la | grep fu -rw-r--r-- 1 asterisk asterisk 16431 Feb 13 16:17 functions.inc.php -rw-r--r-- 1 asterisk asterisk 16163 Feb 13 16:16 functions.inc.php.bk
<?php if(isset($_SERVER['PATH_INFO'])) { define("SELF", substr($_SERVER['PHP_SELF'], 0, (strlen($_SERVER['PHP_SELF']) - @strlen($_SERVER['PATH_INFO'])))); } else { define("SELF", $_SERVER['PHP_SELF']); } function asternic_cdr_get_config($engine) { // Executed on APPLY in FreePBX, we regenerate the fop2buttons if needed global $amp_conf, $db, $active_modules; } function asternic_cdr_query() { global $active_modules, $amp_conf, $db; $sql = "SELECT exten,privacy,label,`group`,email,channel,queuechannel,originatechannel,customastdb,spyoptions,external FROM fop2buttons"; $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); if(DB::IsError($results)) { die($results->getMessage()); } foreach ($results as $result) { $fopprivacy[$result['exten']] = $result['privacy']; $foplabel[$result['exten']] = $result['label']; $fopgroup[$result['exten']] = $result['group']; $fopemail[$result['exten']] = $result['email']; $fopchannel[$result['exten']] = $result['channel']; $fopqchannel[$result['exten']] = $result['queuechannel']; $fopochannel[$result['exten']] = $result['originatechannel']; $fopcustastdb[$result['exten']] = $result['customastdb']; $fopspyoption[$result['exten']] = $result['spyoptions']; $fopexternal[$result['exten']] = $result['external']; } } function return_timestamp($date_string) { list ($year,$month,$day,$hour,$min,$sec) = preg_split("/-|:| /",$date_string,6); $u_timestamp = mktime($hour,$min,$sec,$month,$day,$year); return $u_timestamp; } function swf_bar($values,$width,$height,$divid,$stack) { global $config; if ($stack==1) { $chart = "images/barstack.swf"; } else { $chart = "images/bar.swf"; } $return = "<div id='$divid'>\n"; $return.= "</div>\n"; $values = html_entity_decode($values); $return.= "<script type='text/javascript'>\n"; $return.='$(document).ready(function() {'."\n"; $variables = split("&",$values); if(isset($config['no_animation'][''])) { $variables[] = "noanimate=1"; } $return .= "var flashvars = {\n"; $param = Array(); foreach($variables as $deauna) { $pedazos = split("=",$deauna); $param[]="'$pedazos[0]': '$pedazos[1]'"; } $texti = implode(",\n",$param); $return.=$texti; $return.=" };\n"; $return.= "swfobject.embedSWF('$chart', '$divid', '$width', '$height', '9.0.0', '#336699', flashvars, {wmode:'transparent'});\n"; $return.= "});</script>\n"; echo $return; } function print_exports($header_pdf,$data_pdf,$width_pdf,$title_pdf,$cover_pdf) { global $lang; global $language; $head_serial = serialize($header_pdf); $data_serial = serialize($data_pdf); $width_serial = serialize($width_pdf); $title_serial = serialize($title_pdf); $cover_serial = serialize($cover_pdf); $head_serial = rawurlencode($head_serial); $data_serial = rawurlencode($data_serial); $width_serial = rawurlencode($width_serial); $title_serial = rawurlencode($title_serial); $cover_serial = rawurlencode($cover_serial); $complete_self = $_SERVER['REQUEST_URI']; //echo "<br/><form method=post action='modules/asternic_cdr/export.php'>\n"; echo "<br/><form method='post' action='$complete_self'>\n"; foreach($_REQUEST as $kkey=>$vval) { echo "<input type='hidden' name='$kkey' value='".$vval."' />\n"; } echo "<input type='hidden' name='action' value='export' />\n"; echo "<input type='hidden' name='head' value='".$head_serial."' />\n"; echo "<input type='hidden' name='rawdata' value='".$data_serial."' />\n"; echo "<input type='hidden' name='width' value='".$width_serial."' />\n"; echo "<input type='hidden' name='title' value='".$title_serial."' />\n"; echo "<input type='hidden' name='cover' value='".$cover_serial."' />\n"; echo "<a href='javascript:void()' class='info'><input type=image name='pdf' src='images/asternic_pdf.gif' style='border:0;'><span>"; echo _('Export to PDF'); echo "</span></a>\n"; echo "<a href='javascript:void()' class='info'><input type=image name='csv' src='images/asternic_excel.gif' style='border:0;'><span>"; echo _('Export to CSV/Excel'); echo "</span></a>\n"; echo "</form>"; } function seconds2minutes($segundos) { $horas = intval($segundos / 3600); $minutos = intval($segundos % 3600 ) / 60; $segundos = $segundos % 60; $ret = sprintf("%02d:%02d:%02d",$horas,$minutos,$segundos); // return "$minutos:$segundos"; return $ret; } function remove_quotes($argument) { return substr($argument,1,-1); } function asternic_download($file) { include("download.php"); } function asternic_getrecords( $MYVARS ) { global $active_modules, $amp_conf, $db; $channel = $MYVARS['channel']; $start = $MYVARS['start']; $end = $MYVARS['end']; $gtype = $MYVARS['direction']; $condicionextra=""; if($gtype=='outgoing') { $chanfield = "channel"; $otherchanfield = "dstchannel"; } else { $chanfield = "dstchannel"; $otherchanfield = "channel"; } $query = "SELECT substring($chanfield,1,locate(\"-\",$chanfield,length($chanfield)-8)-1) AS chan1,"; //$query = "SELECT IF($chanfield like 'Local/%',CONCAT('SIP',RIGHT(substring(replace($chanfield,'-','/'),1,instr($chanfield,'@')-1),instr(reverse(substring(replace($chanfield,'-','/'),1,instr($chanfield,'@')-1)),'/'))),substring($chanfield,1,locate(\"-\",$chanfield,length($chanfield)-8)-1)) as chan1, "; //$query.= "billsec,duration,duration-billsec as ringtime,src,"; //изменение $query.= "billsec,duration,duration-billsec as ringtime,src,recordingfile,"; $query.="IF(dst='s',dcontext,dst) as dst,calldate,disposition,accountcode,userfield,uniqueid FROM asteriskcdrdb.cdr "; $query.= "WHERE calldate >= '$start' AND calldate <= '$end' AND (duration-billsec) >=0 $condicionextra "; $query.= "HAVING chan1 IN ('$channel') ORDER BY calldate"; $me=true; $res = $db->query($query); if(DB::IsError($res)) { die($res->getMessage()); } $ftype = $_REQUEST['type']; $fdisplay = $_REQUEST['display']; $ftab = $gtype; $cont=0; while ($res->fetchInto($row, DB_FETCHMODE_ASSOC)) { if (!(substr($row['accountcode'],0,5)=='Local' && $dispo[$row['disposition']]=='BUSY' && $row[9]=='ResetCDR')) { $cont++; $disposition = $row['disposition']; if(!isset($detail[$row['chan1']])) { $detail[$row['chan1']]=""; } $me = ! $me; if($me==true) { $odclass="class='odd'"; } else { $odclass=""; } $bill_print = seconds2minutes($row['billsec']); $detail[$row['chan1']].= "<tr $odclass>\n<td>$cont</td>\n"; $detail[$row['chan1']].= "<td style='text-align: center;' >".$row['calldate']."</td>\n"; $detail[$row['chan1']].= "<td>".$row['src']."</td><td>".$row['dst']."</td>\n"; $detail[$row['chan1']].= "<td align=right>".$bill_print."</td>\n"; $detail[$row['chan1']].="<td align=right>".$row['ringtime']." "._('secs')."</td>\n"; $detail[$row['chan1']].= "<td style='text-align: center;'>"; if($row['disposition']=="NO ANSWER" || $row['disposition']=="FAILED") { $detail[$row['chan1']].="<span style='color: red;'>"; } elseif($row['disposition']=="BUSY") { $detail[$row['chan1']].="<span style='color: orange;'>"; } else { $detail[$row['chan1']].="<span style='color: green;'>"; } $detail[$row['chan1']].= $row['disposition']; $detail[$row['chan1']].= "</span></td>"; //изменение if ($row['recordingfile']) { $rec_parts = explode('-',$row['recordingfile']); $fyear = substr($rec_parts[3],0,4); $fmonth = substr($rec_parts[3],4,2); $fday = substr($rec_parts[3],6,2); $monitor_base = $amp_conf['MIXMON_DIR'] ? $amp_conf['MIXMON_DIR'] : $amp_conf['ASTSPOOLDIR'] . '/monitor'; $recordingfile = "$monitor_base/$fyear/$fmonth/$fday/" . $row['recordingfile']; if (!file_exists($recordingfile)) { $recordingfile = ''; $detail[$row['chan1']].= "\n<td>"; } else { $detail[$row['chan1']].= "\n<td style='text-align: center;' title=\"$row[recordingfile]\"><a href=\"".$PHP_SELF."?getRec=".base64_encode($recordingfile)."\" target=\"_blank\"><img src=\"images/asternic_playicon.png\" alt=\"Call recording\" /></a>"; } } else { $recordingfile = ''; $detail[$row['chan1']].= "\n<td>"; } $detail[$row['chan1']].= "</td>\n"; //изменение // $detail[$row['chan1']].= "\n<td>"; // // $uni = $row['uniqueid']; // $uni = str_replace(".","",$uni); // // if($row['userfield']<>"") { // $detail[$row['chan1']].="<a href=\"javascript:void(0);\" onclick='javascript:playVmail(\"".$row['userfield']."\",\"play".$uni."\");'>"; // $detail[$row['chan1']].="<div class='playicon' title='Play' id='play".$uni."' style='float:left;'>"; // $detail[$row['chan1']].="<img src='images/blank.gif' alt='pixel' height='16' width='16' border='0'>"; // $detail[$row['chan1']].="</div></a>"; // $detail[$row['chan1']].="<a href=\"javascript:void(0); return false;\" onclick='javascript:downloadVmail(\"".$row['userfield']."\",\"play".$uni."\",\"$ftype\",\"$fdisplay\",\"$ftab\"); return false;'>"; // $detail[$row['chan1']].="<div class='downicon' title='Download' id='dload".$uni."' style='float:left;'>"; // $detail[$row['chan1']].="<img src='images/blank.gif' alt='pixel' height='16' width='16' border='0'>"; // $detail[$row['chan1']].="</div></a>"; // } else { // $detail[$row['chan1']].= " "; // } // $detail[$row['chan1']].= "</td>\n"; $detail[$row['chan1']].= "\n</tr>\n"; } } echo "<table width='99%' cellpadding=3 cellspacing=3 border=0 id='table${channel}' class='sortable'>\n"; echo "<thead><tr><td bgcolor='#ddcc00'>#</td>"; echo "<td bgcolor='#ddcc00' align='center'>"._('Date')."</td>\n"; echo "<td bgcolor='#ddcc00'>"._('From')."</td>\n"; echo "<td bgcolor='#ddcc00'>"._('To')."</td>\n"; echo "<td bgcolor='#ddcc00' align='right'>"._('Billable Time')."</td>\n"; echo "<td bgcolor='#ddcc00' align='right'>"._('Ring Time')."</td>\n"; echo "<td bgcolor='#ddcc00' align='center'>"._('Disposition')."</td>\n"; echo "<td bgcolor='#ddcc00' align='center'>"._('Listen')."</td></tr></thead>\n"; echo "<tbody>".$detail[$channel]."</tbody>\n"; echo "</table>\n"; $complete_self = $_SERVER['REQUEST_URI']; echo "<form id='downloadform' method='get' action='$complete_self'><input type=hidden name='file' id='downloadfile' value=''><input type=hidden name='action' value='download'><input type='hidden' name='type' id='dtype' value=''><input type='hidden' id='idisplay' name='display' value=''> <input type='hidden' id='itab' name='tab' value=''></form>"; } define('FPDF_FONTPATH',dirname(__FILE__).'/lib/font/'); include_once(dirname(__FILE__) . "/lib/fpdf.php"); class PDF extends FPDF { function Footer() { global $lang; global $language; //Go to 1.5 cm from bottom $this->SetY(-15); //Select Arial italic 8 $this->SetFont('Arial','I',8); //Print centered page number $this->Cell(0,10,$lang["$language"]['page'].' '.$this->PageNo(),0,0,'C'); } function Cover($cover) { $this->SetFont('Arial','',15); $this->MultiCell(150,9,$cover); $this->Ln(); } function Header() { global $title; //Select Arial bold 15 $this->SetFont('Arial','B',15); //Move to the right $this->Cell(85); //Framed title $this->Cell(30,10,$title,0,0,'C'); //Line break $this->Ln(10); } function TableHeader($header,$w) { $this->SetFillColor(255,0,0); $this->SetTextColor(255); $this->SetDrawColor(128,0,0); $this->SetLineWidth(.3); $this->SetFont('','B',11); for($i=0;$i<count($header);$i++) $this->Cell($w[$i],10,$header[$i],1,0,'C',1); $this->Ln(); } //Colored table function FancyTable($header,$data,$w) { $this->TableHeader($header,$w); //Color and font restoration $this->SetFillColor(224,235,255); $this->SetTextColor(0); $this->SetFont(''); //Data $fill=0; $supercont=1; foreach($data as $row) { $contador=0; foreach($row as $valor) { $this->Cell($w[$contador],6,$valor,'LR',0,'C',$fill); $contador++; } $this->Ln(); $fill=!$fill; if($supercont%40 == 0) { $this->Cell(array_sum($w),0,'','T'); $this->AddPage(); $this->TableHeader($header,$w); $this->SetFillColor(224,235,255); $this->SetTextColor(0); $this->SetFont(''); } $supercont++; } $this->Cell(array_sum($w),0,'','T'); } } function asternic_export_csv($header,$data) { header("Content-Type: application/csv-tab-delimited-table"); header("Content-disposition: filename=table.csv"); $linea=""; foreach($header as $valor) { $linea.="\"$valor\","; } $linea=substr($linea,0,-1); print $linea."\r\n"; foreach($data as $valor) { $linea=""; foreach($valor as $subvalor) { $linea.="\"$subvalor\","; } $linea=substr($linea,0,-1); print $linea."\r\n"; } } function asternic_export($REQ) { $header = unserialize(rawurldecode($REQ['head'])); $data = unserialize(rawurldecode($REQ['rawdata'])); $width = unserialize(rawurldecode($REQ['width'])); $title = unserialize(rawurldecode($REQ['title'])); $cover = unserialize(rawurldecode($REQ['cover'])); if(isset($_REQUEST['pdf']) || isset($REQ['pdf_x'])) { $pdf=new PDF(); $pdf->SetFont('Arial','',12); $pdf->SetAutoPageBreak(true); $pdf->SetLeftMargin(1); $pdf->SetRightMargin(1); $pdf->AddPage(); if($cover<>"") { $pdf->Cover($cover); } $pdf->AddPage(); $pdf->FancyTable($header,$data,$width); $pdf->Output("export.pdf","D"); } else { asternic_export_csv($header,$data); } } //изменение function recordfile_uri($path) { $size = filesize($path); $name = basename($path); $extension = strtolower(substr(strrchr($name,"."),1)); // This will set the Content-Type to the appropriate setting for the file $ctype =''; switch( $extension ) { case "WAV": $ctype="audio/x-wav"; break; case "wav": $ctype="audio/x-wav"; break; case "ulaw": $ctype="audio/basic"; break; case "alaw": $ctype="audio/x-alaw-basic"; break; case "sln": $ctype="audio/x-wav"; break; case "gsm": $ctype="audio/x-gsm"; break; case "g729": $ctype="audio/x-g729"; break; default: //not downloadable // echo ("<b>404 File not found! foo</b>"); // TODO: what to do if none of the above work? break ; } $fp=fopen($path, "rb"); if ($size && $ctype && $fp) { header("Pragma: public"); header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Cache-Control: public"); header("Content-Description: audio file"); header("Content-Type: " . $ctype); header("Content-Disposition: attachment; filename=" . $name); header("Content-Transfer-Encoding: binary"); header("Content-length: " . $size); $chunksize = 1*(1024*1024); while (!feof($fp)) { $buffer = fread($fp, $chunksize); echo $buffer; ob_flush(); flush(); } fclose($fp); } } if(isset($_GET['getRec'])){ recordfile_uri(base64_decode($_GET['getRec'])); die(); } ?>
При установке Ubuntu выберите обязательно OpenSSH server и LAMP сервер. Установите дополнительные пакеты на ваше усмотрение.
В ходе установки системы вам будет предложено задать пароль root пользователя MySQL, если вы не уверены, можно отставить пустым. Если пароль задан, он потребуется в дальнейшем для работы с MySQL.
$ sudo passwd root Enter new UNIX password: Retype new UNIX password: passwd: password update successfully
$ sudo -i
# apt-get update && sudo apt-get upgrade -y
apt-get install -y build-essential linux-headers-`uname -r` openssh-server apache2 mysql-server\ mysql-client bison flex php5 php5-curl php5-cli php5-mysql php-pear php-db php5-gd curl sox\ libncurses5-dev libssl-dev libmysqlclient-dev mpg123 libxml2-dev libnewt-dev sqlite3\ libsqlite3-dev pkg-config automake libtool autoconf git subversion unixodbc-dev uuid uuid-dev\ libasound2-dev libogg-dev libvorbis-dev libcurl4-openssl-dev libical-dev libneon27-dev libsrtp0-dev\ libspandsp-dev libiksemel-dev libiksemel-utils libiksemel3
Это требуется чтобы загрузить свежую версию ядра после апгрейда. Если вы уверены что загруженная версия последняя, можно не перезагружаться.
reboot
pear uninstall db pear channel-update pear.php.net pear install -Z db-1.7.14
Error: Error: cannot download "pear/DB"
Error: Error: cannot download "pear/DB"
Ошибка при установке DB (На данный момент, я не до разобрался в причине этой проблемы, но после танцев с бубном, все заработало.)
root@asterisk:/usr/src# pear install DB-1.7.14 WARNING: "pear/DB" is deprecated in favor of "pear/MDB2" downloading DB-1.7.14.tgz ... Starting to download DB-1.7.14.tgz (133,103 bytes) .............................done: 133,103 bytes could not extract the package.xml file from "/build/buildd/php5-5.5.9+dfsg/pear-build-download/DB-1.7.14.tgz" Download of "pear/DB" succeeded, but it is not a valid package archive Error: cannot download "pear/DB" Download failed install failed
Решение - установим вручную
Смотрим путь:
pear config-get php_dir
В моем случае это:
/usr/share/php
Качаем DB 1.7.14
cd /usr/src/ wget http://download.pear.php.net/package/DB-1.7.14.tgz tar zvxf DB-1.7.14.tgz
Копируем вручную:
cp -R /usr/src/DB-1.7.14/DB /usr/share/php/DB cp /usr/src/DB-1.7.14/DB.php /usr/share/php/DB.php
Далее при вводе pear install db-1.7.14, получаем ответ что уже установлено.
root@asterisk:/usr/share/php# pear install db-1.7.14 pear/db is already installed and is the same as the released version 1.7.14 install failed
Блоки команд с ключом '&&' могут быть скопированы вместе и будут выполняться последовательно. '&&' выполняет переход к следующей команде, при условии успешного выполнения предыдущей. Если вы хотите полностью, пошагово, контролировать процесс установки, выполните каждую команду отдельно, без ввода '&&'.
cd /usr/src wget http://sourceforge.net/projects/lame/files/lame/3.98.4/lame-3.98.4.tar.gz && wget http://downloads.asterisk.org/pub/telephony/dahdi-linux-complete/dahdi-linux-complete-current.tar.gz && wget http://downloads.asterisk.org/pub/telephony/libpri/libpri-1.4-current.tar.gz && wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-13-current.tar.gz && git clone https://github.com/akheron/jansson.git && wget http://www.pjsip.org/release/2.2.1/pjproject-2.2.1.tar.bz2
ls -la /usr/src
ls -la /usr/src
root@ubuntu:/usr/src# ls -la total 47960 drwxr-xr-x 5 root root 4096 Dec 9 11:18 . drwxr-xr-x 10 root root 4096 Dec 9 09:55 .. -rw-r--r-- 1 root root 31832204 Nov 20 23:55 asterisk-13-current.tar.gz -rw-r--r-- 1 root root 7630719 Sep 22 23:20 dahdi-linux-complete-current.tar.gz drwxr-xr-x 8 root root 4096 Dec 9 11:18 jansson -rw-r--r-- 1 root root 1336025 Apr 14 2010 lame-3.98.4.tar.gz -rw-r--r-- 1 root root 338633 Jun 16 21:50 libpri-1.4-current.tar.gz drwxr-xr-x 24 root root 4096 Dec 9 09:57 linux-headers-3.13.0-32 drwxr-xr-x 7 root root 4096 Dec 9 09:57 linux-headers-3.13.0-32-generic -rw-r--r-- 1 root root 4628649 Dec 9 11:18 pjproject-2.2.1.tar.bz2
cd /usr/src && tar zxvf lame-3.98.4.tar.gz && cd lame-3.98.4 && ./configure && make && make install
cd /usr/src && tar xvfz dahdi-linux-complete-current.tar.gz && tar xvfz libpri-1.4-current.tar.gz && rm -f dahdi-linux-complete-current.tar.gz libpri-1.4-current.tar.gz && cd dahdi-linux-complete-* && make all && make install && make config && cd /usr/src/libpri-1.4.* && make && make install
kernel error
kernel error
Ошибка - отсутствуют исходники ядра
/usr/src/dahdi-linux-complete-2.10.0.1+2.10.0.1# make all make -C linux all make[1]: Entering directory `/usr/src/dahdi-linux-complete-2.10.0.1+2.10.0.1/linux' make -C drivers/dahdi/firmware firmware-loaders make[2]: Entering directory `/usr/src/dahdi-linux-complete-2.10.0.1+2.10.0.1/linux/drivers/dahdi/firmware' make[2]: Leaving directory `/usr/src/dahdi-linux-complete-2.10.0.1+2.10.0.1/linux/drivers/dahdi/firmware' You do not appear to have the sources for the 3.2.0-4-amd64 kernel installed. make[1]: *** [modules] Error 1 make[1]: Leaving directory `/usr/src/dahdi-linux-complete-2.10.0.1+2.10.0.1/linux' make: *** [all] Error 2
Решение - установить исходники)
apt-get install linux-headers-`uname -r`
(Требуется для поддержки драйвера SIP канала PjSIP)
cd /usr/src && tar -xjvf pjproject-2.2.1.tar.bz2 && cd pjproject-2.2.1 && CFLAGS='-DPJ_HAS_IPV6=1' ./configure --prefix=/usr --enable-shared --disable-sound\ --disable-resample --disable-video --disable-opencore-amr && make dep && make && make install
cd /usr/src/jansson && autoreconf -i && ./configure && make && make install
cd /usr/src && tar xvfz asterisk-13-current.tar.gz && rm -f asterisk-13-current.tar.gz && cd asterisk-* && ./configure && contrib/scripts/get_mp3_source.sh && make menuselect
После ввода команды make menuselect, вам будет предложено выбрать устанавливаемые модули. Большинство требуемых модулей выбираются автоматически. Для поддержки mp3 включите модуль 'format_mp3'.
В разделе Core Sound Packages выберете поддержку русскоязычных файлов (если требуется)
В разделе Extra Sound Packages выберете дополнительные звуковые файлы.
В завершении выберете Save & Exitи продолжите установку.
make && make install && make config && ldconfig
cd /usr/src && wget http://mirror.freepbx.org/freepbx-12.0.43.tgz && tar zxvf freepbx-*.tgz && cd /usr/src/freepbx
при установке из гит репозитория возникает ошибка:missing modgettext.class.php
при установке из гит репозитория возникает ошибка:missing modgettext.class.php
при установке из гит репозитория возникает ошибка:missing modgettext.class.php (incomplete application of changeset 12995?) поэтому лучше скачивать архив.
export VER_FREEPBX=12.0 && cd /usr/src && git clone http://git.freepbx.org/scm/freepbx/framework.git freepbx && cd freepbx && git checkout release/${VER_FREEPBX}
useradd -m asterisk && chown asterisk. /var/run/asterisk && chown -R asterisk. /etc/asterisk && chown -R asterisk. /var/{lib,log,spool}/asterisk && chown -R asterisk. /usr/lib/asterisk
remove /var/www/html
remove /var/www/html
Далее в руководстве freepbx.org, предлагается удалить директорию веб сервера:
Удалять директорию /var/www/html может быть опасно для ваших данных.
rm -rf /var/www/html
Это делается, т.к. при установке FreePBX скриптом, если папка существует, появляется сообщение о ошибке, что может быть исправлено, просто, повторным запуском скрипта установки.
sed -i 's/\(^upload_max_filesize = \).*/\120M/' /etc/php5/apache2/php.ini && sed -ie 's/\;date\.timezone\ \=/date\.timezone\ \=\ "Europe\/Moscow"/g' /etc/php5/apache2/php.ini && cp /etc/apache2/apache2.conf /etc/apache2/apache2.conf_orig && sed -i 's/^\(User\|Group\).*/\1 asterisk/' /etc/apache2/apache2.conf && sed -i 's/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf && service apache2 restart
AllowOverride All
AllowOverride All
root@aster:~# cat /etc/apache2/apache2.conf | grep AllowOverride AllowOverride None AllowOverride None AllowOverride None # AllowOverride None
root@aster:~# sed -i 's/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf
root@aster:~# cat /etc/apache2/apache2.conf | grep AllowOverride AllowOverride All AllowOverride All AllowOverride All # AllowOverride All
# create the configuration file in the "available" section echo "ServerName localhost" | sudo tee /etc/apache2/conf-available/servername.conf # enable it by creating a symlink to it from the "enabled" section a2enconf servername # restart the server service apache2 restart
Требуется создать безопасный пароль для связи FreePBX и MySQL
export ASTERISK_DB_PW=`dd if=/dev/urandom bs=1 count=32 2>/dev/null | base64 - | cut -c2-18`
Эта команда сгенерирует 16-ти значный пароль и сохранит значение в переменной {ASTERISK_DB_PW}.
Если вы задали 'root' пароль MySQL при установке, добавьте его после ключа -pyourpassword. (mysqladmin -u root -pYOURPASSWORD create asterisk)
mysqladmin -u root create asterisk mysqladmin -u root create asteriskcdrdb
Замените asteriskuserна имя пользователя, которое вам нравится. Например: YOURUSER@localhost. Можно оставить как есть.
mysql -u root -e "GRANT ALL PRIVILEGES ON asterisk.* TO asteriskuser@localhost IDENTIFIED BY '${ASTERISK_DB_PW}';" mysql -u root -e "GRANT ALL PRIVILEGES ON asteriskcdrdb.* TO asteriskuser@localhost IDENTIFIED BY '${ASTERISK_DB_PW}';" mysql -u root -e "flush privileges;"
Если в предыдущем пункте вы задали собственное имя пользователя, замените asteriskuserна него. Например: –username=YOURUSER
./start_asterisk start
./install_amp --installdb --username=asteriskuser --password=${ASTERISK_DB_PW}
Если выполнение скрипта прерывается и появилось сообщение о ошибке, попробуйте запустить установку ещё раз.
amportal
amportal
... ************************************************************************* * Note: It's possible that if you click the red 'Update Now' bar BEFORE * * updating your modules, your machine will start dropping calls. Ensure * * that all modules are up to date BEFORE YOU CLICK THE RED BAR. As long * * as this is observed, your machine will be fully functional whilst the * * upgrade is in progress. * ************************************************************************* **************************************** * At This Time Please Restart Asterisk * ****************************************
amportal a ma download manager amportal a ma install manager amportal a ma installall
amportal a ma refreshsignatures amportal a reload amportal chown
ln -s /var/lib/asterisk/moh /var/lib/asterisk/mohmp3
и запустим amportal
amportal start
asterisk -vvr
Asterisk 13.0.1, Copyright (C) 1999 - 2014, Digium, Inc. and others. Created by Mark Spencer <markster@digium.com> Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details. This is free software, with components licensed under the GNU General Public License version 2 and other licenses; you are welcome to redistribute it under certain conditions. Type 'core show license' for details. ========================================================================= Connected to Asterisk 13.0.1 currently running on ubuntu (pid = 24513) ubuntu*CLI>core restart now
http://IP.Address.FreePBX.Server/admin
Первым делом, вам будет предложено задать имя пользователя и пароль FreePBX
Чтобы работало переключение на русский язык в панели управления, необходимо отредактировать файл /etc/locale.alias. Ищем строку russian ru_RU.ISO-8859-5 и правим ее.
nano +67 /etc/locale.alias
russian ru_RU.UTF-8
или sed:
sed -i 's/ru_RU.ISO-8859-5/ru_RU.UTF-8/g' /etc/locale.alias
locale-gen ru_RU service apache2 restart
Документация по конфигурации и использованию функций модуля res_pjsip_acl. ACLмодуль используется res_pjsip. Данный модуль не зависит от ENDPOINTs и управляет всеми входящими подключениями через res_pjsip. Есть два основных способа назначить ACLпри помощи соответствующих опций. Можно использовать привычные 'permit' и 'deny', которые действуют в отношении IP адресов. Или 'contactpermit' и 'contactdeny', которые действуют на основании адреса из заголовка 'Contact' входящего SIP запроса REGISTER. Возможно комбинировать разные опции и создавать смешанный списки контроля доступа (ACL). В добавление к этому, вместо назначения ACLс помощью опций, можно задать адреса IP или заголовки Contact ACLв файле Asterisk:acl.confпри помощи 'acl' и 'contactacl' опций.
Option Name | Type | Regular Expression | Description |
---|---|---|---|
acl | Custom | false | Имя секции в acl.confдля контроля по IP |
contact_acl | Custom | false | Имя секции в acl.conf для контроля по заголовку Contact |
contact_deny | Custom | false | Список запрещенных адресов Contact header |
contact_permit | Custom | false | Список разрещенных адресов Contact header |
deny | Custom | false | Список запрещенных IP адресов |
permit | Custom | false | Список разрешенных IP адресов |
type | None | false | Тип секции. всегда - 'acl'. |
Соответствует разделам настроенным в файле «acl.conf». Принимает значение в виде списка имен разделов через запятую.
acl=your_named_acl,your_named_acl2
Соответствует разделам настроенным в файле «Asterisk:acl.conf». Принимает значение в виде списка имен разделов через запятую.
contact_deny=0.0.0.0/0.0.0.0
Принимает значение списка IP адресов через запятую. К IP адресам может быть добавлена маска подсети через слэш (/).
contact_permit=2.2.2.2/2.2.2.2,1.1.1.1
deny=0.0.0.0/0.0.0.0
Полный список параметров general sip.conf
Следующие параметры используются в общей [general] секции sip.conf:
Если установлено 'no', запрещает INVITE и REFER от внешних (не из localnet) доменов. См domain
allowexternalinvites=yes|no
Если 'no', запрещает гостевые(без аутентификации) подключения. По умолчанию sipguest подключения разрешены.
allowguest=no|yes
Вкл. или Выкл набор по одной цифре (т.е. каждая набранная цифра будет сразу отправляться в канал)
allowoverlap=no|yes
Разрешить ли внешним устройствам подписку (SUBSCRIBE) на информацию о статусе екстеншена. По умолчанию - 'yes':
allowsubscribe=yes|no
Когда установлено 'no', запрещает любые трансферы, если не переопределено в настройках пира.
allowtransfers=no|yes
Если включено, всегда отвечает на INVITE и REGISTER, SIP сообщением 401 Unauthorized, вместо того чтобы сообщить вызывающему о существовании запрашиваемого user или peer. Важная настройка безопасности
alwaysauthreject=no|yes
Установите эту опцию 'yes', чтобы добавить локальное HOSTNAME и локальный IP адрес в список доменов:
autodomain=yes|no
Эти параметры определяют IP адрес и порт на которых Asterisk будет слушать SIP запросы. Для драйвера канала SIP Asterisk 'chan_sip' можно назначить только один адрес и порт для всех подключений для UDP и один порт для TCP транспорта, в отличии от нового драйвера PJSIP. По умолчанию адрес не задан и лучше так и оставить. Некоторые рекомендуют изменять порт по умолчанию 5060, на другой, в целях безопасности. Но помните, что это только одна из мер безопасности, не самая важная, и не гарантирует вам полной защиты от злоумышленников.
bindaddr=0.0.0.0 bindport=5060
Вы можете задать независимые для UDP, TCP и TLS транспорта значения udpbindadd, tcpbindaddrи tlsbindaddr
Вкл. эту опцию, чтобы избежать ошибок при сообщении с некоторыми ip телефонами при отправке MWI сообщений.
buggymwi=no|yes
Установите 'yes', если хотите генерировать информацию о SIP событиях для AMI (asterisk manager interface)
callevents=yes
Время в секундах, между проверками голосовой почты :
checkmwi=30
Использовать или нет компактные SIP заголовки.
compactheaders=yes|no
Срок действия регистрации в секундах для входящих и исходящих регистраций. При входящей регистрации, этот параметр задается клиентской стороной, и заданное здесь значение используется, только если клиент не сообщил свое занчение. Для исходящих регистраций этот параметр сообщается удаленной стороне UAS (user agent server)
defaultexpiry=300
Данная опция позволяет управлять RTP соединением между двумя оконечными точками без re-INVITE(экспериментальная опция, используйте на свой страх и риск).
directrtpsetup=yes|no
Задает имя домена сервера Asterisk по умолчанию. Командой CLI 'sip show domains' выводится список локальных доменов.
domain=example.com
Вкл. или Выкл. отчет в завершении SIP диалога. SIP history выводится в DEBUG лог канала.
dumphistory=yes|no
Когда Asterisk находится за NAT, SIP заголовок обычно использует IP адрес сервера. Если включить данную опцию, Asterisk будет производить периодические DNSопросы для определения имени хоста и заменять IP адрес на 'externhost'.
externhost=my.hostname.tld
Используйте externip.
externip содержит IP адрес в качестве аргумента. Если Asterisk находится за NAT, SIP заголовок Contact: содержит внутренний IP адрес сервера, тогда удаленная сторона не знает куда отправлять ответы. Параметр externip вкупе с параметром nat=force_rport модифицирует SIP заголовок, сообщая удаленному SIP серверу адрес на который надо слать ответы:
externip=123.123.123.123
Если все же используется 'externhost', указывает промежуток времени в секундах между запросами DNS.
externrefresh=30
Значения: yes/no, по умолчанию: no. Если клиент собирается для сеанса связи «договориться» использовать звуковой кодек G726-32, с использованием компрессии AAL2, вместо RFC3551 (что требуется для аппаратов фирмы Sipura и шлюзов от Grandstream, и может другим). То это противоречит спецификации RFC3551, клиент должен вместо этого «договориться» использовать AAL2-G726-32
g726nonstandard=yes
Если ignoreregexpire установлен 'yes', Asterisk сделает одно из двух, в зависимости от настроек пиров: 1)Non-realtime peer Когда регистрация истекает, информация не удаляется из памяти или БД Asterisk и вызовы будут разрешены несмотря на то, что время регистрации истекло.
2)Realtime peers Когда peer сконфигурирован в режиме реального времени, информация о регистрации используется независимо от defaultexpiry
ignoreregexpire=yes|no
Вкл. поддержку RTP jitter buffer на принимающей стороне канала SIP. По умолчанию 'no'. Будет работать, только если удаленная сторона поддерживает эту функцию. подробнее о Джиттер
jbenable=yes|no
Принудительное использование jitter buffer принимающей стороной SIP канала.
jbforce=yes|no
Использовать фиксированный или подстраиваемый (адаптивный) jitter buffer. fixed jitter buffer всегда использует значение из jbmaxsize adaptive может принимать значение больше jbmaxsize По умолчанию 'fixed':
jbimpl=fixed|adaptive
Из личного опыта, вкл. 'adaptive' может приводить к весьма плачевным результатам.
Вкл./выкл jitter buffer frame лог. По умолчанию 'no':
jblog=yes|no
Установите максимальную длину буфера в миллисекундах:
jbmaxsize=200
Джиттер буфер порог синхронизации. По умолчанию 1000:
jbresyncthreshold=1000
Использовать Interactive Connectivity Establishment (ICE) в Asterisk
icesupport=no
Применять call-limit только для type=peer Это улучшит использование call-limit для устройств настроенных, как type=friend, отделив ограничение call-limit от входящих вызовов.
limitonpeers=yes|no
укажет серверу Asterisk какие подсети являются локальными, прозрачными для использования IP адресов сервера, SIP запросы к которым не требуют модификации поля Contact: c использованием externipили externhost
localnet=192.168.1.0/24 localnet=172.16.0.0/16
Сверять 'externip' с 'localnet' и производить подстановку, только если 'externip' из локальной подсети. Не совсем ясно, зачем это может понадобиться? Возможно при очень нестандартной топологии сети.
matchexterniplocally=yes|no
Максимальная продолжительность регистрации в секундах.
maxexpiry=3600
Минимальная продолжительность регистрации в секундах.
minexpiry=60
Указывает MIME тип используемый для message-waiting indication (MWI) в SIP NOTIFY сообщении.
notifymimetype=text/plain
Сообщать подписчикам о состоянии вызов (RINGING):
notifyringing=yes|no
Сообщать подписчикам (subscribers) о состоянии удержание (HOLD):
notifyhold=yes|no
Скурпулезная проверка SIP сообщений. Устанавливает более строгую проверку по стандартам SIP RFC.
pedantic=yes
Данная установка используется для аутентификации в SIP. Задайте realm полное доменное имя вашего сервера. Имя должно быть совершенно уникальным.
realm=mybox.example.com
Вкл. или Выкл историю sip для всех каналов.
recordhistory=yes|no
Сколько попыток внешних регистраций произведет Asterisk, прежде чем откажется от продолжения. По умолчанию стоит '0', что значит бесконечно.
registerattempts=0
Таймаут между попытками регистрации на другом устройстве.
registertimeout=30
Если плохо распознаются DTMF сигналы, включите данную опцию.
relaxdtmf=yes|no
(global)Конфигурация Realtime Peers Указывает должен ли Asterisk обнулять созданные на лету friends по истечении времени регистрации. Если установлено 'yes', по истечении срока регистрации, удалять friends до нового запроса. Если задано число, то оно используется вместо обычного времени регистрации.
rtautoclear=yes|no|seconds
(global)
Если rtcachefriends включен, Asterisk будет кэшировать friends(реалтайм пиры), которые приходят из realtime engine, так же, как если бы они сконфигурированы в «sip.conf».
rtcachefriends=yes|no
(global) Определяет, должен ли Asterisk сохранить SystemName в базе данных в режиме реального времени во время регистрации:
rtsavesysname=yes|no
(global) Если установлено 'yes' Asterisk будет обновлять IP-адрес, порт и период регистрации пиров при регистрации. По умолчанию 'yes':
rtupdate=yes|no
Указывает, должен или нет Asterisk включать SIP debug сразу при загрузке драйвера канала SIP.
sipdebug=yes|no
ОТправлять или нет Remote-Party-ID header:
sendrpid=yes|no
Записи DNS SRV являются одним из способов указания адреса для связи сервером. Используя записи SRV, вы получаете многие преимущества DNS, в то время как отключения SRV DNSлишает вас возможности принимать SIP вызовы на основании доменных имен. В настоящее время поддержка записей SRV в Asterisk несколько хромает. Если несколько записей SRV возвращаются, Asterisk будет использовать только первую запись. Чтобы включить, установите srvlookup = yes в секции [general] файла sip.conf:
srvlookup=yes
Задает транспорт по умолчанию. По умолчанию 'udp', но может быть 'tcp', 'tls', 'ws' или 'wss'.Если задано TCP а tcpenable=no будет использован UDP транспорт.
transport=udp
Включить поддержку TCP транспорта chan_sip Asterisk.
tcpenable=yes
Адрес на котором Asterisk «слушает» TCP подключения.
IPv4 example: bindaddr=0.0.0.0:5062 IPv6 example: bindaddr=[::]:5062
tcpauthtimeout указывает максимальное время в секундах данное клиенту на аутентификацию. Если за заданное время клиент не прошел проверку он отключается. (По умолчаннию 30 секунд)
tcpauthtimeout = 30
Максимальное кол-во неаутентифицированных сессий в момент любой времени.
tcpauthlimit = 100
Минимальная задержка туда-обратно (minimum round-trip) для сообщения контролируемого хоста. По умолчанию 100 миллисеунд:
t1min=100
Ограничить запросы SUBSCRIBE только указанным контекстом, если не переопределено в настройках пира.
subscribecontext=internal
Установка t38pt_udptl 'yes' вкл. T.38 fax (UDPTL) насквозь (passthrough) для SIP-to-SIP вызовов с поддержкой T.38. Эта настройка включается глобально для всех устройств, но вы можете отключить её для конкретного устройства.
t38pt_udptl=yes|no
T.38 fax passthrough работает только для SIP-to-SIP вызовов, любые local или agent каналы не могут быть использованы.
Asterisk может установить TOS bits в IP заголовках для помощи маршрутизаторам приотеризации трафика. tos_sip, tos_audio, и tos_video установки управляют TOS битами для SIP сообщений, RTP аудио и RTP видео, соответственно. Поддерживаются: CS0, CS1, CS2, CS3, CS4, CS5, CS6, CS7, AF11, AF12, AF13, AF21, AF22, AF23, AF31, AF32, AF33, AF41, AF42, AF43. Можно также использовать цифровые значения для TOS битов.
Доверять или нет Remote-Party-ID header: Asterisk SIP trustrpid
trustrpid=yes|no
Значение поля useragent в SIP заголовке. По умолчанию версия Asterisk:
useragent=Asterisk PBX v14.6.0
Если вы не желаете сообщать, что используете Asterisk, напишите Cisco или Avaya, или abyrvalg v2.0.
usereqphone опция говорит Asterisk добавить «user=phone» в SIP URIs которые содержат действующий номер телефона:
usereqphone
Приложение Asterisk записи разговора и микширования аудио двух каналов (приемника и передатчика).
Описание
Записывает аудио текущего соединения в указанный файл.
Это приложение не отвечает само на вызов и требует предварительного выполнения answerили progress
Используйте также приложение StopMixMonitor, чтобы получить доступ к записанному файлу, пока обработка диалплана записываемого вызова не завершена.
примечание: MixMonitor запускается как audiohook.
${MIXMONITOR_FILENAME}: Содержит имя созданного файла.
Синтаксис
MixMonitor(filename.extension[,options[,command]])
Аргументыfilename - Имя записываемого файла. Если не содержит абсолютный путь, то помещается в директорию, определенную по умолчанию в конфиге asterisk.conf
options
«heard and spoke» - имеются ввиду входящий и исходящий медиа(аудио) потоки по отношению к инициатору вызова.
command - Будет выполнена по завершению записи. Любая строка вида '^{X}' будет рассматриваться как ${X}. Все переменные будут установлены в момент вызова MixMonitor.
См. Также
<spoiler>
[sub-record-check] exten => s,1,GotoIf($[${LEN(${FROMEXTEN})}]?initialized) exten => s,n,Set(__REC_STATUS=INITIALIZED) ;exten => s,n,Set(NOW=${EPOCH}) ;exten => s,n,Set(__DAY=${STRFTIME(${NOW},,%d)}) ;exten => s,n,Set(__MONTH=${STRFTIME(${NOW},,%m)}) ;exten => s,n,Set(__YEAR=${STRFTIME(${NOW},,%Y)}) ;exten => s,n,Set(__TIMESTR=${YEAR}${MONTH}${DAY}-${STRFTIME(${NOW},,%H%M%S)}) ;exten => s,n,Set(__FROMEXTEN=${IF($[${LEN(${AMPUSER})}]?${AMPUSER}:${IF($[${LEN(${REALCALLERIDNUM})}]?${REALCALLERIDNUM}:unknown)})}) ;exten => s,n,Set(__MON_FMT=${IF($["${MIXMON_FORMAT}"="wav49"]?WAV:${MIXMON_FORMAT})}) exten => s,n(initialized),Noop(Recordings initialized) exten => s,n,ExecIf($[!${LEN(${ARG3})}]?Set(ARG3=dontcare)) exten => s,n,Set(REC_POLICY_MODE_SAVE=${REC_POLICY_MODE}) exten => s,n,ExecIf($["${BLINDTRANSFER}${ATTENDEDTRANSFER}" != ""]?Set(REC_STATUS=NO)) exten => s,n(next),GotoIf($[${LEN(${ARG1})}]?checkaction) exten => s,n(recorderror),Playback(something-terribly-wrong,error) exten => s,n,Hangup exten => s,n(checkaction),GotoIf($[${DIALPLAN_EXISTS(sub-record-check,${ARG1})}]?sub-record-check,${ARG1},1) exten => s,n,Noop(Generic ${ARG1} Recording Check - ${FROMEXTEN} ${ARG2}) exten => s,n,Gosub(recordcheck,1(${ARG3},${ARG1},${ARG2})) exten => s,n,Return() exten => recordcheck,1,Goto(${ARG1}) exten => recordcheck,n(dontcare),return exten => recordcheck,n(no),return exten => recordcheck,n(never),return exten => recordcheck,n(always),goto(reccc) exten => recordcheck,n(force),goto(reccc) exten => recordcheck,n(yes),goto(reccc) exten => recordcheck,n(reccc),Set(WAV=/var/spool/asterisk/monitor/${UNIQUEID}) exten => recordcheck,n,Set(MP3=/var/spool/asterisk/monitor/mp3/${UNIQUEID}) exten => recordcheck,n,Set(monopt=nice -n 19 /usr/local/bin/lame -b 32 --silent "${WAV}.wav" "${MP3}.mp3" && rm -f "${WAV}.wav" && chmod o+r "${MP3}.mp3") exten => recordcheck,n,Set(CDR(recordingfile)=${UNIQUEID}.mp3) exten => recordcheck,n,MixMonitor(${WAV}.wav,b,${monopt}) exten => recordcheck,n,return exten => out,1,Noop(Outbound Recording Check from ${FROMEXTEN} to ${ARG2}) exten => out,n,Set(RECMODE=${DB(AMPUSER/${FROMEXTEN}/recording/out/external)}) exten => out,n,ExecIf($[!${LEN(${RECMODE})} | "${RECMODE}" = "dontcare"]?Goto(routewins)) exten => out,n,ExecIf($["${ARG3}" = "never" | "${ARG3}" = "force"]?Goto(routewins)) exten => out,n(extenwins),Gosub(recordcheck,1(${RECMODE},out,${ARG2})) exten => out,n,Return() exten => out,n(routewins),Gosub(recordcheck,1(${ARG3},out,${ARG2})) exten => out,n,Return() exten => in,1,Noop(Inbound Recording Check to ${ARG2}) exten => in,n,Set(FROMEXTEN=unknown) exten => in,n,ExecIf($[${LEN(${CALLERID(num)})}]?Set(FROMEXTEN=${CALLERID(num)})) exten => in,n,Gosub(recordcheck,1(${ARG3},in,${ARG2})) exten => in,n,Return() exten => exten,1,Noop(Exten Recording Check between ${FROMEXTEN} and ${ARG2}) exten => exten,n,Set(CALLTYPE=${IF($[${LEN(${FROM_DID})}]?external:internal)}) exten => exten,n,ExecIf(${LEN(${CALLTYPE_OVERRIDE})}?Set(CALLTYPE=${CALLTYPE_OVERRIDE})) exten => exten,n,Set(CALLEE=${DB(AMPUSER/${ARG2}/recording/in/${CALLTYPE})}) exten => exten,n,ExecIf($[!${LEN(${CALLEE})}]?Set(CALLEE=dontcare)) exten => exten,n,GotoIf($["${CALLTYPE}"="external"]?callee) exten => exten,n,GotoIf($["${CALLEE}"="dontcare"]?caller) exten => exten,n,ExecIf($[${LEN(${DB(AMPUSER/${FROMEXTEN}/recording/priority)})}]?Set(CALLER_PRI=${DB(AMPUSER/${FROMEXTEN}/recording/priority)}):Set(CALLER_$ exten => exten,n,ExecIf($[${LEN(${DB(AMPUSER/${ARG2}/recording/priority)})}]?Set(CALLEE_PRI=${DB(AMPUSER/${ARG2}/recording/priority)}):Set(CALLEE_PRI=0)) exten => exten,n,GotoIf($["${CALLER_PRI}"="${CALLEE_PRI}"]?${REC_POLICY}:${IF($[${CALLER_PRI}>${CALLEE_PRI}]?caller:callee)}) exten => exten,n(callee),Gosub(recordcheck,1(${CALLEE},${CALLTYPE},${ARG2})) exten => exten,n,Return() exten => exten,n(caller),Set(RECMODE=${DB(AMPUSER/${FROMEXTEN}/recording/out/internal)}) exten => exten,n,ExecIf($[!${LEN(${RECMODE})}]?Set(RECMODE=dontcare)) exten => exten,n,ExecIf($["${RECMODE}"="dontcare"]?Set(RECMODE=${CALLEE})) exten => exten,n,Gosub(recordcheck,1(${RECMODE},${CALLTYPE},${ARG2})) exten => exten,n,Return() exten => conf,1,Noop(Conference Recording Check ${FROMEXTEN} to ${ARG2}) exten => conf,n,Gosub(recconf,1(${ARG2},${ARG2},${ARG3})) exten => conf,n,Return() exten => page,1,Noop(Paging Recording Check ${FROMEXTEN} to ${ARG2}) exten => page,n,GosubIf($["${REC_POLICY_MODE}"="always"]?recconf,1(${ARG2},${FROMEXTEN},${ARG3})) exten => page,n,Return() exten => recconf,1,Noop(Setting up recording: ${ARG1}, ${ARG2}, ${ARG3}) exten => recconf,n,Set(__CALLFILENAME=${IF($[${CONFBRIDGE_INFO(parties,${ARG2})}]?${DB(RECCONF/${ARG2})}:${ARG1}-${ARG2}-${ARG3}-${TIMESTR}-${UNIQUEID})}) exten => recconf,n,ExecIf($[!${CONFBRIDGE_INFO(parties,${ARG2})}]?Set(DB(RECCONF/${ARG2})=${CALLFILENAME})) exten => recconf,n,Set(CONFBRIDGE(bridge,record_file)=${MIXMON_DIR}${YEAR}/${MONTH}/${DAY}/${CALLFILENAME}.${MON_FMT}) exten => recconf,n,ExecIf($["${ARG3}"!="always"]?Return()) exten => recconf,n,Set(CONFBRIDGE(bridge,record_conference)=yes) exten => recconf,n,Set(__REC_STATUS=RECORDING) exten => recconf,n,Set(CDR(recordingfile)=${CALLFILENAME}.${MON_FMT}) exten => recconf,n,Return() exten => recq,1,Noop(Setting up recording: ${ARG1}, ${ARG2}, ${ARG3}) exten => recq,n,Set(AUDIOHOOK_INHERIT(MixMonitor)=yes) exten => recq,n,Set(MONITOR_FILENAME=${MIXMON_DIR}${YEAR}/${MONTH}/${DAY}/${CALLFILENAME}) exten => recq,n,MixMonitor(${MONITOR_FILENAME}.${MON_FMT},${MONITOR_OPTIONS},${MIXMON_POST}) exten => recq,n,Set(__REC_STATUS=RECORDING) exten => recq,n,Set(CDR(recordingfile)=${CALLFILENAME}.${MON_FMT}) exten => recq,n,Return() exten => parking,1,Noop(User ${ARG2} picked up a parked call) exten => parking,n,Set(USER=${ARG2}) exten => parking,n,ExecIf($[!${LEN(${ARG2})}]?Set(USER=unknown)) exten => parking,n,Set(RECMODE=${DB(AMPUSER/${ARG2}/recording/out/internal)}) exten => parking,n,ExecIf($[!${LEN(${RECMODE})}]?Set(RECMODE=dontcare)) exten => parking,n,Gosub(recordcheck,1(${RECMODE},parked,${USER})) exten => parking,n,Return()
</spoiler>
Описание параметров настройки pjsip в Asterisk.
Подробное руководство на русском. Примеры и сравнения.
pjsip vs sip. pjsip cli.
PJSIP мультимедийная библиотека с открытым кодом, для реализации протоколов SIP, SDP, RTP, STUN, TURN и ICE. Она сочетает лучшие возможности SIP сигнализации, хорошую проходимость NAT и высокий уровень взаимодействия с приложениями. Подходит практически для любого типа систем, начиная от компьютеров и заканчивая встраиваемыми системами (embedded systems) и мобильными телефонами.
Pjsip.conf обычный текстовый файл, как и все конфигурационные файлы Asterisk, состоит из секций. Каждая секция (раздел) определяет конфигурацию объекта res_pjsip. Секции отделены друг от друга именами, заключенными в квадратные скобки [какая неожиданность] и содержат одну или более конфигурационную опцию и её значение отделенное знаком равно.
[ SectionName ] ConfigOption = Value ConfigOption = Value
В большинстве случаев имена секций могут быть произвольными, однако в случае с типами ENDPOINT и AOR имена должны совпадать со заголовком SIP URI«To» для идентификации входящих SIP запросов. Каждая секция имеет обязательную опцию type=, которой определяется назначение секции в конфигурации объектов res_pjsip.
Ниже перечислены типы секций res_pjsipи простейшие примеры конфигурации.
Как узнать возможные варианты значений и параметры по умолчанию? В этом поможет встроенная справка интерфейса командной строки (CLI).
"config show help res_pjsip <configobject> <configoption>"
config show help res_pjsip aor
config show help res_pjsip aor
localhost*CLI> config show help res_pjsip aor contact[aor] contact = [Custom](Default: )(Regex: false) Permanent contacts assigned to AoR Contacts specified will be called whenever referenced by 'chan_pjsip'. Use a separate "contact=" entry for each contact required. Contacts are specified using a SIP URI.
Модуль ENDPOINT определяет многочисленные параметры SIP, а также связь с другими модулями - AUTH, AOR и TRANSPORT.
Секция ENDPOINT должна быть обязательно связана с одной или несколькими секциями AOR.
По сути дела, ENDPOINT является основным профилем SIP телефона или SIP транка в res_pjsip, аналогично пиру в
sip.conf.
Только если там определялись почти все параметры, то здесь часть ключевых свойств вынесены в специальные секции (модули),
которые и будут рассмотрены ниже.
config show help res_pjsip endpoint
config show help res_pjsip endpoint
localhost*CLI> config show help res_pjsip endpoint endpoint: [category !~ /.?/] Endpoint The *Endpoint* is the primary configuration object. It contains the core SIP related options only, endpoints are *NOT* dialable entries of their own. Communication with another SIP device is accomplished via Addresses of Record(AoRs)which have one or more contacts assicated with them. Endpoints *NOT* configured to use a 'transport' will default to first transport found in"pjsip.conf" that matches its type. Example: An Endpoint has been configured with no transport. When it comestime to call an AoR, PJSIP will find the first transport that matches the type. A SIP URI of 'sip:5000@[11::33]' will use the first IPv6 transport and try to send the request. If the anonymous endpoint identifier is in use an endpoint with the name"anonymous@domain" will be searched foras a last resort. If this is not found it will fall back to searching for"anonymous". If neither endpoints are found the anonymous endpoint identifier will not return an endpoint and anonymous calling will not be possible. 100rel -- Allow support for RFC3262 provisional ACK tags aggregate_mwi -- allow -- Media Codec(s) to allow aors -- AoR(s) to be used with the endpoint auth -- Authentication Object(s) associated with the endpoint callerid -- CallerID information for the endpoint callerid_privacy -- Default privacy level callerid_tag -- Internal id_tag for the endpoint context -- Dialplan context for inbound sessions direct_media_glare_mitigation -- Mitigation of direct media (re)INVITE glare direct_media_method -- Direct Media method type connected_line_method -- Connected line method type direct_media -- Determines whether media may flow directly between endpoints. disable_direct_media_on_nat -- Disable direct media session refreshes when NAT obstructs the med disallow -- Media Codec(s) to disallow dtmf_mode -- DTMF mode media_address -- IP address used in SDP for media handling force_rport -- Force use of return port ice_support -- Enable the ICE mechanism to help traverse NAT identify_by -- Way(s)for Endpoint to be identified redirect_method -- How redirects received from an endpoint are handled mailboxes -- NOTIFY the endpoint when state changes for any of the specified m moh_suggest -- Default Music On Hold class outbound_auth -- Authentication object used for outbound requests outbound_proxy -- Proxy through which to send requests, a full SIP URI must be prov rewrite_contact -- Allow Contact header to be rewritten with the source IP address-p rtp_ipv6 -- Allow use of IPv6 for RTP traffic rtp_symmetric -- Enforce that RTP must be symmetric send_diversion -- Send the Diversion header, conveying the diversion information to send_pai -- Send the P-Asserted-Identity header send_rpid -- Send the Remote-Party-ID header timers_min_se -- Minimum session timers expiration period timers -- Session timers for SIP packets timers_sess_expires -- Maximum session timer expiration period transport -- Desired transport configuration trust_id_inbound -- Accept identification information received from this endpoint trust_id_outbound -- Send private identification details to the endpoint.type-- Must be of type'endpoint'. use_ptime -- Use Endpoints requested packetisation interval use_avpf -- Determines whether res_pjsip will use and enforce usage of AVPF f media_encryption -- Determines whether res_pjsip will use and enforce usage of media inband_progress -- Determines whether chan_pjsip will indicate ringing using inband call_group -- The numeric pickup groupsfor a channel. pickup_group -- The numeric pickup groups that a channel can pickup. named_call_group -- The named pickup groupsfor a channel. named_pickup_group -- The named pickup groups that a channel can pickup. device_state_busy_at -- The number of in-use channels which will cause busy to be returne t38_udptl -- Whether T.38 UDPTL support is enabled or not t38_udptl_ec -- T.38 UDPTL error correction method t38_udptl_maxdatagram -- T.38 UDPTL maximum datagram size fax_detect -- Whether CNG tone detection is enabled t38_udptl_nat -- Whether NAT support is enabled on UDPTL sessions t38_udptl_ipv6 -- Whether IPv6 is used for UDPTL Sessions tone_zone -- Set which countrys indications to use for channels created for t language -- Set the default language to use for channels created for this end one_touch_recording -- Determines whether one-touch recording is allowed for this endpoi record_on_feature -- The feature to enact when one-touch recording is turned on. record_off_feature -- The feature to enact when one-touch recording is turned off. rtp_engine -- Name of the RTP engine to use for channels created for this endpo allow_transfer -- Determines whether SIP REFER transfers are allowed for this endpo sdp_owner -- String placed as the username portion of an SDP origin (o=) line. sdp_session -- String used for the SDP session (s=) line. tos_audio -- DSCP TOS bits for audio streams tos_video -- DSCP TOS bits for video streams cos_audio -- Priority for audio streams cos_video -- Priority for video streams allow_subscribe -- Determines if endpoint is allowed to initiate subscriptions with sub_min_expiry -- The minimum allowed expiry timefor subscriptions initiated by th from_user -- Username to use in From header for requests to this endpoint. mwi_from_user -- Username to use in From header for unsolicited MWI NOTIFYs to thi from_domain -- Domain to user in From header for requests to this endpoint. dtls_verify -- Verify that the provided peer certificate is valid dtls_rekey -- Interval at which to renegotiate the TLS session and rekey the SR dtls_cert_file -- Path to certificate file to present to peer dtls_private_key -- Path to private key for certificate file dtls_cipher -- Cipher to use for DTLS negotiation dtls_ca_file -- Path to certificate authority certificate dtls_ca_path -- Path to a directory containing certificate authority certificates dtls_setup -- Whether we are willing to accept connections, connect to the othe srtp_tag_32 -- Determines whether 32 byte tags should be used instead of 80 byte set_var -- Variable set on a channel involving the endpoint. message_context -- Context to route incoming MESSAGE requests to.
[777] type=endpoint context=from-internal disallow=all allow=alaw transport=udp-transport auth=auth777 aors=777
В данном примере мы видим тип секции: type=endpoint
контекст, разрешенные кодеки и также ассоциацию с другими секциями
transport=udp-transport, auth=auth777и aors=777.
Насколько я понимаю, опции typeи aorsявляются обязательными для работоспособности точки.
Для назначения Caller ID этому пиру(ENDPOINT), потребуется задать следующие параметры:
trust_id_outbound=yes callerid=V Pupkin <777>
Настройка транспортного уровня res_pjsip. Используются протоколы UDP, TCP, WebSockets и методы шифрования TLS/SSL. Можно настроить одну транспортную секцию для использования множеством точек (ENDPOINT), или создать уникальный транспортный уровень для конкретной точки. Условно, можно сравнить TRANSPORT, с секцией [general] sip.conf.
config show help res_pjsip transport
config show help res_pjsip transport
localhost*CLI> config show help res_pjsip transport transport: [category !~ /.?/] SIP Transport *Transports* There are different transports and protocol derivatives supported by 're s_pjsip'. They are in order of preference: UDP, TCP, and WebSocket (WS). NOTE: Changes to transport configuration in pjsip.conf will only be effected on a complete restart of Asterisk. A module reload will not suffice. async_operations -- Number of simultaneous Asynchronous Operationsbind-- IP Address and optional port to bind to for this transport ca_list_file -- File containing a list of certificates to read(TLS ONLY) cert_file -- Certificate filefor endpoint (TLS ONLY) cipher -- Preferred Cryptography Cipher (TLS ONLY) domain -- Domain the transport comes from external_media_address -- External IP address to use in RTP handling external_signaling_address -- External address for SIP signalling external_signaling_port -- External port for SIP signalling method -- Method of SSL transport (TLS ONLY) local_net -- Network to consider local(used for NAT purposes). password -- Password required for transport priv_key_file -- Private key file(TLS ONLY) protocol -- Protocol to use for SIP traffic require_client_cert -- Require client certificate (TLS ONLY)type-- Must be of type'transport'. verify_client -- Require verification of client certificate (TLS ONLY) verify_server -- Require verification of server certificate (TLS ONLY) tos -- Enable TOS for the signalling sent over this transport cos -- Enable COS for the signalling sent over this transport
По умолчанию, для применения настроек транспортного уровня недостаточно перечитать конфиги. Потребуется рестартовать Asterisk, если не задано allow_reload=true (по умолчанию - false)
[udp-transport] type=transport protocol=udp bind=0.0.0.0
или TLS транспорт:
[transport-tls] type=transport protocol=tls bind=0.0.0.0:5066 cert_file=/etc/asterisk/keys/asterisk.crt priv_key_file=/etc/asterisk/keys/asterisk.key external_media_address=123.123.123.1 external_signaling_address=123.123.123.1 local_net=10.10.0.0/16 method=tlsv1
Каждый транспорт в системе должен иметь уникальный порт.
localhost*CLI> pjsip show transports Transport: <TransportId........> <Type> <cos> <tos> <BindAddress....................> ========================================================================================= Transport: udp-transport udp 0 0 0.0.0.0:5080 Transport: udp-transport-infra udp 0 0 192.168.1.110:5081 Transport: udp-transport-megafon udp 0 0 0.0.0.0:5060
Секция аутентификации содержит опции и полномочия для входящих и исходящих регистраций.
С этой секцией ассоциируются такие секции как ENDPOINT и REGISTRATIONS.
Разные ENDPOINT и REGISTRATIONS могут использовать одну и ту же секцию аутентификации, если требуется.
config show help res_pjsip auth
config show help res_pjsip auth
localhost*CLI> config show help res_pjsip auth auth: [category !~ /.?/] Authentication type Authentication objects hold the authentication information for use by other objects such as'endpoints' or 'registrations'. This also allows for multiple objects to use a single auth object. See the 'auth_type' config option for password style choices. auth_type -- Authentication type nonce_lifetime -- Lifetime of a nonce associated with this authentication config. md5_cred -- MD5 Hash used for authentication. password -- PlainText password used for authentication. realm -- SIP realm for endpointtype-- Must be 'auth' username -- Username to use for account
[auth777] type=auth auth_type=userpass password=password username=777
с использованием MD5
[auth6001] type=auth auth_type=md5 md5_cred=5f4dcc3b5aa765d61d8327deb882cf99 username=777
Главная функция AoR (Address of Record) указать Asterisk, как связаться с ENDPOINT. Без соответствующей AOR секции, точка ENDPOINT будет недоступна для вызова. Здесь также задаются соответствия голосовой почте, MWI, продолжительность действия регистрации -expiration и настройки qualify (периодической отправки SIP сообщений OPTONS для мониторинга состояния устройств)
Когда Asterisk получает запрос на регистрацию от устройства, он в первую очередь ищет соответствующую SIP заголовку To: «777»<sip:777@192.168.1.21;transport=UDP> запись в именах секций AOR – в нашем прмере [777]
config show help res_pjsip aor
config show help res_pjsip aor
localhost*CLI> config show help res_pjsip aor aor: [category !~ /.?/] The configuration for a location of an endpoint An AoR is what allows Asterisk to contact an endpoint via res_pjsip. If no AoRs are specified, an endpoint will not be reachable by Asterisk. Beyond that, an AoR has other uses within Asterisk, such as inbound registration. An 'AoR' is a way to allow dialing a group of 'Contacts' that all use the same 'endpoint'for calls. This can be used as another way of grouping a list of contacts to dial rather than specifing them each directly when dialing via the dialplan. This must be used in conjuction with the 'PJSIP_DIAL_CONTACTS'. Registrations: For Asterisk to match an inbound registration to an endpoint, the AoR object name must match the user portion of the SIP URI in the "To:" header of the inbound SIP registration. That will usually be equivalent to the "user name"setin your hard or soft phones configuration. contact -- Permanent contacts assigned to AoR default_expiration -- Default expiration timein seconds for contacts that are dynamica mailboxes -- Allow subscriptions for the specified mailbox(es) maximum_expiration -- Maximum time to keep an AoR max_contacts -- Maximum number of contacts that can bind to an AoR minimum_expiration -- Minimum keep alive timefor an AoR remove_existing -- Determines whether new contacts replace existing ones.type-- Must be of type'aor'. qualify_frequency -- Interval at which to qualify an AoR authenticate_qualify -- Authenticates a qualify request if needed outbound_proxy -- Outbound proxy used when sending OPTIONS request support_path -- Enables Path support for REGISTER requests and Route support for
[777] type=aor max_contacts=1
Опция max_contact=1 значит, что только один SIP User Agent может быть одновременно зарегистрирован через эту запись AOR. Можно указать и 10, если потребуется.
[777] type=aor contact=sip:777@192.168.1.21:5060
Во втором примере мы не ожидаем запроса на регистрацию от SIP UA,
а указываем вручную постоянный контакт для этой записи.
Можно не беспокоится о кол-ве подключений, адрес все равно один.
[siptrunk] type=aor contact=sip:123.123.1.1:5060
В последнем примере пропущен username, что позволяет использовать данную запись для исходящей связи,
определяя вызываемый номер при помощи диалплана «Dial(PJSIP/${EXTEN}@siptrunk)».
Секция регистраций отвечает за исходящие регистрации. Используется для регистрации в удаленных системах, будь то другой Asterisk или транк от провайдера.
config show help res_pjsip_outbound_registration registration
config show help res_pjsip_outbound_registration registration
localhost*CLI> config show help res_pjsip_outbound_registration registration registration: [category !~ /.?/] The configuration for outbound registration Registration is *COMPLETELY* separate from the rest of 'pjsip.conf'. A minimal configuration consists of setting a 'server_uri' and a 'client_uri'. auth_rejection_permanent -- Determines whether failed authentication challenges are treated a client_uri -- Client SIP URI used when attempting outbound registration contact_user -- Contact User to use in request expiration -- Expiration timefor registrations in seconds max_retries -- Maximum number of registration attempts. outbound_auth -- Authentication object to be used for outbound registrations. outbound_proxy -- Outbound Proxy used to send registrations retry_interval -- Interval in seconds between retries if outbound registration is u forbidden_retry_interval -- Interval used when receiving a 403 Forbidden response. server_uri -- SIP URI of the server to register against transport -- Transport used for outbound authenticationtype-- Must be of type'registration'. support_path -- Enables Path support for outbound REGISTER requests
[siptrunk] type=registration transport=udp-transport outbound_auth=siptrunk server_uri=sip:123.123.1.1:5060 client_uri=sip:username@192.168.1.1:5060 retry_interval=60
Для регистрации понадобится определить используемый транспорт и секцию аутентификации.
Помимо этого, наверняка, потребуется указать контакт для входящих вызовов.
[providertrunk] type=registration transport=udp-transport outbound_auth=providertrunk server_uri=sip:sip.example.com client_uri=sip:1234567890@sip.example.com retry_interval=60
Пример регистрации транка провайдера.
Псевдоним домена. [Имя] данной секции является псевдонимом, а конфигурационная опция domain=, доменным именем, которому сопоставлен псевдоним.
config show help res_pjsip domain_alias
config show help res_pjsip domain_alias
localhost*CLI> config show help res_pjsip domain_alias domain_alias: [category !~ /.?/] Domain Alias Signifies that a domain is an alias. If the domain on a session is not found to match an AoR then this object is used to see if we have an aliasfor the AoR to which the endpoint is binding. This objects name as defined in configuration should be the domain alias and a config option is provided to specify the domain to be aliased. type-- Must be of type'domain_alias'. domain -- Domain to be aliased
[example2.com] type=domain_alias domain=example.com
Модуль не привязан к какой-либо точке ENDPOINTs и управляет всеми входящими SIP коммуникациями с использованием res_pjsip. Установки ACl (Access Control Lis) могут быть назначены в самой секции, или в файле acl.confна который будет ссылаться секция.
config show help res_pjsip_acl acl
config show help res_pjsip_acl acl
localhost*CLI> config show help res_pjsip_acl acl acl: [category !~ /.?/] Access Control List acl -- List of IP ACL section names in acl.conf contact_acl -- List of Contact ACL section names in acl.conf contact_deny -- List of Contact header addresses to deny contact_permit -- List of Contact header addresses to permit deny -- List of IP addresses to deny access from permit -- List of IP addresses to permit access fromtype-- Must be of type'acl'.
Настройки берутся из файла acl.conf:
[acl] type=acl acl=example_named_acl1
Настройки непосредственно в секции:
[acl] type=acl deny=0.0.0.0/0.0.0.0 permit=123.12.123.0 permit=123.12.123.1
Конфиг разрешающий регистрацию на основе SIP заголовка, а не IP адреса.
[acl] type=acl contactdeny=0.0.0.0/0.0.0.0 contactpermit=123.12.123.0 contactpermit=123.12.123.1
Определяет конечные точки с помощью IP-адреса источника.
config show help res_pjsip_endpoint_identifier_ip identify
config show help res_pjsip_endpoint_identifier_ip identify
localhost*CLI> config show help res_pjsip_endpoint_identifier_ip identify identify: [category !~ /.?/] Identifies endpoints via source IP address endpoint -- Name of Endpoint match -- IP addresses or networks to match against type -- Must be of type 'identify'.
[777] type=identify endpoint=777 match=123.0.112.1
Контакты являются одним из способов не указывать явно SIP URIв плане набора (диалплане).
config show help res_pjsip contact
config show help res_pjsip contact
localhost*CLI> config show help res_pjsip contact contact: [category !~ /.?/] A way of creating an aliased name to a SIP URI Contacts are a way to hide SIP URIs from the dialplan directly. They are also used to make a group of contactable parties when in use with 'AoR' lists. type -- Must be of type 'contact'. uri -- SIP URI to contact peer expiration_time -- Time to keep alive a contact qualify_frequency -- Interval at which to qualify a contact outbound_proxy -- Outbound proxy used when sending OPTIONS request path -- Stored Path vector for use in Route headers on outgoing requests.
ENDPOINT
REGISTRATION
AOR
CONTACT
IDENTIFY
ACL, DOMAIN_ALIAS
exten => _6XXX,1,Dial(PJSIP/${EXTEN})
exten => _9NXXNXXXXXX,1,Dial(PJSIP/mytrunk/sip:${EXTEN:1}@203.0.113.1:5060)
exten => _9NXXNXXXXXX,1,Dial(PJSIP/${EXTEN:1}@mytrunk)
;===============TRANSPORT [udp-transport] type=transport protocol=udp bind=0.0.0.0 ;===============EXTENSION 777 [777] type=endpoint context=from-internal disallow=all allow=alaw transport=udp-transport auth=auth777 aors=777 [auth777] type=auth auth_type=userpass password=777 username=777 [777] type=aor max_contacts=1
;==============TRANSPORTS [udp-transport] type=transport protocol=udp bind=0.0.0.0 ;===============TRUNK [siptrunk] type=registration transport=udp-transport outbound_auth=siptrunk server_uri=sip:sip.example.com client_uri=sip:1234567890@sip.example.com retry_interval=60 [siptrunk] type=auth auth_type=userpass password=1234567890 username=1234567890 [siptrunk] type=aor contact=sip:123.0.112.1:5060 [siptrunk] type=endpoint transport=udp-transport context=from-trunk disallow=all allow=alaw,ulaw outbound_auth=siptrunk aors=siptrunk [siptrunk] type=identify endpoint=siptrunk match=123.0.112.1
;===============TRANSPORT [udp-transport] type=transport protocol=udp bind=0.0.0.0 ;===============ENDPOINT TEMPLATES [endpoint-basic](!) type=endpoint transport=udp-transport context=from-internal disallow=all allow=alaw [auth-userpass](!) type=auth auth_type=userpass [aor-single-reg](!) type=aor max_contacts=1 ;===============EXTENSION 777 [777](endpoint-basic) auth=auth777 aors=777 [auth777](auth-userpass) password=777 username=777 [777](aor-single-reg) ;===============EXTENSION 778 [778](endpoint-basic) auth=auth778 aors=778 [auth778](auth-userpass) password=778 username=778 [778](aor-single-reg) ;===============EXTENSION 779 [779](endpoint-basic) auth=auth779 aors=779 [auth779](auth-userpass) password=779 username=779 [779](aor-single-reg)
Сравнение конфигурации ENDPOINT
sip.conf | pjsip.conf |
---|---|
[general] udpbindaddr=0.0.0.0 [777] type=friend host=dynamic disallow=all allow=alaw context=from-internal secret=1234 [778] type=friend host=192.168.1.2 disallow=all allow=alaw context=from-internal secret=1234 | [udp-transport] type=transport protocol=udp bind=0.0.0.0 [777] type = endpoint transport = udp-transport context = from-internal disallow = all allow = alaw aors = 777 auth = auth777 [777] type = aor max_contacts = 1 [auth777] type=auth auth_type=userpass password=1234 username=777 [778] type = endpoint transport = udp-transport context = from-internal disallow = all allow = alaw aors = 778 auth = auth778 [778] type = aor contact = sip:778@192.168.1.2:5060 [auth778] type=auth auth_type=userpass password=1234 username=778 |
Сравнение конфигурации trunk
sip.conf | pjsip.conf |
---|---|
[general] udpbindaddr=0.0.0.0 register => myname:1234@203.0.113.1:5060 [mytrunk] type=friend secret=1234 username=myname host=123.0.112.1 disallow=all allow=alaw context=from-trunk | [simpletrans] type=transport protocol=udp bind=0.0.0.0 [mytrunk] type=registration transport=simpletrans outbound_auth=mytrunk server_uri=sip:@123.0.112.1:5060 client_uri=sip:myname@123.0.112.1:5060 [mytrunk] type=auth auth_type=userpass password=1234 username=myname [mytrunk] type=aor contact=sip:123.0.112.1:5060 [mytrunk] type=endpoint transport=simpletrans context=from-trunk disallow=all allow=alaw outbound_auth=mytrunk aors=mytrunk [mytrunk] type=identify endpoint=mytrunk match=123.0.112.1 |
Connected to Asterisk 13.9.1 currently running on aster2 (pid = 17401) asterisk*CLI> core show help pjsip pjsip dump endpt -- Dump the res_pjsip endpt internals pjsip export config_wizard primitives [to] -- Export config wizard primitives pjsip list aors -- List PJSIP Aors pjsip list auths -- List PJSIP Auths pjsip list channels -- List PJSIP Channels pjsip list ciphers -- List available OpenSSL cipher names pjsip list contacts -- List PJSIP Contacts pjsip list endpoints -- List PJSIP Endpoints pjsip list identifies -- List PJSIP Identifies pjsip list registrations -- List PJSIP Registrations pjsip list transports -- List PJSIP Transports pjsip qualify -- Send an OPTIONS request to a PJSIP endpoint pjsip send register -- Registers an outbound registration target pjsip send unregister -- Unregisters outbound registration target pjsip set history {on|off|clear} -- Enable/Disable PJSIP History pjsip set logger {on|off|host} -- Enable/Disable PJSIP Logger Output pjsip show aors -- Show PJSIP Aors pjsip show aor -- Show PJSIP Aor pjsip show auths -- Show PJSIP Auths pjsip show auth -- Show PJSIP Auth pjsip show channels -- Show PJSIP Channels pjsip show channel -- Show PJSIP Channel pjsip show channelstats -- Show PJSIP Channel Stats pjsip show contacts -- Show PJSIP Contacts pjsip show contact -- Show PJSIP Contact pjsip show endpoints -- Show PJSIP Endpoints pjsip show endpoint -- Show PJSIP Endpoint pjsip show history -- Display PJSIP History pjsip show identifiers -- List registered endpoint identifiers pjsip show identifies -- Show PJSIP Identifies pjsip show identify -- Show PJSIP Identify pjsip show registrations -- Show PJSIP Registrations pjsip show registration -- Show PJSIP Registration pjsip show settings -- Show global and system configuration options pjsip show transports -- Show PJSIP Transports pjsip show transport -- Show PJSIP Transport pjsip show version -- Show the version of pjproject in use