SER example outboundproxy

SIP Express Router

example: SER as a multihomed outbound proxy


This is a stripped-down version of the ser.cfg file that powers a SIP application-level gateway (ALG). This configuration is based on the
OnSIP Getting Started 5.0 configuration and the alg.cfg included in SER 0.9.3 and later.

This configuration is currently running with SER 0.9.4 and uses rtpproxy from CVS. The internal NIC has been assigned IP address 192.168.0.1, and the external NIC has 192.168.255.1. Contrary to the example given in alg.cfg, you must start rtpproxy as follows:

rtpproxy -l 192.168.255.1/192.168.0.1

This puts the proxy into bridge mode, which enables the proxy to work properly when faced with user agents on either the internal network or the external network.

For this example to work, you must also follow the nathelper module instructions for creating new location_internal and location_external tables. Be careful to use underscores ("_") and not hyphens ("-") when creating the new tables.


  # $Id: ser.cfg,v 1.9 2005/10/03 01:06:51 root Exp root $
  
  # ----------- global configuration parameters ------------------------
  
  debug=3         # debug level (cmd line: -dddddddddd)
  fork=yes
  log_stderror=no # (cmd line: -E)
  
  port=5060
  check_via=no    # (cmd. line: -v)
  dns=no          # (cmd. line: -r)
  rev_dns=no      # (cmd. line: -R)
  children=3
  fifo="/tmp/ser_fifo"
  
  alias="mydomain.org"
  
  # mhomed -- enable calculation of outbound interface; useful on
  # multihomed servers.
  mhomed=1
  
  
  # ------------------ module loading ----------------------------------
  
  loadmodule "/usr/pkg/lib/ser/modules/mysql.so"
  loadmodule "/usr/pkg/lib/ser/modules/sl.so"
  loadmodule "/usr/pkg/lib/ser/modules/tm.so"
  loadmodule "/usr/pkg/lib/ser/modules/rr.so"
  loadmodule "/usr/pkg/lib/ser/modules/maxfwd.so"
  loadmodule "/usr/pkg/lib/ser/modules/usrloc.so" 
  loadmodule "/usr/pkg/lib/ser/modules/registrar.so"
  loadmodule "/usr/pkg/lib/ser/modules/auth.so"
  loadmodule "/usr/pkg/lib/ser/modules/auth_db.so"
  loadmodule "/usr/pkg/lib/ser/modules/uri.so"
  loadmodule "/usr/pkg/lib/ser/modules/uri_db.so"
  loadmodule "/usr/pkg/lib/ser/modules/group.so"
  loadmodule "/usr/pkg/lib/ser/modules/nathelper.so"
  loadmodule "/usr/pkg/lib/ser/modules/textops.so"
  loadmodule "/usr/pkg/lib/ser/modules/domain.so"
  
  # ----------------- setting module-specific parameters ---------------
  
  # -- usrloc params --
  # 2 enables write-back to persistent mysql storage for speed
  # disable=0, write-through=1
  modparam("usrloc", "db_mode", 2)
  
  # minimize write back window - default is 60 seconds
  modparam("usrloc", "timer_interval", 10)
  
  # database location
  modparam("usrloc", "db_url", "mysql://ser:heslo@localhost/ser")
  
  # -- auth params --
  modparam("auth_db", "calculate_ha1", yes)
  
  # database location
  modparam("auth_db", "db_url", "mysql://ser:heslo@localhost/ser")
  
  #
  # If you set "calculate_ha1" parameter to yes (which true in this config),
  # uncomment the following parameter as well
  #
  modparam("auth_db", "password_column", "password")
  
  # -- rr params --
  # add value to ;lr param to make some broken UAs happy
  modparam("rr", "enable_full_lr", 1)
  
  # -- nathelper --  
  # Enable NAT pinging
  modparam("nathelper", "natping_interval", 30)
  
  # Ping only contacts that are known to be  
  # behind NAT
  modparam("nathelper", "ping_nated_only", 1)
  
  modparam("nathelper", "rtpproxy_sock", "unix:/var/run/rtpproxy.sock")
  
  # -- multi-domain
  modparam("domain", "db_mode", 1)
  
  # -------------------------  request routing logic -------------------
   
  # main routing logic
  
  route{
  
          # -----------------------------------------------------------------
          # Sanity Check Section
          # -----------------------------------------------------------------
          if (!mf_process_maxfwd_header("10")) {
                  sl_send_reply("483", "Too Many Hops");
                  break;
          };
  
          if (msg:len > max_len) {
                  sl_send_reply("513", "Message Overflow");
                  break;
          };
  
          if (method == "REGISTER") { 
                  route(2);
                  break;
          };
  
          # -----------------------------------------------------------------
          # RTP Proxy Teardown Section
          # -----------------------------------------------------------------
  
          if (method == "BYE" || method == "CANCEL") {
                  unforce_rtp_proxy();
          };
  
          # -----------------------------------------------------------------
          # Loose Route Section
          # -----------------------------------------------------------------
  
          if (method != "REGISTER") {
                  record_route();
          };
          
          if (loose_route()) {
                  route(1);
                  break;
          };
          
          # -----------------------------------------------------------------
          # Call Type Processing Section
          # -----------------------------------------------------------------
  
          if (uri != myself) {
                  route(1);
                  break;
          };
  
          if (method == "CANCEL") {
                  route(1); 
                  break;
          } else if (method == "INVITE") {
                  route(3);
                  break;
          } else if (method == "MESSAGE") {
                  route(8);
                  break;
          };
  
          lookup("aliases");
          if (uri != myself) { 
                  route(1);
                  break;
          }; 
  
          if (!lookup("location_internal")) {
                  if (!lookup("location_external")) {
                          if (method != "ACK")
                                  sl_send_reply("403", "Call cannot be served here");             
                          break;
                  };
          };
          
          route(1);
  }
          
  route[1] {      
                  
          # -----------------------------------------------------------------
          # Default Message Handler
          # -----------------------------------------------------------------
                  
          if (!t_relay())
                  sl_reply_error();
  }               
                  
  route[2] {
                  
          # -----------------------------------------------------------------
          # REGISTER Message Handler
          # ----------------------------------------------------------------
          
          if (!search("^Contact:[ ]*\*") && nat_uac_test("19")) {
                  setflag(6);
                  fix_nated_register();
                  force_rport();
          };      
          
          sl_send_reply("100", "Trying");
  
          if (!www_authorize("mydomain.org","subscriber")) {
                  www_challenge("mydomain.org","0");
                  break;
          };
  
          consume_credentials();
  
          # -----------------------------------------------------------------
          # Save user location based on which interface the REGISTER
          # was sent to.
          # -----------------------------------------------------------------
  
          if (dst_ip == 192.168.0.1) {		#!! Internal IP address 
                  if (!save("location_internal")) {
                          sl_reply_error();
                  };
          } else if (dst_ip == 192.168.255.1) {	#!! External IP address
                  if (!save("location_external")) {
                          sl_reply_error();
                  };
          } else {
                  sl_send_reply("403", "Call cannot be served here");
          };
  }
          
  route[3] { 
                  
          # -----------------------------------------------------------------
          # INVITE Message Handler
          # -----------------------------------------------------------------
  
          # -----------------------------------------------------------------
          # Set flags based on which interface the INVITE was sent to.
          # -----------------------------------------------------------------
  
          if (dst_ip == 192.168.0.1) {		#!! Internal IP address 
                  setflag(11);
          } else if (dst_ip == 192.168.255.1) {	#!! External IP address
                  setflag(12);
          };
  
          if (!proxy_authorize("mydomain.org","subscriber")) {
                  proxy_challenge("mydomain.org","0");
                  break;
          };
  
          # -----------------------------------------------------------------
          # Perform custom INVITE rewriting that depends upon user
          # credentials here. For example, routing calls to the PSTN that
          # are limited by ACLs. Don't forget to drop any credentials
          # you've collected if control flow doesn't reach the next line.
          # -----------------------------------------------------------------
  
          consume_credentials();
          
          route(6);
  }
  
  route[6] {      
  
          # -----------------------------------------------------------------
          # Common Routing
          # -----------------------------------------------------------------
  
          if (uri == myself)
                  lookup("aliases"); 
          
          if (uri != myself) {
                  if (nat_uac_test("19")) {
                          if (isflagset(11)) { 
                                  if (force_rtp_proxy("FAEI"))
                                          t_on_reply("1");
                          } else if (isflagset(12)) {
                                  if (force_rtp_proxy("FAEE"))
                                          t_on_reply("1");
                          }
                  };      
                  route(1);
                  break;
          };      
          
          # -----------------------------------------------------------------
          # The logic here bears a tiny bit of explanation: recall that
          # flags 11 and 12 are set for SIP messages arriving on the internal
          # and external interfaces, respectively (see route[3]). We compare
          # the location of the called party (via lookup()) to the location
          # of the calling party (flags 11/12) to determine whether we need
          # to set up the RTP proxy.
          # -----------------------------------------------------------------
  
          if (lookup("location_internal")) {
                  if (isflagset(11)) {
                          # Only do internal-internal proxy if caller is behind NAT
                          if (nat_uac_test("16")) {
                                  if (force_rtp_proxy("FAII"))
                                          t_on_reply("1");
                          };
                  } else if (isflagset(12)) {
                          if (force_rtp_proxy("FAEI"))
                                  t_on_reply("1");
                  };
          } else if (lookup("location_external")) {
                  if (isflagset(11)) {
                          if (force_rtp_proxy("FAIE"))
                                  t_on_reply("1");
                  } else if (isflagset(12)) {  
                          if (force_rtp_proxy("FAEE"))
                                  t_on_reply("1");
                  };      
          } else {                
                  sl_send_reply("403", "Call cannot be served here");
                  break;                  
          };              
                  
          route(1);
  }
                  
  onreply_route[1] {              
                  
          if (!(status =~ "183" || status =~ "200"))
                  break;  
                  
          force_rtp_proxy("FA");
  }

