设为首页 收藏本站
开启辅助访问 切换到宽版
注册会员 找回密码

VoIP88

toasterisk 发表于 2011-12-28 15:01 | 显示全部楼层 |阅读模式

这个文档是根据kamailio 官方网站的文档汇总而成。我的观点是:kamailio 不是asterisk, asterisk 也不是kamailio。
kamailio 主要负责以下任务:
1) 用户注册,使用mysql 强大的数据库。
2) 认证,如果验证是asterisk 用户,两者可以通信。
3) 路由,重定向的功能,kamailio 可以管理几个asterisk, 通过loadblance 自动路由,重定向。
asterisk 主要负责的任务:
1) IVR 功能,asterisk 可以支持很多灵活的IVR 功能,所以asterisk 实现IVR.
2)  asterisk 媒体处理, asterisk 可以支持很多种语音编码(少量通道),711, 723, G729, 所以让asterisk 负责执行处理,
3)语音邮箱, asterisk 的语音邮箱方便简单,用户可以在asterisk 实现。
4) 当然asterisk 还可以拓展出很多应用,这里不多说。
5)   支持asterisk 语音板卡或者网关。
6) asterisk 媒体服务器处理:支持编码转换,sangoma 编码转换卡可以满足用户需求。
7) 大型呼叫中心应用。

注册服务:Kamailio 负责认证,如果通过,kamailio 发一个提醒消息给asterisk, asterisk 检查分机是否在线。
发起呼叫:如果一个认证的呼叫进入到Kamailio,kamailio 将转到asterisk, asterisk 检查分局是否在线,如果在线,将发回复呼叫信息,kamailio 再次限制呼叫分机,重定向.


环境要求:
Linux OS (this tutorial is applied on Ubuntu 10.04), 本人使用centos, 但是很多用户使用debain 设置,文档资料也多。
Kamailio 3.1.x - http://www.kamailio.org
Asterisk 1.6.2.x - http://www.asterisk.org
UnixODBC - http://www.unixodbc.org
MySQL Server and Client (recommended 5.1+, min 5.0) - http://www.mysql.com
MySQL client library
ODBC MySQL connector
-
安装 mySQL, 如果centos 使用 yum 安装
apt-get install mysql-serverFor a more detailed tutorial about MySQL installation on Ubuntu 10.04, see:
To install MySQL client library do:

apt-get install libmysqlclient-dev
Install UnixODBCTo install the UnixODBC devel libraries, run:

apt-get install unixodbc-devIf your operating system does not provide a package for it, download the sources from http://www.unixodbc.org/, compile and install. Then tune the Asterisk compilation system if the unixodbc is not detected automatically.
To install the ODBC MySQL connector, run:

apt-get install libmyodbc
下载安装asterisk 平台

cd /usr/local/src
wget http://downloads.asterisk.org/pu ... isk-1.6.2.13.tar.gz
tar xvfz asterisk-1.6.2.13.tar.gz
cd asterisk-1.6.2.13
./configure
make menuselect   //  选择 voicemail 选项和 ODBC 选项,支持mysql 数据库,保存。
// 这些编译,安装命令:

make
make install


Kamailio 安装:// 源代码安装,git 貌似比较流行

cd /usr/local/src
wget http://www.kamailio.org/pub/kama ... io-3.1.0_src.tar.gz
tar xvfz kamailio-3.1.0_src.tar.gz
cd kamailio-3.1.0
make include_modules="db_mysql" cfg
make all
make install
Kamailio 数据库安装
注意:如果kamailio 成功安装以后,系统将带有一个工具 kamdbctl. 这一步希望用户留意:
/usr/local/sbin/kamdbctl create   //  特别留意。

Asterisk 数据库安装,使用sql client 客户端执行 SQL script 脚本:

CREATE DATABASE asterisk;

USE asterisk;

GRANT ALL ON asterisk.* TO asterisk@localhost IDENTIFIED BY 'asterisk_password';

