Kamailio TLS-UDP with dispatcher and used old openssl 1.0.2 (sslv2\3 support)

This project is how to convert TLS-UDP with kamailio. Problem is that modern Unix (Ubuntu and debian have only modern openssl library so it’s not support ssv2\3 protocol). To make it works you have to

  • do this steps at vanilla system.
  • get source of kamailio
  • for compiling using /make include_modules=”tls”/
  • rtpengine should be installed as usual
  • then everything should go as usual

Benefits from this configs is that working for inbound\outbound calls and use Dispatcher.
this is example of dispatcher file:

#
# dispatcher destination sets (groups)
#

# line format
# setid(int) destination(sip uri) flags(int,opt) priority(int,opt) attributes(str,opt)


1 sip:PEER1:5070;transport=udp 0 0 socket=udp:KAM_SOCKET_UDP:5070
1 sip:PERR2;transport=udp 0 0 socket=udp:KAM_SOcKET_UDP:5070

2 sip:TLS_CARRIER:5061;transport=tls 0 0 socket=tls:TLS_SOCKET_KAM:5061

Example of kamailio config you may get here.

#!KAMAILIO
#
############################################################
# *** Value defines - IDs used later in config
#!ifdef WITH_DEBUG
#!define DBGLEVEL 3
#!else
#!define DBGLEVEL 2
#!endif
#!define DS_LIST "/usr/local/etc/kamailio/dispatcher.list"
#!define LISTEN_UDP_PRIVATE udp:LOCAL_INTERFACE_IP:5070
#!define FLAG_FROM_ASTERISK 10
#!define FLAG_FROM_PEER 11


# - flags
#   FLT_ - per transaction (message) flags
#!define FLT_ACC 1
#!define FLT_ACCMISSED 2
#!define FLT_ACCFAILED 3
#!define FLT_NATS 5

#	FLB_ - per branch flags
#!define FLB_NATB 6
#!define FLB_NATSIPPING 7

####### Global Parameters #########

/* LOG Levels: 3=DBG, 2=INFO, 1=NOTICE, 0=WARN, -1=ERR, ... */
debug=DBGLEVEL

/* set to 'yes' to print log messages to terminal or use '-E' cli option */
log_stderror=no

memdbg=5
memlog=5

log_facility=LOG_LOCAL0
log_prefix="{$mt $hdr(CSeq) $ci} "

children=8

auto_aliases=no

server_signature=no

alias="DOMAIN_NAME"

listen=udp:LOCAL_INTERFACE_IP:5070
listen=tls:LOCAL_INTERFACE_IP:5061 advertise EXTERNAL_IP:5061

tcp_connection_lifetime=3605

tcp_max_connections=20000

tcp_accept_no_cl=yes

enable_tls=yes
tls_max_connections=20000

enable_sctp=no

####### Modules Section ########
mpath="/usr/local/lib64/kamailio/modules/"


#loadmodule "db_mysql.so"
loadmodule "kex.so"
loadmodule "corex.so"
loadmodule "tm.so"
loadmodule "pike.so"
loadmodule "htable.so"
loadmodule "nathelper.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
#loadmodule "registrar"
#loadmodule "usrloc.so"
loadmodule "textops.so"
loadmodule "textopsx.so"
loadmodule "dialog.so"
loadmodule "tls.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "cfg_rpc.so"
loadmodule "acc.so"
loadmodule "counters.so"
loadmodule "dispatcher.so"
loadmodule "outbound.so"
loadmodule "rtpengine.so"
loadmodule "path.so"


####Module Specific Parameters####
modparam("rr", "enable_double_rr", 1)

modparam("tls", "config", "/etc/kamailio/tls.cfg")
modparam("path", "use_received", 1)


modparam("acc", "log_flag", FLT_ACC)
modparam("acc", "failed_transaction_flag", FLT_ACCFAILED)
modparam("acc", "log_extra", "src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd;src_ip=$si")

modparam("rtpengine", "rtpengine_sock", "udp:127.0.0.1:2223")
modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 16)
modparam("pike", "remove_latency", 4)
modparam("htable", "htable", "ipban=>size=8;autoexpire=300;")


modparam("dispatcher", "list_file", DS_LIST)
#modparam("dispatcher", "db_url", DBURL)
modparam("dispatcher", "table_name", "dispatcher")
modparam("dispatcher", "flags", 2)
modparam("dispatcher", "ds_ping_reply_codes", "class=2;code=480;code=404")
modparam("dispatcher", "ds_probing_mode", 1)
modparam("dispatcher", "ds_ping_reply_codes", "class=2;code=480;code=404")
modparam("dispatcher", "force_dst", 1)
modparam("dispatcher", "ds_ping_interval", 20)
modparam("dispatcher", "ds_ping_from", "sip:keepalive@smsglobal.com")
modparam("dispatcher", "ds_ping_reply_codes", "class=2;code=480;code=404")
modparam("nathelper", "received_avp", "$avp(s:rcv)")