See also


External link

OnSIP.org


Back to SER tips and tricks


Create location_internal and location_external tables:

It seems that "nathelper module instructions for creating new location_internal and location_external tables" are nowhere to be found, so after many hours of searching and finding bits and pieces, I have come up with the following...

create table location_internal like location;
create table location_external like location;

Don't forget to add entries in the "version" table for each of the newly created tables. Make sure to copy the version value from the original "location" table entry.

Before I did this I received the following errors:

register_udomain(): Invalid table version (use ser_mysql.sh reinstall)
domain_fixup(): Error while registering domain

SIP Express Router

example: SER as a multihomed outbound proxy


This is a stripped-down version of the ser.cfg file that powers a SIP application-level gateway (ALG). This configuration is based on the
OnSIP Getting Started 5.0 configuration and the alg.cfg included in SER 0.9.3 and later.

This configuration is currently running with SER 0.9.4 and uses rtpproxy from CVS. The internal NIC has been assigned IP address 192.168.0.1, and the external NIC has 192.168.255.1. Contrary to the example given in alg.cfg, you must start rtpproxy as follows:

rtpproxy -l 192.168.255.1/192.168.0.1

This puts the proxy into bridge mode, which enables the proxy to work properly when faced with user agents on either the internal network or the external network.

For this example to work, you must also follow the nathelper module instructions for creating new location_internal and location_external tables. Be careful to use underscores ("_") and not hyphens ("-") when creating the new tables.


  # $Id: ser.cfg,v 1.9 2005/10/03 01:06:51 root Exp root $
  
  # ----------- global configuration parameters ------------------------
  
  debug=3         # debug level (cmd line: -dddddddddd)
  fork=yes
  log_stderror=no # (cmd line: -E)
  
  port=5060
  check_via=no    # (cmd. line: -v)
  dns=no          # (cmd. line: -r)
  rev_dns=no      # (cmd. line: -R)
  children=3
  fifo="/tmp/ser_fifo"
  
  alias="mydomain.org"
  
  # mhomed -- enable calculation of outbound interface; useful on
  # multihomed servers.
  mhomed=1
  
  
  # ------------------ module loading ----------------------------------
  
  loadmodule "/usr/pkg/lib/ser/modules/mysql.so"
  loadmodule "/usr/pkg/lib/ser/modules/sl.so"
  loadmodule "/usr/pkg/lib/ser/modules/tm.so"
  loadmodule "/usr/pkg/lib/ser/modules/rr.so"
  loadmodule "/usr/pkg/lib/ser/modules/maxfwd.so"
  loadmodule "/usr/pkg/lib/ser/modules/usrloc.so" 
  loadmodule "/usr/pkg/lib/ser/modules/registrar.so"
  loadmodule "/usr/pkg/lib/ser/modules/auth.so"
  loadmodule "/usr/pkg/lib/ser/modules/auth_db.so"
  loadmodule "/usr/pkg/lib/ser/modules/uri.so"
  loadmodule "/usr/pkg/lib/ser/modules/uri_db.so"
  loadmodule "/usr/pkg/lib/ser/modules/group.so"
  loadmodule "/usr/pkg/lib/ser/modules/nathelper.so"
  loadmodule "/usr/pkg/lib/ser/modules/textops.so"
  loadmodule "/usr/pkg/lib/ser/modules/domain.so"
  
  # ----------------- setting module-specific parameters ---------------
  
  # -- usrloc params --
  # 2 enables write-back to persistent mysql storage for speed
  # disable=0, write-through=1
  modparam("usrloc", "db_mode", 2)
  
  # minimize write back window - default is 60 seconds
  modparam("usrloc", "timer_interval", 10)
  
  # database location
  modparam("usrloc", "db_url", "mysql://ser:heslo@localhost/ser")
  
  # -- auth params --
  modparam("auth_db", "calculate_ha1", yes)
  
  # database location
  modparam("auth_db", "db_url", "mysql://ser:heslo@localhost/ser")
  
  #
  # If you set "calculate_ha1" parameter to yes (which true in this config),
  # uncomment the following parameter as well
  #
  modparam("auth_db", "password_column", "password")
  
  # -- rr params --
  # add value to ;lr param to make some broken UAs happy
  modparam("rr", "enable_full_lr", 1)
  
  # -- nathelper --  
  # Enable NAT pinging
  modparam("nathelper", "natping_interval", 30)
  
  # Ping only contacts that are known to be  
  # behind NAT
  modparam("nathelper", "ping_nated_only", 1)
  
  modparam("nathelper", "rtpproxy_sock", "unix:/var/run/rtpproxy.sock")
  
  # -- multi-domain
  modparam("domain", "db_mode", 1)
  
  # -------------------------  request routing logic -------------------
   
  # main routing logic
  
  route{
  
          # -----------------------------------------------------------------
          # Sanity Check Section
          # -----------------------------------------------------------------
          if (!mf_process_maxfwd_header("10")) {
                  sl_send_reply("483", "Too Many Hops");
                  break;
          };
  
          if (msg:len > max_len) {
                  sl_send_reply("513", "Message Overflow");
                  break;
          };
  
          if (method == "REGISTER") { 
                  route(2);
                  break;
          };
  
          # -----------------------------------------------------------------
          # RTP Proxy Teardown Section
          # -----------------------------------------------------------------
  
          if (method == "BYE" || method == "CANCEL") {
                  unforce_rtp_proxy();
          };
  
          # -----------------------------------------------------------------
          # Loose Route Section
          # -----------------------------------------------------------------
  
          if (method != "REGISTER") {
                  record_route();
          };
          
          if (loose_route()) {
                  route(1);
                  break;
          };
          
          # -----------------------------------------------------------------
          # Call Type Processing Section
          # -----------------------------------------------------------------
  
          if (uri != myself) {
                  route(1);
                  break;
          };
  
          if (method == "CANCEL") {
                  route(1); 
                  break;
          } else if (method == "INVITE") {
                  route(3);
                  break;
          } else if (method == "MESSAGE") {
                  route(8);
                  break;
          };
  
          lookup("aliases");
          if (uri != myself) { 
                  route(1);
                  break;
          }; 
  
          if (!lookup("location_internal")) {
                  if (!lookup("location_external")) {
                          if (method != "ACK")
                                  sl_send_reply("403", "Call cannot be served here");             
                          break;
                  };
          };
          
          route(1);
  }
          
  route[1] {      
                  
          # -----------------------------------------------------------------
          # Default Message Handler
          # -----------------------------------------------------------------
                  
          if (!t_relay())
                  sl_reply_error();
  }               
                  
  route[2] {
                  
          # -----------------------------------------------------------------
          # REGISTER Message Handler
          # ----------------------------------------------------------------
          
          if (!search("^Contact:[ ]*\*") && nat_uac_test("19")) {
                  setflag(6);
                  fix_nated_register();
                  force_rport();
          };      
          
          sl_send_reply("100", "Trying");
  
          if (!www_authorize("mydomain.org","subscriber")) {
                  www_challenge("mydomain.org","0");
                  break;
          };
  
          consume_credentials();
  
          # -----------------------------------------------------------------
          # Save user location based on which interface the REGISTER
          # was sent to.
          # -----------------------------------------------------------------
  
          if (dst_ip == 192.168.0.1) {		#!! Internal IP address 
                  if (!save("location_internal")) {
                          sl_reply_error();
                  };
          } else if (dst_ip == 192.168.255.1) {	#!! External IP address
                  if (!save("location_external")) {
                          sl_reply_error();
                  };
          } else {
                  sl_send_reply("403", "Call cannot be served here");
          };
  }
          
  route[3] { 
                  
          # -----------------------------------------------------------------
          # INVITE Message Handler
          # -----------------------------------------------------------------
  
          # -----------------------------------------------------------------
          # Set flags based on which interface the INVITE was sent to.
          # -----------------------------------------------------------------
  
          if (dst_ip == 192.168.0.1) {		#!! Internal IP address 
                  setflag(11);
          } else if (dst_ip == 192.168.255.1) {	#!! External IP address
                  setflag(12);
          };
  
          if (!proxy_authorize("mydomain.org","subscriber")) {
                  proxy_challenge("mydomain.org","0");
                  break;
          };
  
          # -----------------------------------------------------------------
          # Perform custom INVITE rewriting that depends upon user
          # credentials here. For example, routing calls to the PSTN that
          # are limited by ACLs. Don't forget to drop any credentials
          # you've collected if control flow doesn't reach the next line.
          # -----------------------------------------------------------------
  
          consume_credentials();
          
          route(6);
  }
  
  route[6] {      
  
          # -----------------------------------------------------------------
          # Common Routing
          # -----------------------------------------------------------------
  
          if (uri == myself)
                  lookup("aliases"); 
          
          if (uri != myself) {
                  if (nat_uac_test("19")) {
                          if (isflagset(11)) { 
                                  if (force_rtp_proxy("FAEI"))
                                          t_on_reply("1");
                          } else if (isflagset(12)) {
                                  if (force_rtp_proxy("FAEE"))
                                          t_on_reply("1");
                          }
                  };      
                  route(1);
                  break;
          };      
          
          # -----------------------------------------------------------------
          # The logic here bears a tiny bit of explanation: recall that
          # flags 11 and 12 are set for SIP messages arriving on the internal
          # and external interfaces, respectively (see route[3]). We compare
          # the location of the called party (via lookup()) to the location
          # of the calling party (flags 11/12) to determine whether we need
          # to set up the RTP proxy.
          # -----------------------------------------------------------------
  
          if (lookup("location_internal")) {
                  if (isflagset(11)) {
                          # Only do internal-internal proxy if caller is behind NAT
                          if (nat_uac_test("16")) {
                                  if (force_rtp_proxy("FAII"))
                                          t_on_reply("1");
                          };
                  } else if (isflagset(12)) {
                          if (force_rtp_proxy("FAEI"))
                                  t_on_reply("1");
                  };
          } else if (lookup("location_external")) {
                  if (isflagset(11)) {
                          if (force_rtp_proxy("FAIE"))
                                  t_on_reply("1");
                  } else if (isflagset(12)) {  
                          if (force_rtp_proxy("FAEE"))
                                  t_on_reply("1");
                  };      
          } else {                
                  sl_send_reply("403", "Call cannot be served here");
                  break;                  
          };              
                  
          route(1);
  }
                  
  onreply_route[1] {              
                  
          if (!(status =~ "183" || status =~ "200"))
                  break;  
                  
          force_rtp_proxy("FA");
  }

See also


External link

OnSIP.org


Back to SER tips and tricks


Create location_internal and location_external tables:

It seems that "nathelper module instructions for creating new location_internal and location_external tables" are nowhere to be found, so after many hours of searching and finding bits and pieces, I have come up with the following...

create table location_internal like location;
create table location_external like location;

Don't forget to add entries in the "version" table for each of the newly created tables. Make sure to copy the version value from the original "location" table entry.

Before I did this I received the following errors:

register_udomain(): Invalid table version (use ser_mysql.sh reinstall)
domain_fixup(): Error while registering domain

Created by: scottr, Last modification: Sat 11 of Sep, 2010 (21:06 UTC) by pegger
Please update this page with new information, just login and click on the "Edit" or "Discussion" tab. Get a free login here: Register Thanks! - Find us on Google+