ซื้อสินค้า VoIP คลิกไปที่ https://www.lazada.co.th/shop/adventek/
0. เมื่อไหร่ใช้ OpenSIPS? เมื่อไหร่ใช้ Asterisk/IssabelPBX/FreePBX?
มี site ที่เคยทำให้ลูกค้าประมาณ 300 extensions ก็สามารถใช้ IssabelPBX run บน server ตัวเดียวได้
อาจจะช้าบ้างในกรณีเปลี่ยน config แล้ว reload server บ่อยๆ สำหรับ site ที่มี extensions > 200 ก็น่าจะใช้
OpenSIPS ได้แล้ว อย่างไรก็ตาม OpenSIPS รองรับเฉพาะ SIP protocol (signaling) ต้องมี media server
(IVR, voicemail, conf. room) มาเสริม ซึ่งก็ต้องใช้ Asterisk หรือ FreeSWITCH หรือ YATE มาทำหน้าที่นี้
ในกรณีที่เป็นบริการสาธารณะ (เช่น โทรศัพท์บ้านของ TOT) ก็สามารถนำ OpenSIPS + media server มา
ทดแทนได้ Asterisk/IssabelPBX/FreePBX ไม่เหมาะกับงานแบบนี้อย่างแน่นอน
1. OpenSIPS - Open SIP Server
OpenSIPS (www.opensips.org) เป็น open source SIP server ที่พัฒนาต่อเนื่องมาจาก SER project ->
OpenSER project มีความเสถียรและมี features ที่ค่อนข้างสมบูรณ์ (แต่การใช้งานไม่ได้ง่ายสำหรับ user
ทั่วไป) OpenSIPS มี features หลักๆ ดังนี้
- SIP registrar server
- SIP router / proxy (lcr, dynamic routing, dialplan features)
- SIP redirect server
- SIP presence agent
- SIP back-to-back User Agent
- SIP IM server (chat and end-2-end IM)
- SIP load-balancer or dispatcher
- SIP front end for gateways/asterisk
บทความของเราในตอนนี้จะเป็นการติดตั้ง OpenSIPS 2.4.11 บน Debian 9.13 หลังจากนั้นบทความใน
ตอนต่อๆ ไป จะกล่าวถึง OpenSIPS GUI, การใช้งานในลักษณะ SIP trunking และ VoIP Service Platform
2. ติดตั้ง OpenSIPS
ขั้นแแรกติดตั้ง Debian 9.13 เลือก options - web server, ssh server, standard system utilities
หลังจากติดตั้ง OS เสร็จ ให้ login ด้วย root แล้ว run คำสั่ง ดังนี้
#apt install gcc bison flex make openssl libssl-dev libncurses5-dev
#apt install libxml2-dev mariadb-server mariadb-client libmariadb2
#apt install libxmlrpc-core-c3-dev libdbi-perl libdbd-mysql-perl libmicrohttpd-dev
libpcre3-dev unzip
#apt install default-libmysqlclient-dev
download opensips-2.4.11.tgz จาก download.opensips.org ไปเก็บที่โฟลเดอร์ /usr/src
#cd /usr/src
#tar zxvf opensips-2.4.11.tgz
#cd opensips-2.4.11
3. คอนฟิก OpenSIPS
คอนฟิก log file
#touch /var/log/opensips.log
แก้ไข file /etc/rsyslog.conf โดยการเพิ่มบรรทัดต่อไปนี้เข้าไป
แก้ไข file /etc/default/opensips
RUN_OPENSIPS=yes
แก้ไข file /etc/init.d/opensips
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin
DAEMON=/sbin/opensips
ระบุ config file = /etc/opensips/opensips.conf
แก้ไข file /etc/opensips/opensipsctlrc
DBENGINE=MYSQL
DBHOST=localhost
DBNAME=opensips
DBRWUSER=opensips
DBRWPW=”opensipsrw”
ALIASES_TYPE=”DB”
สร้าง database โดยการ run คำสั่ง
/sbin/opensipsdbctl create
ถ้าไม่มีอะไรผิดพลาดก็ทำขั้นต่อไป
ให้ได้ตามนี้
###################################
####### 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.10.222:5060
################################
####### Modules Section ##############
################################
#set module path
mpath="/lib64/opensips/modules/"
#### SIGNALING module
loadmodule "signaling.so"
#### StateLess module
loadmodule "sl.so"
#### Transaction Module
loadmodule "tm.so"
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", "append_fromtag", 0)
#### MAX ForWarD module
loadmodule "maxfwd.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)
#### MYSQL module
loadmodule "db_mysql.so"
#### USeR LOCation module
loadmodule "usrloc.so"
modparam("usrloc", "nat_bflag", "NAT")
modparam("usrloc", "db_mode", 2)
modparam("usrloc", "db_url",
"mysql://opensips:opensipsrw@localhost/opensips")
#### 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 the enable "append_fromtag"
in "rr" module */
modparam("acc", "detect_direction", 0)
modparam("acc", "db_url",
"mysql://opensips:opensipsrw@localhost/opensips")
#### AUTHentication modules
loadmodule "auth.so"
loadmodule "auth_db.so"
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
modparam("auth_db|uri", "db_url",
"mysql://opensips:opensipsrw@localhost/opensips")
modparam("auth_db", "load_credentials", "")
#### ALIAS module
loadmodule "alias_db.so"
modparam("alias_db", "db_url",
"mysql://opensips:opensipsrw@localhost/opensips")
#### DOMAIN module
loadmodule "domain.so"
modparam("domain", "db_url",
"mysql://opensips:opensipsrw@localhost/opensips")
modparam("domain", "db_mode", 1) # Use caching
modparam("auth_db|usrloc|uri", "use_domain", 1)
#### DIALOG module
loadmodule "dialog.so"
modparam("dialog", "dlg_match_mode", 1)
modparam("dialog", "default_timeout", 21600) # 6 hours timeout
modparam("dialog", "db_mode", 2)
modparam("dialog", "db_url",
"mysql://opensips:opensipsrw@localhost/opensips")
loadmodule "proto_udp.so"
###########################
####### Routing Logic ###########
###########################
# main request routing logic
route {
if (!mf_process_maxfwd_header("10")) {
send_reply("483","Too Many Hops");
exit;
}
if (has_totag()) {
# handle hop-by-hop ACK (no routing required)
if ( is_method("ACK") && t_check_trans() ) {
t_relay();
exit;
}
# sequential request within a dialog should
# take the path determined by record-routing
if ( !loose_route() ) {
# we do record-routing for all our traffic, so we should not
# receive any sequential requests without Route hdr.
send_reply("404","Not here");
exit;
}
# validate the sequential request against dialog
if ( $DLG_status!=NULL && !validate_dialog() ) {
xlog("In-Dialog $rm from $si (callid=$ci) is not valid according to dialog\n");
## exit;
}
if (is_method("BYE")) {
# do accounting even if the transaction fails
do_accounting("db","failed");
}
# route it out to whatever destination was set by loose_route()
# in $du (destination URI).
route(relay);
exit;
}
# CANCEL processing
if (is_method("CANCEL")) {
if (t_check_trans())
t_relay();
exit;
}
# absorb retransmissions, but do not create transaction
t_check_trans();
if ( !(is_method("REGISTER") ) ) {
if (is_from_local()) {
# authenticate if from local subscriber
# authenticate all initial non-REGISTER request that pretend to be
# generated by local subscriber (domain from FROM URI is local)
if (!proxy_authorize("", "subscriber")) {
proxy_challenge("", "0");
exit;
}
if (!db_check_from()) {
send_reply("403","Forbidden auth ID");
exit;
}
consume_credentials();
# caller authenticated
} else {
# if caller is not local, then called number must be local
if (!is_uri_host_local()) {
send_reply("403","Relay Forbidden");
exit;
}
}
}
# preloaded route checking
if (loose_route()) {
xlog("L_ERR",
"Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]");
if (!is_method("ACK"))
send_reply("403","Preload Route denied");
exit;
}
# record routing
if (!is_method("REGISTER|MESSAGE"))
record_route();
# account only INVITEs
if (is_method("INVITE")) {
# create dialog with timeout
if ( !create_dialog("B") ) {
send_reply("500","Internal Server Error");
exit;
}
do_accounting("db");
}
if (!is_uri_host_local()) {
append_hf("P-hint: outbound\r\n");
route(relay);
}
# requests for my domain
if (is_method("PUBLISH|SUBSCRIBE")) {
send_reply("503", "Service Unavailable");
exit;
}
if (is_method("REGISTER")) {
# authenticate the REGISTER requests
if (!www_authorize("", "subscriber")) {
www_challenge("", "0");
exit;
}
if (!db_check_to()) {
send_reply("403","Forbidden auth ID");
exit;
}
# store the registration and generate a SIP reply
if (!save("location"))
xlog("failed to register AoR $tu\n");
exit;
}
if ($rU==NULL) {
# request with no Username in RURI
send_reply("484","Address Incomplete");
exit;
}
# apply DB based aliases
alias_db_lookup("dbaliases");
# do lookup with method filtering
if (!lookup("location","m")) {
if (!db_does_uri_exist()) {
send_reply("420","Bad Extension");
exit;
}
t_reply("404", "Not Found");
exit;
}
# when routing via usrloc, log the missed calls also
do_accounting("db","missed");
route(relay);
}
route[relay] {
# for INVITEs enable some additional helper routes
if (is_method("INVITE")) {
t_on_branch("per_branch_ops");
t_on_reply("handle_nat");
t_on_failure("missed_call");
}
if (!t_relay()) {
send_reply("500","Internal Error");
}
exit;
}
branch_route[per_branch_ops] {
xlog("new branch at $ru\n");
}
onreply_route[handle_nat] {
xlog("incoming reply\n");
}
failure_route[missed_call] {
if (t_was_cancelled()) {
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;
##}
}
local_route {
if (is_method("BYE") && $DLG_dir=="UPSTREAM") {
acc_db_request("200 Dialog Timeout", "acc");
}
}
4. Start OpenSIPS
#/etc/init.d/opensips start
add domain
#opensipsctl domain add 192.168.10.222
#opensipsctl domain reload 192.168.10.222
(ip address ของ server)
แล้ว add subsciber (เบอร์โทรศัพท์)
#opensipsctl add This email address is being protected from spambots. You need JavaScript enabled to view it. 1000 ### user = 1000 password = 1000
#opensipsctl add This email address is being protected from spambots. You need JavaScript enabled to view it. 1001
5. ทดสอบการใช้งาน
ใช้ ip phone หรือ soft phone 2 ตัว register มาที่ OpenSIPS server โดยใช้ user 1000 password 1000 และ
user 1001 password 1001 เมื่อ register เรียบร้อย ลองโทรหากัน ถ้าโทรหากันได้
ก็ถือว่าการติดตั้งคอนฟิกในเบื้องต้นเสร็จเรียบร้อยแล้ว
6. คำสั่งอื่นๆ
#/etc/init.d/opensips start
#/etc/init.d/opensips stop
#/etc/init.d/opensips restart
#ps -ef | grep opensips