ClearIP In-Line Proxy

The ClearIP In-Line Proxy enables easy integration between a SIP telecommunications network and ClearIP.

This software is not required in all ClearIP deployments. Some ClearIP customers prefer to use it because it can make deployment easier with their telecom network equipment and software.

The ClearIP In-Line Proxy performs the following functions:

  • Receives SIP requests from network elements within a telecommunications network
  • For INVITEs, forwards the SIP INVITE to ClearIP for services
  • Receives SIP responses back from ClearIP based upon services performed
  • For SIP 3xx redirect responses from ClearIP, constructs a new SIP INVITE using the reply headers and sends it to the next destination
  • For non-INVITE requests, relays the request according to routing rules or generates local replies when appropriate (e.g., OPTIONS 200 OK)

Network configuration

The ClearIP In-Line Proxy can be configured in several different ways according to the preferences and requirements of the service provider. Typically, the ClearIP In-Line Proxy will be placed between the Switch and the Provider, and communicate with ClearIP directly.

In this arrangement, the ClearIP In-Line Proxy receives SIP INVITEs, forwards them to ClearIP, receives the replies and sends the message to the appropriate network elements (e.g., switch, SBC).

Outbound

The following figure shows the call flow when ClearIP returns a SIP 302 Redirect response for routing and/or STIR/SHAKEN authentication of an outbound call:

SubscriCbaelrlSetup(SIPorTDMS)witchSIPINVITIEnlinePSSrIIoPPxSyIIINPNVVI3IT0TE2ERweidtihrePcAtSSwpiotrhTPASSporTandProvideraddress(eCsl)earIPProvider
  1. A Subscriber sends a call to the Switch over SIP or TDM.
  2. The Switch sends a SIP INVITE to the In-Line Proxy.
  3. The In-Line Proxy forwards the SIP INVITE to ClearIP for services (e.g., STIR/SHAKEN authentication, routing, toll fraud prevention, robocall mitigation, etc.).
  4. ClearIP responds to the In-Line Proxy with a SIP 302 Redirect message with STIR/SHAKEN Identity header and Contact header, including the IP address(es) of the Provider(s).
  5. The In-Line Proxy constructs a new SIP INVITE using the headers that come back from ClearIP, including the Identity header, and sends that redirected SIP INVITE with Identity header to the first Provider. If the first Provider is unable to complete the call, then the In-Line Proxy continues routing through the remaining destinations returned in the SIP 302 Contact header.

Inbound

The following figure shows the call flow when ClearIP returns a SIP 302 Redirect response for termination and STIR/SHAKEN verification of an inbound call:

ProvidSeIrPINVITEwithPASSpoIrnTlinePSSrIIoPPxSyIIINPNVVI3IT0TE2EwRwieitdthihrPePAcAStISpwoirtThPAIandSwitchaddress(eCsl)earIPSwitchSIPINVITEwithSPuAbIscriber
  1. A Provider sends a call to the In-Line Proxy.
  2. The In-Line Proxy forwards the SIP INVITE to ClearIP for services (e.g., STIR/SHAKEN verification, routing, robocall prevention, TDoS prevention, etc.).
  3. ClearIP responds to the In-Line Proxy with a SIP 302 Redirect message with P-Asserted-Identity header (PAI) and Contact header, including the IP address(es) of the Switch(es).
  4. The In-Line Proxy constructs a new SIP INVITE using the headers that come back from ClearIP, including the P-Asserted-Identity header, and sends that redirected SIP INVITE to the first Switch. If the first Switch is unable to complete the call, then the In-Line Proxy continues routing through the remaining destinations returned in the SIP 302 Contact header.

Installation and setup

Create virtual machines

The virtual machines must have at least 4 GB of RAM. The virtual machines must have direct access to the internet. SIP is a bidirectional protocol, so each virtual machine must either have its own public IP, or must be configured to use one-to-one NAT.

Configure firewall rules

Firewall rules for both UDP and TCP on port 5060 must be configured to prevent unauthorized access to the SIP proxy.

Install Kamailio

Install Kamailio by following these instructions: https://www.kamailio.org/wikidocs/#installation. As an example, to install Kamailio on Ubuntu 26.04, run the following command:

sudo apt install kamailio

Configure Kamailio

