Opensips NAT Script com RTPproxy
Ir para navegação
Ir para pesquisar
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 |
Prefacio
Nat é uma questão que normalmente da um pouco de trabalho para entender no opensips, é bem diferente daquilo que estamos acostumados no asterisk por exemplo onde basta ativar uma flag e pronto tudo acontece.
Não vou demonstrar aqui como instalar o opensips ou rtpproxy, apenas demonstro um arquivo de configuração todo comentado com uma configuração minima para aceitar registros e encaminhar chamadas de um usuario para outro atrás de nat
O script não precisa de usuario previamente configurado, qualquer autenticacao enviada ele ira aceitar, e a cada restart voce tem que se registrar novamente pois a informacao esta toda na memoria, o proposito é unicamente demonstrar as questoes de nat
opensips.cfg
################################### # Este script tem por intuito demonstrar a configuracao # de um script de roteamento com NAT # ################################### ####### Parametros Globais ######### debug=3 log_stderror=no log_facility=LOG_LOCAL0 fork=yes children=4 /* Para fazer debug descomente as linhas abaixo */ #debug=6 #fork=no #log_stderror=yes auto_aliases=no # IP no qual iremos aguardar por requisicoes listen=udp:___IP_DO_OPENSIPS_AQUI___:5060 # Desativacao do suporte a SIP via TCP disable_tcp=yes # Desativacao do suporte a TLS (criptografia) na sinalizacao disable_tls=yes ####### Secao de Modulos ######## # Definicao do diretorio de modulos mpath="/usr//lib64/opensips/modules/" #### Modulo de sinalizacao loadmodule "signaling.so" #### Modulo stateless loadmodule "sl.so" #### Modulo para suporte a transacoes 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) #### Modulo para Record Route loadmodule "rr.so" modparam("rr", "append_fromtag", 0) #### Modulo para deteccao de loop (Max forward) loadmodule "maxfwd.so" #### Modulo para mensagens de operaca loadmodule "sipmsgops.so" #### Modulo para ativacao do gerenciamento via FIFO loadmodule "mi_fifo.so" modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo") modparam("mi_fifo", "fifo_mode", 0666) #### Modulo URI loadmodule "uri.so" modparam("uri", "use_uri_table", 0) #### Modulo para localizacao de usuario loadmodule "usrloc.so" modparam("usrloc", "nat_bflag", "NAT") modparam("usrloc", "db_mode", 0) #### Modulo para suporte a registros loadmodule "registrar.so" #### Modulo para auxilio de NAT loadmodule "nathelper.so" modparam("nathelper", "natping_interval", 10) modparam("nathelper", "natping_socket", "___IP_DO_OPENSIPS_AQUI___:5060") # o parametro abaixo armazena a uri do usuario quando chamada # a funcao fix_nated_register modparam("nathelper", "received_avp", "$avp(42)") #modparam("nathelper", "sipping_bflag", "SIP_PING_FLAG") modparam("nathelper", "sipping_from", "sip:pinger@___IP_DO_OPENSIPS_AQUI___") # o parametro abaixo define qual o formato do pacote a ser enviado # ele pode ser OPTIONS (default) ou INFO modparam("nathelper", "sipping_method", "OPTIONS") #### Modulo rtpproxy (forcar o audio atraves do opensips) loadmodule "rtpproxy.so" modparam("rtpproxy", "rtpproxy_sock", "udp:localhost:7890") ####### Logica de roteamento ######## # Sessao principal route{ # Esta e uma configuracao minima recomendada para # previnir loops if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); exit; } if (has_totag()) { # Requisicao previamente processada if (loose_route()) { xlog("Estamos em loose_route"); if (is_method("INVITE")) { record_route(); } route(relay); } else { if ( is_method("ACK") ) { if ( t_check_trans() ) { t_relay(); exit; } else { xlog("Nao estamos em loose, temos totag, metodo nao ack [ $rm ] "); # Transacao nao encontrada , vamos encerrar o roteamento exit; } } # Rota nao trata de encerramento e nem a resposta # de requisicao, entao enviamos um 404 sl_send_reply("404","Not here"); } exit; } # Processando requisicao de cancelamento if (is_method("CANCEL")) { if (t_check_trans()) t_relay(); exit; } t_check_trans(); if ( !(is_method("REGISTER") ) ) { # Verificando se o from e um usuario valido if (from_uri==myself) { } else { # From nao e usuario valido entao procedemos # para recusa pois o destino nao somos nos if (!uri==myself) { send_reply("403","Rely forbidden"); exit; } } } # Checando pacotes com rotas pre-carregadas if (loose_route()) { xlog("L_ERR", "Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]"); if (!is_method("ACK")) sl_send_reply("403","Preload Route denied"); exit; } # Se metodo nao e register ou message entao gravamos a rota if (!is_method("REGISTER|MESSAGE")) record_route(); # Nao somos o destino da requisicao entao acrescentamos # uma informacao para identificar como saida e enviamos para relay if (!uri==myself) { append_hf("P-hint: outbound\r\n"); route(relay); } # Requisicoes de PUBLISH e SUBSCRIBE # Nao vamos tratar neste documento if (is_method("PUBLISH|SUBSCRIBE")) { sl_send_reply("503", "Service Unavailable"); exit; } # Tratamento para metodo register if (is_method("REGISTER")) { # Aqui estamos recebendo um pedido de register # vamos executar fix_nated_register fix_nated_register(); fix_nated_contact(); # Este script e apenas ilustrativo , nao vamos criar usuarios # qualquer requisicao que chegue no mesmo sera aceita como valida # (registro) e a informacao sera salva if (!save("location")) sl_reply_error(); exit; } if ($rU==NULL) { #requisicao com endereco incompleto sl_send_reply("484","Address Incomplete"); exit; } # Este processamento so vai acontecer quando for uma chamada # com destino a nosso opensips, neste caso ele ira # verificar se o usuario esta registrado, se estiver # ele apenas enviara para relay se nao ele vai responder # com uma mensagem de 404 if (!lookup("location","m")) { t_newtran(); t_reply("404", "Not Found"); exit; } # Enviando para relay route(relay); } route[relay] { # verificamos se trata-se de um invite # para entao podermos definir as funcoes # para resposta dos pacotes if (is_method("INVITE")) { # Para cada perna adicionada ele chama # a rota abaixo ( branch_route(per_branch_ops) ) t_on_branch("per_branch_ops"); # Para cada reply recebido ele executa a rota abaixo # on_reply_route(handle_nat) t_on_reply("handle_nat"); # Chamadas que nao completaram sao procesadas # pela failure_route(missed_call) t_on_failure("missed_call"); # Vamos tentar identificar se o usuario esta atras de nat # fazemos isso no invite porque assim que recebemos # a requisicao procedemos com a correcao se necessaria if(nat_uac_test("127")){ # Usuario identificado como atras de nat xlog("Usuario atras de nat em handle nat"); fix_nated_contact(); } # Vamos verificar se temos cabecalho rtp e entao proceder com o rtpproxy if(has_body("application/sdp")){ xlog("Temos sdp no body para $rm"); rtpproxy_offer(); } } # Loose route quando tudo ok envia cancel e by para ca # entao aqui vamos desligar o rtp proxy if(is_method("CANCEL|BYE")){ unforce_rtp_proxy(); } # Aqui finalmente fazemos o relay do pacote # se nao conseguirmos fazer o relay entao # retornarmos erro 500 como erro interno if (!t_relay()) { send_reply("500","Internal Error"); }; exit; } branch_route[per_branch_ops] { # Nova perna adicionada a chamada xlog("new branch at $ru\n"); } onreply_route[handle_nat] { # Recebemos resposta do pacote xlog("incoming reply\n"); # Verificamos aqui se esta requisicao possui SDP if(is_method("ACK") && has_body("application/sdp")){ # Atendemos no rtpproxy rtpproxy_answer(); }else if(has_body("application/sdp")){ # possuindo sdp vamos re-escrever a informacao #fix_nated_sdp("2"); rtpproxy_offer(); } # Vamos tentar identificar se o usuario esta atras de nat # executamos neste nivel pois aqui sera executado # no momento que recebemos resposta, assim garantimos # que em todos os casos manipularemos o nat if(nat_uac_test("127")){ # Usuario identificado como atras de nat xlog("Usuario atras de nat em handle nat"); fix_nated_contact(); } } failure_route[missed_call] { # Chamada nao completada # verificamos se é um cancess e chamamos # a funcao responsavel por isso e entao # encerramos if (t_was_cancelled()) { exit; } }