Go ahead. I am not sure how good it is. if you find problems , please let me know.
I am sure there must be problems there. But since I am also new, so I can't spot them all. that is why I posted it. it will be nice that there are people spot the problem and tell me. I can continue to improve it. when it is good enough, maybe this can be put in opensips repository for everybody to share. Jinsong ----- Original Message ----- From: "Khan" <[email protected]> To: "Jinsong Hu" <[email protected]> Cc: <[email protected]> Sent: Monday, May 11, 2009 11:55 AM Subject: Re: [OpenSIPS-Users] [OpenSIPS] sample script that works with cdrtools, freeradius, nat, drouting Thanks Jimmy, I have been looking for some sample script for ages at every possible place. So, far no luck but its really nice of you to post your script here. I always wondered with open source software what is the deal of posting your functional script (hiding your confidential info) but never had an answer. Finally I see a brave person posting script... Would you mind if i try your script and see if it works for me??? Thanks, On Mon, May 11, 2009 at 1:31 AM, Jinsong Hu <[email protected]> wrote: > Hi, There: > It looks ag-projects is maintaining the cdrtools, media proxy. but I > searched around and didn't find anywhere there is a script that supports > all > the needed feature: cdrtools, mediaproxy, nat_traversal, and drouting. so > now I'm trying to be a little brave and post my script that includes all > above. this script doesn't handle instance message, but only voice calls. > can any body spot problems with this script ? > The goal of the script is to let locally registered user to use gateway to > make outgoing call, and receive incoming call. the numbering plan is for > US. > free radius should have good authenticaing and accounting for different > messages, and some special DID are mapped to several numbers and routed to > asterisk. Hopefully this script will be useful for a general VOIP carrier. > I try to paste the document to be comment. Hopefully, by going through > this exercise, we can get a good starting script for people to use as a > model starting script. > > > Jimmy > > > > ####################################################################### > # > # $Id: opensips.cfg,v 1.13 2009/05/11 06:06:00 jinsong Exp $ > # > # OpenSIPS basic configuration script > # by Anca Vamanu <[email protected]> > # > # Please refer to the Core CookBook at > http://www.opensips.org/dokuwiki/doku.php > # for a explanation of possible statements, functions and parameters. > # > #INVITE :Invites a user to a call > #ACK : Acknowledgement is used to facilitate reliable message exchange for > INVITEs. > #BYE :Terminates a connection between users > #CANCEL :Terminates a request, or search, for a user. It is used if a > client > sends an INVITE and then changes its decision to call the recipient. > #OPTIONS :Solicits information about a server's capabilities. > #REGISTER :Registers a user's current location > #INFO :Used for mid-session signaling > #MESSAGE : IMS send message > #SUBSCRIBE : IMS presence subscribe message > #PUBLISH: IMS publish message > > #1xx: Provisional -- request received, continuing to process the request; > #2xx: Success -- the action was successfully received, understood, and > accepted; > #3xx: Redirection -- further action needs to be taken in order to complete > the request; > #4xx: Client Error -- the request contains bad syntax or cannot be > fulfilled > at this server; > #5xx: Server Error -- the server failed to fulfill an apparently valid > request; > #6xx: Global Failure -- the request cannot be fulfilled at any server. > > #This function sets the value of the flag given as parameter to 1 (true). > The value of the parameter must be an integer between 0 and 31. > > > > > > ####### Global Parameters ######### > > debug=3 > log_stderror=no > log_facility=LOG_LOCAL0 > > fork=yes > children=4 > > /* uncomment the following lines to enable debugging */ > #debug=6 > #fork=no > #log_stderror=yes > > /* uncomment the next line to disable TCP (default on) */ > #disable_tcp=yes > > /* 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 > > #disable dns to scale > dns=no > rev_dns=no > > /* uncomment the next line to disable the auto discovery of local aliases > based on revers DNS on IPs (default on) */ > #auto_aliases=no > alias=machinename.somedomain.com > > > > /* uncomment the following lines to enable TLS support (default off) */ > #disable_tls = no > #listen = tls:your_IP:5061 > #tls_verify_server = 1 > #tls_verify_client = 1 > #tls_require_client_certificate = 0 > #tls_method = TLSv1 > #tls_certificate = "/etc/opensips/tls/user/user-cert.pem" > #tls_private_key = "/etc/opensips/tls/user/user-privkey.pem" > #tls_ca_list = "/etc/opensips/tls/user/user-calist.pem" > > > port=5060 > > /* uncomment and configure the following line if you want opensips to > bind on a specific interface/port/proto (default bind on all available) > */ > #listen=udp:192.168.1.2:5060 > > > ####### Modules Section ######## > > #set module path > mpath="/usr/lib/opensips/modules/" > > /* uncomment next line for MySQL DB support */ > loadmodule "db_mysql.so" > loadmodule "mi_fifo.so" > loadmodule "sl.so" > loadmodule "tm.so" > loadmodule "rr.so" > loadmodule "maxfwd.so" > loadmodule "usrloc.so" > loadmodule "signaling.so" > loadmodule "registrar.so" > loadmodule "textops.so" > loadmodule "uri_db.so" > loadmodule "uri.so" > loadmodule "xlog.so" > loadmodule "acc.so" > /* uncomment next lines for MySQL based authentication support > NOTE: a DB (like db_mysql) module must be also loaded */ > loadmodule "auth.so" > loadmodule "auth_db.so" > /* uncomment next line for aliases support > NOTE: a DB (like db_mysql) module must be also loaded */ > loadmodule "alias_db.so" > /* uncomment next line for multi-domain support > NOTE: a DB (like db_mysql) module must be also loaded > NOTE: be sure and enable multi-domain support in all used modules > (see "multi-module params" section ) */ > loadmodule "domain.so" > /* uncomment the next two lines for presence server support > NOTE: a DB (like db_mysql) module must be also loaded */ > #loadmodule "presence.so" > #loadmodule "presence_xml.so" > > #loadmodule "carrierroute.so" > loadmodule "drouting.so" > loadmodule "siptrace.so" > loadmodule "pike.so" > loadmodule "ratelimit.so" > > loadmodule "auth_radius.so" > loadmodule "avp_radius.so" > #loadmodule "uri_radius.so" > loadmodule "group_radius.so" > > loadmodule "dispatcher.so" > > loadmodule "dialog.so" > loadmodule "mediaproxy.so" > #loadmodule "nathelper.so" > loadmodule "nat_traversal.so" > > # ----------------- setting module-specific parameters --------------- > > > # ----- mi_fifo params ----- > modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo") > > > # ----- rr params ----- > # add value to ;lr param to cope with most of the UAs > modparam("rr", "enable_full_lr", 1) > > > # ----- rr params ----- > #modparam("registrar", "method_filtering", 1) > /* uncomment the next line to disable parallel forking via location */ > # modparam("registrar", "append_branches", 0) > /* uncomment the next line not to allow more than 10 contacts per AOR */ > modparam("registrar", "max_contacts", 10) > > > # ----- uri_db params ----- > /* by default we disable the DB support in the module as we do not need it > in this configuration */ > modparam("uri_db", "use_uri_table", 0) > modparam("uri_db", "db_url", "") > > > # ----- acc params ----- > /* what sepcial events should be accounted ? */ > #modparam("acc", "early_media", 1) > #modparam("acc", "report_ack", 1) > #modparam("acc", "report_cancels", 1) > /* by default ww do not adjust the direct of the sequential requests. > if you enable this parameter, be sure the enable "append_fromtag" > in "rr" module */ > #modparam("acc", "detect_direction", 0) > /* uncomment the following lines to enable DB accounting also */ > #modparam("acc", "db_flag", 1) > #modparam("acc", "db_missed_flag", 1) > > > # global acc parameters > modparam("acc", "failed_transaction_flag", 1) > modparam("acc", "report_cancels", 0) > modparam("acc", "report_ack", 0) > modparam("acc", "early_media", 0) > > modparam("acc", "log_level", 1) > modparam("acc", "log_flag", 1) > modparam("acc", "log_missed_flag", 1) > > modparam("acc|auth_radius|group_radius|avp_radius", "radius_config", > "/etc//radiusclient-ng/radiusclient.conf") > modparam("acc", "radius_flag", 1) > modparam("acc", "radius_missed_flag", 1) > modparam("acc", "radius_extra", "User-Name=$Au; \ > Calling-Station-Id=$from; \ > Called-Station-Id=$to; \ > Sip-Translated-Request-URI=$ru; \ > Sip-RPid=$avp(s:rpid); \ > Source-IP=$avp(s:source_ip); \ > Source-Port=$avp(s:source_port); \ > SIP-Proxy-IP=$avp(s:sip_proxy_ip); \ > Canonical-URI=$avp(s:can_uri); \ > Billing-Party=$avp(s:billing_party); > \ > Divert-Reason=$avp(s:divert_reason); > \ > User-Agent=$hdr(user-agent); \ > Contact=$hdr(contact); \ > Event=$hdr(event); \ > ENUM-TLD=$avp(s:enum_tld)") > > modparam("siptrace", "db_url", > "mysql://opensips:passw...@localhost/opensips") > modparam("siptrace", "traced_user_avp", "$avp(s:traced_user)") > modparam("siptrace", "trace_on", 1) > modparam("siptrace", "trace_flag", 2) > > > # ----- usrloc params ----- > #0 - This disables database completely. Only memory will be used. Contacts > will not survive restart. > #1 - Write-Through scheme. All changes to usrloc are immediately reflected > in database too. > #2 - Write-Back scheme. All changes are made to memory and database > synchronization is done in the timer. > #3 - DB-Only scheme. No memory > #modparam("usrloc", "db_mode", 0) > /* uncomment the following lines if you want to enable DB persistency > for location entries */ > modparam("usrloc", "db_mode", 2) > modparam("usrloc", "db_url", > "mysql://opensips:passw...@localhost/opensips") > > > # ----- auth_db params ----- > /* uncomment the following lines if you want to enable the DB based > authentication */ > modparam("auth_db", "calculate_ha1", yes) > modparam("auth_db", "password_column", "password") > modparam("auth_db", "db_url", > "mysql://opensips:passw...@localhost/opensips") > modparam("auth_db", "load_credentials", "") > > > # ----- alias_db params ----- > /* uncomment the following lines if you want to enable the DB based > aliases */ > #modparam("alias_db", "db_url", > # "mysql://opensips:passw...@localhost/opensips") > > > # ----- domain params ----- > /* uncomment the following lines to enable multi-domain detection > support */ > #modparam("domain", "db_url", > # "mysql://opensips:passw...@localhost/opensips") > #modparam("domain", "db_mode", 1) # Use caching > > > # ----- multi-module params ----- > /* uncomment the following line if you want to enable multi-domain support > in the modules (dafault off) */ > #modparam("alias_db|auth_db|usrloc|uri_db", "use_domain", 1) > > > # ----- presence params ----- > /* uncomment the following lines if you want to enable presence */ > #modparam("presence|presence_xml", "db_url", > # "mysql://opensips:passw...@localhost/opensips") > #modparam("presence_xml", "force_active", 1) > #modparam("presence", "server_address", "sip:192.168.1.2:5060") > > # ----- carrierroute params ----- > /* uncomment the following line if you want to enable carrierroute support > in the modules (dafault off) */ > #modparam("carrierroute", "db_url", > "mysql://opensips:passw...@localhost/opensips") > #modparam("carrierroute", "config_source", "db") > > modparam("drouting", "db_url", > "mysql://opensips:passw...@localhost/opensips") > modparam("drouting", "ruri_avp", '$avp(dr_ruri)') > > modparam("drouting", "config_source", "db") > > modparam("dispatcher", "db_url", > "mysql://opensips:passw...@localhost/opensips") > > modparam("nat_traversal", "keepalive_state_file", > "/var/run/opensips/keepalive_state") > > modparam("mediaproxy","mediaproxy_socket", > "/var/run/mediaproxy/dispatcher.sock") > modparam("mediaproxy", "mediaproxy_timeout", 500) > modparam("mediaproxy", "signaling_ip_avp", "$avp(s:nat_ip)") > modparam("mediaproxy", "media_relay_avp", "$avp(s:media_relay)") > > > > ####### Routing Logic ######## > > > # main request routing logic > > route{ > > if (!mf_process_maxfwd_header("10")) { > sl_send_reply("483","Too Many Hops"); > exit; > } > > if (msg:len >= 2048 ) { > sl_send_reply("513", "Message too big"); > exit; > }; > > #pike_check_req Process the source IP of the current request and returns > false if the IP was exceeding the blocking limit > if (!pike_check_req()) { exit; }; > > #rate limit > if (is_method("INVITE|REGISTER|SUBSCRIBE")) { > #rl_check The method will return an error code if the limit > for the matched algorithm is reached. > if (!rl_check()) { > #For the current request, a "503 - Server > Unavailable" reply is sent back. > rl_drop(); > exit; > }; > }; > > > #we only handle voice, not any other things. > if (is_method("PUBLISH|MESSAGE|SUBSCRIBE")) > { > sl_send_reply("503", "Service Unavailable"); > exit; > } > > > #1 - tests if client has a private IP address (as defined by RFC1918) > #in the Contact field of the SIP message. > #2 - tests if client has contacted OpenSIPS from an address that is > different > #from the one in the Via field. Both the IP and port are compared by this > test. > #4 - tests if client has a private IP address (as defined by RFC1918) in > the top > #Via field of the SIP message. > > > if (client_nat_test("3")) { > fix_contact(); > > if ((method=="REGISTER" ||(method=="INVITE" && !has_totag())) ) > { > nat_keepalive(); > } > } > > # check if user is suspended > if(is_method("REGISTER|INVITE|OPTIONS")) > { > if (radius_is_user_in("From", "suspended")) { > sl_send_reply("403", "Forbidden - suspended"); > exit; > }; > }; > > #use engate media proxy to fully control the media > if (method==INVITE && (client_nat_test("3") || > search("^Route:.*;nat=yes")) ) { > engage_media_proxy(); > } > > #has_totag() indicate in-dialog request. all in dialog request are > processed in this block > if (has_totag()) { > # sequential request withing a dialog should > # take the path determined by record-routing > > #loose_route() is used to route is usually used to > #route in-dialog requests (like ACK, BYE, reINVITE). > #The loose_route function analyzes the Route: headers in the requests. > #If there is no Route: header, the function returns FALSE and routing > #should be done with normal lookup functions. If a Route: header is found, > #the function returns 1 and behaves as described in section 16.12 of RFC > 3261. > #There is only one exception: If the request is out-of-dialog (no to-tag) > #and there is only one Route: header indicating the local proxy, > #then the Route: header is removed and the function returns FALSE. > if (loose_route()) { > # mark routing logic in request > append_hf("P-hint: rr-enforced\r\n"); > > #some provider GW (incorrectly) updated the contact info of an > established dialog when it got an ACK. fix it > if(is_method("ACK")) { > if(is_present_hf("Contact")) remove_hf("Contact"); > }; > route(1); > } else { > > if ( is_method("ACK") ) { > #t_check_trans Returns true if the current request is associated to a > transaction > if ( t_check_trans() ) { > # non loose-route, but stateful ACK; must be an ACK after a 487 or e.g. > #404 from upstream server > t_relay(); > exit; > } else { > # ACK without matching transaction ... ignore and discard.\n"); > xlog("L_WARN", "[$mi] discarding ACK\n"); > exit; > } > } > #in-dialog , not loose route, and not ACK, we discard. > sl_send_reply("404","Not here"); > } > #regardless of whatever happens, all in-dialog has to end here. > exit; > } > > t_check_trans(); > > # CANCEL processing. > if (is_method("CANCEL")) > { > setflag(1); # do accounting ... > setflag(2); # sip trace > #Returns true if the current request is associated to a transaction. > #CANCEL request - true if the cancelled INVITE transaction exists > if (t_check_trans()) > t_relay(); > exit; > } > > #following must be initial requests, or register. > #command must be INVITE, ACK, BYE, OPTIONS, REGISTER > > # authenticate if from local subscriber (uncomment to enable auth) > #if (!(method=="REGISTER") && from_uri==myself) > #{ > # if (!proxy_authorize("", "subscriber")) { > # proxy_challenge("", "0"); > # exit; > # } > # if (!check_from()) { > # sl_send_reply("403","Forbidden auth ID"); > # exit; > # } > > # consume_credentials(); > # # caller authenticated > #} > > > # record routing > if (!is_method("REGISTER")) > record_route(); > > # account only INVITEs > if (is_method("INVITE")) { > setflag(1); # do accounting > setflag(2); # sip trace > } > > #fraud detection block. we don't allow outsiders who are not authenticated > to use our gateway. > if (!uri==myself) > /* replace with following line if multi-domain support is used */ > ##if (!is_uri_host_local()) > { > # check if user is allowed to do voip calls to other domains > if(is_method("INVITE")) { > #for caller calling outside, but not in our voip group, we > forbid. > #this is needed to fight against fraud. > if (!radius_is_user_in("From", "voip")) { > sl_send_reply("403", "Forbidden VoIP"); > exit; > }; > }; > # mark routing logic in request > append_hf("P-hint: outbound\r\n"); > > route(1); > exit; > } > > > #process REGISTER to local server. > if (is_method("REGISTER")) > { > # authenticate the REGISTER requests (uncomment to enable auth) > if (!radius_www_authorize("machinename.somedomain.com") > && !www_authorize("machinename.somedomain.com", "subscriber")) > { > www_challenge("machinename.somedomain.com", "0"); > exit; > } > ## > ##if (!check_to()) > ##{ > ## sl_send_reply("403","Forbidden auth ID"); > ## exit; > ##} > > if (client_nat_test("3")) fix_nated_register(); > if (!save("location")) > sl_reply_error(); > exit; > } > > #process INVITE, ACK, BYE, OPTIONS for local server in the following > blocks > > if ($rU==NULL) { > # request with no Username in RURI > sl_send_reply("484","Address Incomplete"); > exit; > } > > > #lookup(domain) extracts username from Request-URI and tries to find > #all contacts for the username in usrloc > #return codes > #1 - contacts found and returned. > #-1 - no contact found. > #-2 - contacts found, but method not supported. > #-3 - internal error during processing > #if (!lookup("location")) { > # switch ($retcode) { > # case -1: > # case -3: > # t_newtran(); > # t_reply("404", "Not Found"); > # exit; > # case -2: > # sl_send_reply("405", "Method Not Allowed"); > # exit; > # } > #} > > > #process INVITE, ACK, BYE, OPTIONS for local server in the following > blocks > #It is critical to save $avp(s:can_uri) after the Proxy has performed > #all possible lookups except DNS. > #The Canonical-URI will be used for rating the session. > $avp(s:can_uri) = $ru; > route(1); > } > > > #route[1] process INVITE, ACK, BYE, OPTIONS > route[1] { > > > if (is_method("INVITE") ) { > > # normalization to e164 > # http://en.wikipedia.org/wiki/NANP > if($ruri.user =~ "^\+[1-9][0-9]+") > { > strip(1); > } > # if($ruri.user =~ "^00[1-9][0-9]+") { > # strip(2); > # } > # if($ruri.user =~ "^0[1-9][0-9]+") { > # strip(1); > # #prefix("49"); > # } > > > #in the US , dialing 1NPANXXXXXX 11 digits > if($ruri.user =~ "^1[1-9][0-9]{9}") { > #do nothing > } > #in the US, dialing NPANXXXXXX 10 digits > else if($ruri.user =~ "^[1-9][0-9]{9}") { > prefix("1"); > } > #in the US, dialing NXXXXXX 7 digits local number. > else if($ruri.user =~ "^[1-9][0-9]{6}") { > $rU = $(fU{s.substr, 0, 4}) + $rU; > } > # 411 Local Directory Assistance > else if (uri=~"^sip:4...@.*") { > # the uri with a default call to "local directory > assistance". > $rU = $(fU{s.substr, 0, 4}) + "5551212"; > } > > # 611 Local Directory Assistance > else if (uri=~"^sip:6...@.*") { > # the uri with a default call to "local directory > assistance". > rewriteuri("sip:[email protected]"); > } > #911 is handled by E911 service provider > else { > sl_send_reply("404", "Invalid destination"); > exit; > } > > # Set the callerid for the user from an AVP > #if (avp_db_load("$from/username", "s:callerid")) { > # subst('/^From: (.*)>(.*)$/From: $avp(callerid)>\2/ig'); > #}; > > } > > if (is_method("INVITE|BYE")) { > setflag(1); # do accounting ... > setflag(2); # sip trace > #call the accounting functions explicitly in local_route for > #the internally generated BYEs as they do not trigger accounting by just > #setting the accounting flag > acc_rad_request("200 ok"); > acc_log_request("200 ok"); > } > > #change access point phone number to inbound route for asterisk > alias_db_lookup("dbaliases"); > #forward asterisk inbound route with dispatcher as load balancer > if (is_method("INVITE") && $ruri =~ "^sip:17771000...@.*" ) { > #dispatcher select from set 1 using algorithm 0. > if(!ds_select_dst("1", "0")) > { > sl_send_reply("404", "no destination"); > } > if(!t_relay()) sl_reply_error(); > exit; > }; > > #special relaying to asterisk finished, now we process regular > requests. > > #INVITE, ACK, BYE, OPTIONS to locally registered user. > if (lookup("location")) > { > if (is_method("INVITE")) { > t_on_branch("1"); > t_on_reply("1"); > t_on_failure("1"); > } > if (!t_relay()) { > sl_reply_error(); > }; > exit; > } > > #INVITE to outgoing gateway, route it out. > if (is_method("INVITE") ) { > #if (cr_route("default", "machinename.somedomain.com", > "$rU", "$rU", "call_id")) { > if (do_routing()) { > t_on_failure("11"); > if (!t_relay()) { > sl_reply_error(); > }; > exit; > }; > exit; > }; > > if (!t_relay()) { > sl_reply_error(); > }; > exit; > } > > > branch_route[1] { > xlog("new branch at $ru\n"); > } > > > onreply_route[1] { > xlog("incoming reply\n"); > } > > > failure_route[1] { > 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; > ##} > > # uncomment the following lines if you want to redirect the failed > # calls to a different new destination > ##if (t_check_status("486|408")) { > ## sethostport("192.168.2.100:5060"); > ## append_branch(); > ## # do not set the missed call flag again > ## t_relay(); > ##} > } > > > ###################### > # "default" failover # > ###################### > failure_route[11] { > xlog("L_INFO", "entering failure_route[11] for reply code > '$T_reply_code'\n"); > > if (t_was_cancelled()) { > exit; > } > > if (t_check_status("408|5[0-9][0-9]")) { > #xlog("L_INFO","cr_tree_rewrite_uri(\"default\", \"1\");\n"); > #if (cr_route("default", "machinename.somedomain.com", "$rU", "$rU", > "call_id")) { > if (do_routing()) { > t_on_failure("12"); > append_branch(); > route(1); > }; > exit; > } else if (t_check_status("3[0-9][0-9]")) { > t_reply("404","Not found"); > exit; > } > } > > failure_route[12] { > xlog("L_INFO", "entering failure_route[12] for reply code > '$T_reply_code'\n"); > if (t_was_cancelled()) { > exit; > } > > if (t_check_status("408|5[0-9][0-9]")) { > xlog("L_INFO","cr_tree_rewrite_uri(\"default\", \"2\");\n"); > #if (cr_route("default", "machinename.somedomain.com", "$rU", "$rU", > "call_id")) { > if (do_routing()) { > t_on_failure("13"); > append_branch(); > route(1); > }; > exit; > } else if (t_check_status("3[0-9][0-9]")) { > t_reply("404","Not found"); > exit; > } > } > > failure_route[13] { > xlog("L_INFO", "entering failure_route[13] for reply code > '$T_reply_code'\n"); > if (t_was_cancelled()) { > exit; > } > } > > > > > _______________________________________________ > Users mailing list > [email protected] > http://lists.opensips.org/cgi-bin/mailman/listinfo/users > May be if i run into problems, could i also seek your help???? -- Khan VoIP Rookie Every beginning has an end regardless we believe it or not... _______________________________________________ Users mailing list [email protected] http://lists.opensips.org/cgi-bin/mailman/listinfo/users
