Hello,
I'm setting up a Kamailio MSFT Teams SBC that is connected to our SIP trunk provider. This server is directly connected to the Internet and not behind a NAT routing.
It is successfully processing invites from both sides (MSFT Teams and SIP trunk). Unfortunately the ACKs and CANCEL messages are not relaying to Teams. In the sipdump i can't find these messages.
Does anyone see what I am doing wrong? Below you can find my config
#!KAMAILIO
####### Defined Values #########
#!define MULTIDOMAIN 0
# - 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
#!define FROM_TEAMS 11 #!define FROM_PBX 12
######## Define Modules ########### #!define WITH_RTPENGINE #!define WITH_TLS #!define WITH_SIPDUMP #!define WITH_DISPATCH
####### Global Parameters #########
### LOG Levels: 3=DBG, 2=INFO, 1=NOTICE, 0=WARN, -1=ERR debug=2 log_stderror=no
memdbg=5 memlog=5
log_facility=LOG_LOCAL0 log_prefix="{$mt $hdr(CSeq) $ci} "
/* number of SIP routing processes */ children=2
/* uncomment the next line to disable TCP (default on) */ # disable_tcp=yes
alias=SBC_FQDN
/* listen addresses */ listen=udp:PUBLIC_IP:5060 advertise SBC_FQDN:5060 #!ifdef WITH_TLS listen=tls:PUBLIC_IP:5061 advertise SBC_FQDN:5061 #!endif
server_header= "Server: ABC SBC" user_agent_header= "User-Agent: ABC SBC"
###### TLS Enable ###### #!ifdef WITH_TLS enable_tls=yes #tcp_connect_timeout=1000
tcp_accept_no_cl=yes tcp_async = yes tcp_connection_lifetime=600
/* upper limit for TLS connections */ tls_max_connections=2048 #!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 */
####### Modules Section ########
/* set paths to location of modules */ loadmodule "jsonrpcs.so" loadmodule "kex.so" loadmodule "corex.so" loadmodule "tm.so" loadmodule "tmx.so" loadmodule "sl.so" loadmodule "rr.so" loadmodule "pv.so" loadmodule "maxfwd.so" loadmodule "textops.so" loadmodule "siputils.so" loadmodule "xlog.so" loadmodule "sanity.so" loadmodule "ctl.so" loadmodule "cfg_rpc.so" loadmodule "acc.so" loadmodule "counters.so"
#!ifdef WITH_RTPENGINE loadmodule "rtpengine.so" #!endif
#!ifdef WITH_TLS loadmodule "tls.so" #!endif
#!ifdef WITH_SIPDUMP loadmodule "sipdump.so" #!endif
#!ifdef WITH_DISPATCH loadmodule "dispatcher.so" #!endif
# ----------------- setting module-specific parameters ---------------
#!ifdef WITH_RTPENGINE # ----- rtpengine params -----+ modparam("rtpengine", "rtpengine_sock", "udp:127.0.0.1:12222") #!endif
#!ifdef WITH_TLS # ----- tls params -----+ modparam("tls", "xavp_cfg", "tls") modparam("tls", "config", "/etc/kamailio/tls.cfg") modparam("tls", "connection_timeout", 10) modparam("tls", "ssl_release_buffers", 1) modparam("tls", "send_close_notify", 1) modparam("tls", "session_cache", 0)
#!endif
#!ifdef WITH_SIPDUMP modparam("sipdump", "enable", 1) #!endif
#!ifdef WITH_DISPATCH #---------- dispatch modparam("dispatcher", "ds_probing_mode", 1) modparam("dispatcher", "ds_ping_interval", 300) #!endif
# ----- jsonrpcs params ----- modparam("jsonrpcs", "pretty_format", 1) /* set the path to RPC fifo control file */ # modparam("jsonrpcs", "fifo_name", "/run/kamailio/kamailio_rpc.fifo") /* set the path to RPC unix socket control file */ # modparam("jsonrpcs", "dgram_socket", "/run/kamailio/kamailio_rpc.sock")
# ----- ctl params ----- /* set the path to RPC unix socket control file */ # modparam("ctl", "binrpc", "unix:/run/kamailio/kamailio_ctl")
# ----- 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 ----- # set next param to 1 to add value to ;lr param (helps with some UAs) modparam("rr", "enable_full_lr", 0) # do not append from tag to the RR (no need for this script) modparam("rr", "append_fromtag", 0)
# ----- 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;src_ip=$si;" "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") modparam("acc", "failed_transaction_flag", FLT_ACCFAILED)
####### Routing Logic ########
/* Main SIP request routing logic * - processing of any incoming SIP request starts with this route * - note: this is the same as route { ... } */ request_route { # per request initial checks route(REQINIT);
#check who is the sender route(INITCHECK);
# CANCEL processing if (is_method("CANCEL")) { if (t_check_trans()) { route(RELAY); } exit; }
# handle retransmissions if (!is_method("ACK")) { if(t_precheck_trans()) { t_check_trans(); exit; } t_check_trans(); }
# handle requests within SIP dialogs route(WITHINDLG);
### only initial requests (no To tag)
# 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 }
if ($rU==$null) { # request with no Username in RURI sl_send_reply("484","Address Incomplete"); exit; }
# update $du to set the destination address for proxying #$du = "sip:" + $rd + ":9";
route(RELAY); exit; }
route[INITCHECK] { if(from_uri =~ ".*microsoft.com") { setflag(FROM_TEAMS); $du = "sip:" + "PBX_IP"; route(HANDLE_RTP_FROM_TEAMS); } else if(from_uri =~ ".*" + "PBX_IP") { setflag(FROM_PBX); $du="sip:sip.pstnhub.microsoft.com;transport=tls"; route(HANDLE_RTP_FROM_PBX); } else { exit; } }
#Manage RTP & transcoding comming from Teams to PBX route[HANDLE_RTP_FROM_TEAMS] {
if (has_body("application/sdp")) { t_on_reply("PBX_REPLY_TO_TEAMS"); rtpengine_manage("RTP codec-mask=all codec-transcode=PCMA replace-origin replace-session-connection ICE=remove"); record_route(); t_relay_to_udp("PBX_IP","5060"); }
}
#Manage RTP & transcoding comming from PBX to Teams route[HANDLE_RTP_FROM_PBX] {
if (has_body("application/sdp")) { t_on_reply("TEAMS_REPLY_TO_PBX");
rtpengine_manage("SRTP codec-mask=all ICE=force codec-transcode=PCMA replace-origin replace-session-connection"); record_route_preset("SBC_FQDN:5061;transport=tls"); add_rr_param(";r2=on");
$rd = "sip.pstnhub.microsoft.com"; $td = "SBC_FQDN"; $fd = "SBC_FQDN";
#Set TLS SNI (server name & server id) $xavp(tls=>server_name) = "SBC_FQDN"; $xavp(tls=>server_id) = "SBC_FQDN";
t_relay(); } }
# Wrapper for relaying requests route[RELAY] {
# enable additional event routes for forwarded requests # - serial forking, RTP relaying handling, a.s.o. if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) { if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH"); } if (is_method("INVITE|SUBSCRIBE|UPDATE")) { if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY"); } if (is_method("INVITE")) { if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE"); }
if (!t_relay()) { sl_reply_error(); } exit; }
# Per SIP request initial checks route[REQINIT] { if($ua =~ "friendly-scanner|sipcli|VaxSIPUserAgent") { # silent drop for scanners - uncomment next line if want to reply # sl_send_reply("200", "OK"); exit; }
if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); exit; }
if(is_method("OPTIONS")) { sl_send_reply("200","Keepalive"); exit; }
if(!sanity_check("1511", "7")) { xlog("Malformed SIP message from $si:$sp\n"); exit; } }
# Handle requests within SIP dialogs route[WITHINDLG] { if (!has_totag()) return;
#Teams reINVITEs if(isflagset(FROM_TEAMS)) { t_relay_to_udp("PBX_IP","5060"); exit; }
# 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
#set coresponding cert on transactions if($fd == "SBC_FQDN") { $xavp(tls=>server_name) = "SBC_FQDN"; $xavp(tls=>server_id) = "SBC_FQDN"; }
} else if ( is_method("NOTIFY") ) { # Add Record-Route for in-dialog NOTIFY as per RFC 6665. record_route(); }
route(RELAY); 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 route(RELAY); exit; } else { # ACK without matching transaction ... ignore and discard exit; } } sl_send_reply("404","Not here"); exit; }
# Manage outgoing branches branch_route[MANAGE_BRANCH] { xdbg("new branch [$T_branch_idx] to $ru\n"); }
# Manage incoming replies onreply_route[MANAGE_REPLY] { xdbg("incoming reply\n"); }
#PBX On Reply onreply_route[PBX_REPLY_TO_TEAMS] { if (has_body("application/sdp")) { rtpengine_manage("SRTP codec-mask=all codec-transcode=PCMA replace-origin replace-session-connection media-address=PUBLIC_IP"); } }
#From Teams On Reply onreply_route[TEAMS_REPLY_TO_PBX] { if (has_body("application/sdp")) { rtpengine_manage("RTP codec-mask=all codec-transcode=PCMA replace-origin replace-session-connection media-address=PUBLIC_IP"); } }
# Manage failure routing cases failure_route[MANAGE_FAILURE] { if (t_is_canceled()) exit; }
event_route[tm:local-request] { if(is_method("OPTIONS") && $ru =~ "pstnhub.microsoft.com") { append_hf("Contact: sip:SBC_FQDN:5061;transport=tls\r\n"); } xlog("L_INFO", "Sent out tm request: $mb\n"); }