#!KAMAILIO ################################################################ # # This is a front-end SIP proxy configuration for the xlab1 project # See for more details: https://txlab.wordpress.com/tag/xlab1/ # The configuration requires Kamailio version 3.3.x # # This work is licensed under a Creative Commons Attribution 3.0 License # Author: Stanislav Sinyagin # ################################################################ #!define WITH_DEBUG ####### Defined Values ######### #!define DBURL "text:///var/lib/kamailio/dbtext" #!define BACKEND_NET4 10.100.0.0/24 #!define BACKEND_NET6 2a02:200:8:100::/64 # - 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 #!substdef "!MY_IP_ADDR!192.168.0.36!g" #!substdef "!MY_DOMAIN!192.168.0.36!g" #!substdef "!MY_WS_PORT!8080!g" #!substdef "!MY_WSS_PORT!4443!g" #!substdef "!MY_WS_ADDR!tcp:MY_IP_ADDR:MY_WS_PORT!g" #!substdef "!MY_WSS_ADDR!tls:MY_IP_ADDR:MY_WSS_PORT!g" #!define WITH_WEBSOCKETS ####### Global Parameters ######### #!ifdef WITH_DEBUG debug=4 log_stderror=no #!else debug=2 log_stderror=no #!endif memdbg=5 memlog=5 log_facility=LOG_LOCAL0 fork=yes children=2 auto_aliases=no alias="dial1.xxx.com" # to avoid simple attacks, use unconventional port port=5066 listen=MY_IP_ADDR #!ifdef WITH_WEBSOCKETS listen=MY_WS_ADDR #!ifdef WITH_TLS listen=MY_WSS_ADDR #!endif #!endif # this makes it listen on all ipv6 addresses auto_bind_ipv6=1 dns_try_ipv6=yes # let kamailio choose the right source IP address mhomed=1 # life time of TCP connection when there is no traffic # - a bit higher than registration expires to cope with UA behind NAT tcp_connection_lifetime=3605 ####### Modules Section ######## mpath="/usr/lib64/kamailio/modules/" loadmodule "db_text.so" loadmodule "mi_fifo.so" loadmodule "kex.so" loadmodule "sl.so" loadmodule "rr.so" loadmodule "pv.so" loadmodule "maxfwd.so" loadmodule "textops.so" loadmodule "siputils.so" loadmodule "xlog.so" loadmodule "textopsx.so" loadmodule "corex.so" loadmodule "sanity.so" loadmodule "ctl.so" loadmodule "cfg_rpc.so" loadmodule "mi_rpc.so" loadmodule "usrloc.so" loadmodule "registrar.so" loadmodule "path.so" loadmodule "domain.so" loadmodule "dispatcher.so" loadmodule "nathelper.so" loadmodule "rtpengine.so" loadmodule "tm.so" loadmodule "tmx.so" loadmodule "sdpops.so" loadmodule "xhttp.so" loadmodule "websocket.so" #!ifdef WITH_DEBUG loadmodule "debugger.so" #!endif # ----------------- setting module-specific parameters --------------- modparam("tm", "failure_reply_mode", 3) modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo") # 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) modparam("rr", "append_fromtag", 0) modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)") modparam("nathelper", "nortpproxy_str", "a=sdpmangled:yes\r\n") modparam("path", "use_received", 1) modparam("domain", "db_url", DBURL) modparam("dispatcher", "db_url", DBURL) modparam("rtpengine", "rtpengine_sock", "udp:192.168.0.36:9999 udp:192.168.0.37:9999") #!ifdef WITH_DEBUG # ----- debugger params ----- #modparam("debugger", "cfgtrace", 1) #!endif ####### Routing Logic ######## tcp_accept_no_cl = yes request_route { # Security checks route( REQINIT ); # Fix headers for websockets route( WSDETECT ); if( is_method( "INVITE" ) ) { xlog( "L_INFO", "INVITE" ); route( SETUP_BY_TRANSPORT ); } #route( WITHINDLG ); route( SEND ); } 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) if(src_ip!=myself) { if($sht(ipban=>$si)!=$null) { # ip is already blocked xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n"); exit; } if (!pike_check_req()) { xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n"); $sht(ipban=>$si) = 1; exit; } } if($ua =~ "friendly-scanner") { #sl_send_reply("200", "OK"); #exit; } #!endif if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); exit; } #if(is_method("OPTIONS") && uri==myself && $rU==$null) { # sl_send_reply("200","Keepalive"); # exit; #} if(!sanity_check("1511", "7")) { xlog("Malformed SIP message from $si:$sp\n"); exit; } } route[SETUP_BY_TRANSPORT] { if ($ru =~ "transport=ws") { xlog("L_INFO", "Request going to WS"); # rtpengine_manage("froc+SP"); rtpengine_manage("trust-address replace-origin replace-session-connection ICE=force RTP/SAVPF"); t_on_reply( "REPLY_FROM_WS" ); } else if ($proto =~ "ws") { xlog("L_INFO", "Request coming from WS"); # rtpengine_manage("froc-sp"); rtpengine_manage("trust-address replace-origin replace-session-connection ICE=remove RTP/AVP"); t_on_reply( "REPLY_TO_WS" ); } } onreply_route[REPLY_FROM_WS] { xlog("L_INFO", "Reply from webrtc client: $rs"); route( WSDETECT ); if(status=~"[12][0-9][0-9]") { rtpengine_manage("trust-address replace-origin replace-session-connection ICE=remove RTP/AVP"); # rtpengine_manage("froc-sp"); route(SEND); } } onreply_route[REPLY_TO_WS] { xlog("L_INFO", "Reply from softphone: $rs"); route( WSDETECT ); if (t_check_status("183")) { change_reply_status("180", "Ringing"); remove_body(); exit; } if(!(status=~"[12][0-9][0-9]")) return; # rtpengine_manage("froc+SP"); rtpengine_manage("trust-address replace-origin replace-session-connection ICE=force RTP/SAVPF"); route(SEND); } route[RELAY] { if( !t_relay() ) { sl_reply_error(); } exit; } route[ SEND ] { # If the request cam from the webservice then send to the dispatcher. # otherwise just relay it. if( proto == WS || proto == WSS ) { if( !ds_select_dst( "1", "4" ) ) { send_reply( "480", "Temporarily Unavailable" ); exit; } } route( RELAY ); } route[ WITHINDLG ] { if( has_totag() ) { if( loose_route() ) { if( !handle_ruri_alias() ) { xlog( "L_ERR", "Bad alias <$ru>\n" ); sl_send_reply( "400", "Bad Request" ); exit; } #if( is_method( "ACK" ) ) # route( NATMANAGE ); #else if( is_method( "NOTIFY" ) ) # record_route(); route(RELAY); } else { 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; } } route[ WSDETECT ] { if( proto == WS || proto == WSS ) { force_rport(); if( is_method( "REGISTER" ) ) { fix_nated_register(); #fix_nated_contact(); } # else # { # fix_nated_contact(); # if( !add_contact_alias() ) # { # xlog( "L_ERR", "Error aliasing contact <$ct>\n" ); # sl_send_reply( "400", "Bad Request" ); # exit; # } # } fix_nated_contact(); if( !add_contact_alias() ) { xlog( "L_ERR", "Error aliasing contact <$ct>\n" ); sl_send_reply( "400", "Bad Request" ); exit; } }else { if( $ru != "" ) { handle_ruri_alias(); switch( $rc ) { case -1: xlog( "L_ERR", "Failed to handle alias of R-URI $ru\n" ); send_reply( "400", "Bad Request" ); exit; case 1: xlog( "L_INFO", "Routing in-dialog $rm from $fu to $du\n" ); break; case 2: xlog( "L_INFO", "Routing in-dialog $rm from $fu to $ru\n" ); break; } } } } event_route[websocket:closed] { xlog("L_INFO", "WebSocket connection from $si:$sp has closed\n"); } event_route[xhttp:request] { set_reply_close(); set_reply_no_connect(); if( $hdr(Upgrade)=~"websocket" && $hdr(Connection)=~"Upgrade" && $rm=~"GET") { # Validate as required (Host:, Origin: Cookie:") if( ws_handle_handshake() ) exit; } xhttp_reply( "404", "Not Found", "", "" ); } # Local Variables: # mode: sh # sh-indent-after-if: 0 # indent-tabs-mode: nil # tab-width: 4 # End: