Asterisk : Setting up PJSIP with LDAP Realtime Driver
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 and Asterisk PJSIP knowledge
- New LDAP Schemas : asterisk.ldap-schema and asterisk.ldif
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:5060Endpoint: 102 Unavailable 0 of inf
InAuth: 102/102
Aor: 102 1
Transport: transport-udp udp 0 0 0.0.0.0:5060Objects 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:5060Endpoint: 102 Unavailable 0 of inf
InAuth: 102/102
Aor: 102 1
Transport: transport-udp udp 0 0 0.0.0.0:5060Endpoint: 201/201 Unavailable 0 of inf
InAuth: 201/201
Aor: 201 1
Transport: transport-udp udp 0 0 0.0.0.0:5060Objects 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 ! 👏