Asterisk : Setting up PJSIP with LDAP Realtime Driver

Xavier Brassoud
5 min readJun 2, 2019

--

Hi everyone, I recently succeeded to setting up PJSIP with LDAP Realtime Driver and I wanted to share my work with the Asterisk community.

The procedure to set up this coupling is well documented for the SIP part, but I have not found any documentation regarding the PJSIP part. I also updated the Asterisk LDAP schema to integrate the new PJSIP classes.

For an easier understanding, I will use throughout this guide a concrete example: Store PJSIP peers in LDAP, under the tree "ou=pjsip, dn=test, dn=local".

What you need to know about LDAP/PJSIP storage:

  • New LDAP schema integrating PJSIP classes
  • A PJSIP pair is identified by three LDAP classes: AsteriskPjsipAor, AsteriskPjsipAuth and AsteriskPjsipEndpoint whereas a SIP pair requires one LDAP class: AsteriskSIPUser
  • Realtime drivers in PJSIP requires one more configuration file compared to SIP : sorcery.conf

Prerequisites

LDAP side implementation

I assume that you already have a functioning LDAP server.

Import the new LDAP schema that includes the associated PJSIP classes and LDIF file:

sudo cp asterisk.ldap-schema /etc/ldap/schema/
sudo service slapd restart
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f ./asterisk.ldif

In our example we want to create 2 PJSIP peers in LDAP, a pair will have to implement following classes:

  • AsteriskPjsipAor: For the Address Of Record class
  • AsteriskPjsipAuth: For the Authentication class
  • AsteriskPjsipEndpoint: For the Endpoint class

Here is an example (peers.ldif) with two PJSIP records 101 and 102:

# PEERS
dn: cn=101,ou=pjsip,dc=test,dc=local
objectClass: top
objectClass: AsteriskAccount
objectClass: AsteriskPjsipAor
objectClass: AsteriskPjsipAuth
objectClass: AsteriskPjsipEndpoint
cn: 101
AstAccountName: 101
AstAorId: 101
AstAorMaxContacts: 1
AstAuthId: 101
AstAuthType: userpass
AstAuthUsername: 101
AstAuthPassword: 101
AstEndpointId: 101
AstEndpointTransport: transport-udp
AstEndpointAors: 101
AstEndpointAuth: 101
AstEndpointContext: testing
AstEndpointDisallow: all
AstEndpointAllow: g722;alaw
AstEndpointDirectMedia: no

dn: cn=102,ou=pjsip,dc=test,dc=local
objectClass: top
objectClass: AsteriskAccount
objectClass: AsteriskPjsipAor
objectClass: AsteriskPjsipAuth
objectClass: AsteriskPjsipEndpoint
cn: 102
AstAccountName: 102
AstAorId: 102
AstAorMaxContacts: 1
AstAuthId: 102
AstAuthType: userpass
AstAuthUsername: 102
AstAuthPassword: 102
AstEndpointId: 102
AstEndpointTransport: transport-udp
AstEndpointAors: 102
AstEndpointAuth: 102
AstEndpointContext: testing
AstEndpointDisallow: all
AstEndpointAllow: g722;alaw
AstEndpointDirectMedia: no

In this example, we first created an aor for each peer, one called 101 and the other 102.

Next, we created an auth for each peer with a userpass of 101 and 102, respectively.

Then, we created two endpoints, 101 and 102, each referencing the appropriate auth and aor, we selected the G.722 and alaw codecs and we forced media to route inside of Asterisk (not the default behavior of Asterisk).

I’m using the class AsteriskAccount here to have a “structural” LDAP class, note that you do not need to use it if the object already implements a “structural” LDAP class (example: inetOrgPerson).

Asterisk side implementation

Install LDAP dependencies for Asterisk:

Debian:

sudo apt-get install libldap-2.4–2

CentOS:

sudo yum install openldap-devel

Then go to your Asterisk source directory and run:

./configure
make menuselect

Save, and run:

make install

This command recompiles your Asterisk installation to support the LDAP Realtime driver.

Edit the /etc/asterisk/modules.conf file and specify that you want to preload the LDAP module:

preload => res_config_ldap.so

Realtime LDAP Driver Settings

Edit the /etc/asterisk/res_ldap.conf file with your own settings:

[_general]
host=127.0.0.1
port=389
protocol=3
basedn=dc=test,dc=local
user=cn=admin,dc=test,dc=local
pass=password

Restart Asterisk :

rasterisk
asterisk*CLI> core restart now

Make sure the driver is attached to the LDAP server:

rasterisk
asterisk*CLI> realtime show ldap status
Connected to 'ldap://127.0.0.1:389', baseDN dc=test,dc=local with username cn=admin,dc=test,dc=local for 15 seconds.

Edit the /etc/asterisk/res_ldap.conf file again to map PJSIP classes :

