Search



DUNDi Tutorial for Asterisk@Home

May 27th, 2006 by Alex Robar

Confused by DUNDi? Yeah, so was I. It took me a few weeks of kicking my Asterisk box, but I finally got it working. Here’s a step by step tutorial on how to get DUNDi working with Asterisk@Home. This tutorial was written using an Asterisk@Home 2.5 system with FreePBX 2.1, but should work from Asterisk@Home 2.0 onward.

First, let’s be clear about what the end goal of this setup is.

Nerd speak: The end goal is to connect two or more Asterisk@Home systems using Mark Spencer’s DUNDi protocols so that every system on the network esentially has the same dialing abilities. That is, if system A has the ability to dial the 416-238-XXXX exchange locally, then so would all the other connected systems, even if they’re nowhere near that particular exchange. This setup also enables each system to call the extensions on other connected systems. Both of these things are accomplished without any particular node on the network being statically programmed with routes to access the features on any other node.

Layman’s terms: Free long distance. If you have a friend in New York City, and you live in Toronto, you could use his phones lines, and he could use yours. You don’t have to dial any special access codes or PINS, it just happens transparently in the background.

Caching

Before we start, it’s important to know that DUNDi caches routes for one hour by default. This means that if you make a mistake in your configuration, you need to clear your cache before accurate routes will be returned. At the Asterisk CLI, type dundi flush to clear the cache.

Ports

Note that DUNDi uses UDP port 4520 to communicate between servers. If you’ve got a firewall on your boxes, open that up.

Configuration Files

On BOTH boxes, add the following to the appropriate config files:

[priv]
type=user
dbsecret=dundi/secret
context=dundi-priv-local

iax_custom.conf

[general]
; Define the max depth in which to search the DUNDi system (also max # of
; seconds to wait for a reply)
;
ttl=32
; If we don’t get ACK to our DPREQUEST within 2000ms, and autokill is set
; to yes, then we cancel the whole thing (that’s enough time for one
; retransmission only). This is used to keep things from stalling for a long
; time for a host that is not available, but would be ill advised for bad
; connections. In addition to ‘yes’ or ‘no’ you can also specify a number
; of milliseconds. See ‘qualify’ for individual peers to turn on for just
; a specific peer.
;
autokill=yes
; If the cache time is too large, a route may change and be unreachable
; until the cache expires. By contrast, if you have a large network, it is
; extremely inefficient to be sending every single search out to the network
; simply because one’s cache expires after a few seconds. Try to adjust
; this based upon the size of your network. By default this is set to
; 3600 seconds (one hour). This will work fine for a fairly static setup,
; but should be lowered for a more dynamic environment.
cachetime=3600
[mappings]
priv => dundi-priv-canonical,0,IAX,priv:${SECRET}@${IPADDR}/${NUMBER},nopartial
priv => dundi-priv-customers,100,IAX,priv:${SECRET}@${IPADDR}/${NUMBER},nopartial
priv => dundi-priv-via-pstn,400,IAX,priv:${SECRET}@${IPADDR}/${NUMBER},nopartial

dundi.conf

Important: During some testing, it’s come to my attention that the ${IPADDR} variable may report 127.0.0.1 instead of your actual IP address. I have specified my hostname in place of ${IPADDR}, you may wish to do the same, or use your IP address (if it is a static IP). Thanks to Elliot Spencer for pointing this out!


; Private DUNDi network
[dundi-priv-canonical]
; Direct numbers

[dundi-priv-customers]
; If you are an ITSP or Reseller, list your customers here.

[dundi-priv-via-pstn]
; If you are freely delivering calls to the PSTN, list them here
[dundi-priv-local]
include => dundi-priv-canonical
include => dundi-priv-customers
include => dundi-priv-via-pstn

[dundi-priv-switch]
; Just a wrapper for the switch
switch => DUNDi/priv

[dundi-priv-lookup]
include => dundi-priv-local
include => dundi-priv-switch