CREATE TABLE `sipusers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(80) NOT NULL DEFAULT '',
`host` varchar(31) NOT NULL DEFAULT '',
`nat` varchar(5) NOT NULL DEFAULT 'no',
`type` enum('user','peer','friend') NOT NULL DEFAULT 'friend',
`accountcode` varchar(20) DEFAULT NULL,
`amaflags` varchar(13) DEFAULT NULL,
`call-limit` smallint(5) UNSIGNED DEFAULT NULL,
`callgroup` varchar(10) DEFAULT NULL,
`callerid` varchar(80) DEFAULT NULL,
`cancallforward` char(3) DEFAULT 'yes',
`canreinvite` char(3) DEFAULT 'yes',
`context` varchar(80) DEFAULT NULL,
`defaultip` varchar(15) DEFAULT NULL,
`dtmfmode` varchar(7) DEFAULT NULL,
`fromuser` varchar(80) DEFAULT NULL,
`fromdomain` varchar(80) DEFAULT NULL,
`insecure` varchar(4) DEFAULT NULL,
`language` char(2) DEFAULT NULL,
`mailbox` varchar(50) DEFAULT NULL,
`md5secret` varchar(80) DEFAULT NULL,
`deny` varchar(95) DEFAULT NULL,
`permit` varchar(95) DEFAULT NULL,
`mask` varchar(95) DEFAULT NULL,
`musiconhold` varchar(100) DEFAULT NULL,
`pickupgroup` varchar(10) DEFAULT NULL,
`qualify` char(3) DEFAULT NULL,
`regexten` varchar(80) DEFAULT NULL,
`restrictcid` char(3) DEFAULT NULL,
`rtptimeout` char(3) DEFAULT NULL,
`rtpholdtimeout` char(3) DEFAULT NULL,
`secret` varchar(80) DEFAULT NULL,
`setvar` varchar(100) DEFAULT NULL,
`disallow` varchar(100) DEFAULT NULL,
`allow` varchar(100) DEFAULT NULL,
`fullcontact` varchar(80) NOT NULL DEFAULT '',
`ipaddr` varchar(15) NOT NULL DEFAULT '',
`port` mediumint(5) UNSIGNED NOT NULL DEFAULT '0',
`regserver` varchar(100) DEFAULT NULL,
`regseconds` int(11) NOT NULL DEFAULT '0',
`lastms` int(11) NOT NULL DEFAULT '0',
`username` varchar(80) NOT NULL DEFAULT '',
`defaultuser` varchar(80) NOT NULL DEFAULT '',
`subscribecontext` varchar(80) DEFAULT NULL,
`useragent` varchar(20) DEFAULT NULL,
`sippasswd` varchar(80) DEFAULT NULL,
PRIMARY KEY  (`id`),
UNIQUE KEY `name_uk` (`name`)
);

CREATE TABLE `sipregs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(80) NOT NULL DEFAULT '',
`fullcontact` varchar(80) NOT NULL DEFAULT '',
`ipaddr` varchar(15) NOT NULL DEFAULT '',
`port` mediumint(5) UNSIGNED NOT NULL DEFAULT '0',
`username` varchar(80) NOT NULL DEFAULT '',
`regserver` varchar(100) DEFAULT NULL,
`regseconds` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY  (`id`),
UNIQUE KEY `name` (`name`)
);

CREATE TABLE IF NOT EXISTS `voiceboxes` (
`uniqueid` int(4) NOT NULL AUTO_INCREMENT,
`customer_id` varchar(10) DEFAULT NULL,
`context` varchar(10) NOT NULL,
`mailbox` varchar(10) NOT NULL,
`password` varchar(12) NOT NULL,
`fullname` varchar(150) DEFAULT NULL,
`email` varchar(50) DEFAULT NULL,
`pager` varchar(50) DEFAULT NULL,
`tz` varchar(10) DEFAULT 'central',
`attach` enum('yes','no') NOT NULL DEFAULT 'yes',
`saycid` enum('yes','no') NOT NULL DEFAULT 'yes',
`dialout` varchar(10) DEFAULT NULL,
`callback` varchar(10) DEFAULT NULL,
`review` enum('yes','no') NOT NULL DEFAULT 'no',
`operator` enum('yes','no') NOT NULL DEFAULT 'no',
`envelope` enum('yes','no') NOT NULL DEFAULT 'no',
`sayduration` enum('yes','no') NOT NULL DEFAULT 'no',
`saydurationm` tinyint(4) NOT NULL DEFAULT '1',
`sendvoicemail` enum('yes','no') NOT NULL DEFAULT 'no',
`delete` enum('yes','no') NULL DEFAULT 'no',
`nextaftercmd` enum('yes','no') NOT NULL DEFAULT 'yes',
`forcename` enum('yes','no') NOT NULL DEFAULT 'no',
`forcegreetings` enum('yes','no') NOT NULL DEFAULT 'no',
`hidefromdir` enum('yes','no') NOT NULL DEFAULT 'yes',
`stamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY  (`uniqueid`),
KEY `mailbox_context` (`mailbox`,`context`)
);

CREATE TABLE `voicemessages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`msgnum` int(11) NOT NULL DEFAULT '0',
`dir` varchar(80) DEFAULT '',
`context` varchar(80) DEFAULT '',
`macrocontext` varchar(80) DEFAULT '',
`callerid` varchar(40) DEFAULT '',
`origtime` varchar(40) DEFAULT '',
`duration` varchar(20) DEFAULT '',
`mailboxuser` varchar(80) DEFAULT '',
`mailboxcontext` varchar(80) DEFAULT '',
`recording` longblob,
`flag` varchar(128) DEFAULT '',
PRIMARY KEY  (`id`),
KEY `dir` (`dir`)
);


CREATE TABLE version (
    table_name VARCHAR(32) NOT NULL,
    table_version INT UNSIGNED DEFAULT 0 NOT NULL
);
INSERT INTO version (table_name, table_version) VALUES ('sipusers','6');If you save it to asterisk.sql, then you can load it to MySQL server with:

mysql -u root -p <asterisk.sqlBefore executing the SQL script, be sure you change the password for MySQL asterisk user, in line:

