If there were any concerns that Mark Spencer was in danger of running out of good ideas, Distributed Universal Number Discovery (DUNDi) ought to lay such thoughts to rest. DUNDi is poised to be as revolutionary as Asterisk. The DUNDi web site (http://www.dundi.com) says it best: “DUNDi™ is a peer to peer system for locating Internet gateways to telephony services. Unlike traditional centralized services (such as the remarkably simple and concise ENUM standard; http://www.faqs.org/rfc/rfc2916.txt), DUNDi is fully distributed with no centralized authority whatsoever.” DUNDi is somewhat of a routing protocol for VoIP.
Think of DUNDi as a large phone book that allows you to ask peers if they know of an alternative VoIP route to an extension number or PSTN telephone number.
For example, assume that you are connected to the DUNDi-test network (a free and open network that terminates calls to traditional PSTN numbers). You ask your friend Bob if he knows how to reach 1-212-555-1212, a number for which you have no direct access. Bob replies, “I don’t know how to reach that number, but let me ask my peer Sally.”
Bob asks Sally if she knows how to reach the requested number, and
she responds with, “You can reach that number at
IAX2/dundi:
very_long_password@hostname/extension
.”
Bob then stores the address in his database and passes on to you the
information about how to reach 1-800-555-1212 via VoIP, allowing you an
alternative method of reaching the same destination through a different
network.
Because Bob has stored the information he found, he’ll be able to provide it to any peers who later request the same number from him, so the lookup won’t have to go any further. This helps reduce the load on the network and increases response times for numbers that are looked up often. (However, it should be noted that DUNDi creates a rotating key and, thus, stored information is valid for a limited period of time.)
DUNDi performs lookups dynamically, either with a switch =>
statement in your
extensions.conf file or with the use of the
DUNDiLookup()
application. DUNDi is
available only in Asterisk version 1.2 or higher.
You can use the DUNDi protocol in a private network as well. Say you’re the Asterisk administrator of a very large enterprise installation, and you wish to simplify the administration of extension numbers. You could use DUNDi in this situation, allowing multiple Asterisk boxes (presumably located at each of the company’s locations and peered with one another) to perform dynamic lookups for the VoIP addresses of extensions on the network.
There are three files that need to be configured for DUNDi: dundi.conf, extensions.conf, and iax.conf.[149] The dundi.conf file controls the authentication of peers whom we allow to perform lookups through our system. This file also manages the list of peers to whom we might submit our own lookup requests. Since it is possible to run several different networks on the same box, it is necessary to define a different section for each peer, and then configure the networks in which that peer is allowed to perform lookups. Additionally, we need to define which peers we wish to use to perform lookups.
The General Peering Agreement (GPA) is a legally binding license agreement that is designed to prevent abuse of the DUNDi protocol. Before connecting to the DUNDi-test group, you are required to sign a GPA. The GPA is used to protect the members of the group and to create a “trust” between the members. It is a requirement of the DUNDi-test group that your complete and accurate contact information be configured in dundi.conf, so that members of your peer group can contact you. The GPA can be found in the doc/ subdirectory of the Asterisk source.
The [general]
section
of dundi.conf contains parameters
relating to the overall operation of the DUNDi client and
server:
; DUNDi configuration file ; [general] ; department=IT organization= toronto.example.com locality=Toronto stateprov=ON country=CA email=support@toronto.example.com phone=+19055551212 ; ; Specify bind address and port number. Default is 4520 ;bindaddr=0.0.0.0 port=4520 entityid=FF:FF:FF:FF:FF:FF ttl=32 autokill=yes ;secretpath=dundi
The entity identifier defined by entityid
should generally be the Media Access Control (MAC) address of an interface in
the machine. The entity ID defaults to the first Ethernet address of
the server, but you can override this with entityid
, as long as it is set to the MAC
address of something you own. The MAC address of
the primary external interface is recommended. This is the address
that other peers will use to identify you.
The Time To Live (ttl
)
field defines how many peers away we wish to receive replies
from and is used to break loops. Each time a request is passed on down
the line because the requested number is not known, the value in the
TTL field is decreased by one, much like the TTL field of an ICMP
packet. The TTL field also defines the maximum number of seconds we
are willing to wait for a reply.
When you request a number lookup, an initial query (called a
DPDISCOVER
) is sent to your peers requesting that number. If you do
not receive an acknowledgment (ACK
)
of your query (DPDISCOVER
) within
2,000 ms (enough time for a single transmission only) and autokill
is equal to yes
, Asterisk will send a CANCEL
to the peers. (Note that an
acknowledgment is not necessarily a reply to the query; it is just an
acknowledgment that the peer has received the request.) The purpose of
autokill
is to keep the lookup from
stalling due to hosts with high latency. In addition to the yes
and no
options, you may also specify the number
of milliseconds to wait.
The pbx_dundi module creates a rotating key
and stores it in the local Asterisk database (AstDB). The key name
secret
is stored in the dundi
family. The value of the key can be
viewed with the database show
command at the Asterisk console. The database family can be overridden
with the secretpath
option.
The dundi.conf file defines DUNDi contexts
that are mapped to dialplan contexts in your extensions.conf file. DUNDi
contexts are a way of defining distinct and separate directory service
groups. The contexts in the mapping section point to contexts in the
extensions.conf file, which control the numbers
that you advertise. When you create a peer, you need to define which
mapping contexts you will allow this peer to search. You do this with
the permit
statement (each peer may
contain multiple permit
statements). Mapping contexts
are related to dialplan contexts in the sense that they are a security
boundary for your peers.
Phone numbers must be advertised in the following format:
<country_code><area_code><prefix><number>
For example, a complete North American number could be advertised as 14165551212.
All DUNDi mapping contexts take the form of:
dundi_context
=>local_context
,weight
,technology
,destination
[,options
]]
The following configuration creates a DUNDi mapping context that we will use to advertise our local phone numbers to the DUNDi-test group. Note that this should all appear on one line:
dundi-test => dundi-local,0,IAX2,dundi:${SECRET}@toronto.example.com/ ${NUMBER}, nounsolicited,nocomunsolicit,nopartial
In this example, the mapping context is dundi-test
, which points to the dundi-local
context within
extensions.conf (providing a listing of phone
numbers to reply to). Numbers that resolve to the PBX should be
advertised with a weight
of zero (directly
connected). Numbers higher than 0 indicate an increased number of hops
or paths to reach the final destination. This is useful when multiple
replies for the same lookup are received at the end that initially
requested the number; a weight
with a lower
number will be the preferred path.
If we can reply to a lookup, our response will contain the method by which the other end can connect to the system. This includes the technology to use (such as IAX2, SIP, H323, and so on), the username and password with which to authenticate, which host to send the authentication to, and finally the extension number.
Asterisk provides some shortcuts to allow us to create a “template” with which we can build our responses. The following channel variables can be used to construct the template:
DUNDi peers are defined in the dundi.conf file. Peers are identified by the unique layer-two MAC address of an interface on the remote system. The dundi.conf file is where we define what context to search for peers requesting a lookup and which peers we want to use when doing a lookup for a particular network:
[00:00:00:00:00:00] ; Remote Office model = symmetric host = montreal.example.com inkey = montreal outkey = toronto include = dundi-test permit = dundi-test qualify = yes dynamic=yes
The remote peer’s identifier (MAC address) is enclosed in
square brackets ([]
).
The inkey
and outkey
are the public/private key pairs that
we use for authentication. Key pairs are generated with the astgenkey
script, located in the ./asterisk/contrib/scripts/
source
directory. Be sure to use the -n
flag so that you don’t have to initialize passwords every
time you start Asterisk:
#cd /var/lib/asterisk/keys
#/usr/src/asterisk/contrib/scripts/astgenkey -n toronto
The resulting keys, toronto.pub
and toronto.key
, will be placed in your
/var/lib/asterisk/keys/
directory. The toronto.pub
file
is the public key, which you should post to a web server so that it is
easily accessible for anyone with whom you wish to peer. When you
peer, you can give your peers the HTTP-accessible public key, which
they can then place in their /var/lib/asterisk/keys/
directories.
After you have downloaded the keys, you must reload the res_crypto.so
and pbx_dundi.so
modules in
Asterisk:
*CLI>module reload res_crypto.so
-- Reloading module 'res_crypto.so' (Cryptographic Digital Signatures) -- Loaded PRIVATE key 'toronto' -- Loaded PUBLIC key 'toronto' *CLI>module reload pbx_dundi.so
-- Reloading module 'pbx_dundi.so' (Distributed Universal Number Discovery (DUNDi)) == Parsing '/etc/asterisk/dundi.conf': Found
Then, create the dundi
user
in the iax.conf
file to allow connections into your Asterisk system. When a
call is authenticated, the extension number being requested is passed
to the dundi-local
context in the
extensions.conf
file, where the
call is then handled by Asterisk.
Here is the user definition for the dundi
user:
[dundi] type=user dbsecret=dundi/secret context=dundi-local disallow=all allow=ulaw allow=g726
Instead of using a static password, Asterisk regenerates
passwords every 3,600 seconds (1 hour). The value is stored in
/dundi/secret of the Asterisk database and
advertised using the ${SECRET}
variable defined within the mapping context lines in dundi.conf
. You can see the current keys
for all peers, including your local public and private keys, by
performing a show keys
at the Asterisk CLI.
The context
entry dundi-local
is where authorized callers are
sent in extensions.conf
. From
there, we can manipulate the call just as we would in the dialplan of
any other incoming connection.
The extensions.conf
file
handles what numbers you advertise and what you do with the calls that
connect to them. The dundi-local
context performs double duty:
It controls the numbers we advertise, referenced by the
dundi
mapping context in
dundi.conf
.
It controls what to do with the call, referenced by the
dundi
user in iax.conf
.
You have the power of dialplan pattern matching to advertise ranges of numbers and to control the incoming calls. In the following dialplan, we are only advertising the number +1-416-555-1212, but pattern matching could just as easily have been employed to advertise a range of numbers or extensions:
[dundi-local] exten => 14165551212,1,NoOp(dundi-local: Number advertisement and incoming) exten => 14165551212,n,Answer() exten => 14165551212,n(call),Dial(SIP/1000) exten => 14165551212,n,Voicemail(u1000) exten => 14165551212,n,Hangup() exten => 14165551212,n(call)+101,Voicemail(b1000) exten => 14165551212,n,Hangup()
[149] The dundi.conf and extensions.conf files must be configured. We have chosen to configure iax.conf for our address advertisement on the network, but DUNDi is protocol-agnostic—thus sip.conf, h323.conf, or mgcp.conf could be used instead.