[macro-dundi-priv]
exten => s,1,Goto(${ARG1},1)
include => dundi-priv-lookup

[trydundi]
exten => _.,1,Macro(dundi-priv,${EXTEN})
exten => _.,2,Congestion

extensions_custom.conf

Keys

This is the toughest part of this particular setup… But only because you can’t copy and paste! On each box in the DUNDi cloud you must complete the following procedure. Note that SERVERNAME is the hostname of the box you are currently creating a key for. If you can use a fully qualified hostname, you’re better off doing so to avoid confusion between keys in larger networks (ie. If you have a server bob on the domain domain.com, you should use “astgenkey -n bob.domain.com” instead of just “astgenkey -n bob”).

  1. cd /var/lib/asterisk/keys
  2. astgenkey -n SERVERNAME

You should see two new files created: SERVERNAME.key and SERVERNAME.pub. You need to find a way to copy your public (.pub) keys between all servers in your DUNDi cloud. If you have a web server, put them up there for easy downloading. Otherwise, remember that they key is just text, and you can copy and paste the key’s contents so long as you name it correctly on the receiving server.

Entity ID / Media Access Control

Now that you’ve got all the public keys from all the servers in your cloud copied on to every other server in the cloud, you need to tell each server how each box will identify itself, and which key to associate with each identity. DUNDi uses an Entity ID (EID) number, also known as a Media Access Control (MAC) address, to identify servers within the cloud. DUNDi defaults to using the MAC of eth0. As such, there are two ways to obtain the EID/MAC for each server.

One: At the shell, enter ifconfig eth0. You should see output similar to the following:

[root@pbx ~]# ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:02:A5:AA:08:72
inet addr:192.168.0.1 Bcast:192.168.0.255 Mask:255.255.255.0
inet6 addr: fe80::202:a5ff:feaa:872/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:110179799 errors:0 dropped:0 overruns:2 frame:2
TX packets:110153248 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:3265363193 (3.0 GiB) TX bytes:2060951955 (1.9 GiB)

Note the bolded section. This is the MAC address.

Or, two: At the Asterisk CLI, enter dundi show entityid. You should see output similar to the following:

pbx*CLI> dundi show entityid
Global EID for this system is ‘00:02:a5:aa:08:72

Pretty self explainatory, but the bolded text is the EID. Note how the two commands identified the same ID when used on the same server. Make a note of the EID/MAC for each server, as you will need it finalize your dundi.conf file.

Final dundi.conf Configuration

For clarity in this section, I’ll be pretending I have two servers: pheonix.thegoldfish.net and unlimited.thegoldfish.net. Their keys have been generated as pheonix.thegoldfish.net.key/pheonix.thegoldfish.net.pub and unlimited.thegoldfish.net.key/unlimited.thegoldfish.net.pub, respectively.

In the dundi.conf on pheonix.thegoldfish.net:

[00:14:2a:30:71:a4] ;unlimited.thegoldfish.net EID
model = symmetric
host = unlimited.thegoldfish.net
inkey = unlimited.thegoldfish.net ;Unlimited’s public key
outkey = pheonix.thegoldfish.net ;Pheonix’s private key
include = priv
permit = priv
qualify = yes
order = primary

In the dundi.conf on unlimited.thegoldfish.net:

[00:02:a5:aa:08:72] ;pheonix.thegoldfish.net EID
model = symmetric
host = pheonix.thegoldfish.net
inkey = pheonix.thegoldfish.net ;Pheonix’s public key
outkey = unlimited.thegoldfish.net ;Unlimited’s private key
include = priv
permit = priv
qualify = yes
order = primary

DUNDi Trunk