GRANT ALL ON asterisk.* to asterisk@localhost IDENTIFIED BY 'asterisk_password';
sipusers is the standard table required by Asterisk to store SIP user profile, with one extra column sippasswd where will be stored the password for SIP authentication. By default, Asterisk uses the column secret for SIP user password, but if that is filled in, Asterisk will ask for authentication again, resulting in double-authentication which we want to avoid.
sipregs is used to store SIP registrations. Registrations can be stored in sipusers tables as well, in case you do not want a separate table. Just omit the appropriate entry in /etc/asterisk/extconfig.conf.
voiceboxes is used to store voicemail box profiles and has the standard structure required by Asterisk. Storing voice box profiles in database allows to run several instances of Asterisk that can be load balanced or used in fail-over mode to store or listen to voice messages.
voicemessages is used to store voice messages and has the standard structure required by Asterisk. Storing voice messages in database allows to run several instances of Asterisk that can be load balanced or used in fail-over mode to store or listen to voice messages.
version is a table used by Kamailio to check database structure version. You can just forget about it once you create it.

UnixODBC 配置: 编辑 /etc/odbcinst.ini 增加:

[MySQL]
Description = MySQL driver
Driver = /usr/lib/odbc/libmyodbc.so
Setup = /usr/lib/odbc/libodbcmyS.so
CPTimeout =
CPReuse =
UsageCount = 1

编辑 /etc/odbc.ini 增加:

MySQL-asterisk]
Description = MySQL Asterisk database
Trace = Off
TraceFile = stderr
Driver = MySQL
SERVER = localhost
USER = asterisk
PASSWORD = asterisk_password
PORT = 3306
DATABASE = asterisk

Asterisk UnixODBC 配置文件: /etc/asterisk/res_odbc.conf, 设置:

[asterisk]
enabled => yes
dsn => MySQL-asterisk
username => asterisk
password => asterisk_password
pre-connect => yes

编辑拨号规则 /etc/asterisk/extconfig.conf ,设置:

sipusers => odbc,asterisk,sipusers
sippeers => odbc,asterisk,sipusers
sipregs => odbc,asterisk,sipregs
voicemail => odbc,asterisk,voiceboxes
Asterisk 配置,修改SIP 用户配置 /etc/asterisk/sip.conf

rtcachefriends=yes
修改拨号规则文件,绑定kamailio 端口,IP


拨号规则测试: /etc/asterisk/extensions.conf:

; 分机号码是3位数,1XX 格式
exten => _1XX,1,Dial(SIP/${EXTEN})
exten => _1XX,n,Voicemail(${EXTEN},u)
exten => _1XX,n,Hangup
exten => _1XX,101,Voicemail(${EXTEN},b)
exten => _1XX,102,HangupIt does the classic behaviour:

数据库添加分机101, 102 and 103:

INSERT INTO sipusers (name, username, host, sippasswd, fromuser, fromdomain, mailbox)
  VALUES ('101', '101', 'dynamic', '101', '101', 'yoursip.com', '101');
INSERT INTO sipusers (name, username, host, sippasswd, fromuser, fromdomain, mailbox)
  VALUES ('102', '102', 'dynamic', '102', '102', 'yoursip.com', '102');
INSERT INTO sipusers (name, username, host, sippasswd, fromuser, fromdomain, mailbox)
  VALUES ('103', '103', 'dynamic', '103', '103', 'yoursip.com', '103');

INSERT INTO sipregs(name) VALUES('101');
INSERT INTO sipregs(name) VALUES('102');
INSERT INTO sipregs(name) VALUES('103');

INSERT INTO voiceboxes(customer_id, context, mailbox, password) VALUES ('101', 'default', '101', '1234');
INSERT INTO voiceboxes(customer_id, context, mailbox, password) VALUES ('101', 'default', '102', '1234');
INSERT INTO voiceboxes(customer_id, context, mailbox, password) VALUES ('101', 'default', '103', '1234');
In case you use sipregs you have to create a record for each extension where to set the 'name' to value of 'name' from sipusers. The rest is populated by Asterisk from registrations.

确认,asterisk 端对于 来自kamailio 的SIP 请求不需要认证.

Kamailio 配置

修改kamailio 配置文件,添加 #!define WITH_ASTERISK (i.e., the parts within #!ifdef WITH_ASTERISK … #!endif.

#!define WITH_ASTERISK
#!KAMAILIO

#!define WITH_MYSQL
#!define WITH_AUTH
#!define WITH_USRLOCDB
#!define WITH_ASTERISK

