OpenSIPS3.4组合topology_hiding模块和mid_registrar模块的路由脚本

OpenSIPS3.4.3

启用topology_hiding模块的主要考虑是,某些sip协议栈对record-route支持的不好

启用mid_registrar模块,向FreeSWITCH注册,修改contact为OpenSIPS的地址,但不修改过期时间。不用path模块的主要考虑是,某些sipserver对path支持的不好

测试环境:

  • OpenSIPS ip地址:172.20.10.6
  • FreeSWITCH地址:172.20.10.7

路由逻辑:

  • REGISTER方法,调用mid_registrar_save,再送到FreeSWITCH(172.20.10.7:5060)
  • INVITE方法,如果ip来源是FreeSWITCH,调用mid_registrar_lookup,再调用topology_hiding。否则,设置目的地是FreeSWITCH(172.20.10.7:5060),再调用topology_hiding
  • 为了简单,暂不处理NAT

完整的路由脚本为:

#debug_mode=yes

log_level=3
xlog_level=3
stderror_enabled=no
syslog_enabled=yes
syslog_facility=LOG_LOCAL0

udp_workers=4

/* 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

socket=udp:172.20.10.6:5060   # CUSTOMIZE ME
socket=tcp:172.20.10.6:5060   # CUSTOMIZE ME

####### Modules Section ########

#set module path
mpath="/usr/lib/x86_64-linux-gnu/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"
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)

#### USeR LOCation module
loadmodule "usrloc.so"
modparam("usrloc", "nat_bflag", "NAT")
modparam("usrloc", "working_mode_preset", "single-instance-no-db")

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

#### TEXTOPS module
loadmodule "textops.so"

#### DIALOG module
loadmodule "dialog.so"
modparam("dialog", "reinvite_ping_interval", 300)
modparam("dialog", "options_ping_interval", 60)

#### TOPOLOGY_HIDING module
loadmodule "topology_hiding.so"

#### PATH module
loadmodule "path.so"

#### MID_REGISTRAR module
loadmodule "mid_registrar.so"

#### CACHEDB_LOCAL module
loadmodule "cachedb_local.so"
modparam("cachedb_local", "cachedb_url", "local://")

loadmodule "proto_udp.so"
loadmodule "proto_tcp.so"
####### Routing Logic ########

# main request routing logic

route{
	xlog("$ci|$rm|$fU|$tU|$rp from $si:$sp\n");
	if (!mf_process_maxfwd_header(10)) {
		send_reply(483, "Too Many Hops");
		exit;
	}

	if (has_totag()) {
		if (topology_hiding_match()) {
			xlog("*** Callee side callid  is $TH_callee_callid\n");
			route(relay);
			exit;
		}

		# 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("$ci|In-Dialog $rm from $si (callid=$ci) is not valid according to dialog\n");
			## exit;
		}

		# 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("OPTIONS|NOTIFY")) {
		send_reply(200, "OK");
		exit;
	}

	# record routing
	#if (!is_method("REGISTER|MESSAGE"))
	#	record_route();

	if (is_method("PUBLISH|SUBSCRIBE")) {
		send_reply(200, "OK");
		exit;
	}

	if (is_method("REGISTER")) {
		route(register);
		exit;
	}

	if (is_method("INVITE")) {
		route(invite);
		exit;
	}

	exit;
}

route[register] {
	if (!is_method("REGISTER")) {
		return;
	}

	$var(rc) = mid_registrar_save("location");
	xlog("mid_registrar_save() = $var(rc)\n");

	switch ($var(rc)) {
	case 1:
		xlog("L_INFO", "forwarding REGISTER to main registrar...\n");
		$ru = "sip:172.20.10.7:5060"; # CUSTOMIZE ME, dst to FreeSWITCH
		if (!t_relay()) {
			send_reply(500, "Server Internal Error 1");
		}
		break;

	case 2:
		xlog("L_INFO", "REGISTER has been absorbed!\n");
		break;

	default:
		xlog("L_ERR", "mid-registrar error!\n");
		send_reply(500, "Server Internal Error 2");
	}

	exit;
}

route[invite] {
	if (!is_method("INVITE") || has_totag()) {
		return;
	}

	create_dialog();
	if ($si == "172.20.10.7") { # CUSTOMIZE ME, src from FreeSWITCH
		if (!mid_registrar_lookup("location")) {
			t_reply(404, "Not Found");
			exit;
		}
		topology_hiding("U"); # Propagate the Username in the Contact header URI
		route(relay);
		exit;
	} else {
		$du = "sip:172.20.10.7:5060";  # CUSTOMIZE ME, dst to FreeSWITCH
		topology_hiding("U"); # Propagate the Username in the Contact header URI
		route(relay);
		exit;
	}
}

route[relay] {
	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, status = $rs\n");
	# xlog("****$mb\n");

	if (($rs =~ "18[30]") && has_body("application/sdp")) {
	    # save sdp
    	# xlog("****$rb\n");
		$var(key) = $ci + "+body";
		cache_store("local", $var(key), $rb, 120); # 120 秒超时
		$var(key) = $ci + "+length";
		cache_store("local", $var(key), $hdr(Content-Length), 120); # 120 秒超时
	} else if (($rs == "200") && !has_body("application/sdp")) {
        # restore sdp
		$var(key) = $ci + "+body";
		cache_fetch("local", $var(key), $var(sdp));
        cache_remove("local", $var(key));
		xlog("****$var(sdp)\n");
		$var(key) = $ci + "+length";
		cache_fetch("local", $var(key), $var(length));
        cache_remove("local", $var(key));
		xlog("****$var(length)\n");
        if (($var(sdp) != NULL) && ($var(length) != NULL)) {
    		insert_hf("Content-Type: application/sdp\r\n", "Call-ID");
	    	insert_hf("Content-Length: $var(length)\r\n", "Call-ID");
    		add_body_part($var(sdp), "application/sdp");
        }
	}
}

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

OpenSIPS的拓扑隐藏模块设计的很好,容易使用,本人很喜欢

如果哪天能把OpenSIPS的优点和Kamailio优点都能集中到一起,那就太好了

走过路过的朋友们,请多提宝贵意见

你可能感兴趣的:(OpenSIPS,OpenSIPS拓扑隐藏)