To create a trunk that you can use to check if a number is available anywhere within your DUNDi cloud, complete the following steps in FreePBX:

  1. Click on Setup in the menu in the top right-hand corner of the page.
  2. Click on Trunks in the menu on the left.
  3. Click on Add Custom Trunk.
  4. Fill out your outgoing caller ID to identify yourself.
  5. Fill in your dial rules as appropriate. I have set mine to strip out the 1 passed to the trunk for long distance calls. If users dial extra digits to get an outside line, you may wish to strip those digits out here.
  6. For custom dial string enter the following: local/$OUTNUM$@trydundi
  7. Save the trunk.

You now have a trunk that you can use to check if an alternate route exists for placing a call before it is routed using your standard means. For example, I have setup an outbound route for my long distance calls. The call is first passed to my DUNDi trunk. If no route is found, the call is routed using my ITSP.

So now you can use the DUNDi cloud to make calls. There’s just one last step to make your node a full fledged member of the cloud.

Advertising Routes

A DUNDi network only works if everyone shares their resources as well as consumes them. If you’re in my cloud and you’re not sharing routes, you’re cut immediately. To this end, you must advertise which calls you are willing to terminate. In my case, I simply asked my ITSP for a list of exchanges that were local for me to call, and advertised all of them. That way, anyone who needs to make a call that is local to me can do so at no charge to either of us. Here’s how you advertise routes:A route is simply advertised as if it were normal extension. For example, if I wanted to terminate calls to the 289-242 exchange, I would add this to the [dundi-priv-via-pstn] context in my extensions_custom.conf file:

exten => _!289242XXXX,1,Dial(SIP/Iristel/${EXTEN})

Where SIP/Iristel is my ITSP trunk. Iristel is the name I gave the trunk in FreePBX, so simply use the name you’ve defined for the trunk there. It’s also a good idea to advertise any numbers that you own. In this case, add the following to the [dundi-priv-canoical] context in extensions_custom.conf file:

exten => 4162382936,1,Goto(from-pstn,s,1)

Where 4162382936 is my DID. This sends the call straight into my [from-pstn] context, just as if it were a standard incoming call.

If your goal is to make extensions on one server accessible on another, add lines similar to the following in the [dundi-priv-customers] context in extensions_custom.conf:

exten => _2XX,1,Goto(ext-local,${EXTEN},1)

In this case, we would be advertising that any three digit extension starting with a “2″ is available on this box. This is very dependent on how you split extensions between your boxes. You may need to define this more clearly, such as “2[2-9]X” for extensions 220 through 299 for example.

That’s All She Wrote

Good luck! Thanks to Elliot Spencer for his help with this, and the forum members of FreePBX who gave me a kick in the right direction.

Share this post: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • bodytext
  • del.icio.us
  • Technorati
  • Furl
  • BlogMemes
  • Netvouz
  • MisterWong
  • StumbleUpon

Posted in TGF Tutorials, TechTips, VoIP |