#
# Kamailio (OpenSER) SIP Server v3.1 - default configuration script
#     - web: http://www.kamailio.org
#     - git: http://sip-router.org
#
# Direct your questions about this file to: <sr-users@lists.sip-router.org>
#
# Refer to the Core CookBook at http://www.kamailio.org/dokuwiki/doku.php
# for an explanation of possible statements, functions and parameters.
#
# Several features can be enabled using '#!define WITH_FEATURE' directives:
#
# *** To run in debug mode:
#     - define WITH_DEBUG
#
# *** To enable mysql:
#     - define WITH_MYSQL
#
# *** To enable authentication execute:
#     - enable mysql
#     - define WITH_AUTH
#     - add users using 'kamctl'
#
# *** To enable IP authentication execute:
#     - enable mysql
#     - enable authentication
#     - define WITH_IPAUTH
#     - add IP addresses with group id '1' to 'address' table
#
# *** To enable persistent user location execute:
#     - enable mysql
#     - define WITH_USRLOCDB
#
# *** To enable presence server execute:
#     - enable mysql
#     - define WITH_PRESENCE
#
# *** To enable nat traversal execute:
#     - define WITH_NAT
#     - install RTPProxy: http://www.rtpproxy.org
#     - start RTPProxy:
#        rtpproxy -l _your_public_ip_ -s udp:localhost:7722
#
# *** To enable PSTN gateway routing execute:
#     - define WITH_PSTN
#     - set the value of pstn.gw_ip
#     - check route[PSTN] for regexp routing condition
#
# *** To enable database aliases lookup execute:
#     - enable mysql
#     - define WITH_ALIASDB
#
# *** To enable multi-domain support execute:
#     - enable mysql
#     - define WITH_MULTIDOMAIN
#
# *** To enable TLS support execute:
#     - adjust CFGDIR/tls.cfg as needed
#     - define WITH_TLS
#
# *** To enable XMLRPC support execute:
#     - define WITH_XMLRPC
#     - adjust route[XMLRPC] for access policy
#
# *** To enable anti-flood detection execute:
#     - adjust pike and htable=>ipban settings as needed (default is
#       block if more than 16 requests in 2 seconds and ban for 300 seconds)
#     - define WITH_ANTIFLOOD
#
# *** To enhance accounting execute:
#     - enable mysql
#     - define WITH_ACCDB
#     - add following columns to database
#!ifdef ACCDB_COMMENT
  ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';
  ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';
  ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';
  ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';
  ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';
  ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';
  ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';
  ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';
  ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';
  ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';
#!endif

####### Defined Values #########

# *** Value defines - IDs used later in config
#!ifdef WITH_MYSQL
# - database URL - used to connect to database server by modules such
#       as: auth_db, acc, usrloc, a.s.o.
#!define DBURL "mysql://openserpenserrw@localhost/openser"
#!define DBASTURL "mysql://asterisk:asterisk_password@localhost/asterisk"
#!endif

#!ifdef WITH_MULTIDOMAIN
# - the value for 'use_domain' parameters
#!define MULTIDOMAIN 1
#!else
#!define MULTIDOMAIN 0
#!endif

# - flags
#   FLT_ - per transaction (message) flags
#        FLB_ - per branch flags
#!define FLT_ACC 1
#!define FLT_ACCMISSED 2
#!define FLT_ACCFAILED 3
#!define FLT_NATS 5

#!define FLB_NATB 6
#!define FLB_NATSIPPING 7

####### Global Parameters #########

#!ifdef WITH_DEBUG
debug=4
log_stderror=yes
#!else
debug=2
log_stderror=no
#!endif

memdbg=5
memlog=5

log_facility=LOG_LOCAL0

fork=yes
children=4

/* uncomment the next line to disable TCP (default on) */
#disable_tcp=yes

/* uncomment the next line to disable the auto discovery of local aliases
   based on reverse DNS on IPs (default on) */
#auto_aliases=no

/* add local domain aliases */
#alias="sip.mydomain.com"

/* uncomment and configure the following line if you want Kamailio to
   bind on a specific interface/port/proto (default bind on all available) */
#listen=udp:10.0.0.10:5060
listen=192.168.178.23

/* port to listen to
* - can be specified more than once if needed to listen on many ports */
port=5060

#!ifdef WITH_TLS
enable_tls=yes
#!endif

####### Custom Parameters #########

# These parameters can be modified runtime via RPC interface
# - see the documentation of 'cfg_rpc' module.
#
# Format: group.id = value 'desc' description
# Access: $sel(cfg_get.group.id) or @cfg_get.group.id
#

#!ifdef WITH_PSTN
# PSTN GW Routing
#
# - pstn.gw_ip: valid IP or hostname as string value, example:
# pstn.gw_ip = "10.0.0.101" desc "My PSTN GW Address"
#
# - by default is empty to avoid misrouting
pstn.gw_ip = "" desc "STN GW Address"
#!endif

#!ifdef WITH_ASTERISK   // 注意asterisk 设置部分,必须和asterisk 服务器信息对应
asterisk.bindip = "192.168.178.23" desc "Asterisk IP Address"
asterisk.bindport = "5080" desc "Asterisk Port"
kamailio.bindip = "192.168.178.23" desc "Kamailio IP Address"
kamailio.bindport = "5060" desc "Kamailio Port"
#!endif

####### Modules Section ########

# set paths to location of modules
#!ifdef LOCAL_TEST_RUN
mpath="modules_k:modules"
#!else
mpath="/usr/local/lib/kamailio/modules_k/:/usr/local/lib/kamailio/modules/"
#!endif

#!ifdef WITH_MYSQL
loadmodule "db_mysql.so"
#!endif

loadmodule "mi_fifo.so"
loadmodule "kex.so"
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "mi_rpc.so"
loadmodule "acc.so"

#!ifdef WITH_AUTH
loadmodule "auth.so"
loadmodule "auth_db.so"
#!ifdef WITH_IPAUTH
loadmodule "permissions.so"
#!endif
#!endif