The Kamailio config is typically saved at /etc/kamailio/kamailio.cfg for package-based installs. Replace the active Kamailio config with the configuration below:

#!KAMAILIO

#### Core parameters
debug=1
log_stderror=no
auto_aliases=no
dns_try_naptr=no
dns_use_search_list=no
open_files_limit=8192
server_signature=no
sip_warning=no
children=32
tcp_children=32
tcp_connect_timeout=1
tcp_connection_lifetime=100
tcp_keepalive=yes
tcp_keepcnt=20
tcp_keepidle=5
tcp_keepintvl=5
tcp_max_connections=65536

#### Setup listeners
listen=udp:<PUBLIC_IP>:5060
listen=tcp:<PUBLIC_IP>:5060

#### Load modules
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
loadmodule "textops.so"
loadmodule "pv.so"
loadmodule "uac_redirect.so"

#### Configure modules
modparam("rr", "enable_full_lr", 1)
modparam("rr", "enable_double_rr", 2)
modparam("rr", "append_fromtag", 0)

modparam("tm", "fr_timer", 2000)
modparam("tm", "fr_inv_timer", 5000)
modparam("tm", "restart_fr_on_each_reply", 0)
modparam("tm", "auto_inv_100", 0)
modparam("tm", "contacts_avp", "tm_contacts")
modparam("tm", "contact_flows_avp", "tm_contact_flows")

modparam("uac_redirect", "acc_function", "")

#### Routing logic
request_route {
  if ($ml > 8192) {
    sl_send_reply("413", "Request Entity Too Large");
    exit;
  }

  if (!mf_process_maxfwd_header("10")) {
    sl_send_reply("483", "Too Many Hops");
    exit;
  }

  if (is_method("CANCEL")) {
    if (t_check_trans()) {
      if (!t_relay()) {
        t_reply_error();
      }
    }
    exit;
  }

  if (loose_route()) {
    if (is_method("INVITE") || is_method("ACK")) {
      t_set_disable_internal_reply(1);
      if (!t_relay()) {
        t_reply_error();
      }
      exit;
    }
  } else {
    if (is_method("BYE")) {
      if (!t_check_trans()) {
        sl_send_reply("481", "Call/Transaction Does Not Exist");
      }
      exit;
    }
  }

  if (is_method("INVITE")) {
    if (t_check_trans()) {
      exit;
    }

    record_route();
    sl_send_reply("100", "Trying");
    route(CLEARIP);
  } else if (is_method("ACK")) {
    if (t_check_trans()) {
      t_relay();
    }
  } else if (is_method("OPTIONS")) {
    sl_send_reply("200", "OK");
  } else {
    t_set_disable_internal_reply(1);
    if (!t_relay()) {
      t_reply_error();
    }
  }
}

route[CLEARIP] {
  $(avp(identity)[*]) = $null;
  $(avp(redirect_retry)[*]) = $null;
  $(avp(pai)[*]) = $null;

  t_reset_fr();
  t_on_reply("MANAGE_REPLY");
  t_on_failure("FROM_CLEARIP");

  remove_hf("P-Source-Device");
  append_hf("P-Source-Device: $si\r\n");

  $du = "sip:sip.clearip.com:5060;transport=tcp";
  t_set_disable_internal_reply(1);
  if (!t_relay()) {
    t_reply("502", "Bad Gateway");
  }
  exit;
}

route[REDIRECTS] {
  if (!t_next_contacts()) {
    $(avp(redirect_retry)[*]) = $null;
    t_reply("404", "Not Found");
    exit;
  }

  route(RELAY_REDIRECTS);
}

route[RELAY_REDIRECTS] {
  t_on_branch("APPLY_REDIRECT_HEADERS");
  t_on_reply("MANAGE_REPLY");
  t_on_failure("FROM_CLEARIP");

  if (!t_relay()) {
    t_reply_error();
  }
  exit;
}

branch_route[APPLY_REDIRECT_HEADERS] {
  if ($avp(identity) != $null) {
    remove_hf("Identity");
    append_hf("Identity: $avp(identity)\r\n");
  }

  if ($avp(pai) != $null) {
    remove_hf("P-Asserted-Identity");
    append_hf("P-Asserted-Identity: $avp(pai)\r\n");
  }
}

