Mudanças entre as edições de "OpenSIPs e Asterisk"
| (34 revisões intermediárias por 2 usuários não estão sendo mostradas) | |||
| Linha 1: | Linha 1: | ||
| − | + | {| class="wikitable" | |
| + | |- | ||
| + | |Precisando de recursos de númeração para fazer seus testes ? Contrate conosco em [http://www.brdvoz.com.br BRDVoz] | ||
| + | |Ou talvez gostaria de uma consultoria no seu proejto ? Também estamos disponiveis em [https://www.brdsoft.com.br BRDSoft] | ||
| + | |- | ||
| + | |} | ||
| − | Para esta implementação utilizamos Debian 7.0 amd64 , OpenSIPS 1.9 e | + | |
| + | |||
| + | |||
| + | |||
| + | <table> | ||
| + | <tr><td style="background-color: red;"><b><font color=white> Falta realizar os ajustes / testes para o NAT no mais esta tudo funcionado adequadamente a principio </font></b></td></tr> | ||
| + | </table> | ||
| + | |||
| + | |||
| + | Este tutorial é baseado em um tutorial similar porém utilizando Kamailio e Freeswtich, se quiser verificar o tutorial original acesse http://kb.asipto.com/freeswitch:kamailio-3.1.x-freeswitch-1.0.6d-sbc. | ||
| + | |||
| + | Para esta implementação utilizamos Debian 7.0 amd64 , OpenSIPS 1.9 e Asterisk 1.8.23 | ||
==Funcionalidades== | ==Funcionalidades== | ||
| Linha 9: | Linha 25: | ||
*Localização de usuário (encaminhamento de chamadas) | *Localização de usuário (encaminhamento de chamadas) | ||
*Roteamento de chamadas | *Roteamento de chamadas | ||
| − | |||
| − | Através do | + | |
| + | Através do Asterisk estenderemos estas funcionalidades agregando. | ||
*Correio de voz (Voicemail) | *Correio de voz (Voicemail) | ||
*Conferencia | *Conferencia | ||
| Linha 22: | Linha 38: | ||
*Identidade do correio de voz será o mesmo do ramal | *Identidade do correio de voz será o mesmo do ramal | ||
*Serviços de media (acesso a voicemail e outros) receberão rotas de 4 digitos | *Serviços de media (acesso a voicemail e outros) receberão rotas de 4 digitos | ||
| − | *Opensips e | + | *Opensips e Asterisk utilizarão o mesmo servidor (Neste caso IP: 10.254.254.6) |
| − | *Os serviços rodarão nas portas 5060 (opensips) , 5090 ( | + | *Os serviços rodarão nas portas 5060 (opensips) , 5090 (Asterisk) |
==Funcionamento== | ==Funcionamento== | ||
A autenticação do usuário será realizada pelo OpenSIPs, quando uma chamada é autenticada então ela serguirá: | A autenticação do usuário será realizada pelo OpenSIPs, quando uma chamada é autenticada então ela serguirá: | ||
| − | *Se o usuário de destino não está online a chamada será enviada para o | + | *Se o usuário de destino não está online a chamada será enviada para o Asterisk para função de correio de voz |
| − | *Se o usuário está online a chamada será encaminhada para o | + | *Se o usuário está online a chamada será encaminhada para o Asterisk, dest forma é possivel acionar funcionalidades como anuncios, definição de tempo de chamada, forçar codecs e outras funcionalidades. |
| − | * | + | *Asterisk envia a chamada novamente para o OpenSIPs que verificará no location e entregará a chamada para o usuário. |
| − | *Se a chamada não for atendida o | + | *Se a chamada não for atendida o Opensips irá re-encaminhar para o Asterisk direcionando para função de voicemail |
==OpenSIPs== | ==OpenSIPs== | ||
| Linha 41: | Linha 57: | ||
unixodbc-dev libmysqlclient15-dev libxmlrpc-c3-dev libexpat1-dev zlib1g-dev \ | unixodbc-dev libmysqlclient15-dev libxmlrpc-c3-dev libexpat1-dev zlib1g-dev \ | ||
m4 bison flex libpcre3-dev mysql-server vim apache2-mpm-prefork libapache2-mod-php5 \ | m4 bison flex libpcre3-dev mysql-server vim apache2-mpm-prefork libapache2-mod-php5 \ | ||
| − | php5-mysql php5-xmlrpc php-pear ngrep | + | php5-mysql php5-xmlrpc php-pear ngrep g++ libjpeg62-dev libssl-dev |
</pre> | </pre> | ||
| Linha 56: | Linha 72: | ||
make menuconfig | make menuconfig | ||
| − | Neste ponto o sistema irá abrir uma tela com algumas opções para selecionar, Acesse a primeira opção do menu, no submenu acesse a segunda opção ( Configure excluded modules ), selecione os módulos db_mysql , dialplan , mi_xmlrpc e | + | Neste ponto o sistema irá abrir uma tela com algumas opções para selecionar, Acesse a primeira opção do menu, no submenu acesse a segunda opção ( Configure excluded modules ), selecione os módulos db_mysql , dialplan , mi_xmlrpc , presence e presence_xml |
Agora volte ao submenu, e selecione a opção Save Changes, volte para o menu principal e selecione '''Compile and Install OpenSips''' , deixe que o sistema execute suas funções. | Agora volte ao submenu, e selecione a opção Save Changes, volte para o menu principal e selecione '''Compile and Install OpenSips''' , deixe que o sistema execute suas funções. | ||
| Linha 96: | Linha 112: | ||
DBRWUSER=opensips | DBRWUSER=opensips | ||
DBRWPW="opensipsrw" | DBRWPW="opensipsrw" | ||
| + | SIP_DOMAIN=10.254.254.6 ### caso voce esteja usando outro ip altere aqui | ||
| + | |||
DBROOTUSER="root" | DBROOTUSER="root" | ||
| Linha 116: | Linha 134: | ||
O sistema irá lhe perguntar algumas coisas, responda Y (sim) para todas para que ele instale todas as tabelas, não usaremos todas elas, mas desta forma você fica com praticamente tudo criado para o caso de uma expansão dos recursos. | O sistema irá lhe perguntar algumas coisas, responda Y (sim) para todas para que ele instale todas as tabelas, não usaremos todas elas, mas desta forma você fica com praticamente tudo criado para o caso de uma expansão dos recursos. | ||
| + | |||
| + | |||
| + | ===Instalando o RTP Proxy=== | ||
| + | <pre> | ||
| + | cd /usr/src/ | ||
| + | wget -c http://b2bua.org/chrome/site/rtpproxy-1.2.1.tar.gz | ||
| + | tar -xzvf rtpproxy-1.2.1.tar.gz | ||
| + | cd rtpproxy-1.2.1 | ||
| + | ./configure | ||
| + | make | ||
| + | make install | ||
| + | groupadd rtpproxy | ||
| + | useradd -d /var/run/rtpproxy -s /bin/true -g rtpproxy rtpproxy | ||
| + | mkdir /var/log/rtpproxy | ||
| + | mkdir /var/run/rtpproxy | ||
| + | chown -R rtpproxy.rtpproxy /var/log/rtpproxy | ||
| + | chown -R rtpproxy.rtpproxy /var/run/rtpproxy | ||
| + | </pre> | ||
| + | |||
| + | ====Arquivo de inicialização==== | ||
| + | '''/etc/init.d/rtpproxy''' | ||
| + | <pre> | ||
| + | #!/bin/bash | ||
| + | # | ||
| + | # Este script e de autoria de Mike Tesliuk | ||
| + | # qualquer falha no mesmo por favor informe | ||
| + | # atraves do email mike (a) tesliuk.com | ||
| + | # | ||
| + | ### BEGIN INIT INFO | ||
| + | # Provides: rtpproxy | ||
| + | # Required-Start: $syslog $network $local_fs $time | ||
| + | # Required-Stop: $syslog $network $local_fs | ||
| + | # Default-Start: 2 3 4 5 | ||
| + | # Default-Stop: 0 1 6 | ||
| + | # Short-Description: Start the RTPPROXY server | ||
| + | # Description: Start the RTPPROXY server | ||
| + | ### END INIT INFO | ||
| + | |||
| + | PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin | ||
| + | USELOG=1 | ||
| + | USER=rtpproxy | ||
| + | # Altere o ip abaixo para o ip de seu sistema | ||
| + | IPADDR="10.254.254.6" | ||
| + | |||
| + | . /lib/lsb/init-functions | ||
| + | |||
| + | |||
| + | start(){ | ||
| + | echo "Iniciando RTP PROXY " | ||
| + | if [ -z $(pidof rtpproxy) ]; then | ||
| + | if [ "${USELOG}" = "1" ]; then | ||
| + | echo "Iniciando com LOG" | ||
| + | /usr/local/bin/rtpproxy -l $IPADDR -s udp:127.0.0.1:7722 -u $USER -F -f d DBUG 2&> /var/log/rtpproxy/rtpproxy.log & | ||
| + | else | ||
| + | echo "Iniciando sem LOG" | ||
| + | /usr/local/bin/rtpproxy -l $IPADDR -s udp:127.0.0.1:7722 -u $USER -F -f d DBUG 2&> /dev/null | ||
| + | fi | ||
| + | |||
| + | if [ -n $(pidof rtpproxy) ]; then | ||
| + | echo "START OK" | ||
| + | fi | ||
| + | else | ||
| + | echo "Processo ja em execucao" | ||
| + | fi | ||
| + | } | ||
| + | |||
| + | |||
| + | stop(){ | ||
| + | |||
| + | if [ -z $(pidof rtpproxy) ]; then | ||
| + | echo "Processo nao encontrado" | ||
| + | else | ||
| + | kill -9 $(pidof rtpproxy) | ||
| + | if [ -n $(pidof rtpproxy) ]; then | ||
| + | echo "STOP OK" | ||
| + | else | ||
| + | echo "Falha em realizar stop do servico" | ||
| + | fi | ||
| + | |||
| + | fi | ||
| + | } | ||
| + | |||
| + | case $1 in | ||
| + | start) | ||
| + | start | ||
| + | ;; | ||
| + | stop) | ||
| + | stop | ||
| + | ;; | ||
| + | restart) | ||
| + | stop | ||
| + | start | ||
| + | |||
| + | ;; | ||
| + | *) | ||
| + | echo "Utilize: stop | start | restart" | ||
| + | ;; | ||
| + | esac | ||
| + | |||
| + | </pre> | ||
| + | |||
| + | Vamos dar permissao e colocar na inicialização | ||
| + | chmod +x /etc/init.d/rtpproxy | ||
| + | update-rc.d rtpproxy defaults | ||
| + | /etc/init.d/rtpproxy start | ||
===Criando o arquivo opensips.cfg=== | ===Criando o arquivo opensips.cfg=== | ||
O arquivo opensips.cfg é a onde a coisa toda acontece para o opensips, claro que ele dependerá de informações que estarão no banco de dados, mas é onde criamos todas as nossas rotas e validações. | O arquivo opensips.cfg é a onde a coisa toda acontece para o opensips, claro que ele dependerá de informações que estarão no banco de dados, mas é onde criamos todas as nossas rotas e validações. | ||
| + | |||
| + | |||
| + | |||
| + | <pre> | ||
| + | ####### Global Parameters ######### | ||
| + | debug=3 | ||
| + | log_stderror=no | ||
| + | log_facility=LOG_LOCAL0 | ||
| + | |||
| + | fork=yes | ||
| + | children=4 | ||
| + | |||
| + | /* Descomente as linhas abaixo para ativar o debug */ | ||
| + | #debug=7 | ||
| + | #fork=no | ||
| + | #log_stderror=yes | ||
| + | |||
| + | |||
| + | /* Comente a linha abaixo para ativar a descoberta automatica de enderecos locais | ||
| + | , isso significa que o sistema ira verificar todos os ips ativos e hosts e entao ativara | ||
| + | o protocolo para todos eles */ | ||
| + | auto_aliases=no | ||
| + | |||
| + | /* Defina aqui o ip a ser utilizado */ | ||
| + | listen=udp:10.254.254.6:5060 # Altere este IP para o seu ambiente | ||
| + | |||
| + | /* Nao usaremos sip por tcp nem tls neste script */ | ||
| + | disable_tcp=yes | ||
| + | |||
| + | disable_tls=yes | ||
| + | |||
| + | |||
| + | ####### Secao de modulos ######## | ||
| + | |||
| + | #set module path | ||
| + | mpath="/usr//lib64/opensips/modules/" | ||
| + | |||
| + | loadmodule "signaling.so" | ||
| + | loadmodule "sl.so" | ||
| + | loadmodule "tm.so" | ||
| + | modparam("tm", "fr_timer", 5) | ||
| + | modparam("tm", "fr_inv_timer", 30) | ||
| + | modparam("tm", "restart_fr_on_each_reply", 0) | ||
| + | modparam("tm", "onreply_avp_mode", 1) | ||
| + | |||
| + | loadmodule "rr.so" | ||
| + | /* do not append from tag to the RR (no need for this script) */ | ||
| + | modparam("rr", "append_fromtag", 0) | ||
| + | |||
| + | |||
| + | loadmodule "maxfwd.so" | ||
| + | loadmodule "sipmsgops.so" | ||
| + | loadmodule "mi_fifo.so" | ||
| + | modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo") | ||
| + | modparam("mi_fifo", "fifo_mode", 0666) | ||
| + | |||
| + | loadmodule "db_mysql.so" | ||
| + | |||
| + | |||
| + | loadmodule "uri.so" | ||
| + | modparam("uri", "use_uri_table", 0) | ||
| + | |||
| + | loadmodule "usrloc.so" | ||
| + | modparam("usrloc", "nat_bflag", "FLB_NATB") | ||
| + | modparam("usrloc", "db_mode", 2) | ||
| + | modparam("usrloc", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") | ||
| + | |||
| + | |||
| + | loadmodule "registrar.so" | ||
| + | modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT") | ||
| + | |||
| + | /* Descomente a linha abaixo para nao permitir mais de 10 contatos por conta */ | ||
| + | #modparam("registrar", "max_contacts", 10) | ||
| + | |||
| + | loadmodule "acc.so" | ||
| + | /* Quais eventos deverao ser registrados ? */ | ||
| + | modparam("acc", "early_media", 0) | ||
| + | modparam("acc", "report_cancels", 0) | ||
| + | /* por padrao nos nao ajustamos a direcao em requisicoes sequencias, | ||
| + | se voce deseja usar este recurso tenha certeza de ativar o "appen_fromtag" | ||
| + | para o modulo "rr" */ | ||
| + | modparam("acc", "detect_direction", 0) | ||
| + | modparam("acc", "failed_transaction_flag", "FLT_ACCFAILED") | ||
| + | /* Gatilhos para accounting (flags) */ | ||
| + | modparam("acc", "log_flag", "FLT_ACC") | ||
| + | modparam("acc", "log_missed_flag", "FLT_ACCMISSED") | ||
| + | modparam("acc", "log_extra", | ||
| + | "src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") | ||
| + | modparam("acc", "db_flag", "FLT_ACC") | ||
| + | modparam("acc", "db_missed_flag", "FLT_ACCMISSED") | ||
| + | modparam("acc", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") | ||
| + | modparam("acc", "db_extra", "src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd" ) | ||
| + | |||
| + | loadmodule "auth.so" | ||
| + | loadmodule "auth_db.so" | ||
| + | modparam("auth_db", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") | ||
| + | modparam("auth_db", "calculate_ha1", yes) | ||
| + | modparam("auth_db", "password_column", "password") | ||
| + | modparam("auth_db", "load_credentials", "") | ||
| + | |||
| + | |||
| + | loadmodule "permissions.so" | ||
| + | modparam("permissions", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") | ||
| + | |||
| + | loadmodule "alias_db.so" | ||
| + | modparam("alias_db", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") | ||
| + | |||
| + | loadmodule "presence.so" | ||
| + | modparam("presence", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") | ||
| + | |||
| + | #loadmodule "presence_xml.so" | ||
| + | |||
| + | |||
| + | loadmodule "dialog.so" | ||
| + | modparam("dialog", "db_mode", 2) | ||
| + | modparam("dialog", "db_url","mysql://opensips:opensipsrw@localhost/opensips") | ||
| + | modparam("dialog", "dlg_match_mode", 1) | ||
| + | #modparam("dialog", "default_timeout", 60) | ||
| + | |||
| + | loadmodule "siptrace.so" | ||
| + | modparam("siptrace", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") | ||
| + | modparam("siptrace", "trace_flag", 22) | ||
| + | modparam("siptrace", "traced_user_avp", "$avp(s:traceuser)") | ||
| + | |||
| + | |||
| + | loadmodule "nathelper.so" | ||
| + | modparam("nathelper", "natping_interval", 30) | ||
| + | modparam("nathelper", "ping_nated_only", 1) | ||
| + | modparam("nathelper", "sipping_bflag", "FLB_NATSIPPING") | ||
| + | modparam("nathelper", "sipping_from", "sip:pinger@10.254.254.6") # Altere o ip para o ip do servidor | ||
| + | modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)") | ||
| + | |||
| + | loadmodule "rtpproxy.so" | ||
| + | modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722") | ||
| + | |||
| + | |||
| + | |||
| + | ####### Logica de roteamento ######## | ||
| + | |||
| + | |||
| + | route { | ||
| + | |||
| + | if (!mf_process_maxfwd_header("3")) { | ||
| + | send_reply("483","looping"); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | xlog("REQUISICAO RECEBIDA, ENVIANDO PARA REQINIT"); | ||
| + | # Checagem inicial por requisicao | ||
| + | route(REQINIT); | ||
| + | |||
| + | xlog("ENVIANDO PARA NAT"); | ||
| + | # Deteccao de nat | ||
| + | route(NAT); | ||
| + | |||
| + | xlog("ENVIANDO PARA WITHINDLG"); | ||
| + | # Gerenciando requisicaoes com dialog | ||
| + | route(WITHINDLG); | ||
| + | |||
| + | # Manipulando requisicoes iniciais (nao consta To tag) | ||
| + | |||
| + | # Processando CANCEL | ||
| + | |||
| + | if(is_method("CANCEL")){ | ||
| + | xlog("METHOD CANCEL"); | ||
| + | if(t_check_trans()){ | ||
| + | t_relay(); | ||
| + | } | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | t_check_trans(); | ||
| + | |||
| + | # Enviando para autenticacao | ||
| + | xlog("ENVIANDO PARA AUTENTICACAO"); | ||
| + | route(AUTH); | ||
| + | |||
| + | # gravando rota para formacao dos dialogs (caso sejam roteados) | ||
| + | # removemos qualquer cabecalho de rota pre carregado | ||
| + | remove_hf("Route"); | ||
| + | if(is_method("INVITE|SUBSCRIBE")){ | ||
| + | xlog("METHOD INVITE OU SIBSCRIBE"); | ||
| + | record_route(); | ||
| + | } | ||
| + | |||
| + | # Contabilizando (acc) INVITES | ||
| + | if(is_method("INVITE")){ | ||
| + | xlog("METHOD INVITE, FAZENDOA ACC"); | ||
| + | setflag(FLT_ACC); | ||
| + | } | ||
| + | |||
| + | # Enviando chamada para destinos externos | ||
| + | xlog("ENVIANDO PARA SIPOUT"); | ||
| + | route(SIPOUT); | ||
| + | |||
| + | # Requisicoes para dominio local | ||
| + | |||
| + | # Roteando requisicoes de PRESENCE | ||
| + | xlog("ENVIANDO PARA PRESENCE"); | ||
| + | |||
| + | route(PRESENCE); | ||
| + | |||
| + | # Gerenciando pedidos de registro | ||
| + | xlog("ENVIANDO PARA REGISTRAR"); | ||
| + | route(REGISTRAR); | ||
| + | |||
| + | if($ru==""){ | ||
| + | xlog("ru --> vazio"); | ||
| + | # Requisicao sem usuario na RURI | ||
| + | sl_send_reply("484", "Address Incomplete"); | ||
| + | } | ||
| + | |||
| + | # Enviando requisicao para PSTN | ||
| + | xlog("ENVIANDO PARA PSTN"); | ||
| + | route(PSTN); | ||
| + | |||
| + | |||
| + | # Salvando informacao de quem originou a chamad | ||
| + | $avp(callee)=$rU; | ||
| + | xlog("ENVIANDO PARA DISPATCH PSTN"); | ||
| + | route(FSDISPATCH); | ||
| + | |||
| + | |||
| + | |||
| + | # Servico de localizacao de usuario | ||
| + | route(LOCATION); | ||
| + | |||
| + | # Efetuando o relay (encaminhamento) | ||
| + | route(RELAY); | ||
| + | |||
| + | |||
| + | |||
| + | } | ||
| + | |||
| + | |||
| + | route[RELAY] { | ||
| + | if(check_route_param("nat=yes")){ | ||
| + | setbflag(FLB_NATB); | ||
| + | } | ||
| + | |||
| + | if(isflagset(FLT_NATS) || isbflagset(FLB_NATB)){ | ||
| + | #route(RTPPROXY); | ||
| + | } | ||
| + | |||
| + | # if(is_method("INVITE")){ | ||
| + | # t_on_reply("REPLY_ONE"); | ||
| + | # t_on_failure("FAIL_ONE"); | ||
| + | # } | ||
| + | |||
| + | xlog("AQUI TENTAMOS ENVIAR A CHAMADA $fU $tU"); | ||
| + | if(!t_relay()){ | ||
| + | xlog("FALHA EM ENVIAR A CHAMADA, NAO FOI POSSIVEL FAZER O RELAY"); | ||
| + | sl_reply_error(); | ||
| + | } | ||
| + | xlog("CHAMADA FOI ENVIADA AQUI, QUAL O ERRO ENTAO"); | ||
| + | |||
| + | exit; | ||
| + | } | ||
| + | |||
| + | |||
| + | route[REQINIT] { | ||
| + | if(!mf_process_maxfwd_header("10")){ | ||
| + | sl_send_reply("483", "Too Many Hops"); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | } | ||
| + | |||
| + | |||
| + | route[WITHINDLG] { | ||
| + | if(has_totag()){ | ||
| + | if(loose_route()){ | ||
| + | if(is_method("BYE")){ | ||
| + | setflag(FLT_ACC); | ||
| + | setflag(FLT_ACCFAILED); | ||
| + | } | ||
| + | route(RELAY); | ||
| + | }else{ | ||
| + | if(is_method("SUBSCRIBE") && uri==myself) { | ||
| + | # requisicao de subscribe pre-estabelecida | ||
| + | route(PRESENCE); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | if(is_method("ACK")){ | ||
| + | if(t_check_trans()){ | ||
| + | t_relay(); | ||
| + | exit; | ||
| + | } | ||
| + | }else{ | ||
| + | # ACK para transacao nao encontrada, ignoramos... | ||
| + | exit; | ||
| + | |||
| + | } | ||
| + | |||
| + | sl_send_reply("404", "Not Here"); | ||
| + | |||
| + | } | ||
| + | exit; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | |||
| + | route[REGISTRAR] { | ||
| + | |||
| + | if(is_method("REGISTER")){ | ||
| + | if(isflagset(FLT_NATS)){ | ||
| + | setbflag(FLB_NATB); | ||
| + | } | ||
| + | |||
| + | if(!save("location")){ | ||
| + | sl_reply_error(); | ||
| + | } | ||
| + | |||
| + | exit; | ||
| + | } | ||
| + | |||
| + | } | ||
| + | |||
| + | route[LOCATION] { | ||
| + | |||
| + | alias_db_lookup("dbaliases"); | ||
| + | if(!lookup("location")){ | ||
| + | switch($rc) { | ||
| + | case -1: | ||
| + | case -3: | ||
| + | t_newtran(); | ||
| + | t_reply("404","Not Found"); | ||
| + | exit; | ||
| + | case -2: | ||
| + | sl_send_reply("405", "Method Not Allowed"); | ||
| + | exit; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | |||
| + | if(is_method("INVITE")){ | ||
| + | setflag(FLT_ACCMISSED); | ||
| + | } | ||
| + | |||
| + | |||
| + | |||
| + | } | ||
| + | |||
| + | route[PRESENCE] { | ||
| + | if(!is_method("PUBLISH|SUBSCRIBE")){ | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | if(!t_newtran()){ | ||
| + | sl_reply_error(); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | if(is_method("PUBLISH")){ | ||
| + | handle_publish(); | ||
| + | }else if(is_method("SUBSCRIBE")){ | ||
| + | handle_subscribe(); | ||
| + | } | ||
| + | exit; | ||
| + | |||
| + | } | ||
| + | |||
| + | |||
| + | route[AUTH]{ | ||
| + | xlog("PEDIDO DE AUTENTICACAO"); | ||
| + | if(is_method("REGISTER")){ | ||
| + | # atentica pedidos de registro | ||
| + | if(!www_authorize("", "subscriber")){ | ||
| + | www_challenge("", "0"); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | if($au!=$tU){ | ||
| + | sl_send_reply("403", "Forbidden auth ID"); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | |||
| + | }else{ | ||
| + | if(route(FSINBOUND)){ | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | if(check_source_address("0")){ | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | if(from_uri==myself){ | ||
| + | if(!proxy_authorize("", "subscriber")){ | ||
| + | proxy_challenge("","0"); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | if(is_method("PUBLISH")){ | ||
| + | if($au!=$tU){ | ||
| + | sl_send_reply("403", "Forbidden auth ID"); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | }else{ | ||
| + | if($au!=$fU){ | ||
| + | sl_send_reply("403", "Forbidden auth ID"); | ||
| + | exit; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | |||
| + | # Validamos (autenticamos) o usuario | ||
| + | consume_credentials(); | ||
| + | }else{ | ||
| + | |||
| + | # usuario nao e local, vamos negar | ||
| + | if(!uri==myself){ | ||
| + | sl_send_reply("403", "Not relaying"); | ||
| + | exit; | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | return; | ||
| + | } | ||
| + | |||
| + | |||
| + | route[NAT] { | ||
| + | force_rport(); | ||
| + | if(nat_uac_test("19")){ | ||
| + | if(method=="REGISTER"){ | ||
| + | fix_nated_register(); | ||
| + | }else{ | ||
| + | fix_nated_contact(); | ||
| + | } | ||
| + | setflag(FLT_NATS); | ||
| + | } | ||
| + | |||
| + | return; | ||
| + | } | ||
| + | |||
| + | route[RTPPROXY] { | ||
| + | if(is_method("BYE")){ | ||
| + | unforce_rtp_proxy(); | ||
| + | }else if(is_method("INVITE")){ | ||
| + | engage_rtp_proxy(); | ||
| + | } | ||
| + | |||
| + | if(!has_totag()){ | ||
| + | |||
| + | if(!check_route_param("nat=yes")){ | ||
| + | add_rr_param(";nat=yes"); | ||
| + | xlog("NAT yes NAO ENCONTRADO"); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | return; | ||
| + | } | ||
| + | |||
| + | route[SIPOUT]{ | ||
| + | if(!uri==myself){ | ||
| + | append_hf("P-hint: outbound\r\n"); | ||
| + | route(RELAY); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | route[PSTN]{ | ||
| + | # neste caso apenas para exemplificar um uso simples | ||
| + | # vamos fazer o redirecionamento par ao asterisk | ||
| + | # realizar a dicagem da chamada | ||
| + | |||
| + | if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$")) | ||
| + | return; | ||
| + | |||
| + | ## a regra acima aceita para discagem externa qualquer numero | ||
| + | # comecado com 00 ou + | ||
| + | # | ||
| + | |||
| + | if(from_uri!=myself){ | ||
| + | sl_send_reply("403", "Not Allowed"); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | $ru = "sip:" + $rU + "@" + "10.254.254.6:5090"; | ||
| + | xlog("NOVO DESTINO: $ru"); | ||
| + | route(RELAY); | ||
| + | exit; | ||
| + | |||
| + | } | ||
| + | |||
| + | route[XMLRPC]{ | ||
| + | # nao vamos implementar esta funcionalidade | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | route[FSINBOUND] { | ||
| + | # verificar para validar o ip do asterisk:porta | ||
| + | # se bater , responder com return 1; | ||
| + | if($si=="10.254.254.6" && $sp=="5090"){ | ||
| + | return(1); | ||
| + | }else{ | ||
| + | return(-1); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | route[FSDISPATCH] { | ||
| + | |||
| + | if(!is_method("INVITE")){ | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | if(route(FSINBOUND)){ | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | |||
| + | xlog("CAIMOS NO SWITCH, VAMOS LOCALIZAR O PERFIL DA CHAMADA $rU"); | ||
| + | |||
| + | |||
| + | if($rU =~ "^41$"){ | ||
| + | xlog("SWITCH expressa comeca e termina em 41"); | ||
| + | #regra de menu de voicemail, apenas | ||
| + | # usuarios autenticados | ||
| + | if($au==""){ | ||
| + | sl_send_reply("403", "Not Allowed"); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | $rU = "vma-" + $au; | ||
| + | }else if($rU =~ "^441[0-9][0-9]$"){ | ||
| + | xlog("SWTICH OPCA 441XX "); | ||
| + | # numero discado comeca com 441 seguido de dois digitos | ||
| + | # chamada direta para inbox do voicemail | ||
| + | strip(2); | ||
| + | route(FSVBOX); | ||
| + | }else if($rU =~ "^433[01][0-9][0-9]$"){ | ||
| + | xlog("SWITCH OPCAO 433[01]XX"); | ||
| + | # numero comecado em 443, seguido de 0 ou 1, mais dois digitos | ||
| + | # sistema de conferencia | ||
| + | strip(2); | ||
| + | }else if($rU =~ "^45[0-9]+$"){ | ||
| + | xlog("SWTICH OPCAO 45X."); | ||
| + | #numero comecado com 45, seguindo de numeros; | ||
| + | strip(2); | ||
| + | }else{ | ||
| + | xlog("OPCAO DEFAULT DO SWITCH"); | ||
| + | # usuario offline, enviando para voicemail | ||
| + | if(!registered("location")){ | ||
| + | route(FSVBOX); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | # usuario online, fazendo bridging | ||
| + | xlog("USUARIO ESTA ONLINE VAMOS FAZER BRIDGE"); | ||
| + | prefix("kb-"); | ||
| + | if(is_method("INVITE")){ | ||
| + | t_on_failure("FAIL_FSVBOX"); | ||
| + | } | ||
| + | } | ||
| + | route(FSRELAY); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | route[FSVBOX]{ | ||
| + | xlog("ENVIANDO PARA FSVBOX"); | ||
| + | $du = "sip:" + "10.254.254.6" + ":" + "5090"; | ||
| + | if($rU =~ "^441[0-9][0-9]"){ | ||
| + | strip(2); | ||
| + | } | ||
| + | prefix("vm-"); | ||
| + | if($var(newbranch)==1){ | ||
| + | append_branch(); | ||
| + | $var(newbranch)=0; | ||
| + | } | ||
| + | route(RELAY); | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | |||
| + | route[FSRELAY] { | ||
| + | xlog("ENVIANDO PARA FSRELAY"); | ||
| + | $du = "sip:" + "10.254.254.6" + ":" + "5090"; | ||
| + | if($var(newbranch)==1){ | ||
| + | append_branch(); | ||
| + | $var(newbranch)=0; | ||
| + | } | ||
| + | route(RELAY); | ||
| + | exit; | ||
| + | |||
| + | } | ||
| + | |||
| + | branch_route[BRANCH_ONE]{ | ||
| + | xlog("new branch at $ru"); | ||
| + | } | ||
| + | |||
| + | |||
| + | onreply_route[REPLY_ONE]{ | ||
| + | xlog("Incoming reply"); | ||
| + | if((isflagset(FLT_NATS) || isbflagset(FLB_NATB) && status =~ "(183)|(2[0-9][0-9])")){ | ||
| + | #rtpproxy_offer(); | ||
| + | |||
| + | } | ||
| + | if(isbflagset(FLB_NATB)){ | ||
| + | fix_nated_contact(); | ||
| + | } | ||
| + | |||
| + | |||
| + | } | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | failure_route[FAIL_ONE]{ | ||
| + | xlog("FAILURE ROUTE FAIL_ONE"); | ||
| + | if(is_method("INVITE") && (isbflagset(FLB_NATB) || isflagset(FLT_NATS))){ | ||
| + | unforce_rtp_proxy(); | ||
| + | } | ||
| + | |||
| + | if(t_was_cancelled()){ | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | |||
| + | } | ||
| + | |||
| + | |||
| + | failure_route[FAIL_FSVBOX]{ | ||
| + | xlog("FAILURE ROUTE FAIL_FSVBOX"); | ||
| + | if(is_method("INVITE") && (isbflagset(FLB_NATB) || isflagset(FLT_NATS))){ | ||
| + | unforce_rtp_proxy(); | ||
| + | } | ||
| + | |||
| + | if(t_was_cancelled()){ | ||
| + | exit; | ||
| + | } | ||
| + | |||
| + | if(t_check_status("486|408|480")){ | ||
| + | $rU = $avp(callee); | ||
| + | $var(newbranch) = 1; | ||
| + | route(FSVBOX); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | |||
| + | </pre> | ||
| + | |||
| + | ==Testes com Opensips (registro)== | ||
| + | |||
| + | Antes de podermos testar precisamos iniciar o serviço, no momento estamos com ele operando em modo debug, então a inicialização deve ser realizada com o comando abaixo | ||
| + | /etc/init.d/opensips debug | ||
| + | |||
| + | Abra uma nova sessão no servidor e então vamos criar os usuários | ||
| + | opensipsctl add 101 101 | ||
| + | opensipsctl add 102 102 | ||
| + | opensipsctl add 103 103 | ||
| + | |||
| + | usuario 101 com senha 101 e assim por diante | ||
| + | |||
| + | Faça a onexão com seu softphone, aqui para testes utilizei o jitsi e o zoiper, neste momento vamos apenas fazer o registro do usuário para testar a autenticação, se você tentar realizar uma discagem não funcionará pois neste caso o processo depende do Asterisk que ainda não está configurado, vamos dar inicio nesta configuração agora. | ||
| + | |||
| + | ==Asterisk== | ||
| + | Não vamos dar muitos detalhes da instalação do asterisk aqui, a ideia é simplesmente ter o mesmo funcionando da forma que necessitamos. | ||
| + | apt-get install asterisk | ||
| + | |||
| + | Após a instalação , abra o arquivo /etc/asterisk/sip.conf, localize a linha '''udpbindaddr=0.0.0.0''' e altere para '''udpbindaddr=0.0.0.0:5090''' , depois ao fim do arquivo adicione. | ||
| + | <pre> | ||
| + | [opensips] | ||
| + | type=peer | ||
| + | host=10.254.254.6 | ||
| + | port=5060 | ||
| + | qualify=yes | ||
| + | context=opensips | ||
| + | insecure=port,invite | ||
| + | canreinvite=no | ||
| + | </pre> | ||
| + | |||
| + | Agora abra o arquivo '''/etc/asterisk/extensions.conf''' , crie no fim do arquivo a seguinte entrada. | ||
| + | <pre> | ||
| + | [opensips] | ||
| + | |||
| + | exten => _kb-1XX,1,NoOp(CHAMADA INTERNA - FAZER BRIDGE - ${CALLERID(num)} ${EXTEN:3}) | ||
| + | same => n,Dial(SIP/opensips/${EXTEN:3}) | ||
| + | same => n,Goto(opensips,vm-${EXTEN:3},1) | ||
| + | same => n,Hangup() | ||
| + | |||
| + | exten => _vm-1XX,1,NoOp(CHAMADA PARA VOICEMAIL) | ||
| + | same => n,Voicemail(${EXTEN:3}@default) | ||
| + | same => n,Hangup() | ||
| + | |||
| + | exten => _vma-1XX,1,NoOp(CHAMADA PARA VOICEMAIL - ADMINISTRATIVO) | ||
| + | same => n,VoicemailMain(${EXTEN:4}@default) | ||
| + | same => n,Hangup() | ||
| + | |||
| + | exten => _3[01]XX,1,NoOp(CHAMADA PARA CONFERENCIA) | ||
| + | same => n,Answer() | ||
| + | same => n,ConfBridge(${EXTEN},cM1) | ||
| + | same => n,Hangup() | ||
| + | |||
| + | exten => _00.,1,NoOp(CHAMADA PARA PSTN) | ||
| + | same => n,Wait(2) | ||
| + | same => n,Answer() | ||
| + | same => n,Wait(1) | ||
| + | same => n,PlayBack(tt-monkeys) | ||
| + | same => n,Hangup() | ||
| + | |||
| + | exten => h,1,Hangup() | ||
| + | |||
| + | </pre> | ||
| + | |||
| + | Finalmente precisamos criar as entradas do voicemail, para isso altere o arquivo '''/etc/asterisk/voicemail.conf''' localize o contexto '''[default]''' e então adicione as entradas para seu voicemail, segue dois exemplos abaixo. | ||
| + | <pre> | ||
| + | 101 => 123123,Mike Tesliuk | ||
| + | 102 => 123123,Mike Tesliuk 2 | ||
| + | </pre> | ||
| + | |||
| + | Feito isso, faça um restart no asterisk | ||
| + | /etc/init.d/asterisk restart | ||
| + | |||
| + | Agora você ja poderá fazer os testes, basicamente criamos as seguintes situações para serem testadas. | ||
| + | |||
| + | *1 Autenticação de usuários | ||
| + | *2 Chamada entre usuários | ||
| + | *3 Encaminhamento para caixa postal | ||
| + | *4 Acesso a caixa postal | ||
| + | *5 Acesso a conferência | ||
Edição atual tal como às 22h56min de 15 de abril de 2021
| Precisando de recursos de númeração para fazer seus testes ? Contrate conosco em BRDVoz | Ou talvez gostaria de uma consultoria no seu proejto ? Também estamos disponiveis em BRDSoft |
| Falta realizar os ajustes / testes para o NAT no mais esta tudo funcionado adequadamente a principio |
Este tutorial é baseado em um tutorial similar porém utilizando Kamailio e Freeswtich, se quiser verificar o tutorial original acesse http://kb.asipto.com/freeswitch:kamailio-3.1.x-freeswitch-1.0.6d-sbc.
Para esta implementação utilizamos Debian 7.0 amd64 , OpenSIPS 1.9 e Asterisk 1.8.23
Índice
Funcionalidades
Este tutorial tem por objetivo atingir as seguintes funcionalidades.
- Autenticação de usuário
- Registro de usuário
- Localização de usuário (encaminhamento de chamadas)
- Roteamento de chamadas
Através do Asterisk estenderemos estas funcionalidades agregando.
- Correio de voz (Voicemail)
- Conferencia
- SBC ( Pode ser utilizado para transcoding, esconder topologia, play de mensagens e tarifação )
- Outros serviços de media (Anuncios, Ura's e coisas do tipo)
Definições
Para um melhor entendimento da solução vamos expor aqui algumas definições de nosso sistema.
- Usuários locais terão ramais com 3 digitos (ex: 101, 102, 103)
- Identidade do correio de voz será o mesmo do ramal
- Serviços de media (acesso a voicemail e outros) receberão rotas de 4 digitos
- Opensips e Asterisk utilizarão o mesmo servidor (Neste caso IP: 10.254.254.6)
- Os serviços rodarão nas portas 5060 (opensips) , 5090 (Asterisk)
Funcionamento
A autenticação do usuário será realizada pelo OpenSIPs, quando uma chamada é autenticada então ela serguirá:
- Se o usuário de destino não está online a chamada será enviada para o Asterisk para função de correio de voz
- Se o usuário está online a chamada será encaminhada para o Asterisk, dest forma é possivel acionar funcionalidades como anuncios, definição de tempo de chamada, forçar codecs e outras funcionalidades.
- Asterisk envia a chamada novamente para o OpenSIPs que verificará no location e entregará a chamada para o usuário.
- Se a chamada não for atendida o Opensips irá re-encaminhar para o Asterisk direcionando para função de voicemail
OpenSIPs
Vamos iniciar o processo de instalação com o OpenSIPs, siga os procedimentos abaixo para evitar qualquer dificuldade.
Dependencias
Execute o comando abaixo para instalar todas as dependencias necessárias
apt-get install gcc make libncurses5-dev libnewt-dev libxml2-dev unixodbc \ unixodbc-dev libmysqlclient15-dev libxmlrpc-c3-dev libexpat1-dev zlib1g-dev \ m4 bison flex libpcre3-dev mysql-server vim apache2-mpm-prefork libapache2-mod-php5 \ php5-mysql php5-xmlrpc php-pear ngrep g++ libjpeg62-dev libssl-dev
Durante a instalação o sistema irá lhe perguntar a senha de root para o servidor MySQL é importante que você se lembre da mesma posteriormente pois utilizaremos a mesma.
Compilando o OpenSIPs
Para manter um padrão onde os dados estao vamos utilizar o diretório /usr/src/ para o download de código fonte.
cd /usr/src/ wget -c http://opensips.org/pub/opensips/1.9.1/src/opensips-1.9.1_src.tar.gz tar -xzvf opensips-1.9.1_src.tar.gz cd opensips-1.9.1-tls/ make menuconfig
Neste ponto o sistema irá abrir uma tela com algumas opções para selecionar, Acesse a primeira opção do menu, no submenu acesse a segunda opção ( Configure excluded modules ), selecione os módulos db_mysql , dialplan , mi_xmlrpc , presence e presence_xml
Agora volte ao submenu, e selecione a opção Save Changes, volte para o menu principal e selecione Compile and Install OpenSips , deixe que o sistema execute suas funções.
Ao finalizar a compilação você retornará ao menu, va na opção Exit and Save all changes
Preparando a Configuração
Antes de darmos inicio ao arquivo de configuração, vamos ajustar algumas questões, o opensips instala os arquivos (se voce nao alterar o parametro) em /usr, consequentemente as configurações ficam em /usr/etc , eu por padrão faço um link para o diretório /etc, assim acesso as configurações em /etc/opensips
ln -s /usr/etc/opensips /etc/
No caso do debian o script de inicialização utiliza um arquivo extra de configuração
cp packaging/debian/opensips.default /etc/default/opensips
Para o script de inicialização execute o comando abaixo
cp packaging/debian/opensips.init /etc/init.d/opensips chmod +x /etc/init.d/opensips update-rc.d opensips defaults
Edite o arquivo /etc/default/opensips , a altere o parametro RUN_OPENSIPS para yes
Você pode notar que no arquivo é mensionado o usuário de execução do opensips como opensips, então vamos ter de criar este usuário ( e grupo )
groupadd opensips mkdir /var/run/opensips useradd -d /var/run/opensips/ -s /bin/false -g opensips opensips chown -R opensips.opensips /var/run/opensips
Configurando o opensipsctl
O opensipsctl (e opensipsdbctl) utilizam o arquivo de configuração /etc/opensips/opensipsctlrc, abaixo segue o conteúdo do arquivo. (Sugiro que você faça um backup dos arquivos originais para ter uma copia, existem parametros que você pode estudar depois).
DBENGINE=MYSQL DBHOST=localhost DBNAME=opensips DBRWUSER=opensips DBRWPW="opensipsrw" SIP_DOMAIN=10.254.254.6 ### caso voce esteja usando outro ip altere aqui DBROOTUSER="root" INSTALL_EXTRA_TABLES=ask ALIASES_TYPE="DB" MI_CONNECTOR=FIFO:/tmp/opensips_fifo # VERIFY_ACL=1 # ACL_GROUPS="local ld int voicemail free-pstn" # VERBOSE=1 # STORE_PLAINTEXT_PW=0 # NOHLPRINT=1 PID_FILE=/var/run/opensips/opensips.pid
Criando o banco de dados
Agora que temos nosso arquivo configurado vamos fazer a criação do banco de dados, execute o comando abaixo.
opensipsdbctl create opensips
O sistema irá lhe perguntar algumas coisas, responda Y (sim) para todas para que ele instale todas as tabelas, não usaremos todas elas, mas desta forma você fica com praticamente tudo criado para o caso de uma expansão dos recursos.
Instalando o RTP Proxy
cd /usr/src/ wget -c http://b2bua.org/chrome/site/rtpproxy-1.2.1.tar.gz tar -xzvf rtpproxy-1.2.1.tar.gz cd rtpproxy-1.2.1 ./configure make make install groupadd rtpproxy useradd -d /var/run/rtpproxy -s /bin/true -g rtpproxy rtpproxy mkdir /var/log/rtpproxy mkdir /var/run/rtpproxy chown -R rtpproxy.rtpproxy /var/log/rtpproxy chown -R rtpproxy.rtpproxy /var/run/rtpproxy
Arquivo de inicialização
/etc/init.d/rtpproxy
#!/bin/bash
#
# Este script e de autoria de Mike Tesliuk
# qualquer falha no mesmo por favor informe
# atraves do email mike (a) tesliuk.com
#
### BEGIN INIT INFO
# Provides: rtpproxy
# Required-Start: $syslog $network $local_fs $time
# Required-Stop: $syslog $network $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start the RTPPROXY server
# Description: Start the RTPPROXY server
### END INIT INFO
PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
USELOG=1
USER=rtpproxy
# Altere o ip abaixo para o ip de seu sistema
IPADDR="10.254.254.6"
. /lib/lsb/init-functions
start(){
echo "Iniciando RTP PROXY "
if [ -z $(pidof rtpproxy) ]; then
if [ "${USELOG}" = "1" ]; then
echo "Iniciando com LOG"
/usr/local/bin/rtpproxy -l $IPADDR -s udp:127.0.0.1:7722 -u $USER -F -f d DBUG 2&> /var/log/rtpproxy/rtpproxy.log &
else
echo "Iniciando sem LOG"
/usr/local/bin/rtpproxy -l $IPADDR -s udp:127.0.0.1:7722 -u $USER -F -f d DBUG 2&> /dev/null
fi
if [ -n $(pidof rtpproxy) ]; then
echo "START OK"
fi
else
echo "Processo ja em execucao"
fi
}
stop(){
if [ -z $(pidof rtpproxy) ]; then
echo "Processo nao encontrado"
else
kill -9 $(pidof rtpproxy)
if [ -n $(pidof rtpproxy) ]; then
echo "STOP OK"
else
echo "Falha em realizar stop do servico"
fi
fi
}
case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo "Utilize: stop | start | restart"
;;
esac
Vamos dar permissao e colocar na inicialização
chmod +x /etc/init.d/rtpproxy update-rc.d rtpproxy defaults /etc/init.d/rtpproxy start
Criando o arquivo opensips.cfg
O arquivo opensips.cfg é a onde a coisa toda acontece para o opensips, claro que ele dependerá de informações que estarão no banco de dados, mas é onde criamos todas as nossas rotas e validações.
####### Global Parameters #########
debug=3
log_stderror=no
log_facility=LOG_LOCAL0
fork=yes
children=4
/* Descomente as linhas abaixo para ativar o debug */
#debug=7
#fork=no
#log_stderror=yes
/* Comente a linha abaixo para ativar a descoberta automatica de enderecos locais
, isso significa que o sistema ira verificar todos os ips ativos e hosts e entao ativara
o protocolo para todos eles */
auto_aliases=no
/* Defina aqui o ip a ser utilizado */
listen=udp:10.254.254.6:5060 # Altere este IP para o seu ambiente
/* Nao usaremos sip por tcp nem tls neste script */
disable_tcp=yes
disable_tls=yes
####### Secao de modulos ########
#set module path
mpath="/usr//lib64/opensips/modules/"
loadmodule "signaling.so"
loadmodule "sl.so"
loadmodule "tm.so"
modparam("tm", "fr_timer", 5)
modparam("tm", "fr_inv_timer", 30)
modparam("tm", "restart_fr_on_each_reply", 0)
modparam("tm", "onreply_avp_mode", 1)
loadmodule "rr.so"
/* do not append from tag to the RR (no need for this script) */
modparam("rr", "append_fromtag", 0)
loadmodule "maxfwd.so"
loadmodule "sipmsgops.so"
loadmodule "mi_fifo.so"
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
modparam("mi_fifo", "fifo_mode", 0666)
loadmodule "db_mysql.so"
loadmodule "uri.so"
modparam("uri", "use_uri_table", 0)
loadmodule "usrloc.so"
modparam("usrloc", "nat_bflag", "FLB_NATB")
modparam("usrloc", "db_mode", 2)
modparam("usrloc", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
loadmodule "registrar.so"
modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT")
/* Descomente a linha abaixo para nao permitir mais de 10 contatos por conta */
#modparam("registrar", "max_contacts", 10)
loadmodule "acc.so"
/* Quais eventos deverao ser registrados ? */
modparam("acc", "early_media", 0)
modparam("acc", "report_cancels", 0)
/* por padrao nos nao ajustamos a direcao em requisicoes sequencias,
se voce deseja usar este recurso tenha certeza de ativar o "appen_fromtag"
para o modulo "rr" */
modparam("acc", "detect_direction", 0)
modparam("acc", "failed_transaction_flag", "FLT_ACCFAILED")
/* Gatilhos para accounting (flags) */
modparam("acc", "log_flag", "FLT_ACC")
modparam("acc", "log_missed_flag", "FLT_ACCMISSED")
modparam("acc", "log_extra",
"src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
modparam("acc", "db_flag", "FLT_ACC")
modparam("acc", "db_missed_flag", "FLT_ACCMISSED")
modparam("acc", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("acc", "db_extra", "src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd" )
loadmodule "auth.so"
loadmodule "auth_db.so"
modparam("auth_db", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
modparam("auth_db", "load_credentials", "")
loadmodule "permissions.so"
modparam("permissions", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
loadmodule "alias_db.so"
modparam("alias_db", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
loadmodule "presence.so"
modparam("presence", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
#loadmodule "presence_xml.so"
loadmodule "dialog.so"
modparam("dialog", "db_mode", 2)
modparam("dialog", "db_url","mysql://opensips:opensipsrw@localhost/opensips")
modparam("dialog", "dlg_match_mode", 1)
#modparam("dialog", "default_timeout", 60)
loadmodule "siptrace.so"
modparam("siptrace", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("siptrace", "trace_flag", 22)
modparam("siptrace", "traced_user_avp", "$avp(s:traceuser)")
loadmodule "nathelper.so"
modparam("nathelper", "natping_interval", 30)
modparam("nathelper", "ping_nated_only", 1)
modparam("nathelper", "sipping_bflag", "FLB_NATSIPPING")
modparam("nathelper", "sipping_from", "sip:pinger@10.254.254.6") # Altere o ip para o ip do servidor
modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")
loadmodule "rtpproxy.so"
modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722")
####### Logica de roteamento ########
route {
if (!mf_process_maxfwd_header("3")) {
send_reply("483","looping");
exit;
}
xlog("REQUISICAO RECEBIDA, ENVIANDO PARA REQINIT");
# Checagem inicial por requisicao
route(REQINIT);
xlog("ENVIANDO PARA NAT");
# Deteccao de nat
route(NAT);
xlog("ENVIANDO PARA WITHINDLG");
# Gerenciando requisicaoes com dialog
route(WITHINDLG);
# Manipulando requisicoes iniciais (nao consta To tag)
# Processando CANCEL
if(is_method("CANCEL")){
xlog("METHOD CANCEL");
if(t_check_trans()){
t_relay();
}
exit;
}
t_check_trans();
# Enviando para autenticacao
xlog("ENVIANDO PARA AUTENTICACAO");
route(AUTH);
# gravando rota para formacao dos dialogs (caso sejam roteados)
# removemos qualquer cabecalho de rota pre carregado
remove_hf("Route");
if(is_method("INVITE|SUBSCRIBE")){
xlog("METHOD INVITE OU SIBSCRIBE");
record_route();
}
# Contabilizando (acc) INVITES
if(is_method("INVITE")){
xlog("METHOD INVITE, FAZENDOA ACC");
setflag(FLT_ACC);
}
# Enviando chamada para destinos externos
xlog("ENVIANDO PARA SIPOUT");
route(SIPOUT);
# Requisicoes para dominio local
# Roteando requisicoes de PRESENCE
xlog("ENVIANDO PARA PRESENCE");
route(PRESENCE);
# Gerenciando pedidos de registro
xlog("ENVIANDO PARA REGISTRAR");
route(REGISTRAR);
if($ru==""){
xlog("ru --> vazio");
# Requisicao sem usuario na RURI
sl_send_reply("484", "Address Incomplete");
}
# Enviando requisicao para PSTN
xlog("ENVIANDO PARA PSTN");
route(PSTN);
# Salvando informacao de quem originou a chamad
$avp(callee)=$rU;
xlog("ENVIANDO PARA DISPATCH PSTN");
route(FSDISPATCH);
# Servico de localizacao de usuario
route(LOCATION);
# Efetuando o relay (encaminhamento)
route(RELAY);
}
route[RELAY] {
if(check_route_param("nat=yes")){
setbflag(FLB_NATB);
}
if(isflagset(FLT_NATS) || isbflagset(FLB_NATB)){
#route(RTPPROXY);
}
# if(is_method("INVITE")){
# t_on_reply("REPLY_ONE");
# t_on_failure("FAIL_ONE");
# }
xlog("AQUI TENTAMOS ENVIAR A CHAMADA $fU $tU");
if(!t_relay()){
xlog("FALHA EM ENVIAR A CHAMADA, NAO FOI POSSIVEL FAZER O RELAY");
sl_reply_error();
}
xlog("CHAMADA FOI ENVIADA AQUI, QUAL O ERRO ENTAO");
exit;
}
route[REQINIT] {
if(!mf_process_maxfwd_header("10")){
sl_send_reply("483", "Too Many Hops");
exit;
}
}
route[WITHINDLG] {
if(has_totag()){
if(loose_route()){
if(is_method("BYE")){
setflag(FLT_ACC);
setflag(FLT_ACCFAILED);
}
route(RELAY);
}else{
if(is_method("SUBSCRIBE") && uri==myself) {
# requisicao de subscribe pre-estabelecida
route(PRESENCE);
exit;
}
if(is_method("ACK")){
if(t_check_trans()){
t_relay();
exit;
}
}else{
# ACK para transacao nao encontrada, ignoramos...
exit;
}
sl_send_reply("404", "Not Here");
}
exit;
}
}
route[REGISTRAR] {
if(is_method("REGISTER")){
if(isflagset(FLT_NATS)){
setbflag(FLB_NATB);
}
if(!save("location")){
sl_reply_error();
}
exit;
}
}
route[LOCATION] {
alias_db_lookup("dbaliases");
if(!lookup("location")){
switch($rc) {
case -1:
case -3:
t_newtran();
t_reply("404","Not Found");
exit;
case -2:
sl_send_reply("405", "Method Not Allowed");
exit;
}
}
if(is_method("INVITE")){
setflag(FLT_ACCMISSED);
}
}
route[PRESENCE] {
if(!is_method("PUBLISH|SUBSCRIBE")){
return;
}
if(!t_newtran()){
sl_reply_error();
exit;
}
if(is_method("PUBLISH")){
handle_publish();
}else if(is_method("SUBSCRIBE")){
handle_subscribe();
}
exit;
}
route[AUTH]{
xlog("PEDIDO DE AUTENTICACAO");
if(is_method("REGISTER")){
# atentica pedidos de registro
if(!www_authorize("", "subscriber")){
www_challenge("", "0");
exit;
}
if($au!=$tU){
sl_send_reply("403", "Forbidden auth ID");
exit;
}
}else{
if(route(FSINBOUND)){
return;
}
if(check_source_address("0")){
return;
}
if(from_uri==myself){
if(!proxy_authorize("", "subscriber")){
proxy_challenge("","0");
exit;
}
if(is_method("PUBLISH")){
if($au!=$tU){
sl_send_reply("403", "Forbidden auth ID");
exit;
}
}else{
if($au!=$fU){
sl_send_reply("403", "Forbidden auth ID");
exit;
}
}
# Validamos (autenticamos) o usuario
consume_credentials();
}else{
# usuario nao e local, vamos negar
if(!uri==myself){
sl_send_reply("403", "Not relaying");
exit;
}
}
}
return;
}
route[NAT] {
force_rport();
if(nat_uac_test("19")){
if(method=="REGISTER"){
fix_nated_register();
}else{
fix_nated_contact();
}
setflag(FLT_NATS);
}
return;
}
route[RTPPROXY] {
if(is_method("BYE")){
unforce_rtp_proxy();
}else if(is_method("INVITE")){
engage_rtp_proxy();
}
if(!has_totag()){
if(!check_route_param("nat=yes")){
add_rr_param(";nat=yes");
xlog("NAT yes NAO ENCONTRADO");
}
}
return;
}
route[SIPOUT]{
if(!uri==myself){
append_hf("P-hint: outbound\r\n");
route(RELAY);
}
}
route[PSTN]{
# neste caso apenas para exemplificar um uso simples
# vamos fazer o redirecionamento par ao asterisk
# realizar a dicagem da chamada
if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$"))
return;
## a regra acima aceita para discagem externa qualquer numero
# comecado com 00 ou +
#
if(from_uri!=myself){
sl_send_reply("403", "Not Allowed");
exit;
}
$ru = "sip:" + $rU + "@" + "10.254.254.6:5090";
xlog("NOVO DESTINO: $ru");
route(RELAY);
exit;
}
route[XMLRPC]{
# nao vamos implementar esta funcionalidade
return;
}
route[FSINBOUND] {
# verificar para validar o ip do asterisk:porta
# se bater , responder com return 1;
if($si=="10.254.254.6" && $sp=="5090"){
return(1);
}else{
return(-1);
}
}
route[FSDISPATCH] {
if(!is_method("INVITE")){
return;
}
if(route(FSINBOUND)){
return;
}
xlog("CAIMOS NO SWITCH, VAMOS LOCALIZAR O PERFIL DA CHAMADA $rU");
if($rU =~ "^41$"){
xlog("SWITCH expressa comeca e termina em 41");
#regra de menu de voicemail, apenas
# usuarios autenticados
if($au==""){
sl_send_reply("403", "Not Allowed");
exit;
}
$rU = "vma-" + $au;
}else if($rU =~ "^441[0-9][0-9]$"){
xlog("SWTICH OPCA 441XX ");
# numero discado comeca com 441 seguido de dois digitos
# chamada direta para inbox do voicemail
strip(2);
route(FSVBOX);
}else if($rU =~ "^433[01][0-9][0-9]$"){
xlog("SWITCH OPCAO 433[01]XX");
# numero comecado em 443, seguido de 0 ou 1, mais dois digitos
# sistema de conferencia
strip(2);
}else if($rU =~ "^45[0-9]+$"){
xlog("SWTICH OPCAO 45X.");
#numero comecado com 45, seguindo de numeros;
strip(2);
}else{
xlog("OPCAO DEFAULT DO SWITCH");
# usuario offline, enviando para voicemail
if(!registered("location")){
route(FSVBOX);
exit;
}
# usuario online, fazendo bridging
xlog("USUARIO ESTA ONLINE VAMOS FAZER BRIDGE");
prefix("kb-");
if(is_method("INVITE")){
t_on_failure("FAIL_FSVBOX");
}
}
route(FSRELAY);
exit;
}
route[FSVBOX]{
xlog("ENVIANDO PARA FSVBOX");
$du = "sip:" + "10.254.254.6" + ":" + "5090";
if($rU =~ "^441[0-9][0-9]"){
strip(2);
}
prefix("vm-");
if($var(newbranch)==1){
append_branch();
$var(newbranch)=0;
}
route(RELAY);
exit;
}
route[FSRELAY] {
xlog("ENVIANDO PARA FSRELAY");
$du = "sip:" + "10.254.254.6" + ":" + "5090";
if($var(newbranch)==1){
append_branch();
$var(newbranch)=0;
}
route(RELAY);
exit;
}
branch_route[BRANCH_ONE]{
xlog("new branch at $ru");
}
onreply_route[REPLY_ONE]{
xlog("Incoming reply");
if((isflagset(FLT_NATS) || isbflagset(FLB_NATB) && status =~ "(183)|(2[0-9][0-9])")){
#rtpproxy_offer();
}
if(isbflagset(FLB_NATB)){
fix_nated_contact();
}
}
failure_route[FAIL_ONE]{
xlog("FAILURE ROUTE FAIL_ONE");
if(is_method("INVITE") && (isbflagset(FLB_NATB) || isflagset(FLT_NATS))){
unforce_rtp_proxy();
}
if(t_was_cancelled()){
exit;
}
}
failure_route[FAIL_FSVBOX]{
xlog("FAILURE ROUTE FAIL_FSVBOX");
if(is_method("INVITE") && (isbflagset(FLB_NATB) || isflagset(FLT_NATS))){
unforce_rtp_proxy();
}
if(t_was_cancelled()){
exit;
}
if(t_check_status("486|408|480")){
$rU = $avp(callee);
$var(newbranch) = 1;
route(FSVBOX);
}
}
Testes com Opensips (registro)
Antes de podermos testar precisamos iniciar o serviço, no momento estamos com ele operando em modo debug, então a inicialização deve ser realizada com o comando abaixo
/etc/init.d/opensips debug
Abra uma nova sessão no servidor e então vamos criar os usuários
opensipsctl add 101 101 opensipsctl add 102 102 opensipsctl add 103 103
usuario 101 com senha 101 e assim por diante
Faça a onexão com seu softphone, aqui para testes utilizei o jitsi e o zoiper, neste momento vamos apenas fazer o registro do usuário para testar a autenticação, se você tentar realizar uma discagem não funcionará pois neste caso o processo depende do Asterisk que ainda não está configurado, vamos dar inicio nesta configuração agora.
Asterisk
Não vamos dar muitos detalhes da instalação do asterisk aqui, a ideia é simplesmente ter o mesmo funcionando da forma que necessitamos.
apt-get install asterisk
Após a instalação , abra o arquivo /etc/asterisk/sip.conf, localize a linha udpbindaddr=0.0.0.0 e altere para udpbindaddr=0.0.0.0:5090 , depois ao fim do arquivo adicione.
[opensips] type=peer host=10.254.254.6 port=5060 qualify=yes context=opensips insecure=port,invite canreinvite=no
Agora abra o arquivo /etc/asterisk/extensions.conf , crie no fim do arquivo a seguinte entrada.
[opensips]
exten => _kb-1XX,1,NoOp(CHAMADA INTERNA - FAZER BRIDGE - ${CALLERID(num)} ${EXTEN:3})
same => n,Dial(SIP/opensips/${EXTEN:3})
same => n,Goto(opensips,vm-${EXTEN:3},1)
same => n,Hangup()
exten => _vm-1XX,1,NoOp(CHAMADA PARA VOICEMAIL)
same => n,Voicemail(${EXTEN:3}@default)
same => n,Hangup()
exten => _vma-1XX,1,NoOp(CHAMADA PARA VOICEMAIL - ADMINISTRATIVO)
same => n,VoicemailMain(${EXTEN:4}@default)
same => n,Hangup()
exten => _3[01]XX,1,NoOp(CHAMADA PARA CONFERENCIA)
same => n,Answer()
same => n,ConfBridge(${EXTEN},cM1)
same => n,Hangup()
exten => _00.,1,NoOp(CHAMADA PARA PSTN)
same => n,Wait(2)
same => n,Answer()
same => n,Wait(1)
same => n,PlayBack(tt-monkeys)
same => n,Hangup()
exten => h,1,Hangup()
Finalmente precisamos criar as entradas do voicemail, para isso altere o arquivo /etc/asterisk/voicemail.conf localize o contexto [default] e então adicione as entradas para seu voicemail, segue dois exemplos abaixo.
101 => 123123,Mike Tesliuk 102 => 123123,Mike Tesliuk 2
Feito isso, faça um restart no asterisk
/etc/init.d/asterisk restart
Agora você ja poderá fazer os testes, basicamente criamos as seguintes situações para serem testadas.
- 1 Autenticação de usuários
- 2 Chamada entre usuários
- 3 Encaminhamento para caixa postal
- 4 Acesso a caixa postal
- 5 Acesso a conferência