#!ifdef WITH_ALIASDB
loadmodule "alias_db.so"
#!endif

#!ifdef WITH_MULTIDOMAIN
loadmodule "domain.so"
#!endif

#!ifdef WITH_PRESENCE
loadmodule "presence.so"
loadmodule "presence_xml.so"
#!endif

#!ifdef WITH_NAT
loadmodule "nathelper.so"
loadmodule "rtpproxy.so"
#!endif

#!ifdef WITH_TLS
loadmodule "tls.so"
#!endif

#!ifdef WITH_ANTIFLOOD
loadmodule "htable.so"
loadmodule "pike.so"
#!endif

#!ifdef WITH_XMLRPC
loadmodule "xmlrpc.so"
#!endif

#!ifdef WITH_ASTERISK
loadmodule "uac.so"
#!endif

# ----------------- setting module-specific parameters ---------------


# ----- mi_fifo params -----
modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")


# ----- tm params -----
# auto-discard branches from previous serial forking leg
modparam("tm", "failure_reply_mode", 3)
# default retransmission timeout: 30sec
modparam("tm", "fr_timer", 30000)
# default invite retransmission timeout after 1xx: 120sec
modparam("tm", "fr_inv_timer", 120000)


# ----- rr params -----
# add value to ;lr param to cope with most of the UAs
modparam("rr", "enable_full_lr", 1)
# do not append from tag to the RR (no need for this script)
#!ifdef WITH_ASTERISK
modparam("rr", "append_fromtag", 1)
#!else
modparam("rr", "append_fromtag", 0)
#!endif

# ----- registrar params -----
modparam("registrar", "method_filtering", 1)
/* uncomment the next line to disable parallel forking via location */
# modparam("registrar", "append_branches", 0)
/* uncomment the next line not to allow more than 10 contacts per AOR */
#modparam("registrar", "max_contacts", 10)


# ----- acc params -----
/* what special events should be accounted ? */
modparam("acc", "early_media", 0)
modparam("acc", "report_ack", 0)
modparam("acc", "report_cancels", 0)
/* by default ww do not adjust the direct of the sequential requests.
   if you enable this parameter, be sure the enable "append_fromtag"
   in "rr" module */
modparam("acc", "detect_direction", 0)
/* account triggers (flags) */
modparam("acc", "log_flag", FLT_ACC)
modparam("acc", "log_missed_flag", FLT_ACCMISSED)
modparam("acc", "log_extra",
        "src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
modparam("acc", "failed_transaction_flag", FLT_ACCFAILED)
/* enhanced DB accounting */
#!ifdef WITH_ACCDB
modparam("acc", "db_flag", FLT_ACC)
modparam("acc", "db_missed_flag", FLT_ACCMISSED)
modparam("acc", "db_url", DBURL)
modparam("acc", "db_extra",
        "src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
#!endif


# ----- usrloc params -----
/* enable DB persistency for location entries */
#!ifdef WITH_USRLOCDB
modparam("usrloc", "db_url", DBURL)
modparam("usrloc", "db_mode", 2)
modparam("usrloc", "use_domain", MULTIDOMAIN)
#!endif


# ----- auth_db params -----
#!ifdef WITH_AUTH
modparam("auth_db", "use_domain", MULTIDOMAIN)
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "load_credentials", "")

#!ifdef WITH_ASTERISK
modparam("auth_db", "user_column", "username")
modparam("auth_db", "password_column", "sippasswd")
modparam("auth_db", "db_url", DBASTURL)
#!else
modparam("auth_db", "db_url", DBURL)
modparam("auth_db", "password_column", "password")
#!endif

# ----- permissions params -----
#!ifdef WITH_IPAUTH
modparam("permissions", "db_url", DBURL)
modparam("permissions", "db_mode", 1)
#!endif

#!endif


# ----- alias_db params -----
#!ifdef WITH_ALIASDB
modparam("alias_db", "db_url", DBURL)
modparam("alias_db", "use_domain", MULTIDOMAIN)
#!endif


# ----- domain params -----
#!ifdef WITH_MULTIDOMAIN
modparam("domain", "db_url", DBURL)
# use caching
modparam("domain", "db_mode", 1)
# register callback to match myself condition with domains list
modparam("domain", "register_myself", 1)
#!endif


#!ifdef WITH_PRESENCE
# ----- presence params -----
modparam("presence", "db_url", DBURL)

# ----- presence_xml params -----
modparam("presence_xml", "db_url", DBURL)
modparam("presence_xml", "force_active", 1)
#!endif


#!ifdef WITH_NAT
# ----- rtpproxy params -----
modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722")

# ----- nathelper params -----
modparam("nathelper", "natping_interval", 30)
modparam("nathelper", "ping_nated_only", 1)
modparam("nathelper", "sipping_bflag", FLB_NATSIPPING)
modparam("nathelper", "sipping_from", "sip:pinger@kamailio.org")

# params needed for NAT traversal in other modules
modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")
modparam("usrloc", "nat_bflag", FLB_NATB)
#!endif


#!ifdef WITH_TLS
# ----- tls params -----
modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg")
#!endif

#!ifdef WITH_ANTIFLOOD
# ----- pike params -----
modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 16)
modparam("pike", "remove_latency", 4)

