10.6. DUNDi
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:
"DUNDiTM 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),
DUNDi is fully distributed with no centralized authority
whatsoever."
10.6.1. How Does DUNDi Work?
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 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-800-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.
10.6.2. Configuring Asterisk for Use
with DUNDi
There are three files that need to be configured
for DUNDi: dundi.conf,
extensions.conf, and iax.conf. The
dundi.conf file controls the
authentication of peers who 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.
10.6.2.1. The General Peering
Agreement
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.
10.6.2.2. General configuration
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.
10.6.2.3. Creating mapping
contexts
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
numbera 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:
${SECRET}
-
Replaced with the password stored in the local
AstDB
${NUMBER}
-
The number being requested
${IPADDR}
-
The IP address to connect to
|
It is generally safest to statically configure
the hostname, rather than making use of the ${IPADDR}
variable. The ${IPADDR} variable will sometimes reply with
an address in the private IP space, which is unreachable from the
Internet.
|
|
10.6.2.4. Defining DUNDi peers
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> reload res_crypto.so
-- Reloading module 'res_crypto.so' (Cryptographic Digital Signatures)
-- Loaded PRIVATE key 'toronto'
-- Loaded PUBLIC key 'toronto'
*CLI> 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.
10.6.2.5. Allowing remote
connections
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.
10.6.2.6. Configuring the
dialplan
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( )
|