opensips简介
概述
在众多的sip服务器中,主要有俩大类,一类侧重于媒体/业务服务器,比如freeswitch/asterisk,另一类侧重于代理/负载服务器,比如opensips/kamailio。
今天我们对opensips做一个简单介绍。
OpenSIPS 是用于语音、视频、IM、在线状态和任何其他SIP扩展的开源 SIP 代理服务器。
OpenSIPS 是一种多功能、多用途的SIP信令服务器,运营商、电信或 ITSP 将其用于 Class4/5平台、中继、企业/虚拟 PBX 解决方案、会话边界控制器、应用服务器、前端负载等解决方案、IMS 平台、呼叫中心等等。
OpenSIPS 被推荐用于任何类型的 SIP 场景/服务:
- 高吞吐量 - 数万CPS,数百万个在线呼叫(参见官方测试)
- 路由和集成的灵活性 - 用于实现自定义路由逻辑的路由脚本,多个接口 API(参见手册)
- 有效的应用程序构建 - 超过 120 个模块提供功能,用于 SIP 处理、后端操作、集成、路由逻辑(请参阅模块列表)
本章节主要介绍opensips的编译安装、配置启动的通用流程。
开发环境
Centos:CentOS release 6 (Final)或以上版本
opensips:2.4.9
GCC/C++:4.4.7
编译安装
依赖库
yum install -y autoconf automake libtool gcc-c++ ncurses-devel make zlib-devel lynx flex bison mysql pcre python-devel openssl-devel mysql-devel
安装hiredis
git clone https://github.com/redis/hiredis.git hiredis
cd hiredis
make install
源码安装包:
https://opensips.org/pub/opensips/2.4.9/opensips-2.4.9.tar.gz
wget https://opensips.org/pub/opensips/2.4.9/opensips-2.4.9.tar.gz
tar –zxvf opensips-2.4.9.tar.gz
编译安装:
方法1:
cd opensips-2.4.9
make include_modules="cachedb_redis db_mysql dialplan python tls_mgm proto_tls proto_ws proto_wss " prefix="/usr/local/opensips" install
方法2:
cd opensips-2.4.9
make menuconfig
增加 cachedb_redis db_mysql dialplan python tls_mgm proto_tls proto_ws proto_wss 模块编译
修改安装目录为 /usr/local/opensips
保存退出menuconfig
make install
目录结构
默认安装路径为 /usr/local/opensips
编译安装完成后,检查安装目录
opensips
├── etc
│ └── opensips
│ ├── opensips.cfg
│ ├── opensipsctlrc
│ ├── osipsconsolerc
│ ├── scenario_callcenter.xml
│ └── tls
│ ├── ca.conf
│ ├── README
│ ├── request.conf
│ ├── rootCA
│ │ ├── cacert.pem
│ │ ├── certs
│ │ │ └── 01.pem
│ │ ├── index.txt
│ │ ├── private
│ │ │ └── cakey.pem
│ │ └── serial
│ ├── user
│ │ ├── user-calist.pem
│ │ ├── user-cert.pem
│ │ ├── user-cert_req.pem
│ │ └── user-privkey.pem
│ └── user.conf
├── lib64
│ └── opensips
│ ├── modules
│ │ ├── acc.so
│ │ ├── alias_db.so
│ │ ├── auth_aaa.so
│ │ ├── auth_db.so
│ │ ├── auth.so
│ │ ├── avpops.so
│ │ ├── b2b_entities.so
│ │ ├── b2b_sca.so
│ │ ├── benchmark.so
│ │ ├── cachedb_local.so
│ │ ├── cachedb_redis.so
│ │ ├── cachedb_sql.so
│ │ ├── call_center.so
│ │ ├── call_control.so
│ │ ├── cfgutils.so
│ │ ├── clusterer.so
│ │ ├── db_cachedb.so
│ │ ├── db_flatstore.so
│ │ ├── db_mysql.so
│ │ ├── db_text.so
│ │ ├── db_virtual.so
│ │ ├── dialog.so
│ │ ├── dialplan.so
│ │ ├── dispatcher.so
│ │ ├── diversion.so
│ │ ├── dns_cache.so
│ │ ├── domainpolicy.so
│ │ ├── domain.so
│ │ ├── drouting.so
│ │ ├── enum.so
│ │ ├── event_datagram.so
│ │ ├── event_flatstore.so
│ │ ├── event_jsonrpc.so
│ │ ├── event_route.so
│ │ ├── event_routing.so
│ │ ├── event_virtual.so
│ │ ├── event_xmlrpc.so
│ │ ├── exec.so
│ │ ├── fraud_detection.so
│ │ ├── freeswitch_scripting.so
│ │ ├── freeswitch.so
│ │ ├── gflags.so
│ │ ├── group.so
│ │ ├── imc.so
│ │ ├── jsonrpc.so
│ │ ├── load_balancer.so
│ │ ├── mangler.so
│ │ ├── mathops.so
│ │ ├── maxfwd.so
│ │ ├── mediaproxy.so
│ │ ├── mi_datagram.so
│ │ ├── mid_registrar.so
│ │ ├── mi_fifo.so
│ │ ├── mi_http.so
│ │ ├── mi_json.so
│ │ ├── msilo.so
│ │ ├── nathelper.so
│ │ ├── nat_traversal.so
│ │ ├── options.so
│ │ ├── path.so
│ │ ├── peering.so
│ │ ├── permissions.so
│ │ ├── pike.so
│ │ ├── presence_callinfo.so
│ │ ├── presence_xcapdiff.so
│ │ ├── proto_bin.so
│ │ ├── proto_hep.so
│ │ ├── proto_ws.so
│ │ ├── python.so
│ │ ├── qos.so
│ │ ├── ratelimit.so
│ │ ├── registrar.so
│ │ ├── rr.so
│ │ ├── rtpengine.so
│ │ ├── rtpproxy.so
│ │ ├── script_helper.so
│ │ ├── seas.so
│ │ ├── signaling.so
│ │ ├── sipcapture.so
│ │ ├── sip_i.so
│ │ ├── sipmsgops.so
│ │ ├── siptrace.so
│ │ ├── sl.so
│ │ ├── sms.so
│ │ ├── speeddial.so
│ │ ├── sql_cacher.so
│ │ ├── sst.so
│ │ ├── statistics.so
│ │ ├── stun.so
│ │ ├── textops.so
│ │ ├── tls_mgm.so
│ │ ├── tm.so
│ │ ├── topology_hiding.so
│ │ ├── uac_auth.so
│ │ ├── uac_redirect.so
│ │ ├── uac_registrant.so
│ │ ├── uac.so
│ │ ├── uri.so
│ │ ├── userblacklist.so
│ │ └── usrloc.so
│ └── opensipsctl
│ ├── dbtextdb
│ │ └── dbtextdb.py
│ ├── opensipsctl.base
│ ├── opensipsctl.ctlbase
│ ├── opensipsctl.dbtext
│ ├── opensipsctl.fifo
│ ├── opensipsctl.mysql
│ ├── opensipsctl.sqlbase
│ ├── opensipsctl.unixsock
│ ├── opensipsdbctl.base
│ ├── opensipsdbctl.dbtext
│ └── opensipsdbctl.mysql
├── sbin
│ ├── opensips
│ ├── opensipsctl
│ ├── opensipsdbctl
│ ├── opensipsunix
│ ├── osipsconfig
│ └── osipsconsole
└── share
├── doc
│ └── opensips
│ ├── AUTHORS
│ ├── INSTALL
│ ├── NEWS
│ ├── README
│ ├── README.acc
│ ├── README.alias_db
│ ├── README.auth
│ ├── README.auth_aaa
│ ├── README.auth_db
│ ├── README.avpops
│ ├── README.b2b_entities
│ ├── README.b2b_sca
│ ├── README.benchmark
│ ├── README.cachedb_local
│ ├── README.cachedb_redis
│ ├── README.cachedb_sql
│ ├── README.call_center
│ ├── README.call_control
│ ├── README.cfgutils
│ ├── README.clusterer
│ ├── README.db_cachedb
│ ├── README.db_flatstore
│ ├── README.db_mysql
│ ├── README.db_text
│ ├── README.db_virtual
│ ├── README.dialog
│ ├── README.dialplan
│ ├── README.dispatcher
│ ├── README.diversion
│ ├── README.dns_cache
│ ├── README.domain
│ ├── README.domainpolicy
│ ├── README.drouting
│ ├── README.enum
│ ├── README.event_datagram
│ ├── README.event_flatstore
│ ├── README.event_jsonrpc
│ ├── README.event_route
│ ├── README.event_routing
│ ├── README.event_virtual
│ ├── README.event_xmlrpc
│ ├── README.exec
│ ├── README.fraud_detection
│ ├── README.freeswitch
│ ├── README.freeswitch_scripting
│ ├── README.gflags
│ ├── README.group
│ ├── README.imc
│ ├── README.jsonrpc
│ ├── README.load_balancer
│ ├── README.mangler
│ ├── README.mathops
│ ├── README.maxfwd
│ ├── README.mediaproxy
│ ├── README.mi_datagram
│ ├── README.mid_registrar
│ ├── README.mi_fifo
│ ├── README.mi_http
│ ├── README.mi_json
│ ├── README-MODULES
│ ├── README.msilo
│ ├── README.nathelper
│ ├── README.nat_traversal
│ ├── README.options
│ ├── README.path
│ ├── README.peering
│ ├── README.permissions
│ ├── README.pike
│ ├── README.presence_callinfo
│ ├── README.presence_xcapdiff
│ ├── README.proto_bin
│ ├── README.proto_hep
│ ├── README.proto_ws
│ ├── README.python
│ ├── README.qos
│ ├── README.ratelimit
│ ├── README.registrar
│ ├── README.rr
│ ├── README.rtpengine
│ ├── README.rtpproxy
│ ├── README.script_helper
│ ├── README.seas
│ ├── README.signaling
│ ├── README.sipcapture
│ ├── README.sip_i
│ ├── README.sipmsgops
│ ├── README.siptrace
│ ├── README.sl
│ ├── README.sms
│ ├── README.speeddial
│ ├── README.sql_cacher
│ ├── README.sst
│ ├── README.statistics
│ ├── README.stun
│ ├── README.textops
│ ├── README.tls_mgm
│ ├── README.tm
│ ├── README.topology_hiding
│ ├── README.uac
│ ├── README.uac_auth
│ ├── README.uac_redirect
│ ├── README.uac_registrant
│ ├── README.uri
│ ├── README.userblacklist
│ └── README.usrloc
├── man
│ ├── man5
│ │ └── opensips.cfg.5
│ └── man8
│ ├── opensips.8
│ ├── opensipsctl.8
│ └── opensipsunix.8
└── opensips
├── dbtext
│ └── opensips
│ ├── acc
│ ├── active_watchers
│ ├── address
│ ├── aliases
│ ├── b2b_entities
│ ├── b2b_logic
│ ├── b2b_sca
│ ├── cachedb
│ ├── carrierfailureroute
│ ├── carrierroute
│ ├── cc_agents
│ ├── cc_calls
│ ├── cc_cdrs
│ ├── cc_flows
│ ├── closeddial
│ ├── clusterer
│ ├── cpl
│ ├── dbaliases
│ ├── dialog
│ ├── dialplan
│ ├── dispatcher
│ ├── domain
│ ├── domainpolicy
│ ├── dr_carriers
│ ├── dr_gateways
│ ├── dr_groups
│ ├── dr_partitions
│ ├── dr_rules
│ ├── emergency_report
│ ├── emergency_routing
│ ├── emergency_service_provider
│ ├── fraud_detection
│ ├── freeswitch
│ ├── freeswitch_scripting
│ ├── globalblacklist
│ ├── grp
│ ├── imc_members
│ ├── imc_rooms
│ ├── load_balancer
│ ├── location
│ ├── missed_calls
│ ├── presentity
│ ├── pua
│ ├── registrant
│ ├── re_grp
│ ├── rls_presentity
│ ├── rls_watchers
│ ├── route_tree
│ ├── rtpengine
│ ├── rtpproxy_sockets
│ ├── silo
│ ├── sip_trace
│ ├── speed_dial
│ ├── subscriber
│ ├── tls_mgm
│ ├── uri
│ ├── userblacklist
│ ├── usr_preferences
│ ├── version
│ ├── watchers
│ └── xcap
├── menuconfig_templates
│ ├── opensips_loadbalancer_def.m4
│ ├── opensips_loadbalancer.m4
│ ├── opensips_residential_def.m4
│ ├── opensips_residential.m4
│ ├── opensips_trunking_def.m4
│ └── opensips_trunking.m4
└── mysql
├── acc-create.sql
├── alias_db-create.sql
├── auth_db-create.sql
├── avpops-create.sql
├── b2b-create.sql
├── b2b_sca-create.sql
├── cachedb_sql-create.sql
├── call_center-create.sql
├── carrierroute-create.sql
├── closeddial-create.sql
├── clusterer-create.sql
├── cpl-create.sql
├── dialog-create.sql
├── dialplan-create.sql
├── dispatcher-create.sql
├── domain-create.sql
├── domainpolicy-create.sql
├── drouting-create.sql
├── emergency-create.sql
├── fraud_detection-create.sql
├── freeswitch_scripting-create.sql
├── group-create.sql
├── imc-create.sql
├── load_balancer-create.sql
├── msilo-create.sql
├── permissions-create.sql
├── presence-create.sql
├── registrant-create.sql
├── rls-create.sql
├── rtpengine-create.sql
├── rtpproxy-create.sql
├── siptrace-create.sql
├── speeddial-create.sql
├── standard-create.sql
├── tls_mgm-create.sql
├── uri_db-create.sql
├── userblacklist-create.sql
└── usrloc-create.sql
创建数据库
注意事项:该操作需要保证对应数据库没有创建过
cd /usr/local/opensips/etc/opensips/
vi opensipsctlrc
DBENGINE=MYSQL
DBPORT=3306
DBHOST=192.168.0.110
DBNAME=opensips
DBRWUSER=root
DBRWPW="opensips"
DBROOTUSER="root"
执行命令
/usr/local/opensips/sbin/opensipsdbctl create
防火墙
CENTOS6
iptables -I INPUT 1 –p udp –dport 5060 –j ACCEPT
iptables -I INPUT 1 –p tcp –dport 7443 –j ACCEPT
service iptables save
CENTOS7
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" port port="5060" protocol="udp" accept'
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" port port="7443" protocol="tcp" accept'
firewall-cmd --reload
配置日志
修改 /usr/local/opensips/etc/opensips/opensips.cfg
log_facility=LOG_LOCAL0
修改 /etc/rsyslog.conf
local0.* -/var/log/opensips/opensips.log
新增 /etc/logrotate.d/opensips
/var/log/opensips/opensips.log {
copytruncate
noolddir
size 20M
rotate 64
dateext
dateformat .%Y%m%d.%s
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2>/dev/null` 2>/dev/null || true
endscript
}
设置定时任务
sudo crontab -e
* * * * * /usr/sbin/logrotate /etc/logrotate.d/opensips
重启rsyslog服务
service rsyslog restart
TCP最大连接数限制
用户级别
查看linux系统用户最大打开文件限制
ulimit -n
修改limits.conf
vi /etc/security/limits.conf
* soft nofile 100000
* hard nofile 100000
linux系统级别
查看linux系统对同时打开文件数的硬限制
sysctl -a|grep file-max
修改sysctl.conf
vi /etc/sysctl.conf
fs.file-max = 100000
使sysctl配置立即生效:
sysctl -p
网络端口限制修改,服务器需要作为client时配置
查看linux系统最大追踪TCP连接数量
sysctl -a | grep ipv4.ip_conntrack_max
查看linux系统端口范围
sysctl -a | grep ipv4.ip_local_port_range
修改sysctl.conf
vi /etc/sysctl.conf
net.ipv4.ip_local_port_range = 10240 65535
net.netfilter.nf_conntrack_max = 100000
使sysctl配置立即生效:
sysctl -p
Linux下查看tcp连接数及状态命令:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
统计7443端口连接数
netstat -nat|grep -i "7443"|wc -l
统计已连接上的,状态为established
netstat -na|grep ESTABLISHED|wc -l
查出哪个IP地址连接最多,异常情况需要封IP
netstat -na|grep ESTABLISHED|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -r
netstat -na|grep SYN|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -r
启动脚本
cd opensips-2.4.9/packaging/redhat_fedora
cp opensips.init /etc/init.d/opensips
chmod 777 /etc/init.d/opensips
sed -i "s/\/usr\/sbin/\/usr\/local\/opensips\/sbin/g" /etc/init.d/opensips
sed -i "s/\/etc\/\$prog/\/usr\/local\/opensips\/etc\/\$prog/g" /etc/init.d/opensips
开机自动启动
useradd -d /usr/local/opensips -s /sbin/nologin opensips
chkconfig --add opensips
chkconfig opensips on
启停命令
启动:
service opensips start
或者
/usr/local/opensips/sbin/opensipsctl start
后台启动方式,如果启动失败,需要查看log文件
停止:
service opensips stop
或者
/usr/local/opensips/sbin/opensipsctl stop
常用命令
/usr/local/opensips/sbin/opensips -C //检查配置文件是否有错误
/usr/local/opensips/sbin/opensipsctl monitor //opensips运行参数监控
/usr/local/opensips/sbin/opensipsctl ping <uri> //使用OPTION 检测uri
/usr/local/opensips/sbin/opensipsctl dispatcher show //dispatcher模块信息展示
配置文件
当前文档主要描述,opensips作为注册服务器的信令代理和负载节点的配置方法。
/usr/local/opensips/etc/opensips/opensips.cfg
#
# OpenSIPS residential configuration script
# by OpenSIPS Solutions <team@opensips-solutions.com>
#
# This script was generated via "make menuconfig", from
# the "Residential" scenario.
# You can enable / disable more features / functionalities by
# re-generating the scenario with different options.#
#
# Please refer to the Core CookBook at:
# https://opensips.org/Resources/DocsCookbooks
# for a explanation of possible statements, functions and parameters.
#
####### Global Parameters #########
log_level=3
log_stderror=no
log_facility=LOG_LOCAL0
children=4
/* uncomment the following lines to enable debugging */
#debug_mode=yes
/* uncomment the next line to enable the auto temporary blacklisting of
not available destinations (default disabled) */
#disable_dns_blacklist=no
/* uncomment the next line to enable IPv6 lookup after IPv4 dns
lookup failures (default disabled) */
#dns_try_ipv6=yes
/* comment the next line to enable the auto discovery of local aliases
based on reverse DNS on IPs */
auto_aliases=no
listen=udp:192.168.0.202:5080 # CUSTOMIZE ME
listen=udp:192.168.0.202:5060
#listen = wss:192.168.0.202:7443 use_children 5
tcp_max_connections=4096
user_agent_header="REG-PXY001"
####### Modules Section ########
#set module path
mpath="/usr/local/opensips/lib64/opensips/modules/"
loadmodule "db_mysql.so"
#### SIGNALING module
loadmodule "signaling.so"
#### StateLess module
loadmodule "sl.so"
#### Transaction Module
loadmodule "tm.so"
modparam("tm", "fr_timer", 2)
modparam("tm", "fr_timeout", 5)
modparam("tm", "fr_inv_timeout", 30)
modparam("tm", "restart_fr_on_each_reply", 0)
modparam("tm", "onreply_avp_mode", 1)
#### Record Route Module
loadmodule "rr.so"
/* do not append from tag to the RR (no need for this script) */
modparam("rr", "enable_double_rr", 1)
modparam("rr", "append_fromtag", 1)
loadmodule "dialog.so"
modparam("dialog", "db_url", "mysql://root:123456@localhost/opensips")
#### MAX ForWarD module
loadmodule "maxfwd.so"
loadmodule "textops.so"
#### SIP MSG OPerationS module
loadmodule "sipmsgops.so"
#### FIFO Management Interface
loadmodule "mi_fifo.so"
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
modparam("mi_fifo", "fifo_mode", 0666)
#### URI module
loadmodule "uri.so"
modparam("uri", "use_uri_table", 0)
#### USeR LOCation module
loadmodule "usrloc.so"
modparam("usrloc", "nat_bflag", "NAT")
modparam("usrloc", "working_mode_preset", "single-instance-no-db")
#### REGISTRAR module
loadmodule "registrar.so"
modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT")
/* uncomment the next line not to allow more than 10 contacts per AOR */
#modparam("registrar", "max_contacts", 10)
#### ACCounting module
loadmodule "acc.so"
/* what special events should be accounted ? */
modparam("acc", "early_media", 0)
modparam("acc", "report_cancels", 0)
/* by default we do not adjust the direct of the sequential requests.
if you enable this parameter, be sure to enable "append_fromtag"
in "rr" module */
modparam("acc", "detect_direction", 0)
loadmodule "proto_udp.so"
loadmodule "dispatcher.so"
modparam("dispatcher", "db_url", "mysql://root:123456@localhost/opensips")
modparam("dispatcher", "ds_ping_method", "OPTIONS")
modparam("dispatcher", "ds_ping_interval", 60)
modparam("dispatcher", "ds_probing_threshhold", 2)
modparam("dispatcher", "ds_probing_mode", 1)
loadmodule "load_balancer.so"
modparam("load_balancer", "db_url", "mysql://root:123456@localhost/opensips")
modparam("load_balancer", "probing_method", "OPTIONS")
modparam("load_balancer", "probing_interval", 60)
####### Routing Logic ########
# main request routing logic
route{
script_trace( 1, "$rm from $si, ruri=$ru", "me");
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
exit;
}
if (!has_totag()) {
# initial request
record_route();
}
else {
# sequential request - obey the indicated route
loose_route();
t_relay();
exit;
}
# handle cancel and re-transmissions
# from now on we have only the initial requests
# select the node that'll handle the call (load balanced)
# the method used is different for invite/register requests
# unknown methods are rejected here
if ( is_method("CANCEL") ) {
if ( t_check_trans() )
t_relay();
exit;
}
else if(is_method("OPTIONS")) {
# send reply for each options request
sl_send_reply("200", "ok");
exit;
}
else if (is_method("INVITE")) {
xlog("L_INFO", "INFO: this sip message is an invite\n");
if (!ds_select_dst("1", "1")) {
send_reply("503","Service Unavailable");
exit;
}
}
else if (is_method("REGISTER")) {
xlog("L_INFO", "INFO: this sip message is a register\n");
if (!ds_select_dst("1", "1")) {
send_reply("503","Service Unavailable");
exit;
}
}
else {
send_reply("405","Method Not Allowed");
exit;
}
# route the request
if (!t_relay()) {
sl_reply_error();
}
}
增加网关数据
/usr/local/opensips/sbin/opensipsctl dispatcher addgw 1 sip:192.168.0.146:5060 '' 0 50 'fs1' 'reg001'
/usr/local/opensips/sbin/opensipsctl dispatcher addgw 1 sip:192.168.0.150:5060 '' 0 50 'fs2' 'reg002'
sip软终端配置
加载测试
通过sip软终端注册,发起呼叫,测试信令和媒体的连通性。
总结
opensips作为负载均衡的代理网关,性能非常好。
网关常见的功能,我们通过opensips.cfg配置文件的路由脚本基本很容易实现,具体请关注opensips的子模块介绍和接口。
空空如常
求真得真