注:以下文章如需转载,请注明所属作者,转载地址,谢谢!
安装 MySQL支持
为了允许持续性,换句话说,为了能够将用户的证书保存在数据库中,也就是说,为了避免这些数据在断电和重启的情况下被毁,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;
}
Openser.cfg文件分析(openser.cfg File Analysis)
现在,配置已经做好准备来对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的参数相同。