#!KAMAILIO /* */ /* GLOBAL Parameters Section */ /* */ #!ifdef WITH_DEBUG debug=6 log_stderror=no sip_warning=1 #!else debug=2 log_stderror=no #!endif memdbg=5 memlog=5 // Selecting the right socket for sending packets mhomed=1 // Sending log to dedicated syslog log_engine_type="udp" log_engine_data="127.0.0.1:5514" log_facility=LOG_LOCAL0 fork=yes children=2 tcp_children=2 mlock_pages=yes shm_force_alloc=yes // merge freed blocks in memory mem_join=1 // print a summary of used memory (pkg and shm) on exit or SIGUSR1 mem_summary=12 // milliseconds to query db, if longer print log information latency_limit_db=500 // how many files descriptor (including db, sip, wss,...etc) open_files_limit=8192 // do not consider uri with user=phone parameter as tel uris phone2tel=0 /* 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 auto_bind_ipv6=0 disable_sctp=yes # 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 tcp_accept_no_cl=yes tcp_rd_buf_size=16384 tcp_connect_timeout=3 tcp_keepcnt=3 tcp_keepidle=30 tcp_keepintvl=15 tcp_linger2=30 tcp_max_connections=2048 user_agent_header="User-Agent: WebRTCProxy 57a827d68580d05e068b4567" server_signature=yes server_header="Server: WebRTCProxy 57a827d68580d05e068b4567" server_id=2 sip_warning=0 dns=no rev_dns=no // MongoDB url using replica set #!define DBURL "mongodb://kamailiorw:kamailiorwpwd@192.168.138.34,192.168.138.36/kamailio?replicaSet=replicaCCAPI0&w=1&readPreference=primaryPreferred&connectTimeoutMS=300" #!define DBURLCDRS "mongodb://kamailiocdrsrw:kamailiocdrsrwpwd@192.168.138.34,192.168.138.36/kamailiocdrs?replicaSet=replicaCCAPI0&w=1&readPreference=primaryPreferred&connectTimeoutMS=300" #!substdef "!MY_INTERNAL_IP_ADDR!111.99.88.4!g" #!substdef "!MY_EXTERNAL_IP_ADDR!192.168.138.73!g" #!substdef "!MY_DOMAIN!fakeclientdomain.org!g" #!substdef "!MY_WS_PORT!10080!g" #!substdef "!MY_WSS_PORT!10443!g" #!substdef "!MY_SIP_PORT!5060!g" #!substdef "!MY_INTERNAL_SIP_PORT!5080!g" #!substdef "!MY_EXTERNAL_SIP_PORT!5060!g" #!substdef "!MY_EXTERNAL_WS_ADDR!tcp:MY_EXTERNAL_IP_ADDR:MY_WS_PORT!g" #!substdef "!MY_EXTERNAL_WSS_ADDR!tls:MY_EXTERNAL_IP_ADDR:MY_WSS_PORT!g" #!substdef "!MY_EXTERNAL_SIP_ADDR!udp:MY_EXTERNAL_IP_ADDR:MY_EXTERNAL_SIP_PORT!g" #!substdef "!MY_INTERNAL_SIP_ADDR!udp:MY_INTERNAL_IP_ADDR:MY_INTERNAL_SIP_PORT!g" #!substdef "!DEFAULTHTTPTIMEOUTMSEC!1000!g" #!define MY_RTPENG_SOCK "udp:127.0.0.1:2223" # - 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 FLT_OUT 8 #!define FLT_DIALOG 9 #!define FLT_SIPTRACE 10 #!define MULTIDOMAIN 1 #!define WITH_ACCDB #!define WITH_NAT #!define WITH_HOMER_SECURITY_CHECKS #!define WITH_AUTH #!define WITH_MULTIDOMAIN #!define WITH_TLS #!define WITH_SIPTRACE #!define WITH_TOPOH kaminternal.ip = "MY_INTERNAL_IP_ADDR" desc "Internal IP Address" kaminternal.sip_port = "MY_INTERNAL_SIP_PORT" desc "Internal SIP port" kamexternal.ip = "MY_EXTERNAL_IP_ADDR" desc "External IP Address" kamexternal.sip_port = "MY_EXTERNAL_SIP_PORT" desc "External SIP port" kamexternal.ws_port = "MY_WS_PORT" desc "External WS port" kamexternal.wss_port = "MY_WSS_PORT" desc "External WSS port" ####### Modules Section ######## # set paths to location of modules (to sources or installation folders) #!ifdef WITH_SRCPATH mpath="modules" #!else mpath="/product/CCAPI/WebRTC/Kamailio/lib64/kamailio/modules/" #!endif #!ifdef WITH_TLS enable_tls=yes #!endif listen=MY_INTERNAL_SIP_ADDR listen=MY_EXTERNAL_SIP_ADDR listen=MY_EXTERNAL_WS_ADDR listen=MY_EXTERNAL_WSS_ADDR // listening on local interface as kamailio needs a local socket to send data to syslog listen=udp:127.0.0.1:6060 loadmodule "log_custom.so" #!ifdef WITH_TLS loadmodule "tls.so" #!endif loadmodule "db_mongodb.so" loadmodule "textopsx.so" loadmodule "websocket.so" loadmodule "xhttp.so" loadmodule "mi_fifo.so" loadmodule "kex.so" loadmodule "corex.so" loadmodule "tm.so" loadmodule "tmx.so" loadmodule "sl.so" loadmodule "stun.so" loadmodule "outbound.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 "topoh.so" loadmodule "ctl.so" loadmodule "cfg_rpc.so" loadmodule "mi_rpc.so" loadmodule "sdpops.so" loadmodule "dialog.so" loadmodule "acc.so" #!ifdef WITH_SIPTRACE loadmodule "siptrace.so" #!endif #!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_NAT loadmodule "nathelper.so" loadmodule "rtpengine.so" #!endif #!ifdef WITH_ANTIFLOOD loadmodule "pike.so" #!endif loadmodule "htable.so" loadmodule "presence.so" loadmodule "http_async_client.so" loadmodule "http_client.so" loadmodule "json.so" loadmodule "uac.so" loadmodule "rtjson.so" #!ifdef WITH_DEBUG loadmodule "debugger.so" #!endif loadmodule "ipops.so" # ----------------- setting module-specific parameters --------------- # ----- xlog ----- modparam("xlog", "buf_size", 8192) modparam("xlog", "long_format", 1) # ----- mi_fifo params ----- modparam("mi_fifo", "fifo_name", "/var/run/kamailio/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) modparam("tm", "reparse_on_dns_failover", 0) modparam("tm", "xavp_contact", "ulattrs") # ----- 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) modparam("rr", "append_fromtag", 1) modparam("corex", "alias_subdomains", "MY_DOMAIN") # -- dialog params -- modparam("dialog", "dlg_flag", FLT_DIALOG) # ----- registrar params ----- modparam("registrar", "method_filtering", 1) /* uncomment the next line to disable parallel forking via location */ # modparam("registrar", "append_branches", 0) modparam("registrar", "max_contacts", 1) # max value for expires of registrations modparam("registrar", "max_expires", 600) modparam("registrar", "min_expires", 30) # default expires if not specified, 5 minutes modparam("registrar", "default_expires", 300) # set it to 1 to enable GRUU modparam("registrar", "gruu_enabled", 0) # ----- acc params ----- /* what special events should be accounted ? */ modparam("acc", "early_media", 1) modparam("acc", "report_ack", 1) modparam("acc", "report_cancels", 1) modparam("acc", "time_mode", 1) modparam("acc", "cdr_enable", 1) modparam("acc", "cdr_start_on_confirmed", 1) modparam("acc", "cdr_on_failed", 1) modparam("acc", "cdr_expired_dlg_enable", 1) modparam("acc", "cdrs_table", "acc_cdrs") modparam("acc", "cdr_extra", "src_user=$fU;src_domain=$fd;src_ip=$si;" "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") 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) modparam("acc", "db_flag", FLT_ACC) modparam("acc", "db_missed_flag", FLT_ACCMISSED) modparam("acc", "db_extra", "src_user=$fU;src_domain=$fd;src_ip=$si;" "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") modparam("acc", "db_url", DBURLCDRS) #!ifdef WITH_SIPTRACE # ----- sip tracing modparam("siptrace", "duplicate_uri", "sip:192.168.138.71:9060") modparam("siptrace", "hep_mode_on", 1) modparam("siptrace", "hep_capture_id", 2) modparam("siptrace", "hep_version", 2) modparam("siptrace", "trace_to_database", 0) modparam("siptrace", "trace_flag", FLT_SIPTRACE) modparam("siptrace", "trace_on", 1) modparam("siptrace", "trace_sl_acks", 1) modparam("siptrace", "trace_mode", 1) modparam("siptrace", "force_send_sock", "sip:192.168.138.73:5060") #!endif # ----- usrloc params ----- /* enable DB persistency for location entries */ modparam("usrloc", "db_url", DBURL) modparam("usrloc", "db_mode", 1) modparam("usrloc", "db_insert_null", 1) modparam("usrloc", "use_domain", MULTIDOMAIN) modparam("usrloc", "close_expired_tcp", 1) modparam("usrloc", "xavp_contact", "ulattrs") # ----- auth_db params ----- #!ifdef WITH_AUTH modparam("auth_db", "db_url", DBURL) #modparam("auth_db", "calculate_ha1", yes) modparam("auth_db", "calculate_ha1", 0) #modparam("auth_db", "password_column", "password") modparam("auth_db", "password_column", "ha1") modparam("auth_db", "password_column_2", "ha1b") modparam("auth_db", "load_credentials", "") modparam("auth_db", "use_domain", MULTIDOMAIN) # Need to add configuration tips to avoid replay attack # ----- permissions params ----- #!ifdef WITH_IPAUTH modparam("permissions", "db_url", DBURL) modparam("permissions", "db_mode", 1) #!endif #!endif #!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) # register callback to match myself condition with domains list modparam("domain", "register_myself", 1) #!endif modparam("presence", "db_url", DBURL) modparam("presence", "subs_db_mode", 1) #!ifdef WITH_ANTIFLOOD # ----- pike params ----- modparam("pike", "sampling_time_unit", 2) modparam("pike", "reqs_density_per_unit", 45) modparam("pike", "remove_latency", 4) # ----- htable params ----- # ip ban htable with autoexpire after 5 minutes modparam("htable", "htable", "ipban=>size=8;autoexpire=3600;") #!endif #!ifdef WITH_NAT # ----- rtpproxy params ----- modparam("rtpengine", "rtpengine_sock", MY_RTPENG_SOCK) modparam("rtpengine", "rtpengine_allow_op", 1) modparam("rtpengine", "force_send_interface", "127.0.0.1") // No db_url set, we read configuration from file and not from db. # ----- nathelper params ----- modparam("nathelper", "natping_interval", 15) modparam("nathelper", "ping_nated_only", 1) modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) modparam("nathelper", "sipping_from", "sip:pinger@webrtcproxy.invalid") # params needed for NAT traversal in other modules modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)") modparam("usrloc", "nat_bflag", FLB_NATB) #!endif # ----- rtjson params ----- modparam("http_async_client", "connection_timeout", 2 ) modparam("http_async_client", "workers", 5) modparam("http_async_client", "curl_verbose", 1) modparam("http_async_client", "memory_manager", "sys") #!ifdef WITH_TLS # ----- tls params ----- modparam("tls", "config", "tls.cfg") #!endif # ----- blocking http client modparam("http_client", "connection_timeout", 2) # ----- websockets params ----- modparam("websocket", "keepalive_mechanism", 1) modparam("websocket", "keepalive_timeout", 60) modparam("websocket", "keepalive_processes", 1) modparam("websocket", "keepalive_interval", 10) modparam("websocket", "ping_application_data", "WebRTCProxy Ping" ) modparam("websocket", "sub_protocols", 1) modparam("websocket", "cors_mode", 2) # cors_mode # default value 0 means no Access-Control-Allow-Origin header sent back # value 1 send back 'Access-Control-Allow-Origin:*', but the string '*' cannot be used for a resource that supports credentials # value 2 means 'Access-Control-Allow-Origin: XXXXXX', where XXXXXX is the same body as 'Origin' header in request. # ---- topo hidding #!ifdef WITH_TOPOH modparam("topoh", "mask_key", "a not so secure key" ) modparam("topoh", "mask_ip", "127.8.8.8" ) modparam("topoh", "mask_callid", 0) modparam("topoh", "sanity_checks", 1) #!endif #!ifdef WITH_DEBUG # ----- debugger params ----- modparam("debugger", "cfgtrace", 1) #!endif /* */ /* Routing Blocks Sectioon */ /* */ /* request_route is called for each request */ request_route { if ((($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT) && !(proto == WS || proto == WSS))) { xlogl("L_WARN", "SIP request or something else received on $Rp\n"); sl_send_reply("403", "Forbidden"); exit; } xlogl("L_INFO","Received message from $si:$sp $mb\n"); #!ifdef WITH_SIPTRACE # xlogl("L_INFO", "SIP trace activated\n"); # sip_trace(); # setflag(FLT_SIPTRACE); #!endif remove_hf("X-FS-Support"); remove_hf("Allow-Events"); # per request initial checks route(REQINIT); # NAT detection route(NATDETECT); route(HOMER_SECURITY_CHECKS); # CANCEL processing if (is_method("CANCEL")) { if (t_check_trans()) { route(RELAY); } exit; } # handle requests within SIP dialogs route(WITHINDLG); ### only initial requests (no To tag) t_check_trans(); if (!is_method("REGISTER|INVITE|ACK|BYE|CANCEL|PRACK|MESSAGE|INFO|UPDATE")) { sl_send_reply("405", "Method not allowed"); exit; } # 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(); if (is_method("INVITE|REGISTER")) { setflag(FLT_ACC); setflag(FLT_ACCMISSED); } if(is_method("INVITE")) { if(route(MSG_RECV_EXTERNAL)) { append_hf("P-hint: inbound\r\n"); } else { append_hf("P-hint: outbound\r\n"); } } route(PRESENCE); # handle registrations route(REGISTRAR); if ($rU==$null) { # request with no Username in RURI sl_send_reply("484","Address Incomplete"); exit; } if (!is_method("INVITE")) { route(RELAY); exit; } // Now processing INVITE if (route(MSG_RECV_EXTERNAL)) { // Received on external leg, assuming inbound call route(REQUESTRTJSON); exit; } route(LOCATION); } route[REQUESTRTJSON] { xlogl("L_INFO", "Requesting JSON routes\n"); t_newtran(); $http_req(hdr) = "Expect:"; $http_req(timeout) = DEFAULTHTTPTIMEOUTMSEC; http_async_query("http://127.0.0.1/webrtcwslb/forwarder.php?forwardservice=kamailiort&rU=$(rU{s.encode.hexa})&fU=$(fU{s.encode.hexa})&dd=$(dd{s.encode.hexa})&du=$(du{s.encode.hexa})&rd=$(rd{s.encode.hexa})&fn=$(fn{s.encode.hexa})&fd=$(fd{s.encode.hexa})&td=$(td{s.encode.hexa})&tn=$(tn{s.encode.hexa})&tU=$(tU{s.encode.hexa})&ci=$(ci{s.encode.hexa})&ct=$(ct{s.encode.hexa})&si=$(si{s.encode.hexa})&mb=$(mb{s.encode.hexa})&dP=$(dP{s.encode.hexa})","HTTPRTJSONREPLY"); } route[HTTPRTJSONREPLY] { if($http_ok) { xlogl("L_INFO", "route[HTTPRTJSONREPLY]: status $http_rs\n"); xlogl("L_INFO", "route[HTTPRTJSONREPLY]: body $http_rb\n"); json_get_field($http_rb,"routing", "$var(routing)"); if($var(routing)=="location") { route(LOCATION); exit; } xlogl("L_INFO", "route[HTTPRTJSONREPLY]: init routes\n"); rtjson_init_routes("$http_rb"); xlogl("L_INFO", "route[HTTPRTJSONREPLY]: pushing routes\n"); rtjson_push_routes(); xlogl("L_INFO", "route[HTTPRTJSONREPLY]: pushed routes\n"); t_on_branch("MANAGE_BRANCH"); t_on_failure("MANAGE_FAILURE"); route(RELAY); exit; } else { xlogl("L_INFO", "route[HTTPRTJSONREPLY]: error $http_err\n"); exit; } } route[PRESENCE] { if (!is_method("PUBLISH|SUBSCRIBE")) return; if (route(MSG_RECV_INTERNAL)) { sl_send_reply("403", "Forbidden"); exit; } if(!t_newtran()) { sl_reply_error(); exit; } if(is_method("PUBLISH")) { handle_publish(); t_release(); } else if(is_method("SUBSCRIBE")) { handle_publish(); t_release(); } exit; } /* Routes to check the leg the message was received on */ route[MSG_RECV_INTERNAL] { xlogl("L_INFO", "Checking if message is on internal leg, Comparing Ri $Ri\n"); if($Ri=="MY_INTERNAL_IP_ADDR") { xlogl("L_INFO", "is internal\n"); return 1; } return -1; } route[MSG_RECV_INTERNAL_SIP] { xlogl("L_INFO", "Checking if message is on internal leg, Comparing Ri $Ri and Rp $Rp\n"); if( $Ri == "MY_INTERNAL_IP_ADDR" && $Rp == MY_INTERNAL_SIP_PORT) { xlogl("L_INFO", "is internal\n"); return 1; } return -1; } route[MSG_RECV_EXTERNAL] { xlogl("L_INFO", "Checking if message is on external leg, Comparing Ri $Ri\n"); if( $Ri == "MY_EXTERNAL_IP_ADDR") { xlogl("L_INFO", "is external\n"); return 1; } return -1; } route[MSG_RECV_EXTERNAL_SIP] { xlogl("L_INFO", "Checking if message is on external leg SIP, Comparing Ri $Ri and Rp $Rp\n"); if( $Ri == "MY_EXTERNAL_IP_ADDR" && $Rp == MY_EXTERNAL_SIP_PORT) { xlogl("L_INFO", "is external\n"); return 1; } return -1; } route[MSG_RECV_EXTERNAL_WS] { xlogl("L_INFO", "Checking if message is on external leg WS, Comparing Ri $Ri and Rp $Rp\n"); if( $Ri == "MY_EXTERNAL_IP_ADDR" && $Rp == MY_WS_PORT) { xlogl("L_INFO", "is external\n"); return 1; } return -1; } route[MSG_RECV_EXTERNAL_WSS] { xlogl("L_INFO", "Checking if message is on external leg WSS, Comparing Ri $Ri and Rp $Rp\n"); if( $Ri == "MY_EXTERNAL_IP_ADDR" && $Rp == MY_WSS_PORT) { xlogl("L_INFO", "is external\n"); return 1; } return -1; } route[RELAY] { if (is_method("INVITE")) { setflag(FLT_DIALOG); route(SETUP_BY_TRANSPORT); if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE"); if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY"); if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE"); } if(route(MSG_RECV_EXTERNAL)) { if(is_method("BYE|INFO")) { if (auth_check("$fd", "subscriber", "1")) { consume_credentials(); } } } if (is_method("BYE")) { append_hf("X-RTP-Statistics: $rtpstat\r\n"); xlogl("L_INFO", "rtpengine_manage()\n"); rtpengine_manage(); } if (!t_relay()) { sl_reply_error(); } exit; } route[SETUP_BY_TRANSPORT] { // Processing INVITE Request xlogl("L_INFO", "Transport Setup for ruri $ru , proto $proto, recv ip $Ri\n"); if ($ru =~ "transport=ws") { xlogl("L_INFO", "Request going to WS\n"); if(sdp_with_transport("RTP/SAVPF")) { xlogl("L_INFO", "rtpengine_manage(direction=internal direction=external trust-address replace-origin replace-session-connection ICE=force)\n"); rtpengine_manage("direction=internal direction=external trust-address replace-origin replace-session-connection ICE=force"); t_on_reply("REPLY_WS_TO_WS"); return; } xlogl("L_INFO", "rtpengine_manage(direction=internal direction=external trust-address replace-origin replace-session-connection ICE=force RTP/SAVPF)\n"); rtpengine_manage("direction=internal direction=external trust-address replace-origin replace-session-connection ICE=force RTP/SAVPF"); t_on_reply("REPLY_FROM_WS"); } else if ($proto =~ "ws") { xlogl("L_INFO", "Request coming from WS\n"); xlogl("L_INFO", "rtpengine_manage(direction=external direction=internal trust-address replace-origin replace-session-connection ICE=remove RTP/AVP)\n"); rtpengine_manage("direction=external direction=internal trust-address replace-origin replace-session-connection ICE=remove RTP/AVP"); t_on_reply("REPLY_TO_WS"); } else { xlogl("L_INFO", "This is a classic phone call\n"); if(route(MSG_RECV_INTERNAL)) { xlogl("L_INFO", "This is a classic phone call INTERNAL => EXTERNAL\n"); xlogl("L_INFO", "rtpengine_manage(direction=internal direction=external replace-origin replace-session-connection)\n"); rtpengine_manage("direction=internal direction=external replace-origin replace-session-connection"); force_send_socket(MY_EXTERNAL_SIP_ADDR); t_on_reply("MANAGE_CLASSIC_REPLY_TO_EXTERNAL"); } else { xlogl("L_INFO", "This is a classic phone call EXTERNAL => INTERNAL\n"); xlogl("L_INFO", "rtpengine_manage(direction=external direction=internal replace-origin replace-session-connection)\n"); rtpengine_manage("direction=external direction=internal replace-origin replace-session-connection"); force_send_socket(MY_INTERNAL_SIP_ADDR); t_on_reply("MANAGE_CLASSIC_REPLY_TO_INTERNAL"); } } } event_route[xhttp:request] { set_reply_close(); set_reply_no_connect(); if ($Rp != MY_WS_PORT #!ifdef WITH_TLS && $Rp != MY_WSS_PORT #!endif ) { xlogl("L_WARN", "HTTP request received on $Rp from $si:$sp Forbidden\n"); xhttp_reply("403", "Forbidden", "", ""); exit; } xlogl("L_INFO", "HTTP Request Received from $si:$sp\n"); if ($hdr(Upgrade)=~"websocket" && $hdr(Connection)=~"Upgrade" && $rm=~"GET") { # Validate Host - make sure the client is using the correct # alias for WebSockets xlogl("L_INFO", "HTTP Request checking $hdr(Host)\n"); if ( $hdr(Host) == $null || ( $hdr(Host) != "MY_EXTERNAL_IP_ADDR" && $hdr(Host) != "MY_EXTERNAL_IP_ADDR:MY_WS_PORT" && $hdr(Host) != "MY_EXTERNAL_IP_ADDR:MY_WSS_PORT" && $hdr(Host) != $HN(n) && $hdr(Host) != $HN(n) + ":MY_WS_PORT" && $hdr(Host) != $HN(n) + ":MY_WSS_PORT" ) ) { xlogl("L_WARN", "MY_EXTERNAL_IP_ADDR\n"); xlogl("L_WARN", "MY_EXTERNAL_IP_ADDR:MY_WS_PORT\n"); xlogl("L_WARN", "MY_EXTERNAL_IP_ADDR:MY_WSS_PORT\n"); xlogl("L_WARN", "$HN(n)\n"); xlogl("L_WARN", "$HN(n):MY_WS_PORT\n"); xlogl("L_WARN", "$HN(n):MY_WSS_PORT\n"); xlogl("L_WARN", "Bad host $hdr(Host)\n"); if(strlen("vip=10.1.1.1;vip=ip.fqdn.org;") > 0) { /* Checking all VIP using regexp */ if ( !( "vip=10.1.1.1;vip=ip.fqdn.org;" =~ ".*vip=" + $hdr(Host) + ";.*")) { xlogl("L_WARN", "Unauthorised client, bad hostname $hdr(Host) from $si:$sp Forbidden\n"); xhttp_reply("403", "Forbidden", "", ""); exit; } } else { xhttp_reply("403", "Forbidden", "", ""); exit; } } xlogl("L_INFO", "Requesting check on Origins\n"); $var(retcode) = http_client_query("http://127.0.0.1/webrtcwslb/forwarder.php?forwardservice=kamailioorigins&origin=$(hdr(Origin){s.encode.hexa})", "$var(httpor)"); xlogl("L_INFO", "Processing Answer on Origins HTTP return code from webservice is $var(retcode) \n"); if($var(retcode) == 200) { xlogl("L_INFO", "route[HTTPORIGINREPLY]: status 200\n"); xlogl("L_INFO", "route[HTTPORIGINREPLY]: body $var(httpor)\n"); if ( !( $var(httpor) =~ "allowed")) { xlogl("L_WARN", "Unauthorised client origin $hdr(Origin) from $si:$sp Forbidden\n"); xhttp_reply("403", "Forbidden", "", ""); exit; } if (ws_handle_handshake()) { # Optional... cache some information about the # successful connection xlogl("L_INFO","ws handshake done\n"); exit; } } xlogl("L_WARN", "route[HTTPORIGINREPLY]: error $var(retcode)\n"); xhttp_reply("500", "Error", "", ""); exit; } xhttp_reply("404", "Not Found", "", ""); } event_route[websocket:closed] { xlogl("L_INFO", "WebSocket connection from $si:$sp has closed\n"); } # 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) if(src_ip!=myself) { if($sht(ipban=>$si)!=$null) { # ip is already blocked xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)"); exit; } if (!pike_check_req()) { xlogl("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\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")) { xlogl("L_ERR","Malformed SIP message from $si:$sp\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 ($du == "") { if (!handle_ruri_alias()) { xlogl("L_ERR", "Bad alias <$ru>\n"); sl_send_reply("400", "Bad Request"); exit; } } # else # route(DLGURI); xlogl("L_INFO","==> duri=[$du]\n"); if ( is_method("ACK") ) { # ACK is forwarded statelessy if(route(MSG_RECV_EXTERNAL)) { if (is_present_hf("Proxy-Authorization")) { xlogl("L_INFO","ACK statelessy before NATMANAGE, removing Proxy-Authorization\n"); remove_hf("Proxy-Authorization"); } } route(NATMANAGE); } 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 xlogl("L_INFO","ACK before RELAY\n"); route(RELAY); exit; } else { # ACK without matching transaction ... ignore and discard xlogl("L_INFO","ACK without matching transaction\n"); exit; } } sl_send_reply("404","Not here"); } exit; } } # Handle SIP registrations route[REGISTRAR] { if (is_method("REGISTER")) { if(route(MSG_RECV_INTERNAL)) { xlogl("L_INFO","REGISTER received on internal leg\n"); sl_send_reply("403", "Forbidden"); exit; } if(isflagset(FLT_NATS)) { setbflag(FLB_NATB); # uncomment next line to do SIP NAT pinging setbflag(FLB_NATSIPPING); } # $xavp(ulattrs[0]=>internal_ip)="MY_INTERNAL_IP_ADDR"; $xavp(ulattrs=>internal_ip)="MY_INTERNAL_IP_ADDR"; $xavp(ulattrs[0]=>external_ip)="MY_EXTERNAL_IP_ADDR"; $xavp(ulattrs[0]=>proxyname)=$HN(n); $xavp(ulattrs[0]=>srcip)=$si; if (!save("location","0x04")) { xlogl("L_ERR","Can't save location\n"); sl_reply_error(); } exit; } } # USER location service route[LOCATION] { if (!lookup("location")) { $var(rc) = $rc; t_newtran(); switch ($var(rc)) { case -1: case -3: send_reply("404", "Not Found"); exit; case -2: send_reply("405", "Method Not Allowed"); exit; } } route(RELAY); exit; } # Authentication route route[AUTH] { #!ifdef WITH_AUTH xlogl("L_INFO","Checking Authentication\n"); if (is_method("REGISTER")) { xlogl("L_INFO","Checking REGISTER Authentication\n"); # authenticate requests if (!auth_check("$fd", "subscriber", "1")) { xlogl("L_INFO","auth_check failed using $fd\n"); auth_challenge("$fd", "0"); exit; } # user authenticated - remove auth header if(!is_method("REGISTER|PUBLISH")) consume_credentials(); } if (is_method("INVITE")) { if(route(MSG_RECV_EXTERNAL)) { xlogl("L_INFO","Checking INVITE Authentication for external\n"); if (!auth_check("$fd", "subscriber", "1")) { xlogl("L_INFO","INVITE auth_check failed using $fd\n"); auth_challenge("$fd", "0"); exit; } consume_credentials(); } else { xlogl("L_INFO","No need to check INVITE Authentication for internal\n"); } } #!endif return; } # Caller NAT detection route route[NATDETECT] { force_rport(); # if (nat_uac_test("64")) { if (is_method("REGISTER")) { fix_nated_register(); } else { add_contact_alias(); # fix_nated_contact(); } setflag(FLT_NATS); # } return; } # RTPProxy control route[NATMANAGE] { if (is_request()) { if(has_totag()) { if(check_route_param("nat=yes")) { setbflag(FLB_NATB); } } } if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) return; if (is_request()) { if (!has_totag()) { if(t_is_branch_route()) { add_rr_param(";nat=yes"); } } } if (is_reply()) { if(isbflagset(FLB_NATB)) { add_contact_alias(); } } } # URI update for dialog requests route[DLGURI] { if(!isdsturiset()) { handle_ruri_alias(); } return; } route[HOMER_SECURITY_CHECKS] { #!ifdef WITH_HOMER_SECURITY_CHECKS if (is_method("INVITE|REGISTER")) { if($ua =~ "(friendly-scanner|sipvicious)") { xlogl("L_INFO","On more scriptkiddie, coming from $si, blocking\n"); exit; } /* #hostname in contact if($sel(contact.uri.host) =~ "^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$") { xlogl("L_INFO","Someone coming from $si using IP addressess instead of DNS ? blocking\n"); exit; } */ if($au =~ "(\=)|(\-\-)|(')|(\#)|(\%27)|(\%24)" and $au != $null) { xlogl("L_INFO","Someone from $si is doing an sql injection attack, blocking!\n"); exit; } if($(hdr(Record-Route)[0]{nameaddr.uri}) != $si and $(hdr(Record-Route)[0]{nameaddr.uri}) != $null) { xlogl("L_INFO","Spoofing attack detected from $si, blocking\n"); exit; } } #!endif } onreply_route[REPLY_TO_WS] { xlogl("L_INFO", "onreply_route REPLY_TO_WS Reply to softphone : $rs\n"); xlogl("L_INFO","onreply_route REPLY_TO_WS Reply message $mb\n"); remove_hf("Allow-Events"); 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"); xlogl("L_INFO", "rtpengine_manage(force trust-address replace-origin replace-session-connection ICE=force RTP/SAVPF)\n"); rtpengine_manage("force trust-address replace-origin replace-session-connection ICE=force RTP/SAVPF"); route(NATMANAGE); } onreply_route[REPLY_FROM_WS] { xlogl("L_INFO", "Reply REPLY_FROM_WS from webrtc client: $rs\n"); xlogl("L_INFO","onreply_route REPLY_FROM_WS Received message $mb\n"); remove_hf("Allow-Events"); if(status=~"[12][0-9][0-9]") { xlogl("L_INFO", "rtpengine_manage(force trust-address replace-origin replace-session-connection ICE=remove RTP/AVP)\n"); rtpengine_manage("force trust-address replace-origin replace-session-connection ICE=remove RTP/AVP"); # rtpengine_manage("froc-sp"); route(NATMANAGE); } } onreply_route[MANAGE_CLASSIC_REPLY_TO_EXTERNAL] { xlogl("L_INFO", "Boring reply from softphone: $rs\n"); xlogl("L_INFO","onreply_route MANAGE_CLASSIC_REPLY_TO_EXTERNAL Received message $mb\n"); remove_hf("Allow-Events"); if(status=~"[12][0-9][0-9]") { xlogl("L_INFO", "rtpengine_manage(direction=external direction=internal replace-origin replace-session-connection)\n"); rtpengine_manage("direction=external direction=internal replace-origin replace-session-connection"); route(NATMANAGE); } } onreply_route[MANAGE_CLASSIC_REPLY_TO_INTERNAL] { xlogl("L_INFO", "Boring reply from softphone: $rs\n"); xlogl("L_INFO","onreply_route MANAGE_CLASSIC_REPLY_TO_INTERNAL Received message $mb\n"); remove_hf("Allow-Events"); if(status=~"[12][0-9][0-9]") { xlogl("L_INFO", "rtpengine_manage(direction=internal direction=external replace-origin replace-session-connection)\n"); rtpengine_manage("direction=internal direction=external replace-origin replace-session-connection"); route(NATMANAGE); } } onreply_route[REPLY_WS_TO_WS] { xlogl("L_INFO", "WS to WS\n"); xlogl("L_INFO","onreply_route REPLY_WS_TO_WS Received message $mb\n"); remove_hf("Allow-Events"); if(status=~"[12][0-9][0-9]") { xlogl("L_INFO", "rtpengine_manage(force trust-address replace-origin replace-session-connection ICE=force)\n"); rtpengine_manage("force trust-address replace-origin replace-session-connection ICE=force"); route(NATMANAGE); } } # Manage outgoing branches branch_route[MANAGE_BRANCH] { xlogl("L_INFO","new branch [$T_branch_idx] to $ru\n"); rtjson_update_branch(); route(NATMANAGE); } onreply_route[MANAGE_REPLY] { xlogl("L_INFO","incoming reply\n"); xlogl("L_INFO","onreply_route MANAGE_REPLY message $mb\n"); remove_hf("Allow-Events"); if(status=~"[12][0-9][0-9]") route(NATMANAGE); } # manage failure routing cases failure_route[MANAGE_FAILURE] { xlogl("L_INFO","Handling failure route\n"); route(NATMANAGE); if (t_is_canceled()) { exit; } if(rtjson_next_route()) { t_on_branch("MANAGE_BRANCH"); t_on_failure("MANAGE_FAILURE"); route(RELAY); exit; } }