Chinaunix首页 | 论坛 | 博客
  • 博客访问: 195973
  • 博文数量: 31
  • 博客积分: 2595
  • 博客等级: 少校
  • 技术积分: 334
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-28 16:03
个人简介

知行合一

文章分类

全部博文(31)

文章存档

2015年(1)

2014年(1)

2010年(9)

2009年(20)

我的朋友

分类: 系统运维

2009-07-23 20:33:18

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

第四章:OpenSER标准配置(OpenSER Standard Configuration

OpenSER的标准配置文件安装在/etc/openser/openser.cfg。它是OpenSER的最简单的配置文件之一。而且它还是一个可以开始进行解释OpenSER功能的理想脚本。和一些基本的模块,参数和函数一样,还有一些区段是你应该熟悉了解的。

这个章节结束后,你将能够:

l        识别出openser.cfg配置文件的各个区段

l        识别出标准配置的限制

l        使用ngrep工具跟踪SIP事务

l        使用XLOG模块记录路由过程

l        使用append_hf命令标记ngrep工具跟踪的包

标准配置是一个好的出发点。它拥有最小化的功能集合,不支持验证,所以你可以不使用密码就可以连接你的SIP话机。不管怎样,你都可以从一部话机呼向另一部,我们将在之后测试之。

我们在哪?(Where Are We?)

我们要再一次提到的是,VoIP服务提供商的解决方案中有许多的部件。为了失去对整体的把握,我们会在大多数的章节中展示这幅图片。在这一章中,我们仍然会与标准配置的SIP代理部件打交道。

分析标准配置(Analyzing the Standard Configuration

下面是OpenSER 1.2.2版本的标准配置的展示。在这一节,我们将开始描述标准配置中的每一行的命令和函数。

#

# $Id: openser.cfg 1676 2007-02-21 13:16:34Z bogdan_iancu $

 #

 #simple quick-start config script

 #Please refer to the Core CookBook at

 doku.php

 #for a explanation of possible statements, functions and parameters.

 #

 # ----------- global configuration parameters ------------------------

 debug=3            # debug level (cmd line: -dddddddddd)

 fork=yes

 log_stderror=no    # (cmd line: -E)

 children=4

 port=5060

 #uncomment the following lines for TLS support

 #disable_tls = 0

 #listen = tls:your_IP:5061

 #tls_verify_server = 1

 #tls_verify_client = 1

 #tls_require_client_certificate = 0

 #tls_method = TLSv1

 #tls_certificate = "//etc/openser/tls/user/user-cert.pem"

 #tls_private_key = "//etc/openser/tls/user/user-privkey.pem"

 #tls_ca_list = "//etc/openser/tls/user/user-calist.pem"

 # ------------------ 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

                            authentication

                          #if (!www_authorize("openser.org",

                                "subscriber")) {

                          #        www_challenge("openser.org", "0");

                          #        exit;

                          #};

                          save("location");

                          exit;

                 };

                 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;

}

这个标准的配置是最简单的可以使用的配置。我们将以它作为出发点,然后再在接下来的章节中循序渐进的包含新的命令和函数。使用这个配置,客户端能够进行注册(不需要认证)并且UACs能够互相之间进行沟通。注册服务器,定位服务器和代理服务器使用最小配置进行工作。下面我们将解释一些脚本中的引用。

debug=3 # debug level (cmd line: -dddddddddd)

设置日志级别(Set log level):它是一个-34之间的一个数。默认为2。数越大,那么写道日志中的信息就越多。不过如果将其设为4,那么系统的性能可能会变得很差。日志级别是:

l        L_ALERT-3——这个级别只被用来报告需要立即响应的错误。

l        L_CRIT-2——这个级别只被用来报告造成危险状况的错误。

l        L_ERR-1——这个级别用来报告数据处理过程中不会造成系统故障的错误。

l        L_WARN1——这个级别用来写入一些警告消息。

l        L_NOTICE2——这个级别用来报告不寻常的状况。

l        L_INFO3——这个解别用来写入一些提示信息的消息。

l        L_DBG4——这个级别用来写入用来调试的消息。

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加载外部的模块。这个时候,只有需要的那些模块被加载了。其余附加的功能需要加载其他诸如RADIUSMYSQL的模块。所有这些模块都有一个README文件来描述其功能。

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

创建FIFO文件及其名称用来监听和读取外部命令。

modparam("usrloc", "db_mode", 0)

modparam核心命令配置了相应的模块。上面的usrloc模块负责定位服务。当一个用户注册时,它用来保存定位信息,也就是我们知道的变量db_mode表明的相对于位置的AORAddress of Record)。为0表示是内存。所以如果你关闭了服务器,那么你将丢失所有的注册记录。表的位置靠的就是db_mode变量。将db_mode设置为0表明这个数据将被保存到数据库中。换句话说,如果OpenSER关闭,所有记录丢失。

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

上面的语句设置rrRecord 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:lenOpenSER核心用来返回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_relayroute(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被找到,则在操作进行前用其取代RURI。最终的URI既可以被放置在我们域的里面,也可以是外面。如果在外面,那么系统只是简单的将包前转到负责该域的SIP代理上。如果在外面则开始请求的处理。

if (!lookup("location")) {

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

        exit;

};

append_hf("P-hint: usrloc applied\r\n");

lookup(“location”)函数将试着恢复R-URIAOR。如果AOR被定位到(UA注册了)那么UAip地址将替代RURI。如果没有找到,我们只是简单的发回错误消息“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的有状态的请求。域部分将使用NAPTRSRVA records等来进行解析。这个函数是由TRANSACTION模块(tm.so)提供的,负责发送请求并处理重发和响应。如果请求不能被成功的被发送到目的地,错误信息将由t_relay()函数自动产生。如果错误产生,s1_reply_error()将发送响应信息给UA

Using标准配置(Using the Standard Configuration

在这个实验中,我们将使用协议分析机来抓取一个完整的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

 user: 1000

 password: 1000

 使用下面的描述来配置第二个UAC

sip proxy 10.1.x.y – IP of your proxy

 user: 1001

password: 1001

 在完成配置后,你需要注册IP话机。不是所有的设备都会做自动注册的操作。

  1. 使用下面的命令检查电话是否注册上:

                     openserctl u1 show

  1. 用第一个UAC拨打1001。第二个UAC会振铃。
  2. 验证抓取的包没有相对于INVITE请求的“407- Proxy authentication required”错误和相对于REGISTER请求的“401- Unauthorize”错误。这证明了不需要验证。
  3. 你可以使用如下命令查看抓包:

more test.txt

阅读(2484) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~