# ----- htable params -----
# ip ban htable with autoexpire after 5 minutes
modparam("htable", "htable", "ipban=>size=8;autoexpire=300;")
#!endif

#!ifdef WITH_XMLRPC
# ----- xmlrpc params -----
modparam("xmlrpc", "route", "XMLRPC");
modparam("xmlrpc", "url_match", "^/RPC")
#!endif

####### Routing Logic ########


# Main SIP request routing logic
# - processing of any incoming SIP request starts with this route
route {

        # per request initial checks
        route(REQINIT);

        # NAT detection
        route(NAT);

        # handle requests within SIP dialogs
        route(WITHINDLG);

        ### only initial requests (no To tag)

        # CANCEL processing
        if (is_method("CANCEL"))
        {
                if (t_check_trans())
                        t_relay();
                exit;
        }

        t_check_trans();

        # authentication
        route(AUTH);

        # record routing for dialog forming requests (in case they are routed)
        # - remove preloaded route headers
        remove_hf("Route");
        if (is_method("INVITE|SUBSCRIBE"))
                record_route();

        # account only INVITEs
        if (is_method("INVITE"))
        {
                setflag(FLT_ACC); # do accounting
        }

        # dispatch requests to foreign domains
        route(SIPOUT);

        ### requests for my local domains

        # handle presence related requests
        route(PRESENCE);

        # handle registrations
        route(REGISTRAR);

        if ($rU==$null)
        {
                # request with no Username in RURI
                sl_send_reply("484","Address Incomplete");
                exit;
        }

        # dispatch destinations to PSTN
        route(PSTN);

        # user location service
        route(LOCATION);

        route(RELAY);
}


route[RELAY] {
#!ifdef WITH_NAT
        if (check_route_param("nat=yes")) {
                setbflag(FLB_NATB);
        }
        if (isflagset(FLT_NATS) || isbflagset(FLB_NATB)) {
                route(RTPPROXY);
        }
#!endif

        /* example how to enable some additional event routes */
        if (is_method("INVITE")) {
                #t_on_branch("BRANCH_ONE");
                t_on_reply("REPLY_ONE");
                t_on_failure("FAIL_ONE");
        }

        if (!t_relay()) {
                sl_reply_error();
        }
        exit;
}

# Per SIP request initial checks
route[REQINIT] {
#!ifdef WITH_ANTIFLOOD
        # flood dection from same IP and traffic ban for a while
        # be sure you exclude checking trusted peers, such as pstn gateways
        # - local host excluded (e.g., loop to self)
        # - traffic from Asterisk excluded
        if((src_ip!=myself) && (!route(FROMASTERISK)))
        {
                if($sht(ipban=>$si)!=$null)
                {
                        # ip is already blocked
                        xdbg("request from blocked IP - $rm from $fu (IPsisp)\n");
                        exit;
                }
                if (!pike_check_req())
                {
                        xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IPsisp)\n");
                        $sht(ipban=>$si) = 1;
                        exit;
                }
        }
#!endif

        if (!mf_process_maxfwd_header("10")) {
                sl_send_reply("483","Too Many Hops");
                exit;
        }

        if(!sanity_check("1511", "7"))
        {
                xlog("Malformed SIP message from $sisp\n");
                exit;
        }
}

# Handle requests within SIP dialogs
route[WITHINDLG] {
        if (has_totag()) {
                # sequential request withing a dialog should
                # take the path determined by record-routing
                if (loose_route()) {
                        if (is_method("BYE")) {
                                setflag(FLT_ACC); # do accounting ...
                                setflag(FLT_ACCFAILED); # ... even if the transaction fails
                        }
                        route(RELAY);
                } else {
                        if (is_method("SUBSCRIBE") && uri == myself) {
                                # in-dialog subscribe requests
                                route(PRESENCE);
                                exit;
                        }
                        if ( is_method("ACK") ) {
                                if ( t_check_trans() ) {
                                        # no loose-route, but stateful ACK;
                                        # must be an ACK after a 487
                                        # or e.g. 404 from upstream server
                                        t_relay();
                                        exit;
                                } else {
                                        # ACK without matching transaction ... ignore and discard
                                        exit;
                                }
                        }
                        sl_send_reply("404","Not here");
                }
                exit;
        }
}

# Handle SIP registrations
route[REGISTRAR] {
        if (is_method("REGISTER"))
        {
                if(isflagset(FLT_NATS))
                {
                        setbflag(FLB_NATB);
                        # uncomment next line to do SIP NAT pinging
                        ## setbflag(FLB_NATSIPPING);
                }
                if (!save("location"))
                        sl_reply_error();

#!ifdef WITH_ASTERISK
                route(REGFWD);
#!endif

                exit;
        }
}