[_general]
host=127.0.0.1
port=389
protocol=3
basedn=dc=test,dc=local
user=cn=admin,dc=test,dc=local
pass=password
[ps_aors]
id=AstAorId
max_contacts=AstAorMaxContacts
[ps_auths]
id=AstAuthId
auth_type=AstAuthType
username=AstAuthUsername
password=AstAuthPassword
[ps_endpoints]
id=AstEndpointId
transport=AstEndpointTransport
aors=AstEndpointAors
auth=AstEndpointAuth
context=AstEndpointContext
disallow=AstEndpointDisallow
allow=AstEndpointAllow
direct_media=AstEndpointDirectMedia

Warning: Never reuse a field even if the value is the same, Asterisk considers the field as unique and it will not be accessible for the rest of the matches.

Configure the realtime driver for LDAP

Edit the /etc/asterisk/extconfig.conf file :

[settings]
ps_endpoints => ldap,"ou=pjsip,dc=test,dc=local",ps_endpoints
ps_auths => ldap,"ou=pjsip,dc=test,dc=local",ps_auths
ps_aors => ldap,"ou=pjsip,dc=test,dc=local",ps_aors

Here we announce to Asterisk to get the information in the LDAP, in the “pjsip” OU and to “map” the fields found with the tables of correspondences that we defined in res_ldap.conf.

Bind the Realtime Driver

Edit the /etc/asterisk/sorcery.conf file :

[test_sorcery_section]
test=memory
[test_sorcery_cache]
test/cache=test
test=memory
[res_pjsip]
endpoint=realtime,ps_endpoints
auth=realtime,ps_auths
aor=realtime,ps_aors

Unlike the implementation of the SIP protocol, Asterisk’s PJSIP layer implements a new “sorcery.conf” file, which is the starting point for retrieving PJSIP information.

Here we tell Asterisk to retrieve PJSIP information from the driver defined in extconfig.conf (in our case: the LDAP driver).

Restart Asterisk :

asterisk*CLI> core restart now

Verify that LDAP endpoints 101 and 102 appear:

asterisk*CLI> pjsip show endpoints
Endpoint: 101 Unavailable 0 of inf
InAuth: 101/101
Aor: 101 1
Transport: transport-udp udp 0 0 0.0.0.0:5060
Endpoint: 102 Unavailable 0 of inf
InAuth: 102/102
Aor: 102 1
Transport: transport-udp udp 0 0 0.0.0.0:5060
Objects found: 2

The endpoints do not necessarily appear immediately, it is necessary to wait for the initialization synchronization.

Great! You have successfully integrated your PJSIP accounts into the LDAP.

Combine Realtime Driver with pjsip.conf

If you want to configure both realtime and static configuration file lookups for PJSIP then you need to add additional lines to the sorcery config.

For example if you want to read endpoints from both realtime and static configuration:

[res_pjsip]
endpoint=config,pjsip.conf,criteria=type=endpoint
endpoint=realtime,ps_endpoints
auth=config,pjsip.conf,criteria=type=auth
auth=realtime,ps_auths
aor=config,pjsip.conf,criteria=type=aor
aor=realtime,ps_aors

You can swap the order to control which data source is read first.

In this example, the extension 201 is defined statically in pjsip.conf:

asterisk*CLI> module reload
asterisk*CLI> pjsip show endpoints
Endpoint: 101 Unavailable 0 of inf
InAuth: 101/101
Aor: 101 1
Transport: transport-udp udp 0 0 0.0.0.0:5060
Endpoint: 102 Unavailable 0 of inf
InAuth: 102/102
Aor: 102 1
Transport: transport-udp udp 0 0 0.0.0.0:5060
Endpoint: 201/201 Unavailable 0 of inf
InAuth: 201/201
Aor: 201 1
Transport: transport-udp udp 0 0 0.0.0.0:5060
Objects found: 3

TroubleShooting

“realtime show ldap status” failed

Your configuration may not be well set.
I encountered errors in res_ldap.conf when I used the “url” field, choose the “host” field and fill in an IP address.
Also, be careful not to put space between parameters and their values, nor comments on the same line:

DO NOT :

basedn= dc=test,dc=local ; My base DN

DO :

basedn=dc=test,dc=local

“pjsip show endpoints” does not return LDAP endpoints

In the res_ldap.conf mapping tables, keep attention to never reuse a field even if the value is the same, Asterisk considers the field as unique and it will not be accessible for the rest of the matches.
Also check that you do not specify “plain” values ​​that will not be interpreted by Asterisk:

DO NOT :

[ps_aors]
id=AstAorId
max_contacts=AstAorMaxContacts
[ps_auths]
id=AstAorId
auth_type=userpass
username=AstAuthUsername
password=AstAuthPassword

DO :

[ps_aors]
id=AstAorId
max_contacts=AstAorMaxContacts
[ps_auths]
id=AstAuthId
auth_type=AstAuthType
username=AstAuthUsername
password=AstAuthPassword

Conclusion

Taking advantage of the LDAP Realtime Drivers available in Asterisk will allow you to automate the creation of your PJSIP accounts on an infrastructure that is (still) based on LDAP technology.

It’s not easy to set up and It’s not always easy to debug the reason for a problem with Asterisk Realtime drivers, enable the DEBUG mode will facilitate long hours of searching … Good luck

Helpful ? I will appreciate your claps. Thanks ! 👏

--

--