debug=3 # debug level (cmd line: -dddddddddd) fork=yes log_stderror=no # (cmd line: -E) sip_warning=no /* Uncomment these lines to enter debugging mode # fork=no # log_stderror=yes */ check_via=no # (cmd. line: -v) dns=no # (cmd. line: -r) rev_dns=no # (cmd. line: -R) port=5060 children=20 # ------------------ module loading ---------------------------------- mpath="/usr/local/lib/openser/modules" loadmodule "sl.so" loadmodule "tm.so" loadmodule "maxfwd.so" loadmodule "rr.so" loadmodule "textops.so" loadmodule "usrloc.so" loadmodule "registrar.so" loadmodule "auth.so" loadmodule "mi_fifo.so" loadmodule "options.so" loadmodule "xlog.so" # Load OSP module loadmodule "osp.so" # ----------------- setting module-specific parameters --------------- # # PEERING PARAMETERS: # =================== # This section contains OSP parameters that users may need to configure for multi-lateral # peering. (sp1_uri must be configured.) Additional detail on OSP Module parameters and # functions is provided in the "OSP Module for Secure, Multi-Lateral Peering" document # located at:http://developer.berlios.de/docman/?group_id=3799 # # Configure Peering Servers: # ========================== # OpenSER can be configured to query two peering servers for routing information and peering # authorization tokens using the sp1_uri and sp2_uri parameters. A configuration for sp1_uri # is required, configuring sp2_uri is optional. The peering server address should be # configured as a standard URL beginning with either http:// or https:// followed by the # domain name of the OSP server or the IP address enclosed in brackets. The domain name # or IP address should be followed by the peering server TCP port number and uniform # resource identifier. Below are example configurations. # modparam("osp", "sp1_uri", "http://osptestserver.transnexus.com:1080/osp") # modparam("osp", "sp2_uri", "https://[1.2.3.4]:1443/osp") # # OpenSER IP Address # ============== # device_ip is a recommended parameter that explicitly defines the IP address of OpenSER in # a peering request message (as SourceAlternate type=transport). The IP address must # be in brackets as shown in the example below. # # modparam("osp", "device_ip", "[1.1.1.1]") # # Peering Token Validation # ======================== # When OpenSER receives a SIP INVITE with a peering token, the OSP Module will validate the token to # determine whether or not the call has been authorized by a peering server. Peering tokens may, # or may not, be digitally signed. This parameter defines if OpenSER will validate signed or unsigned # tokens or both. The values for "token format" are defined below. The default value is 2. # # 0 - Validate only signed tokens. Calls with valid signed tokens are allowed. # 1 - Validate only unsigned tokens. Calls with valid unsigned tokens are allowed. # 2 - Validate both signed and unsigned tokens are allowed. Calls with valid tokens are allowed. # # modparam("osp", "token_format", 2) # # Crypto files from Peering Server Enrollment # =========================================== # These parameters identify crypto files used for validating peering authorization tokens # and establishing a secure channel between OpenSER and a peering server using SSL. The files are # generated using the 'Enroll' utility from the OSP toolkit. By default, the proxy will look # for pkey.pem, localcert.pem, and cacart_0.pem in the default configuration directory. # The default config directory is set at compile time using CFG_DIR and defaults to # /usr/local/etc/openser/. The files may be copied to the expected file location or the # parameters below may be changed. # # If the default CFG_DIR value was used at compile time, the files will be loaded from: # modparam("osp", "private_key", "/usr/local/etc/openser/pkey.pem") # modparam("osp", "local_certificate", "/usr/local/etc/openser/localcert.pem") # modparam("osp", "ca_certificates", "/usr/local/etc/openser/cacert_0.pem") # # Use Remote-Party-ID for calling number # =========================================== # This parameter is used to tell OSP module if the calling number should be obtained from RPID header. # The default value is 1. # # 0 - OSP module will use the calling number in From header. # 1 - OSP module will use the calling number in RPID header if a RPID header exists. # # modparam("osp", "use_rpid_for_calling_number", 1) # # URI Format for Redirection Messages # =========================================== # This parameter is used to tell OSP module which URI format should be used for redirection messages. # The default value is 0. # # 0 - "xxxxxxxxxx@xxx.xxx.xxx.xxx" # 1 - "". This is for Cisco 2600 IP-IP gateway. # # modparam("osp", "redirection_uri_format", 0) # -- mi_fifo params -- modparam("mi_fifo", "fifo_name", "/tmp/openser_fifo") # -- usrloc params -- modparam("usrloc", "db_mode", 0) # -- rr params -- # add value to ;lr param to make some broken UAs happy modparam("rr", "enable_full_lr", 1) # enable append_fromtag, request's from-tag is appended to record-route; # that's useful for understanding whether subsequent requests (such as BYE) come from # caller (route's from-tag==BYE's from-tag) or callee (route's from-tag==BYE's to-tag) modparam("rr", "append_fromtag", 1) # Timer which hits if no final reply for a request or ACK for a # negative INVITE reply arrives (in seconds). For example - UA server is off-line. # In other words, if the proxy does not receive a response to an Invite before this # timer expires, the proxy will retry the call and send an Invite to the next VoIP # destination in the routing list. modparam("tm", "fr_timer", 5) # Timer which hits if no final reply for an INVITE arrives after # a provisional message was received (in seconds). # For example - user is not picking up the phone modparam("tm", "fr_inv_timer", 30) # ------------------------- request routing logic ------------------- # main routing logic route{ log(3, "----ROUTE: Route IN\n"); # initial sanity checks if (!mf_process_maxfwd_header("10")) { xlog("L_WARN", "----ROUTE: Too many hops, $rm from '$fu' to '$tu'\n"); sl_send_reply("483", "Too Many Hops"); return; }; if (msg:len >= max_len) { xlog("L_WARN", "----ROUTE: Message too big, $rm from '$fu' to '$tu'\n"); sl_send_reply("513", "Message too big"); return; }; # we record-route all messages -- to make sure that # subsequent messages will go through our proxy; that's # particularly good if upstream and downstream entities # use different transport protocol record_route(); # loose-route processing if(loose_route()) { if (method=="INVITE") { log(2, "----ROUTE: Relay re-INVITE\n"); # send it out now; use stateful forwarding as it works reliably even for UDP2TCP if (!t_relay()) { sl_reply_error(); } return; } else if (method=="ACK") { log(2, "----ROUTE: Relay ACK\n"); # send it out now; use stateful forwarding as it works reliably even for UDP2TCP if (!t_relay()) { sl_reply_error(); } return; } } if (method=="REGISTER") { log(2, "----ROUTE: Processing REGISTER\n"); # Stop retransmission sl_send_reply("100", "Trying"); if (uri==myself) { log(2, "----ROUTE: Registered\n"); save("location"); } else { log(2, "----ROUTE: Register from outside domain rejected\n"); sl_send_reply("488", "Unknown domain"); } } else if (method=="INVITE") { log(2, "----ROUTE: Processing INVITE\n"); # Stop retransmission sl_send_reply("100", "Trying"); if (t_check_trans()) { log(2, "----ROUTE: Duplicated INVITE\n"); return; } # Authentication log(3, "OSP authorization validation logic\n"); # This function looks for OSP peering token in the message. It will fail # if the token is not present if (checkospheader()) { log(3, "With OSP token, validate it\n"); # The function validates OSP tokens. It will fail # if the token is not valid or has expired if (validateospheader()) { # Authorization is valid. The proxy can now use its own database of # registered users for routing information. # The proxy could also issue another OSP peering authorization and # routing request by calling route(1) function. log(3, "OSP authorization valid\n"); # Remove the OSP peering token from the received message # Otherwise it will be forwarded on to the next hop remove_hf("P-OSP-Auth-Token"); } else { log(3, "OSP authorization invalid\n"); sl_send_reply("401", "Unauthorized"); return; }; } else { log(3, "Without OSP token, apply different authentication strategy\n"); log(3, "Go ahead, everyone is welcomed\n"); # # Implement authentication strategy here or simply add the # # statements below to block all invites without OSP peering tokens # sl_send_reply("401", "Unauthorized"); # return; } log(2, "----ROUTE: Authentication passed\n"); # Routing if (lookup("location")) { log(2, "----ROUTE: Registered user, forward the message\n"); append_hf("P-hint: usrloc\r\n"); t_relay(); } else { log(2, "----ROUTE: Unregistered user, use OSP to get routing\n"); route(2); } } else if (method=="ACK") { log(2, "----ROUTE: Processing ACK\n"); log(2, "----ROUTE: Not to relay ACK"); } else if (method=="BYE") { log(2, "----ROUTE: Processing BYE\n"); if (t_check_trans()) { log(2, "----ROUTE: Duplicated BYE\n"); return; } # NOTE - don't t_relay before reporting usage if (is_direction("downstream")) { log(2, "----ROUTE: BYE from SOURCE\n"); if (!reportospusage("0")) { xlog("L_WARN", "----ROUTE: BYE without OSP information, from '$fu' to '$tu'\n"); } } else { log(2, "----ROUTE: BYE from DESTINATION\n"); if (!reportospusage("1")) { xlog("L_WARN", "----ROUTE: BYE without OSP information, from '$fu' to '$tu'\n"); } } t_relay(); } else if (method=="CANCEL") { log(2, "----ROUTE: Processing CANCEL\n"); if (t_check_trans()) { t_relay(); } else { xlog("L_WARN", "----ROUTE: CANCEL without matching transaction, from '$fu' to '$tu'\n"); } } else if ((method=="OPTIONS") && (uri==myself)) { log(2, "----ROUTE: Processing OPTIONS\n"); options_reply(); } else if (method=="PRACK") { log(2, "----ROUTE: Processing PRACK\n"); t_relay(); } else if (method=="INFO") { log(2, "----ROUTE: Processing INFO\n"); t_relay(); } else if (method=="UPDATE") { log(2, "----ROUTE: Processing UPDATE\n"); t_relay(); } else { xlog("L_WARN", "----ROUTE: Unsupported message, $rm from '$fu' to '$tu'\n"); sl_send_reply("500", "Unsupported message"); } log(3, "----ROUTE: Route OUT\n"); } # OSP Authorization and Routing route[2] { log(3, "OSP authorization and routing logic\n"); # Is request to a phone number? # A phone number consists of digits (0 through 9) # and can begin with + # if (uri=~"sip:[+,0-9][0-9]*@") { # Requesting OSP peering routing and authorization # The request may fail if: # o OSP peering servers are not available # o Authentication failed # o There is no route to destination or the route is blocked log(3, "Requesting OSP authorization and routing\n"); if (requestosprouting()) { log(3, "Response received\n"); # Now we have 3 options. # o route(3) - sends a redirect to all available routes # o route(4) - fork off to all available routes # o route(5) in conjunction with failure_route(1) - sequentially tries all routes # route(3); # route(4); route(5); } else { log(3, "OSP Authorization failed\n"); sl_send_reply("503", "Service not available - No OSP routes"); } # } else { # log(3, "Wrong phone number\n"); # sl_send_reply("401", "Not a phone number"); # } } route[3] { log(3, "Prepare all routes and redirect\n"); if (prepareallosproutes()) { sl_send_reply("300", "Redirect"); } else { log(3, "Failed to prepare all routes\n"); sl_send_reply("500", "Internal Server Error"); } } route[4] { log(3, "Prepare all routes and fork-off\n"); if (prepareallosproutes()) { t_relay(); } else { log(3, "Failed to prepare all routes\n"); sl_send_reply("500", "Internal Server Error"); } } route[5] { log(3, "Try the 1st route\n"); if (checkosproute()) { t_on_branch("1"); t_on_failure("1"); t_relay(); } else { log(3, "Could not use the 1st route\n"); sl_send_reply("500", "Internal Server Error"); } } failure_route[1] { log(3, "Try the next route\n"); if (t_check_status("487")) { log(3, "Call canceled (status 487)\n"); return; } if (t_check_status("486")) { log(3, "User busy (status 486)\n"); return; } if (t_check_status("408")) { if (!t_local_replied("last")) { log(3, "User unavailable (status 408)\n"); return; } } if (checkosproute()) { t_on_branch("1"); append_branch(); t_on_failure("1"); t_relay(); } else { log(3, "No more routes\n"); t_reply("503", "Service not available - No more OSP routes"); } } branch_route[1] { log(3, "Prepare route specific OSP information\n"); prepareosproute(); # Only add/change Remote-Party-ID if calling number is translated if (checkcallingtranslation()) { log(3, "Calling number translated, add a new RPID header\n"); # Remove the Remote_Party-ID from the received message # Otherwise it will be forwarded on to the next hop remove_hf("Remote-Party-ID"); # Append a new Remote_Party append_rpid_hf(); } }