知行合一
全部博文(31)
分类: 系统运维
2009-08-16 13:38:58
让我们使用LCR来执行一个简单的实验。对于这个实验,我们需要一个OpenSER服务器,两个网关和一个IP电话。你可以使用asterisk作为网关和虚拟机很容易的模拟这个实验环境。
步骤1:使用网关构建LAB。配置一台名为usa1的网关来接收以+1作为前缀的通话,另配置一台名为br1的网关来接收以+55作为前缀的通话。在网关中,你可以在将通话发送到PSTN之前添加前缀或删除一个数字。可以使用strip()和prefix()核心函数来加前缀和删除数字。要了解更多的细节,请登录。
步骤2:从。
cd /etc/openser
wget
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
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命令添加路由和网关
你可以使用SerMyAdmin来插入网关组。
步骤5:对任何以+1或+55开头的号码进行测试
步骤6:关闭网关br1,并在此测试+55的通话。通话此时应该走另一个可供选择的网关,因为现在的br1已经关闭了。
既然我们连上了PSTN,那么对于安全性的考虑就很重要了。Re-INVITES在松散路由区段中被处理。这些re-INVITES不会被要求他们的凭据。为了增强安全性,需要添加下面脚本的内容到你的loose_route区段中。如果是接续请求(has_totag()),需要其拥有ROUTE头。如果它没有该头(由函数loose_route()检查得到),我们将丢弃请求并给出错误“404,not 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;
}
DNS黑名单是用来进行DNS故障转移的特性。如果你发送一通通话给一个网关,并且这个网关不能被访问或是返回5××或6××错误码,OpenSER使用了一个叫做“dns blacklist”的资源,并将你的网关插入黑名单。在能够继续发送前,你的网关在此黑名单将持续4分钟(这个数字可以在编译时在blacklists.h中被修改)。当网关在黑名单中时,如果你试图继续向该网关发送通话,那么你将收到“473/Filtered Destination”消息。要关闭该特性(默认是打开的),可以使用下面的语句:
disable_dns_blacklist=yes
你也可以创建你自己的永久的网关黑名单或暂时的服务之外的名单。
在本章中,你已经学会如何配置OpenSER来将通话前转到网关。注意安全性是很重要的。使用permissions模块你能够允许网关避开摘要认证(digest authentication)并允许他们只验证IP地址。组模块对于控制由UAC到来的访问尤其重要。确认re-INVITES的凭据也是很有趣的工作。从你连上PSTN的那一刻起,就要特别注意通行欺骗(toll fraud)。我建议你找一个安全专家定期检查你的环境。还要经常的对你的通话记录进行分析以检查出不正常的通话活动。