29 Responses

  1. syn Says:

    Very informative.

  2. Thomas Says:

    Very impressiv! Thank you fo rthe good work..

  3. Nelson Says:

    In which conf file would one add the first section(indicated below)
    [priv]
    type=user
    dbsecret=dundi/secret
    context=dundi-priv-local

  4. arobar Says:

    Nelson:

    [priv]
    type=user
    dbsecret=dundi/secret
    context=dundi-priv-local

    Should be placed in iax_custom.conf. Sorry if this wasn’t clear!

    Alex

  5. lwj Says:

    iax_custom.conf

    I can’t find the file of iax_custom.conf , should i creat one?

  6. arobar Says:

    Iwj,

    Yes, you do need to create this file.

    Alex

  7. Andy Says:

    This may be a silly question, but the ${NUMBER} variable under [mappings] in dundi.conf - what should this refer to? Is there a dundi module on the cards for FreePBX?

  8. arobar Says:

    Andy,

    The ${NUMBER} variable refers to the number that was dialed by the calling party (ie. If someone places a call through your system, that is the number they dialed).

    Alex

  9. Peter Says:

    With the exception of the following statement everything worked as suggested:

    exten => _!905XXXXXXX,1,Dial(ZAP/g0/${EXTEN})

    The “!” is a wildcard that matches zero or more characters immediately so even when dialing XXX on server A from an extension on server B, a match is made that goes to ZAP/g0 instead of server A. Taking out the “!” resolved the problem.

    Thanks for a well written document…

  10. Dan G. Says:

    Hello all,

    i am trying to figure out the posibilities dundi can provide me with…
    if i understand correctly, with dundi i could implement the following:

    assuming i have a cluster of asterisk servers, where a user of mine who has a single DID, can register to any one of those servers randomly (for example by dns round-robin)
    if my carrier wants to send an incoming call to the user’s DID,
    then if i had that carrier implement a dundi peering with me, then
    his system would just query my dundi cloud and know exactly
    which server the specific user is registered to and thus make the call directly to that server?

    Dan.

  11. arobar Says:

    Dan,

    What you are proposing is theoretically possible, but not very likely. There are huge logistical hurdles to think about when considering peering with someone. Most VoIP providers will not take that lightly. The normal course of action would be to have a gateway box on your side that does that routing action for you. You VoIP provider would send calls for that DID to the gateway box. The gateway box then queries the cloud to see who is taking calls from that DID. When it finds the current owner, it routes the call to that box. This saves the ITSP from having to worry about peering with you, and leaves you with a network topology to do dozens of different things.

    Say for example you have several thousands extensions. On commodity hardware, it becomes brutally obvious that you don’t want to route more than 200 calls or so over a single box. So, setup several boxes with extensions spread out evenly over them. When a call comes in to your gateway box on a particular DID (or for a particular extension), it queries the cloud for which box is handling calls for the called number. It then passes the call off to that box. All of a sudden, you’ve got huge scalability for a fraction of the cost of a powerhouse server… And all using hardware that’s easy to maintain, easy to learn, and easy to replace in the event of a failure. This is kind of like the Google methodology, wherein several thousand cheap servers are used instead of a few hundred behemoths.

    Alex

  12. Mark Says:

    Thanks for the great work - I’ve followed the examples you have with two trixbox installations, and while ‘dundi show peers’ will list the other box, ‘dundi query xx:xx:xx:xx:xx:xx’ returns “DUNDi Query EID returned no results.”.

    Any idea what I may have mucked up?

    Thanks - Mark

  13. alfonso Says:

    tengo tres servidores configurados y quiero llamar a extensiones de un servidor pero al realizar la llamada se vaya por el servidor que no esta a el conectado directamente

  14. arobar Says:

    Mark:

    Without looking at the box, it’s tough to say. I’d venture a guess that the issue is related to the keys. Keys are the most often incorrect component of DUNDi. Peers will show up even if your keys are incorrect, so this is most likely your issue.

    To gain more insight into the issue, issue the “dundi debug” command at the Asterisk CLI, and make some DUNDi queries. You should see more information contained in the debug output.

    Cheers,
    Alex

  15. alfonso Says:

    tengo tres servidores conectados entre si, y en cada uno de ellos tengo dadas de alta estensiones, asi como esta si puedo marcar de una extension de un servidor a otro, pero pongo una regla en el firewall para bloquear la entrada de un servidor y quiero que al realizar una llamada entre los servidores que estan bloqueados se vaya por el otro servidor que no esta bloqueado por ninguno de los otros dos, en teoria se supone que se tiene que poder hacer ya que lo estoy haciendo con dundi y ofrece redundancia, pero no lo hace

    espero que me puedan ayudar

  16. luis Says:

    I have three servers connected between if, and in each of them I have given of discharge estensiones, like that as this one if I can mark with an extension of a server other one, but I put a rule in the firewall to block the entry of a server and want that on having realized a call between the servers that estan blocked it(he,she) goes away for another server that not this one blocked by none of other two, I am doing it with dundi since it offers redundancy, but it does not do it
    I hope that they could help me

  17. zibi Says:

    Okay, I followed the directions exactly, and i was able to do asterisk -r and do a dundi lookup ext#@priv and get an answer. However when try to call i get fast busy signals. Do i need to set up a trunk between the two machines, or am i missing something that will allow them to talk to each other?

  18. Marco Mouta Says:

    Funtastic! I’ve test your article, after reading and trying dundi, and finally is working.

    This is the best tutorial for what i think would be a standard use of dundi.

    Congratulations and thanks!

  19. David Adams Says:

    I have gone though the setup you have listed and get the following.
    Tx-Frame Retry[No] — OSeqno: 000 ISeqno: 000 Type: NULL (Command)
    Flags: 00 STrans: 13912 DTrans: 00000 [10.10.4.234:4520] (Final)
    Rx-Frame Retry[No] — OSeqno: 000 ISeqno: 001 Type: ACK (Response)
    Flags: 00 STrans: 13362 DTrans: 13912 [63.146.52.178:52920] (Final)

    Any thoughts on this would be most helpful.

  20. David Adams Says:

    I can not get the IVR to work on this at all. Everthing eles works.

  21. Dhaval Says:

    my question is where i should have to configur my users
    suppose server A have 1000 number registered
    and server B have 1001 number registered

    so how i connect 1000 to 1001 using IAX2 protocol

  22. Mimmus Says:

    There is some problem when DUNDi party is BUSY/NOANSWER because DIALSTATUS variable returns always CHANUNAVAIL when I use Local channel. I don’t know if this is a bug.

  23. Dave Says:

    One issue I found that took me far too long to solve…if the public key was present in the same folder as the private key, it failed to connect to the other site. Moving the public key, rebooting or reloading the pbx_dundi and res_crypto modules resolved it. Works great now. Thanks all for their contributions.

  24. Timba Says:

    I want to connect two servers on the same subnetwork. One with 50XX extension the other with the 60XX extension. If I do ‘dundi show peers’ it gives me the other server. I can do a lookup… but I’m always failing to call. How do I setup the extensions to call from 5000 to 6000?

  25. Rob Says:

    I’m not sure if anyone is following this still. However, I was able to impliment most of what is laid out here. I can call extension no problem. I’m still hung up on how to share my dial plans. When I add exten => _905XXXXXXX,1,Dial(ZAP/g0/${EXTEN}) to my dundi-priv-via-pstn context is won’t dial. Can anyone offer some insight.

  26. Rob Henry Says:

    Ik, I have figured out my dialing problem for anyone that is interested. I added these lines

    [trydundi]
    exten => _.,1,Macro(dundi-priv,${EXTEN:1})
    exten => _1NXXNXXXXXX,2,Macro(dialout-trunk,1,${EXTEN},,)
    exten => _.,3,Congestion

    What this does is try the dundi cloud stripping out the 1 for long distance. If it cannot find a pattern with one of my peers it will then dial out through the local PSTN.

    Hope it helps some one.

  27. John Says:

    I’m a little confused regarding the final location of the keys. I put them all in the /var/lib/asterisk/keys directory on both hosts and have set inkeys and outkeys as you did above as well as explicitly set them to /var/lib/asterisk/keys/xxx.xxx.ws as well as /var/lib/asterisk/keys/xxx.xxx.ws.pub, etc and although the extensions see each other and dundi/asterisk boxes are communicating as expected, when running iax2 debug at the CLI I consistently get “No Authority Found” and calls are REJECTED.

    Am I just plain confused here or doing something radically wrong?

  28. Bobbys Pad » Cool Link of the day! Says:

    [...] This link talks about DUNDI and how to implement it on TrixBox in order to link TrixBox servers together. http://blog.thegoldfish.net/dundi-tutorial-for-asteriskhome/ [...]

  29. hiutopor Says:

    Hello

    Very interesting information! Thanks!

    Bye

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.