# USER location service
route[LOCATION] {

#!ifdef WITH_ALIASDB
        # search in DB-based aliases
        alias_db_lookup("dbaliases");
#!endif

#!ifdef WITH_ASTERISK
        if(!is_method("INVITE")) {
                # non-INVITE request are routed directly by Kamailio
#!endif
        if (!lookup("location")) {
                switch ($rc) {
                        case -1:
                        case -3:
                                t_newtran();
                                t_reply("404", "Not Found");
                                exit;
                        case -2:
                                sl_send_reply("405", "Method Not Allowed");
                                exit;
                }
        }
#!ifdef WITH_ASTERISK    // 重定向asterisk 信息
        } /* end non-INVITE test */
        # only INVITE from now on
        if(route(FROMASTERISK))
        {
                # coming from Asterisk - do location lookup
                if (!lookup("location")) {
                        switch ($rc) {
                                case -1:
                                case -3:
                                        t_newtran();
                                        t_reply("404", "Not Found");
                                        exit;
                                case -2:
                                        sl_send_reply("405", "Method Not Allowed");
                                        exit;
                        }
                }
        } else {
                # new call - send to Asterisk
                route(TOASTERISK);
        }
#!endif

        # when routing via usrloc, log the missed calls also
        if (is_method("INVITE"))
        {
                setflag(FLT_ACCMISSED);
        }
}

# Presence server route
route[PRESENCE] {
        if(!is_method("UBLISH|SUBSCRIBE"))
                return;

#!ifdef WITH_PRESENCE
        if (!t_newtran())
        {
                sl_reply_error();
                exit;
        };

        if(is_method("UBLISH"))
        {
                handle_publish();
                t_release();
        }
        else
        if( is_method("SUBSCRIBE"))
        {
                handle_subscribe();
                t_release();
        }
        exit;
#!endif

        # if presence enabled, this part will not be executed
        if (is_method("UBLISH") || $rU==$null)
        {
                sl_send_reply("404", "Not here");
                exit;
        }
        return;
}

# Authentication route
route[AUTH] {
#!ifdef WITH_AUTH

#!ifdef WITH_ASTERISK   // 信任的呼叫方向,确认asterisk 接受
        # do not auth traffic from Asterisk - trusted!
        if(route(FROMASTERISK))
                return;
#!endif

        if (is_method("REGISTER"))
        {
                # authenticate the REGISTER requests (uncomment to enable auth)
#!ifdef WITH_ASTERISK
                if (!www_authorize("$td", "sipusers"))
#!else
                if (!www_authorize("$td", "subscriber"))
#!endif
                {
                        www_challenge("$td", "0");
                        exit;
                }

                if ($au!=$tU)
                {
                        sl_send_reply("403","Forbidden auth ID");
                        exit;
                }
        } else {

#!ifdef WITH_IPAUTH
                if(allow_source_address())
                {
                        # source IP allowed
                        return;
                }
#!endif

                # authenticate if from local subscriber
                if (from_uri==myself)
                {
#!ifdef WITH_ASTERISK
                        if (!proxy_authorize("$fd", "sipusers")) {
#!else
                        if (!proxy_authorize("$fd", "subscriber")) {
#!endif
                                proxy_challenge("$fd", "0");
                                exit;
                        }
                        if (is_method("UBLISH"))
                        {
                                if ($au!=$tU) {
                                        sl_send_reply("403","Forbidden auth ID");
                                        exit;
                                }
                        } else {
                                if ($au!=$fU) {
                                        sl_send_reply("403","Forbidden auth ID");
                                        exit;
                                }
                        }

                        consume_credentials();
                        # caller authenticated
                } else {
                        # caller is not local subscriber, then check if it calls
                        # a local destination, otherwise deny, not an open relay here
                        if (!uri==myself)
                        {
                                sl_send_reply("403","Not relaying");
                                exit;
                        }
                }
        }
#!endif
        return;
}

# Caller NAT detection route
route[NAT] {
#!ifdef WITH_NAT
        force_rport();
        if (nat_uac_test("19")) {
                if (method=="REGISTER") {
                        fix_nated_register();
                } else {
                        fix_nated_contact();
                }
                setflag(FLT_NATS);
        }
#!endif
        return;
}

# RTPProxy control
route[RTPPROXY] {
#!ifdef WITH_NAT
        if (is_method("BYE")) {
                unforce_rtp_proxy();
        } else if (is_method("INVITE")){
                force_rtp_proxy();
        }
        if (!has_totag()) add_rr_param(";nat=yes");
#!endif
        return;
}

# Routing to foreign domains
route[SIPOUT] {
        if (!uri==myself)
        {
                append_hf("-hint: outbound\r\n");
                route(RELAY);
        }
}

# PSTN GW routing
route[PSTN] {
#!ifdef WITH_PSTN
        # check if PSTN GW IP is defined
        if (strempty($sel(cfg_get.pstn.gw_ip))) {
                xlog("SCRIPT: PSTN rotuing enabled but pstn.gw_ip not defined\n");
                return;
        }

        # route to PSTN dialed numbers starting with '+' or '00'
        #     (international format)
        # - update the condition to match your dialing rules for PSTN routing
        if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$"))
                return;

        # only local users allowed to call
        if(from_uri!=myself) {
                sl_send_reply("403", "Not Allowed");
                exit;
        }

        $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip);

        route(RELAY);
        exit;
#!endif

        return;
}

