知行合一
全部博文(31)
分类: 系统运维
2009-07-23 20:33:18
OpenSER的标准配置文件安装在/etc/openser/openser.cfg。它是OpenSER的最简单的配置文件之一。而且它还是一个可以开始进行解释OpenSER功能的理想脚本。和一些基本的模块,参数和函数一样,还有一些区段是你应该熟悉了解的。
这个章节结束后,你将能够:
l
识别出openser.cfg配置文件的各个区段
l
识别出标准配置的限制
l
使用ngrep工具跟踪SIP事务
l
使用XLOG模块记录路由过程
l
使用append_hf命令标记ngrep工具跟踪的包
标准配置是一个好的出发点。它拥有最小化的功能集合,不支持验证,所以你可以不使用密码就可以连接你的SIP话机。不管怎样,你都可以从一部话机呼向另一部,我们将在之后测试之。
我们要再一次提到的是,VoIP服务提供商的解决方案中有许多的部件。为了失去对整体的把握,我们会在大多数的章节中展示这幅图片。在这一章中,我们仍然会与标准配置的SIP代理部件打交道。
下面是OpenSER
#
# $Id: openser.cfg 1676 2007-02-21 13:16:34Z bogdan_iancu $
# If you set "calculate_ha1" parameter to yes (which true in this
config),
# uncomment also the following parameter)
#
}
exit;
}
这个标准的配置是最简单的可以使用的配置。我们将以它作为出发点,然后再在接下来的章节中循序渐进的包含新的命令和函数。使用这个配置,客户端能够进行注册(不需要认证)并且UACs能够互相之间进行沟通。注册服务器,定位服务器和代理服务器使用最小配置进行工作。下面我们将解释一些脚本中的引用。
debug=3 # debug level (cmd line: -dddddddddd)
设置日志级别(Set log level):它是一个-3到4之间的一个数。默认为2。数越大,那么写道日志中的信息就越多。不过如果将其设为4,那么系统的性能可能会变得很差。日志级别是:
l
L_ALERT(-3)——这个级别只被用来报告需要立即响应的错误。
l
L_CRIT(-2)——这个级别只被用来报告造成危险状况的错误。
l
L_ERR(-1)——这个级别用来报告数据处理过程中不会造成系统故障的错误。
l
L_WARN(1)——这个级别用来写入一些警告消息。
l
L_NOTICE(2)——这个级别用来报告不寻常的状况。
l
L_INFO(3)——这个解别用来写入一些提示信息的消息。
l
L_DBG(4)——这个级别用来写入用来调试的消息。
fork=yes
fork参数用来定义OpenSER进程是运行在前台还是后台。运行在后台则设置fork=yes。有时候你会发现如果在前台运行对于定位脚本错误是非常有用的。如果fork被禁用的话,OpenSER将不能够同时监听多个接口,TCP/TLS支持功能将被自动禁用。在单进程模式下,只有一个UDP接口被接受。
log_stderror=no # (cmd line: -E)
如果被设为yes,服务器将打印调试信息到标准错误输出。如果设为no,syslog会被使用。
Children=4
“children”核心参数告诉OpenSER每个创建处理接入请求的进程的接口有多少孩子进程。四个进程对于大多数系统来书都是很好的一个出发点。这个参数只适用于UDP接口,对于TCP没有影响。
Port=5060
如果在监听参数中没有被指明,那么这个参数就是默认使用的端口号。
mpath="/lib/openser/modules/"
设置模块搜索路径。这可以被用来简化模块的加载。
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"
上面的这些行是OpenSER加载外部的模块。这个时候,只有需要的那些模块被加载了。其余附加的功能需要加载其他诸如RADIUS和MYSQL的模块。所有这些模块都有一个README文件来描述其功能。
modparam("mi_fifo", "fifo_name",
"/tmp/openser_fifo")
创建FIFO文件及其名称用来监听和读取外部命令。
modparam("usrloc", "db_mode", 0)
modparam核心命令配置了相应的模块。上面的usrloc模块负责定位服务。当一个用户注册时,它用来保存定位信息,也就是我们知道的变量db_mode表明的相对于位置的AOR(Address
of Record)。为0表示是内存。所以如果你关闭了服务器,那么你将丢失所有的注册记录。表的位置靠的就是db_mode变量。将db_mode设置为0表明这个数据将被保存到数据库中。换句话说,如果OpenSER关闭,所有记录丢失。
modparam("rr", "enable_full_lr", 1)
上面的语句设置rr(Record
Routing)模块的enable_full_1r变量为1。它告诉OpenSER要支持那些不对record_route头域进行管理的SIP客户端。如果设为1,;lr=on将被使用而不是;lr。
Route {
这是SIP请求的路由逻辑的开始。“块(block)”起始于“{”。在这个块中,SIP请求将被处理。通过下面的语句你将看清大概:
# 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;
};
当一个请求进入主路由块时,要进行一些检查。
首先检查的是前转(forward)的最大次数。为了避免回环(loop),我们使用mf_process_maxfwd_header()函数来检查包到底传递了多少SIP跳(SIP
hops)。如果回环(loop)被发现,那么脚本则使用s1_send_reply()函数发送“483
too many hops”消息。
Msg:len是OpenSER核心用来返回SIP请求长度(单位byte)的函数。这是一个标准的用来检查消息大小限制方法。
if (!method=="REGISTER")
record_route();
如果不是REGISTER方法,OpenSER将进行record-route。这条消息告诉SIP服务器要处在两个UAC请求的路径当中。
record_route()函数只是简单的增加了一个新的record-route头域。
# Subsequent messages within 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);
};
loose_route()函数是用来试着看看请求有没有使用record-route头域进行路由的。这个函数标识的请求将使用最上面的record-route头域的内容进行路由。
如果请求是在同一个对话中,我们将进入if,并前转该包。我们只是简单的前转该请求。我们将调用次级路由块route(1)做这件事,在该块中t_relay()函数将被调用。
按照record-route头域(rr-enforced),append_hf函数将添加一个表明请求被处理的提示。
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(!uri==myself),使用调用t_relay的route(1)来前转该请求。 默认的情况下,代理只是一个开放式的中继器。在下面的章节中我们将讨论怎样改进带外通话(outbound call)的处理过程。将请求前转至其他的代理是很重要的;然而,还应该进行一些合适的标识检查。现在,我们将处理指向被我们的SIP代理处理的域的请求。
if (uri==myself) {
if (method=="REGISTER") {
# Uncomment this if you want to use digest
authentication
#if (!www_authorize("openser.org",
"subscriber")) {
# www_challenge("openser.org", "0");
# exit;
#};
save("location");
exit;
};
如果是REGISTER请求,使用save(“location”)将AOR保存至位置表(location table)中。理解两个概念至关重要。验证被取消(www_authorize被注释掉)和因为我们没有把数据库安装在SIP代理上,所以定位数据库不是持续起作用的。
lookup("aliases");
if (!uri==myself) {
append_hf("P-hint: outbound alias\r\n");
route(1);
};
别名(alias)是可选的URI(比如,8590@voffice.com.br可以是原有URI flavio@voffice.com.br的别名)。lookup(“aliases”)函数寻找在请求中表示的URI的典型的URI。如果该URI被找到,则在操作进行前用其取代R-URI。最终的URI既可以被放置在我们域的里面,也可以是外面。如果在外面,那么系统只是简单的将包前转到负责该域的SIP代理上。如果在外面则开始请求的处理。
if (!lookup("location")) {
sl_send_reply("404", "Not Found");
exit;
};
append_hf("P-hint: usrloc applied\r\n");
lookup(“location”)函数将试着恢复R-URI的AOR。如果AOR被定位到(UA注册了)那么UA的ip地址将替代R-URI。如果没有找到,我们只是简单的发回错误消息“404 Not Found”。
route(1);
如果找到AOR我们将使用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;
}
最后,路由块被调用。t_relay()函数前转基于请求URI的有状态的请求。域部分将使用NAPTR,SRV和A records等来进行解析。这个函数是由TRANSACTION模块(tm.so)提供的,负责发送请求并处理重发和响应。如果请求不能被成功的被发送到目的地,错误信息将由t_relay()函数自动产生。如果错误产生,s1_reply_error()将发送响应信息给UA。
在这个实验中,我们将使用协议分析机来抓取一个完整的SIP通话。我们将分析消息头和消息流程。你可以创建一个PC和带有两个UAC的实验环境。UAC可以是软电话,ATA,或是IP电话。
| 调整以满足你的实验需要。 |
| 1:使用ngrep开始抓取包。如果你没有安装ngrep, |
| 使用下面的命令安装: |
| apt-get
install ngrep |
| 2:使用下面命令抓取包: |
| ngrep
-p -q -W byline port 5060 > test.txt |
| 3:配置UAC(软电话,IP电话,或ATA)。 |
使用下面的描述来配置第一个UAC:
sip proxy 10.1.x.y – IP of your proxy
sip proxy 10.1.x.y – IP of your proxy
password: 1001
openserctl u1 show
more test.txt