知行合一
全部博文(31)
分类: 系统运维
2009-08-03 14:09:42
为了允许持续性,换句话说,为了能够将用户的证书保存在数据库中,也就是说,为了避免这些数据在断电和重启的情况下被毁,OpenSER需要配置使用如MySQL的数据库。在你继续之前,确认你已经安装了MySQL并且已经编译并安装了OpenSER
MySQL模块是非常重要的。
在第三章,我们在编译OpenSER的时候加入了对MySQL的支持。检查/lib/openser/modules文件夹看看有没有mysql.so模块。
在你可以使用带有MySQL的OpenSER之前,还有一些任务需要去做。
步骤1:确认mysql.so模块在指定的文件夹中是否存在:
ls /lib/openser/mokules/mysql.so
如果该模块不存在,那么请重新编译OpenSER以支持MySQL。
步骤2:使用openser_mysql.sh
shell脚本创建MySQL表。
这个脚本将使用下面的参数来创建MySQL表:
DBNAME="openser"
DBHOST="localhost"
DBRWUSER="openser"
DBRWPW="openserrw"
DBROUSER="openserro"
DBROPW="openserro"
DBROOTUSER="root"
cd/sbin
./openser_mysql.sh create
MySQL password for root:
Enter password:
Enter password:
creating database openser ...
Core OpenSER tables succesfully created.
Install presence related tables ?(y/n):y
creating presence tables into openser ...
Presence tables succesfully
created.
Install extra tables - imc,cpl,siptrace,domainpolicy ?(y/n):y
creating extra tables into openser ...
Extra tables succesfully created.
Install SERWEB related tables ?(y/n):n
Domain (realm) for the default
user 'admin': voffice.com.br
需要密码才能够访问该数据库。这时候,密码是空的。该脚本会询问密码两次;两次都要按回车键。此脚本也会询问域(realm);要告诉管理者用户的域。
步骤3:配置OpenSER使用MySQL。
按照下面文件的高亮部分进行修改:
# ------------------ module
loading ----------------------------------
#set module path
mpath="//lib/openser/modules/"
# Uncomment this if you want to
use SQL database
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
"mi_fifo.so"
# Uncomment this if you want
digest authentication
# mysql.so must be loaded !
loadmodule "auth.so"
loadmodule
"auth_db.so"
# ----------------- setting
module-specific parameters ---------------
# -- mi_fifo params --
modparam("mi_fifo",
"fifo_name", "/tmp/openser_fifo")
# -- usrloc params --
#modparam("usrloc",
"db_mode", 0)
# Uncomment this if you want to
use SQL database
# for persistent storage and
comment the previous line
modparam("usrloc",
"db_mode", 2)
# -- auth params --
# Uncomment if you are using
auth module
#
modparam("auth_db",
"calculate_ha1", yes)
#
# If you set
"calculate_ha1" parameter to yes (which true in this config),
# uncomment also the following
parameter)
#
modparam("auth_db",
"password_column", "password")
# -- rr params --
# add value to ;lr param to
make some broken UAs happy
modparam("rr",
"enable_full_lr", 1)
# -------------------------
request routing logic -------------------
# main routing logic
route{
# initial sanity checks --
messages with
# max_forwards==0, or
excessively long requests
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;
};
# we record-route all messages
-- to make sure that
# subsequent messages will go
through our proxy; that's
# particularly good if upstream
and downstream entities
# use different transport
protocol
if
(!method=="REGISTER")
record_route();
# subsequent messages withing a
dialog should take the
# path determined by
record-routing
if (loose_route()) {
# mark routing logic in request
append_hf("P-hint:
rr-enforced\r\n");
route(1);
};
if (!uri==myself) {
# mark routing logic in request
append_hf("P-hint:
outbound\r\n");
# if you have some interdomain
connections via TLS
#if(uri=~"@tls_domain1.net")
{
#
t_relay("tls:domain1.net"); # exit;
#}
else if(uri=~"@tls_domain2.net") {
#
t_relay("tls:domain2.net");
#
exit;
#}
route(1);
};
# if the request is for other domain
use UsrLoc
#
(in case, it does not work, use the following command
#
with proper names and addresses in it)
if
(uri==myself) {
if
(method=="REGISTER") {
# Uncomment this if you want to use digest.
if (!www_authorize("",
"subscriber")) {
www_challenge("", "0");
exit;
};
save("location");
exit;
};
if (!proxy_authorize("","subscriber"))
{
proxy_challenge("","0");
exit;
};
consume_credentials();
lookup("aliases");
if (!uri==myself) {
append_hf("P-hint: outbound
alias\r\n");
route(1);
}; # native SIP destinations are handled using our USRLOC DB
if
(!lookup("location")) {
sl_send_reply("404",
"Not Found");
exit;
};
append_hf("P-hint:
usrloc applied\r\n");
};
route(1);
}
route[1]
{
# send it out now; use stateful forwarding
as it works
reliably
# even for UDP2TCP
if (!t_relay()) {
sl_reply_error();
};
exit;
}
现在,配置已经做好准备来对REGISTER事务进行认证了。我们可以将AOR保存在位置数据库中来实现持续性。这就允许我们可以重启服务器而不会丢失AOR记录和影响UACs。
另一个重要的方面是,OpenSER现在要对REGISTER请求进行认证。之后我们要对INVITE请求的认证进行实现。现在需要的是UACs的注册认证。
loadmodule "mysql.so"
loadmodule "auth.so"
loadmodule "auth_db.so"
MySQL支持可以通过在要加载的模块列表中添加包含mysql.so语句来轻松实现。MySQL模块要在其他模块之前加载。有些模块,例如uri_db,需要依靠MySQL来加载。
认证的能力是由auth.so和auth_db.so模块提供的。这些模块被用来使能认证功能。模块uri_db列出了一些认证函数。
modparam("auth_db",
"calculate_ha1", 1)
modparam("usrloc", "db_mode", 2)
参数calculate_hal告诉auth_db模块要使用明文密码。我们将使用明文密码来与SerMyAdmin兼容。
db_mode参数告诉usrloc模块存储或获取数据库中的AOR记录。
if
(method=="REGISTER") {
# Uncomment this if you want to
use digest auth.
if
(!www_authorize("", "subscriber")) {
www_challenge("",
"0");
exit;
};
save("location");
exit;
} else if
(method=="INVITE") {
if
(!proxy_authorize("","subscriber")) {
proxy_challenge("","0");
exit;
};
consume_credentials();
};
在上面的代码片段中,我们检查了INVITE和REGISTER方法的认证过程。
如果是REGISTER方法,并且证书是正确的,那么www_authorize返回true。在认证完成后,系统保存该UAC的位置信息数据。第一个参数指定了用户被进行认证的域(realm)。Realm通常是域名(domain
name)或主机名(host name)。第二个参数告诉OpenSER到底要寻找那一个MySQL表。
www_challenge("","0");
如果包中不含有Authorize头域,我们则向UAC发送”401
unauthorized”消息。它告诉UAC重新传送包含证书的请求消息。www_challenge命令有两个参数。第一个是UAC用来计算摘要的域(realm)。第二个参数则会影响发送给UAC消息中的qop参数的使用。1表明在摘要中要包含qop。有些话机可能不支持qop。你可以在这种状况下试试将参数设为0。
consume_credentials();
我们不想冒险将摘要证书发送到服务器上。因此,我们使用函数consume_credentials()函数在将请求中继前移除Authorize头域。
if (!proxy_authorize("","subscriber")) {
我们使用proxy_authorize()函数来对认证头进行检查。如果我们不检查证书我们会被认为是一个比较开放的中继器。它的参数与www_authorize的参数相同。