onreply_route[MANAGE_REPLY] {
  if (t_check_status("180|183|100")) {
    t_set_fr(60000);
  }
}

failure_route[FROM_CLEARIP] {
  if (t_is_canceled()) {
    t_reply("487", "Request Terminated");
    exit;
  }

  if (t_check_status("3[0-9][0-9]")) {
    if ($T_rpl($hdr(Identity)) != $null) {
      $(avp(identity)[*]) = $T_rpl($hdr(Identity));
    } else if ($T_rpl($hdr(X-Identity)) != $null) {
      $(avp(identity)[*]) = $T_rpl($hdr(X-Identity));
    }

    if ($T_rpl($hdr(P-Asserted-Identity)) != $null) {
      $(avp(pai)[*]) = $T_rpl($hdr(P-Asserted-Identity));
    }

    if ($T_rpl($hdr(Contact)) == $null) {
      t_reply("404", "Not Found");
      exit;
    }

    get_redirects("*:*");

    # One redirect target is promoted and relayed directly.
    # Multiple redirect targets use t_load_contacts() and t_next_contacts().
    if ($branch(count) > 1) {
      if (!t_load_contacts()) {
        t_reply("500", "Redirect Processing Error");
        exit;
      }

      $(avp(redirect_retry)[*]) = 1;
      route(REDIRECTS);
      exit;
    }

    $ru = $(branch(uri)[0]);
    if ($(branch(dst_uri)[0]) != $null && $(branch(dst_uri)[0]) != "") {
      $du = $(branch(dst_uri)[0]);
    } else {
      $du = $null;
    }
    $(branch(uri)[0]) = $null;
    route(RELAY_REDIRECTS);
    exit;
  } else if (t_check_status("486|487|6[0-9][0-9]")) {
    exit;
  } else if (t_check_status("408")) {
    if ($T(reply_type) == 1 && $avp(redirect_retry) != $null) {
      route(REDIRECTS);
    }
    exit;
  }

  if ($avp(redirect_retry) != $null) {
    route(REDIRECTS);
  }
  exit;
}

Configure Kamailio IP address

No NAT

Replace <PUBLIC_IP> with the virtual machine’s public IP address in the following two lines from the above Kamailio config:

listen=udp:<PUBLIC_IP>:5060
listen=tcp:<PUBLIC_IP>:5060

One-to-One NAT

In some environments, such as AWS EC2, the network interface is assigned a private IP address and one-to-one NAT is used to translate the private IP address to a public IP address. For these environments, change the following lines in the above Kamailio config from this:

listen=udp:<PUBLIC_IP>:5060
listen=tcp:<PUBLIC_IP>:5060

to this:

listen=udp:<PRIVATE_IP>:5060 advertise <PUBLIC_IP>:5060
listen=tcp:<PRIVATE_IP>:5060 advertise <PUBLIC_IP>:5060

and replace <PRIVATE_IP> with the virtual machine’s private IP address and <PUBLIC_IP> with the virtual machine’s public IP address.

Adjust timeout if needed

The default timeout is 5 seconds (5000 ms). Change the following line to the desired timeout (in milliseconds):

modparam("tm", "fr_inv_timer", 5000)

Restart Kamailio

sudo systemctl restart kamailio

Troubleshooting

Check TCP connection using nc (ncat)

It is important to ensure that the In-Line Proxy can connect to ClearIP and provider devices. The Linux command nc can be used to test the TCP connection between the In-Line Proxy and ClearIP/provider devices.

To test the TCP connection to ClearIP:

nc -zv sip.clearip.com 5060

To test the TCP connection to provider devices:

nc -zv provider_device_fqdn/ip 5060

This command also can be used for troubleshooting connection issues.

Capture a call trace using tcpdump

You can capture a call trace in your network traffic by running the tcpdump command with different parameters.

Run tcpdump to view SIP messages on the default SIP port 5060 with messages displayed on the console:

sudo tcpdump -A -s 0 -n -nn -i any port 5060

You can also choose to save all network traffic to a pcap file:

sudo tcpdump -w trace.pcap -i any

If you encounter any fragmented packets, most likely when capturing larger SIP INVITEs with Identity headers, you will want to save the network traffic to a pcap file.