# XMLRPC routing
#!ifdef WITH_XMLRPC
route[XMLRPC]
{
        # allow XMLRPC from localhost
        if ((method=="OST" || method=="GET")
                        && (src_ip==127.0.0.1)) {
                # close connection only for xmlrpclib user agents (there is a bug in
                # xmlrpclib: it waits for EOF before interpreting the response).
                if ($hdr(User-Agent) =~ "xmlrpclib")
                        set_reply_close();
                set_reply_no_connect();
                dispatch_rpc();
                exit;
        }
        send_reply("403", "Forbidden");
        exit;
}
#!endif


#!ifdef WITH_ASTERISK   // 来自asterisk 的呼叫,检查IP 和端口信息
# Test if coming from Asterisk
route[FROMASTERISK] {
        if($si==$sel(cfg_get.asterisk.bindip)
                        && $sp==$sel(cfg_get.asterisk.bindport))
                return 1;
        return -1;
}

# Send to Asterisk
route[TOASTERISK] {
        $du = "sip:" + $sel(cfg_get.asterisk.bindip) + ":"
                        + $sel(cfg_get.asterisk.bindport);
        route(RELAY);
        exit;
}

# Forward REGISTER to Asterisk  // 检查asterisk 注册
route[REGFWD] {
        if(!is_method("REGISTER"))
        {
                return;
        }
        $var(rip) = $sel(cfg_get.asterisk.bindip);
        $uac_req(method)="REGISTER";
        $uac_req(ruri)="sip:" + $var(rip) + ":" + $sel(cfg_get.asterisk.bindport);
        $uac_req(furi)="sip:" + $au + "@" + $var(rip);
        $uac_req(turi)="sip:" + $au + "@" + $var(rip);
        $uac_req(hdrs)="Contact: <sip:" + $au + "@"
                                + $sel(cfg_get.kamailio.bindip)
                                + ":" + $sel(cfg_get.kamailio.bindport) + ">\r\n";
        if($sel(contact.expires) != $null)
                $uac_req(hdrs)= $uac_req(hdrs) + "Expires: " + $sel(contact.expires) + "\r\n";
        else
                $uac_req(hdrs)= $uac_req(hdrs) + "Expires: " + $hdr(Expires) + "\r\n";
        uac_req_send();
}
#!endif


# Sample branch router
branch_route[BRANCH_ONE] {
        xdbg("new branch at $ru\n");
}

# Sample onreply route
onreply_route[REPLY_ONE] {
        xdbg("incoming reply\n");
#!ifdef WITH_NAT
        if ((isflagset(FLT_NATS) || isbflagset(FLB_NATB))
                        && status=~"(183)|(2[0-9][0-9])") {
                force_rtp_proxy();
        }
        if (isbflagset("6")) {
                fix_nated_contact();
        }
#!endif
}

# Sample failure route
failure_route[FAIL_ONE] {
#!ifdef WITH_NAT
        if (is_method("INVITE")
                        && (isbflagset(FLB_NATB) || isflagset(FLT_NATS))) {
                unforce_rtp_proxy();
        }
#!endif

        if (t_is_canceled()) {
                exit;
        }

        # uncomment the following lines if you want to block client
        # redirect based on 3xx replies.
        ##if (t_check_status("3[0-9][0-9]")) {
        ##t_reply("404","Not found");
        ##        exit;
        ##}

        # uncomment the following lines if you want to redirect the failed
        # calls to a different new destination
        ##if (t_check_status("486|408")) {
        ##        sethostport("192.168.2.100:5060");
        ##        append_branch();
        ##        # do not set the missed call flag again
        ##        t_relay();
        ##}
}

架构优势:
  • 增加了系统的安全性,Kamailio 负责SIP 信令,可以防止洪水攻击,保护了asterisk 安全。
  • 传输协议层网关- Kamailio 已经有相当成熟的UDP, TCP, TLS and SCTP应用,用户可以充分部署执行协议,而不需要asterisk 处理
  • 负载均衡-用户可以部署几个asterisk 服务器,Kamailio 实施负载均衡管理
  • 高可靠性方案 - Kamailio 可以充分相应前端的asterisk 服务器的工作状态,每隔几秒中可以检测到asterisk 的状态,如果其中一个重新问题,另一个可以及时相应启动。
  • 拓展性:根据用户的要求,asterisk 应用服务器可以灵活拓展,新的asterisk 服务器直接对接到kamailio 上面。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
xifan5 发表于 2012-3-7 20:36 | 显示全部楼层
看过必回,人品超好!











xjyjwh 发表于 2014-9-9 10:39 | 显示全部楼层
好好学习一下,里面配置的各个方法还不是很懂,正在研究。
seehu550 发表于 2015-4-21 04:41 | 显示全部楼层
绝对好。。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

关闭

站长推荐上一条 /1 下一条

手机版|VoIP88 ( 粤ICP备11095982号   填写您的邮件地址,订阅我们的精彩内容:

GMT+8, 2017-9-24 18:33 , Processed in 0.280851 second(s), 29 queries .

Powered by VoIP88

© 2001-2017 VoIP88

快速回复 返回顶部 返回列表