OpenSIPS#
OpenSIPS is an open-source SIP signaling server for routing calls between SIP devices, PBX systems, and service providers.
This guide explains how to connect OpenSIPS 4.0 to DIDWW SIP Trunking for inbound and outbound calling. It covers configuring DIDWW inbound and outbound SIP trunks, assigning DID numbers, and routing calls between DIDWW and a user agent behind OpenSIPS.
The inbound configuration supports Static Endpoint and Dynamic Registration trunks. The outbound configuration uses SIP digest authentication. No database is required.
Important
OpenSIPS handles SIP signaling only in this configuration. A user agent is required to handle call media. Add the user agent’s public RTP address to the allowed RTP addresses of the DIDWW inbound and outbound trunks.
1. Configure inbound voice trunk#
Configure an Inbound SIP Trunk in the DIDWW User Panel to send incoming calls from your DIDWW numbers to OpenSIPS. Select the delivery method that matches your OpenSIPS deployment.
Before you begin#
An active DIDWW account is required. Sign in to DIDWW or create a DIDWW account.
At least one active DID number with capacity to receive incoming calls is required. If you do not have one, see How to buy numbers.
Step 1: Create New Inbound SIP trunk#
In the DIDWW User Panel, go to Voice > Inbound Trunks.
Click Create New > SIP Trunk.
Creating a new inbound SIP trunk.#
Step 2: Configure general SIP trunk settings#
In the Create Inbound SIP Trunk form, enter the settings for the selected trunk type.
Enter a descriptive Name for the trunk (e.g.,
OpenSIPS).Select Static Endpoint as the trunk Type.
In Host, enter the public IP address of the OpenSIPS server or a domain name that resolves to it.
Select UDP as the signaling Transport and enter
5060as the Port. These values must match the OpenSIPS listening socket.Set User Part of R-URI to
{DID}. This placeholder inserts the called DID in E.164 format into the user part of the Request-URI.Leave Preferred Server at Auto unless calls must originate from a specific Point of Presence.
Static Endpoint trunk settings.#
Enter a descriptive Name for the trunk (e.g.,
OpenSIPS).Select Dynamic Registration as the trunk Type.
Configure the remaining media and signaling settings required by your deployment.
Dynamic Registration trunk settings.#
For either trunk type, open Media & DTMF and configure the following:
Enter the user agent’s public RTP address in Allowed RTP IP Addresses. OpenSIPS does not relay RTP in this configuration.
Enable Force Symmetric RTP if the user agent is behind NAT.
Important
Keep Allowed RTP IP Addresses configured when using Force Symmetric RTP to restrict accepted media sources. Leaving the address list empty allows RTP from any source.
Inbound trunk media settings.#
Step 3: Click Create and Save Inbound SIP Trunk Configuration#
When all required fields in the Create Inbound SIP Trunk form are filled, click Create to save the trunk.
Note
For advanced SIP trunk configuration, see Advanced Inbound SIP Trunk documentation.
Step 4: Copy Inbound Trunk Credentials (Dynamic Registration Only)#
For a Dynamic Registration trunk, open the created trunk and copy its generated username, password, and registration endpoint. You will use these values when you register the inbound trunk. Static Endpoint trunks do not use registration credentials.
Note
The example registers with sip.didww.com. A regional endpoint such as
ams.sip.didww.com registers the trunk with a specific location.
OpenSIPS takes the registration digest realm from the registrar’s challenge.
Dynamic Registration credentials and endpoints.#
Step 5: Assign inbound SIP trunk to your DID numbers#
After creating the Inbound SIP Trunk for OpenSIPS, assign it to the DID number(s) that will deliver incoming calls to OpenSIPS.
In the DIDWW User Panel, go to Phone Numbers > My Numbers.
Select the DID number(s) you want to assign to the inbound SIP trunk.
At the bottom of the page, click Batch Actions > Update Trunks.
Selecting Update Trunks from the Batch Actions menu.#
From the dropdown menu, choose the OpenSIPS SIP trunk created in Step 3.
Click Confirm to apply the changes.
Assigning the newly created SIP trunk to the selected DID(s).#
2. Configure outbound voice trunk#
Configure an Outbound SIP Trunk in the DIDWW User Panel to allow OpenSIPS to place outbound calls through DIDWW. This trunk provides the SIP credentials and routing settings required for outbound calls to external phone numbers.
Before you begin#
Access to DIDWW Outbound Trunks is required for making outbound calls. See Get access to outbound trunks.
Step 1: Create New Outbound SIP Trunk#
In the DIDWW User Panel, go to Voice > Outbound Trunks.
Click Create New.
Creating a new outbound SIP trunk.#
Step 2: Configure Authentication#
Update the Friendly Name (e.g.,
OpenSIPS).Keep the default Credentials & IP-Based authentication method selected. The SIP digest credentials will be provided after the trunk is created.
Leave Tech Prefix empty for this example.
In Allowed SIP IP addresses, enter the public IP address or subnet from which OpenSIPS will send outbound SIP traffic.
In Allowed RTP IP addresses, enter the public address from which the user agent will send RTP.
Configure Allowed CLI(s) and the other termination settings required by your deployment.
Note
At least one Allowed SIP IP address is required. The trunk accepts up to 60 SIP addresses or subnets. If you configure a Tech Prefix, the outgoing Request-URI must include it before the dialed number.
Outbound trunk authentication settings.#
Important
The caller ID must match the value set by uac_replace_from() in the
OpenSIPS outbound route.
A call can pass digest authentication and still be rejected by the trunk’s
CLI or destination settings.
Step 3: Click Create and Save Outbound SIP Trunk Configuration#
When all required fields in the Create Outbound SIP Trunk form are filled, click Create to save the trunk.
Note
For advanced outbound SIP trunk configuration, see Outbound SIP Trunk Guide.
Creating the outbound SIP trunk.#
Note
Check that the trunk’s Status is enabled before testing calls. Reaching the rolling 24-hour limit disables the trunk, blocks new calls, and disconnects active calls shortly afterward. Review usage before enabling the trunk again.
Step 4: View Outbound Trunk Credentials#
After the outbound trunk is created, you can view its credentials by selecting the key icon in the Credentials column on the Outbound Trunks page.
Go to Voice > Outbound Trunks.
Locate your outbound trunk and click the key icon in the Credentials column.
Opening the OpenSIPS outbound trunk credentials.#
The trunk credentials will appear, showing the Username and Password (click the eye icon to reveal the password).
Copy and securely store the credentials, and choose an outbound endpoint from Host(s). You will use them when you configure outbound routing.
OpenSIPS outbound trunk credentials and hostnames.#
The example uses ams.eu.out.didww.com. See
Outbound SIP information for regional
endpoints, DNS SRV failover, and BGP Anycast.
Important
The outbound digest authentication realm is out.didww.com for all
DIDWW outbound endpoints. Use this value in the uac_auth credential,
even when calls are sent to a regional hostname or any.out.didww.com.
Note
If an outbound password is exposed, regenerate it in the DIDWW User Panel. Regenerating the password invalidates the previous value immediately. Update the OpenSIPS credential and restart the proxy to use the new value.
3. Configure OpenSIPS#
Configure OpenSIPS to use the DIDWW trunks created in Part 1 and Part 2. The script routes calls between DIDWW and one user agent and authenticates outbound calls without a database.
The examples use /etc/opensips/opensips.cfg and the module directory for
an x86-64 installation. They use UDP on port 5060. Replace the example
addresses, caller ID, and uppercase credential placeholders with the values
for your deployment.
Note
For general information about the script and its routing model, see the official Types of routes and Core Parameters documentation.
Before you begin#
OpenSIPS 4.0 is required.
Install opensips-auth-modules to provide the uac_auth module for outbound digest authentication.
If you use a Dynamic Registration inbound trunk, install OpenSIPS CLI to manage the registration.
Step 1: Configure the OpenSIPS script#
The same OpenSIPS script supports Static Endpoint and Dynamic Registration trunks. Dynamic Registration additionally requires the registration in Step 3.
The following blocks build /etc/opensips/opensips.cfg in order. Back up
the current file, then replace its contents with the global parameters,
module settings, and routing blocks below.
The examples use the following deployment values. Replace them consistently before loading the configuration.
Value in this guide |
Replace with |
|---|---|
|
The public address through which DIDWW can reach OpenSIPS. |
|
The address of the user agent behind OpenSIPS. |
|
The user agent extension that receives incoming calls. |
|
A caller ID permitted by the outbound trunk’s CLI settings. |
|
The outbound endpoint selected from the trunk’s credentials. |
|
The outbound trunk credentials. |
|
The Dynamic Registration trunk credentials used when you register the inbound trunk. |
1.1 Configure the listening socket and advertised address#
Begin the file with the global parameters:
log_level=3
stderror_enabled=yes
syslog_enabled=no
udp_workers=4
socket=udp:0.0.0.0:5060
advertised_address="203.0.113.10"
Set advertised_address to the public address of the proxy or the NAT
device in front of it. This is normally the same address configured in the
outbound trunk authentication settings.
The process writes logs to standard error at info level. Use this output when verifying calls.
Important
The advertised address must be reachable by DIDWW. OpenSIPS uses it in
Via and Record-Route headers. With the wildcard socket in this
example, leaving it unset can advertise 0.0.0.0 and prevent an
ACK from reaching the proxy. A call may connect and then disconnect
after approximately 30 seconds. Adding rport does not correct the
address used to route this request.
1.2 Load the required modules and credentials#
Add the module settings below the global parameters:
mpath="/usr/lib/x86_64-linux-gnu/opensips/modules/"
loadmodule "proto_udp.so"
loadmodule "signaling.so"
loadmodule "sl.so"
loadmodule "tm.so"
modparam("tm", "fr_timeout", 5)
modparam("tm", "fr_inv_timeout", 30)
loadmodule "rr.so"
modparam("rr", "append_fromtag", 1)
loadmodule "maxfwd.so"
loadmodule "sipmsgops.so"
loadmodule "mi_fifo.so"
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
modparam("mi_fifo", "fifo_mode", 0666)
loadmodule "uac_auth.so"
modparam("uac_auth", "credential", "OUTBOUND_USERNAME:out.didww.com:OUTBOUND_PASSWORD")
loadmodule "uac.so"
modparam("uac", "restore_mode", "none")
loadmodule "uac_registrant.so"
modparam("uac_registrant", "hash_size", 2)
modparam("uac_registrant", "timer_interval", 30)
Set mpath to the module directory for your installation. The example
uses the x86-64 directory.
Replace OUTBOUND_USERNAME and OUTBOUND_PASSWORD with the
outbound trunk credentials.
Keep out.didww.com as the digest realm. Inbound registration credentials
are supplied separately in Step 3.
The FIFO path is the default used by opensips-cli. The registration
timer runs every 30 seconds. With the 60-second expiry in
Step 3, the proxy refreshes the
registration every 30 seconds to help keep the NAT mapping active.
Note
Keep the following settings from the tested configuration:
loadmodule "proto_udp.so"is required in the tested build even though a separate module file is not present. Omitting it causesno transport protocol loadedat startup.append_fromtagmust be1foruac_auth(), including whenrestore_modeisnone.The tested build logs
ERROR:uac:mod_init: Can't load dlg APIwhile checking for the dialog API. It can continue without that API. Check subsequent output to confirm whether startup succeeded.
1.3 Configure the DIDWW ACL#
Open the main route with the request checks and DIDWW source-address match:
route {
if (!mf_process_maxfwd_header(10)) {
send_reply(483, "Too Many Hops");
exit;
}
if (has_totag()) {
if (is_method("ACK") && t_check_trans()) {
t_relay();
exit;
}
if (!loose_route()) {
send_reply(404, "Not here");
exit;
}
route(RELAY);
exit;
}
if (is_method("CANCEL")) {
if (t_check_trans())
t_relay();
exit;
}
if (is_method("OPTIONS")) {
send_reply(200, "OK");
exit;
}
if (!is_method("INVITE")) {
send_reply(405, "Method Not Allowed");
exit;
}
t_check_trans();
record_route();
if ($si =~ "^46\.19\.(2(08|09|1[0-5]))\." || $si =~ "^185\.238\.17[2-5]\.") {
The source-address expressions cover 46.19.208.0/21 and
185.238.172.0/22. These ranges contain the published DIDWW IPv4 signaling
addresses used by the tested configuration.
Important
Allow the DIDWW sources for the selected trunk type and failover locations. With Preferred Server set to Auto, calls can arrive from different DIDWW Points of Presence. See Technical Specifications for the signaling addresses and network requirements.
The example opens an IPv4 socket only. An IPv6 deployment requires additional socket and source-address configuration.
1.4 Configure inbound routing#
Continue inside the DIDWW branch opened in the previous block:
xlog("L_INFO", "inbound from carrier $si ruri=$ru from=$fu callid=$ci\n");
$ru = "sip:1000@192.168.1.20:5060";
route(RELAY);
exit;
}
Replace the URI with the extension, address, and port of the user agent
behind OpenSIPS. The xlog line records incoming requests for call testing.
Important
This example rewrites the Request-URI for every incoming call and sends all DIDs to one destination. Keep the unconditional rewrite when using this setup. Routing by called number requires a separate configuration and confirmation of the Request-URI delivered by your trunk.
To serve several DIDs and route calls by the called number, use a Static Endpoint trunk. DIDWW builds the Request-URI from User Part of R-URI, so the number is included in the request line. Dynamic Registration trunks cannot be distinguished by DIDWW source address because calls arrive from the same DIDWW ranges. Separating them requires individual registration sockets and routing based on the inbound socket, which is outside this guide.
1.5 Configure outbound routing and digest authentication#
Below the DIDWW branch, add the user-agent match and outbound routing:
if ($si == "192.168.1.20") {
add_local_rport();
uac_replace_from("", "sip:442079460000@ams.eu.out.didww.com");
$ru = "sip:" + $rU + "@ams.eu.out.didww.com";
t_on_failure("CARRIER_AUTH");
route(RELAY);
exit;
}
send_reply(403, "Forbidden");
exit;
}
route[RELAY] {
if (!t_relay())
sl_reply_error();
exit;
}
failure_route[CARRIER_AUTH] {
if (t_was_cancelled())
exit;
if (t_check_status("401|407")) {
if (uac_auth()) {
t_relay();
exit;
}
xlog("L_ERR", "uac_auth() failed for callid=$ci\n");
}
}
Replace 192.168.1.20 with the user agent’s address. Replace
442079460000 with the permitted caller ID and
ams.eu.out.didww.com with the selected outbound endpoint in both URIs.
The digest realm in the module settings remains out.didww.com
regardless of the outbound endpoint.
Note
add_local_rport()addsrportto relayed requests so responses can return to the source port used by a NAT device.uac_replace_from()takes two arguments in OpenSIPS 4.0. The first is the display name, which is empty in this example.DIDWW can challenge an outbound
INVITEwith401andWWW-Authenticate. The failure route handles both401and407responses.
Important
DIDWW checks the caller ID written by uac_replace_from() against
CLI Settings. A successful digest exchange does not override caller ID
restrictions. With On CLI Mismatch set to Reject Call, an unlisted
caller ID causes the call to fail.
1.6 Add rport to locally generated requests#
Add a local route for requests generated by OpenSIPS, including registration:
local_route {
add_local_rport();
}
The outbound route’s add_local_rport() applies to relayed requests.
This local route also adds rport to REGISTER requests generated by
the proxy. Without it, a NAT device that changes the source port can prevent
registration responses from returning.
Step 2: Load the configuration#
Check that the configuration parses:
opensips -C -f /etc/opensips/opensips.cfg
Important
config file ok, exiting... confirms that the script parses. This
check does not initialize the modules. Start OpenSIPS and review the
startup output as well.
Start OpenSIPS in the foreground:
opensips -F -f /etc/opensips/opensips.cfg
Leave OpenSIPS running. If you use a Dynamic Registration trunk, open another terminal and complete Step 3.
Step 3: Register the inbound trunk#
Complete this step for a Dynamic Registration trunk. Skip it for a Static Endpoint trunk.
Submit the registration through the management interface:
opensips-cli -x mi uac_registrant:upsert \
aor="sip:INBOUND_USERNAME@sip.didww.com" \
contact="sip:INBOUND_USERNAME@203.0.113.10:5060" \
registrar="sip:sip.didww.com" \
proxy="" \
third_party_registrant="" \
username="INBOUND_USERNAME" \
password="INBOUND_PASSWORD" \
binding_params="" \
expiry=60 \
forced_socket="" \
cluster_shtag="" \
state=0
Replace the username and password with the inbound trunk credentials. Use the selected registration endpoint for the address-of-record domain and registrar. Set the contact address to the public address and port through which DIDWW can reach OpenSIPS.
All 12 parameters are required, including those with empty values. Missing
parameters return Invalid params (Too few or too many parameters).
Incorrect parameter names return
Invalid params (Named parameters do not match).
Important
An OK response confirms that the registration record was accepted.
Run opensips-cli -x mi uac_registrant:list and check the state
field to confirm registration:
REGISTERED_STATEindicates a successful registration.NOT_REGISTERED_STATEcan appear until the registration timer processes the record, which may take up to 30 seconds.WRONG_CREDENTIALS_STATEindicates rejected credentials.
The registration is supplied at runtime through the management interface, so this setup does not require a database. The short expiry and registration timer help maintain the inbound NAT mapping.
Important
The registration record is created at runtime and is not stored in a database. Submit the registration command again after restarting OpenSIPS.
Step 4: Verify the configuration#
Check |
Action |
Expected result |
|---|---|---|
Listening socket |
Review the startup output. |
A |
Dynamic Registration |
Run |
The |
Inbound calling |
Call a DID assigned to the inbound trunk. |
The process output includes the inbound |
Outbound calling |
Place a call from the user agent. |
The SIP trace shows a |
Check the user agent as well to confirm that incoming calls are received and audio works in both directions.
Common issues#
Calls disconnect after approximately 30 seconds
Check advertised_address. An unreachable address in Record-Route
prevents DIDWW from delivering the ACK. The user agent retransmits
200 OK until the call times out. See
listening socket and advertised address.
An inbound call does not reach the user agent
Check for the inbound xlog message. If it is missing, confirm that
the request reached OpenSIPS and that its source matched the DIDWW ACL.
For Dynamic Registration, check the registration state as well.
If the message is present, check the destination URI and the user agent’s reachability. Keep the unconditional Request-URI rewrite from inbound routing.
OpenSIPS rejects inbound calls with 403 Forbidden
Compare the request’s $si source address with the
DIDWW ACL. Check the published addresses
for the trunk type and its failover locations.
The inbound trunk does not register
Allow up to 30 seconds for the registration timer to process the record. If registration still fails, check the state:
REGISTER_TIMEOUT_STATEindicates that no response was received. Check the network path and the local route used to addrportbehind NAT.WRONG_CREDENTIALS_STATEindicates rejected credentials.REGISTRAR_ERROR_STATEindicates another error from the registrar.
Outbound calls fail after successful authentication
Check the caller ID set by uac_replace_from() against Allowed
CLI(s) and On CLI Mismatch. Then check Destination Dialing
Settings and the trunk’s Status. Reaching the 24-hour limit
automatically disables the trunk.
OpenSIPS does not answer an outbound 401 challenge
Check that the outbound credential uses out.didww.com as its realm.
A credential stored under a regional hostname will not match the
challenge. The failure route logs uac_auth() failed when
authentication cannot be completed. See
module settings and credentials.
Outbound calls receive no response behind NAT
Confirm that the outbound branch includes add_local_rport().
This allows responses to return to the source port used by NAT. See
outbound routing.
OpenSIPS reports no transport protocol loaded
Keep loadmodule "proto_udp.so" in the
module settings. It is required by the
tested build even though a separate module file is not present.
OpenSIPS reports an append_fromtag initialization error
Keep modparam("rr", "append_fromtag", 1) in the
module settings. The tested configuration
requires it when using uac_auth(), including with restore_mode
set to none.
OpenSIPS logs Can’t load dlg API at startup
The tested build can continue after
ERROR:uac:mod_init: Can't load dlg API. Review the following log
messages and confirm that the proxy is listening. Do not treat this
message alone as proof that startup failed.
For more information about OpenSIPS scripting, see the official Types of routes and Core Parameters documentation.