[OpenSIPS-Users] OpenSIPS + OpenIMS + NAT issues
Olivier Dugeon
Olivier.Dugeon at orange-ftgroup.com
Fri Jul 10 17:44:49 CEST 2009
Hello all,
I have some problems with OpenSIPS and OpenIMS due to NAT configuration.
My setup is a follow:
UA <--> HGW (embedded both OpenSIPS and NAT stuff) <--> P-CSCF (OpenIMS)
I used different UA (mainly Twinkle and X-Lite). The HGW (Home GateWay)
is running under OpenWRT on which I compile and install OpenSIPS. The
P-CSCF, S-CSCF and I-CSCF are all running on the same PC (standard
configuration from OpenIMS installation).
My OpenSIPS is just used to manage local message (perform some security
check) and manage the NAT configuration of the HGW.
My problem come from the fact that the P-CSCF (and subsequently the
S-CSCF) is registered my UA with its private @IP address and not the
public @IP address of the HGW. So, each time I sent a SIP message to the
IMS Core, the P-CSCF reject my messages with a 403 "Forbidden. You must
registered first in the P-CSCF". This come from that the P-CSCF check
who is sending the SIP message based on the source @IP. In my case, the
source @IP address is the public one (i.e. the HGW public one). However,
this public @IP address is not know by the P-CSCF i.e. it doesn't
correspond to a registered UA. So, Outgoing call are not working.
Fortunately, Incoming call (i.e. from a UA which is directly connected
to the IMS Core) are working well.
I try several configuration using nathelper module, but I just got a
negative reply from the S-CSCF instead of the P-CSCF (I.e. I pass the
P-CSCF check by using force_rport in register and invite message)).
I fact, the problem come from the fix_nated_contact() and
fix_nated_register() function which don't do the job I want. They
rewrite the contact field with the source IP and Port of the original
message i.e. the @IP address and port of the UA.
So, what I'm looking for, is a way to hide the private @IP address and
the possibility to rewrite the Contact field with the public @IP of the
HGW in order for the P-CSCF thinks that the UA is registered with the
public @IP address and not the private one.
Is it possible and how ?
Thanks a lot for your help.
Olivier
PS: Here it is my opensips configuration:
# ----------- global configuration parameters ------------------------
debug=3 # debug level (cmd line: -dddddddddd)
log_stderror=yes # (cmd line: -E)
log_facility=LOG_LOCAL1
fork=yes
sip_warning=0
check_via=no # (cmd. line: -v)
#dns=yes # (cmd. line: -r)
dns=no # (cmd. line: -r)
#rev_dns=yes # (cmd. line: -R)
rev_dns=no # (cmd. line: -R)
disable_tcp=yes
disable_dns_blacklist=yes
disable_dns_failover=yes
listen=udp:192.168.1.1:5060
listen=udp:217.70.81.211:5060
children=1
auto_aliases=no
alias="zpna.systerminal.eu:5060"
# ------------------ module loading ----------------------------------
mpath="/usr/lib/opensips/modules"
loadmodule "db_text.so"
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "xlog.so"
loadmodule "mi_fifo.so"
loadmodule "maxfwd.so"
loadmodule "uac.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "auth.so"
loadmodule "auth_db.so"
loadmodule "alias_db.so"
loadmodule "uri.so"
loadmodule "uri_db.so"
loadmodule "domain.so"
loadmodule "nathelper.so"
loadmodule "textops.so"
loadmodule "avpops.so"
loadmodule "permissions.so"
loadmodule "presence.so"
loadmodule "presence_xml.so"
loadmodule "pua.so"
loadmodule "rls.so"
loadmodule "xcap_client.so"
# ----------------- setting module-specific parameters ---------------
# -- multi-modules params --
modparam("usrloc|permissions|auth_db|uri_db|domain|presence|presence_xml|rls|pua|xcap_client|alias_db",
"db_url", "text:///etc/opensips/opensipsdb")
modparam("auth_db|alias_db|uri_db|usrloc", "use_domain", 1)
# -- mi_fifo params --
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
modparam("mi_fifo", "fifo_mode", 0666)
# -- rr params --
# add value to ;lr param to make some broken UAs happy
modparam("rr", "enable_full_lr", 1)
# -- nathelper --
modparam("nathelper", "rtpproxy_sock", "unix:/var/run/rtpproxy.sock")
modparam("nathelper", "natping_interval", 60)
modparam("nathelper", "ping_nated_only", 1)
modparam("nathelper", "received_avp", "$avp(i:9)")
# -- timer params --
modparam("tm", "fr_timer", 5)
modparam("tm", "fr_inv_timer", 100)
modparam("tm", "wt_timer", 10)
# -- usrloc params --
modparam("usrloc", "db_mode", 1)
modparam("usrloc", "timer_interval", 10)
modparam("usrloc", "nat_bflag", 6)
modparam("usrloc", "desc_time_order", 1)
# -- auth params --
modparam("auth", "nonce_expire", 300)
modparam("auth", "realm_prefix", "sip.")
# modparam("auth", "rpid_avp", "$avp(rpid)")
# -- auth_db params --
modparam("auth_db", "password_column", "password")
modparam("auth_db", "calculate_ha1", 1)
# -- registrar params --
modparam("registrar", "max_contacts", 2)
modparam("registrar", "received_avp", "$avp(i:9)")
modparam("registrar", "sock_flag", 12)
modparam("registrar", "sock_hdr_name", "Local-Sock")
modparam("registrar", "max_expires", 3600)
# -- permissions params --
modparam("permissions", "db_mode", 1)
modparam("permissions", "trusted_table", "trusted")
# -- presence params --
modparam("presence", "server_address", "sip:192.168.1.1:5060")
modparam("presence_xml", "force_active", 1)
modparam("presence_xml", "integrated_xcap_server", 0)
modparam("presence_xml", "xcap_server", "192.168.1.8")
# -- rls parameters --
modparam("rls", "xcap_root", "http://192.168.1.8/xcap-root:8000")
modparam("rls", "server_address", "sip:192.168.1.1:5060")
modparam("rls", "integrated_xcap_server", 0)
modparam("rls", "presence_server", "sip:192.168.1.1:5060")
modparam("rls", "to_presence_code", 10)
# ---- flags
# 6 - do NAT
# 10 - to P-CSCF
# ------------------------- request routing logic -------------------
# Main routing logic
route {
# initial sanity checks -- messages with
# max_forwards==0, or excessively long requests
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
exit;
};
if ( msg:len > 16384 ) {
sl_send_reply("513", "Message too big");
exit;
};
# Sanity Check: Accept only messages from local hosts and P-CSCF
if (!(allow_address("1", "$si", "$sp") || allow_trusted())) {
xlog("L_WARN", "Received SIP message from unkown host: $si:$sp\n");
sl_send_reply("403", "Forbidden");
exit;
};
# Record Route Section
if (!is_method("REGISTER")) {
record_route();
};
# Call Tear down Section
if (is_method("BYE") || is_method("CANCEL")) {
unforce_rtp_proxy();
};
# Loose Route Section
if (loose_route()) {
xlog("L_INFO", "Start loose_route() statement\n");
if (is_method("INVITE|REFER") && !has_totag()) {
sl_send_reply("403", "Forbidden");
exit;
};
if (is_method("INVITE|REFER")) {
if (nat_uac_test("19")) {
setflag(6);
force_rport();
fix_nated_contact();
}
force_rtp_proxy("l");
};
route(1);
exit;
};
# Call Processing Section
xlog("L_INFO", "Start Call Processing Section\n");
if (is_method("ACK|CANCEL")) {
xlog("L_INFO", "Process ACK & CANCEL\n");
route(1);
exit;
} else if (is_method("INVITE|REFER")) {
xlog("L_INFO", "Process INVITE & REFER\n");
route(3);
exit;
} else if( is_method("PUBLISH|SUBSCRIBE|NOTIFY")) {
# xlog("L_INFO", "Process PRESENCE\n");
route(5);
exit;
} else if (is_method("REGISTER")) {
xlog("L_INFO", "Process REGISTER\n");
route(2);
exit;
};
lookup("aliases");
if (uri!=myself) {
route(4);
route(1);
exit;
};
if (!lookup("location")) {
sl_send_reply("404", "User Not Found");
exit;
};
route(1);
}
# Default Message Handler
route[1] {
xlog("L_INFO", "Ready to route the message\n");
t_on_reply("1");
# Route packet accordingly the WAN flag i.e. via P-CSCF or directly
if (isflagset(10)) {
if (!t_relay("udp:217.70.81.197:4060")) {
if (is_method("INVITE|REFER") && isflagset(6)) {
unforce_rtp_proxy();
};
sl_reply_error();
};
} else {
if (!t_relay()) {
if (is_method("INVITE|REFER") && isflagset(6)) {
unforce_rtp_proxy();
};
sl_reply_error();
};
};
}
# IMS REGISTER Handler
route[6] {
xlog("L_INFO", "Handle IMS register\n");
if (!($rd=~"^ims.systerminal.eu")) {
sl_send_reply("403", "Your are only authorize to register in
ims.systerminal.eu domain\n");
exit;
}
if (has_totag()) {
xlog("L_INFO", "Spoofed To-URI detected - M=$rm RURI=$ru F=$fu
T=$tu IP=$si ID=$ci\n");
sl_send_reply("403", "Spoofed To-URI Detected");
exit;
}
# Record Route to tell IMS Core that I'm behind the HGW
record_route();
# Fix NAT
if (!search("^Contact:[ ]*\*") && nat_uac_test("19")) {
xlog("L_INFO", "Request NAT for REGISTER of contact $ct for $fu\n");
setflag(6);
fix_nated_contact();
force_rport();
}
# Send message to P-CSCF
if (!t_relay("udp:217.70.81.197:4060")) {
if (!t_relay()) {
xlog("L_WARN", "Failed to send REGISTER message to IMS\n");
}
}
# INVITE & REFER Message Handler
route[3] {
xlog("L_INFO", "Start Processing INVITE & REFER Messages\n");
if (nat_uac_test("19")) {
xlog("L_INFO", "Request NAT for INVITE of $fu to $ru [$tu]\n");
setflag(6);
}
lookup("location");
switch ($retcode) {
case 1: # LAN Session
xlog("L_INFO", "LAN Session\n");
route(1);
exit;
case -1: # WAN Session
xlog("L_INFO", "WAN Session\n");
setflag(10);
route(4);
route(1);
exit;
case -3:
sl_send_reply("404", "Not Found");
exit;
case -2:
sl_send_reply("405", "Not Found");
exit;
};
}
# NAT Traversal Section
route[4] {
if (isflagset(6)) {
xlog("L_INFO", "Performe NAT of $ct for $fu\n");
force_rport();
fix_nated_contact();
force_rtp_proxy();
}
}
# Presence routing handler
route[5] {
# Test if PRESENCE is for IMS CORE
if ($rd=~"^ims.systerminal.eu") {
# xlog("L_INFO", "Send Presence message to P-CSCF\n");
setflag(10);
setflag(6);
route(4);
route(1);
exit;
};
if (!t_newtran()) {
sl_reply_error();
exit;
};
if (is_method("PUBLISH")) {
# xlog("L_INFO", "Process PRESENCE PUBLISH message\n");
handle_publish();
t_release();
exit;
}
if (is_method("NOTIFY")) {
# xlog("L_INFO", "Process PRESENCE NOTIFY message\n");
rls_handle_notify();
switch ($retcode) {
case 1:
# Notify processed by rls
xlog("L_INFO", "$rm processed by RLS\n");
t_release();
break;
case -1:
# Error
xlog("L_INFO", "$rm processed by RLS but has error\n");
t_reply("500", "Server error while processing RLS NOTIFY");
break;
default:
if (uri == "sip:rls at 192.168.1.1") {
xlog("L_ERR", "$rm should be processed by RLS but was
not recognized\n");
xlog("L_INFO", "Dropping $rm because it will loop\n");
t_reply("500", "Server error while processing RLS NOTIFY");
} else {
xlog("L_INFO", "$rm handled by presence\n");
t_release();
}
}
exit;
}
if (is_method("SUBSCRIBE")) {
# Internal presence handling
# xlog("L_INFO", "Process PRESENCE SUBSCRIBE message\n");
rls_handle_subscribe();
switch ($retcode) {
case 10:
# RLS indicated that message should be processed by presence
if (is_uri_host_local()) {
if (does_uri_exist()) {
handle_subscribe();
t_release();
} else {
t_reply("404", "User not found");
}
exit;
}
break;
default:
t_release();
exit;
}
}
}
# NAT for ACK, BYE, CANCEL & co.
onreply_route[1] {
xlog("L_INFO", "Process ACK, BYE & CANCEL Messages\n");
if (isflagset(6) && status=~"(180)|(183)|2[0-9][0-9]") {
if (!search("^Content-Length:[ ]*0")) {
xlog("L_INFO", "Check NAT for reply route\n");
force_rtp_proxy();
};
};
if (nat_uac_test("1")) {
xlog("L_INFO", "Fix NAT on reply route\n");
fix_nated_contact();
};
}
--
Olivier Dugeon
More information about the Users
mailing list