###Routing Logic

request_route {

	# per request initial checks
	route(REQINIT);
	
	# 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();
	}

        route(CHECK_SOURCE_IP);

	# 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
	}

	# handle presence related requests
	route(PRESENCE);

	# handle registrations
	route(REGISTRAR);

	if ($rU==$null) {
		# request with no Username in RURI
		sl_send_reply("484","Address Incomplete");
		exit;
	}

	# dispatch destinations
	route(DISPATCH);
}


route[RELAY] {
    if (is_method("INVITE")) {
        if(!t_is_set("failure_route")) {
            t_on_failure("MANAGE_FAILURE");
        }
    }

    if (isflagset(FLAG_FROM_PEER)) {
	    xlog("L_INFO","seems call from $si goig from PEER");
	    
    } else {
            
            xlog("L_INFO","Relaying TO TLS\n ");
    }


    if (!t_relay()) {
            sl_reply_error();
    }
    #exit;

}

# Per SIP request initial checks
route[REQINIT] {
	if (!mf_process_maxfwd_header("10")) {
		sl_send_reply("483","Too Many Hops");
		exit;
	}

	if(!sanity_check("1511", "7")) {
		xlog("Malformed SIP message from $si:$sp\n");
		exit;
	}
	force_rport();
	
	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|sipcli|sipvicious|VaxSIPUserAgent") {
		# silent drop for scanners - uncomment next line if want to reply
		# sl_send_reply("200", "OK");
		exit;
	}
	if(is_method("OPTIONS") && uri==myself && $rU==$null) {
		sl_send_reply("200","Keepalive");
		exit;
	}



}

route[CHECK_SOURCE_IP] {
    if(ds_is_from_list("1")) {
            setflag(FLAG_FROM_ASTERISK);
    } else {
            setflag(FLAG_FROM_PEER);
    }
}

# 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 (is_method("BYE")) {
				setflag(FLT_ACC); # do accounting ...
				setflag(FLT_ACCFAILED); # ... even if the transaction fails
			}
			route(RELAY);
		} else {
			if (is_method("SUBSCRIBE") && uri == myself) {
				# in-dialog subscribe requests
				exit;
			}
			if ( is_method("ACK") ) {
				if ( t_check_trans() ) {
					# non loose-route, but stateful ACK;
					# must be ACK after a 487 or e.g. 404 from upstream server
					t_relay();
					exit;
				} else {
					# ACK without matching transaction ... ignore and discard.
					exit;
				}
			}
			sl_send_reply("404","Not here");
		}
		exit;
	}
}

# Handle SIP registrations
route[REGISTRAR] {
	if(!is_method("REGISTER"))
		return;

	sl_send_reply("404", "Not Acceptable");
	exit;
}

# Presence server route
route[PRESENCE] {
	if(!is_method("PUBLISH|SUBSCRIBE"))
		return;

	sl_send_reply("404", "Not Acceptable");
	exit;
}

# Dispatch requests
route[DISPATCH] {
        # round robin dispatching on gateways group '1'
        # record routing for dialog forming requests (in case they are routed)
        # - remove preloaded route headers
        remove_hf("Route");
        if (is_method("INVITE|REFER")) {
                record_route();
                if (has_body("application/sdp")) {
                    if (rtpengine_offer()) {
                            t_on_reply("1");
                    }
                } else {
                    t_on_reply("2");
                }

                if (isflagset(FLAG_FROM_PEER)) {
		    xlog("L_INFO","Call from $si seems from PEER");
                    if(!ds_select_domain("1", "4")) {
                            send_reply("404", "No destination");
                            exit;
                    }

                }

                if (isflagset(FLAG_FROM_ASTERISK)) {
		    xlog("L_INFO","Call from $si seems from ASTERISK");
                    if(!ds_select_domain("2", "4")) {

                            send_reply("404", "No destination");
                            exit;
                    }
		    xlog("L_INFO","Call from $si seems from ASTERISK [$du] [$ru]");
		    
                }
		    

		    xlog("L_INFO","DESTINATION is $du");
        }

        if (is_method("ACK") && has_body("application/sdp")) {
                rtpengine_answer("force");
        }

        route(RELAY);
}


failure_route[RTF_DISPATCH] {
	if (t_is_canceled()) {
		exit;
	}
	# next DST - only for 500 or local timeout
	if (t_check_status("500")
			or (t_branch_timeout() and !t_branch_replied())) {
		if(ds_next_dst()) {
			xdbg("--- SCRIPT: retrying to <$ru> via <$du> (attrs: $xavp(_dsdst_=>attrs))\n");
			t_on_failure("RTF_DISPATCH");
			route(RELAY);
			exit;
		}
	}
}

onreply_route[1] {
        if (has_body("application/sdp")) {
                rtpengine_answer("force");
        }
}

onreply_route[2] {
        if (has_body("application/sdp")) {
                rtpengine_offer("force");
        }
}

Leave a Reply