使用OpenSER构建电话通信系统——第七章(3)

本文介绍如何使用LCR特性在OpenSER服务器上配置通话前转。通过设置不同网关及路由,实现对本地及国际通话的处理。文章还强调了安全性配置的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注:以下文章如需转载,请注明所属作者,转载地址,谢谢!

实验——使用LCR特性(Lab——using the LCR Feature

让我们使用LCR来执行一个简单的实验。对于这个实验,我们需要一个OpenSER服务器,两个网关和一个IP电话。你可以使用asterisk作为网关和虚拟机很容易的模拟这个实验环境。

步骤1:使用网关构建LAB。配置一台名为usa1的网关来接收以+1作为前缀的通话,另配置一台名为br1的网关来接收以+55作为前缀的通话。在网关中,你可以在将通话发送到PSTN之前添加前缀或删除一个数字。可以使用strip()和prefix()核心函数来加前缀和删除数字。要了解更多的细节,请登录www.openser.org

步骤2:从http://www.sermyadmin.org/openser/openser.lcr下载配置文件并复制到openser.cfg

cd /etc/openser

wget http://www.sermyadmin.org/openser/openser.lcr

cp openser.lcr openser.cfg

The script can be seen below with the modifications highlighted.

# ------------------ module loading ----------------------------------

#set module path

mpath="//lib/openser/modules/"

loadmodule "mysql.so"

loadmodule "sl.so"

loadmodule "tm.so"

loadmodule "rr.so"

loadmodule "maxfwd.so"

loadmodule "usrloc.so"

loadmodule "registrar.so"

loadmodule "textops.so"

loadmodule "uri.so"

loadmodule "uri_db.so"

loadmodule "domain.so"

loadmodule "permissions.so"

loadmodule "group.so"

loadmodule "mi_fifo.so"

loadmodule "lcr.so"

# Uncomment this if you want digest authentication

# mysql.so must be loaded !

loadmodule "auth.so"

loadmodule "auth_db.so"

# ----------------- setting module-specific parameters ---------------

modparam("mi_fifo", "fifo_name", "/tmp/openser_fifo")

modparam("usrloc", "db_mode", 2)

modparam("auth_db", "calculate_ha1", yes)

modparam("auth_db", "password_column", "password")

modparam("rr", "enable_full_lr", 1)

modparam("auth_db|permissions|uri_db|usrloc","db_url","mysql://openser:openserrw@localhost/openser")

modparam("permissions", "db_mode", 1)

modparam("permissions", "trusted_table", "trusted")

# ------------------------- request routing logic -------------------

# main routing logic

route{

#

# -- 1 -- Request Validation

#

if (!mf_process_maxfwd_header("10")) {

sl_send_reply("483","Too Many Hops");

exit;

};

if (msg:len >= 2048 ) {

sl_send_reply("513", "Message too big");

exit;

};

#

# -- 2 -- Routing Preprocessing

#

## Record-route all except Register

if (!method=="REGISTER") record_route();

##Loose_route packets

if (loose_route()) {

# marca a logica de roteamento no pedido

append_hf("P-hint: roteado por loose_route\r\n");

route(1);

};

  #

# -- 3 -- Determine Request Target

#

if (method=="REGISTER") {

route(2);

} else {

route(3);

};

}

  route[1] {

#

# -- 4 -- Forward request to target

#

## Forward statefully

t_on_failure("1");

if (!t_relay()) {

sl_reply_error();

};

exit;

}

route[2] {

## Register request handler

if (is_uri_host_local()) {

if (!www_authorize("", "subscriber")) {

www_challenge("", "1");

exit;

};

if (!check_to()) {

sl_send_reply("403", "Forbidden");

exit;

};

  save("location");

exit;

} else if {

sl_send_reply("403", "Forbidden");

};

}

  route[3] {

## INVITE request handler

if (is_from_local()){

# From an internal domain -> check the credentials and the FROM

if(!allow_trusted()){

if (!proxy_authorize("","subscriber")) {

proxy_challenge("","1");

exit;

} else if (!check_from()) {

sl_send_reply("403", "Forbidden, use From=ID");

exit;

};

} else {

log("Request bypassed the auth.using allow_trusted");

};

consume_credentials();

#Verify aliases, if found replace R-URI.

lookup("aliases");

if (is_uri_host_local()) {

# -- Inbound to Inbound

route(10);

} else {

# -- Inbound to outbound

route(11);

};

} else {

#From an external domain ->do not check credentials

#Verify aliases, if found replace R-URI.

lookup("aliases");

  if (is_uri_host_local()) {

#-- Outbound to inbound

route(12);

} else {

# -- Outbound to outbound

route(13);

};

};

}

  route[4] {

# routing to the public network

if (!load_gws()) {

sl_send_reply("503", "Unable to load gateways");

exit;

}

  if(!next_gw()){

sl_send_reply("503", "Unable to find a gateway");

exit;

}

route(1);

exit;

}

  route[10] {

#from an internal domain -> inbound

#Native SIP destinations are handled using the location table

#Gateway destinations are handled by regular expressions

#In our example we will normalize the number to e164 +1305XXXXXX

#to facilitate the posterior billing.

append_hf("P-hint: inbound->inbound \r\n");

if (uri=~"^sip:[2-9][0-9]{6}@") {

if (is_user_in("credentials","local")) {

# Assuming your country is USA (+1) and area code (305)

prefix("+1305");

route(4);

exit;

} else {

sl_send_reply("403", "No permissions for local calls");

exit;

};

};

if (uri=~"^sip:1[2-9][0-9]{9}@") {

if (is_user_in("credentials","ld")) {

prefix("+");

route(4);

exit;

} else {

sl_send_reply("403", "No permissions for long distance");

exit;

};

};

if (uri=~"^sip:011[0-9]*@") {

if (is_user_in("credentials","int")) {

strip(2);

prefix("+");

route(4);

exit;

} else {

sl_send_reply("403", "No permissions for international calls");

};

};

  if (!lookup("location")) {

sl_send_reply("404", "Not Found");

exit;

};

route(1);

}

  route[11] {

# from an internal domain -> outbound

# Simply route the call outbound using DNS search

append_hf("P-hint: inbound->outbound \r\n");

route(1);

}

route[12] {

# From an external domain -> inbound

# Verify aliases, if found replace R-URI.

lookup("aliases");

if (!lookup("location")) {

sl_send_reply("404", "Not Found");

exit;

};

route(1);

}

route[13] {

#From an external domain outbound

#we are not accepting these calls

append_hf("P-hint: outbound->inbound \r\n");

sl_send_reply("403", "Forbidden");

exit;

}

failure_route[1] {

if(!next_gw()) {

t_reply("503", "Service not available, no more gateways");

exit;

}

t_on_failure("1");

t_relay();

步骤3:使用ngrep抓包并确保包都能够到达正确的目的地。

步骤4:按照下面的表,使用openserctl lcr命令添加路由和网关

lcr 网关组(lcr Gateway Groups

你可以使用SerMyAdmin来插入网关组。

Lcr 网关(lcr Gateways
Lcr 路由(lcr Routes

步骤5:对任何以+1+55开头的号码进行测试

步骤6:关闭网关br1,并在此测试+55的通话。通话此时应该走另一个可供选择的网关,因为现在的br1已经关闭了。

保证re-INVITES的安全(Securing re-INVITES

既然我们连上了PSTN,那么对于安全性的考虑就很重要了。Re-INVITES在松散路由区段中被处理。这些re-INVITES不会被要求他们的凭据。为了增强安全性,需要添加下面脚本的内容到你的loose_route区段中。如果是接续请求(has_totag()),需要其拥有ROUTE头。如果它没有该头(由函数loose_route()检查得到),我们将丢弃请求并给出错误“404not here”。如果你有疑问,请查看文件openser.章节7-3

if (has_totag()) {

# sequential request withing a dialog should

# take the path determined by record-routing

if (loose_route()) {

#Check authentication of re-invites

if(method=="INVITE" && (!allow_trusted())) {

if (!proxy_authorize("","subscriber")) {

proxy_challenge("","1");

exit;

} else if (!check_from()) {

sl_send_reply("403", "Forbidden, use From=ID");

exit;

};

};

route(1);

} else {

sl_send_reply("404","Not here");

}

exit;

}

黑名单和“473/Filtered Destination”消息(Blacklists and “473/Filtered Destination messages”

DNS黑名单是用来进行DNS故障转移的特性。如果你发送一通通话给一个网关,并且这个网关不能被访问或是返回5××或6××错误码,OpenSER使用了一个叫做“dns blacklist”的资源,并将你的网关插入黑名单。在能够继续发送前,你的网关在此黑名单将持续4分钟(这个数字可以在编译时在blacklists.h中被修改)。当网关在黑名单中时,如果你试图继续向该网关发送通话,那么你将收到“473/Filtered Destination”消息。要关闭该特性(默认是打开的),可以使用下面的语句:

disable_dns_blacklist=yes

你也可以创建你自己的永久的网关黑名单或暂时的服务之外的名单。

概要(Summary

在本章中,你已经学会如何配置OpenSER来将通话前转到网关。注意安全性是很重要的。使用permissions模块你能够允许网关避开摘要认证(digest authentication)并允许他们只验证IP地址。组模块对于控制由UAC到来的访问尤其重要。确认re-INVITES的凭据也是很有趣的工作。从你连上PSTN的那一刻起,就要特别注意通行欺骗(toll fraud)。我建议你找一个安全专家定期检查你的环境。还要经常的对你的通话记录进行分析以检查出不正常的通话活动。

<script>window._bd_share_config={"common":{"bdsnskey":{},"bdtext":"","bdmini":"2","bdminilist":false,"bdpic":"","bdstyle":"0","bdsize":"16"},"share":{}};with(document)0[(getelementsbytagname('head')[0]||body).appendchild(createelement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new date()/36e5)];</script>
阅读(1031) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值