Connecting two FreePBX machines together

One of the most common issues that people come up against is that they’ve rolled out one FreePBX machine, and now they want another, somewhere else. And to make it just that little bit harder, they want to link them together. At first, this can be a bit daunting, but it’s not – when you know how.

One of the first things you need to know, is that there are two ‘entry points’ in the freePBX dialplan. They are ‘from-trunk’ and ‘from-internal’. When a call is sent into the ‘from-trunk’ context, it is routed through the ‘DID’ logic, and treated as if it’s an external call. A call sent into the ‘from-internal’ context is treated as if it was dialed from a normal SIP, IAX or Zap extension of your PABX.
Normally, when you’re linking two freePBX machines together, you want the users pretty much be unaware that there are two machines, so you need a dialplan set up so that calls are treated that way. This means you need to have a little bit of forward planning if you don’t want your outbound routes and trunk setup to be pretty messy. As an example, let’s set up a couple of pretend freePBX machine here:
freePBX Machine ‘office1’

  • Has an outgoing IAX trunk to Faktortel, that is configured as 0|. — eg, they dial 0numbernumber to make an external call. (As a minor unpaid plug, I’ve had nothing but good from Faktortel. Very happy with them.)
  • Has extensions in the range 300 to 350

freePBX Machine ‘office2’

  • Has an outgoing IAX trunk to MyTel (Yes, both of these are Australian providers. I’m Australian. Handle it 8-)) that is configured as 9|.
  • Has extensions in the range 600 to 620

The first thing you want to do is set up the IAX trunk between the two sites. Something like this would do it:
At office1
Trunk Name office2
PEER Details
deny=all
allow=g729&alaw
type=friend
host=office2
qualify=yes
context=from-internal

Those options mean, in order:

  • Deny ALL audio codecs.
  • Except for g729 and alaw – if you were in the US, you’d use ulaw
  • Use this entry to send calls to, and receive calls from a device.
  • Use this entry when sending or receiving calls from the host ‘office2’
  • Regularily send a keep-alive packet that ensures that the other machine is up and is responding to IAX traffic
  • When a call comes in from host ‘office2’, send it to the ‘from-internal’ context – eg, treat it as if it originated locally in this PABX.

Now set up exactly the same trunk on office2, but changing host=office2 to host=office1 (normally, you’d use IP addresses here, rather than hostnames, to avoid potential DNS errors)
Trunk Name: office1
deny=all
allow=g729&alaw
type=friend
host=office1
qualify=yes
context=from-internal

That’s almost it. You now have the ‘pipe’ between the two sites set up. Now all you need to do is set up the routing, which is easily done.
Go into your outbound routing on office1, which you should remember has extensions in the range 300 to 350, and they want to be able to call extensions 600 to 620 at office2. Create an outbound route name called ‘tooffice2’ with the dial plan match of ‘6[012]X’ (which means a three digit number anything starting with 6, with the second digit being 0, 1 or 2, and any last digit), and the trunk set to be ‘office2’. Do the same thing on office2, but with the dial plan match set to be ‘3[0-5]X’, and the trunk set to office1.
That’s it! You’ve now linked the two offices together. Someone on office1 will pick up the phone, dial 600 and it’ll fire off out the ‘tooffice2’ trunk because of the match, and arrive in the ‘from-internal’ context of office2 so it’s treated as an internal call.
As a caveat, this post handily avoids the issue of sites having conflicting extensions. If that is an issue, you could, possibly, re-map them in your Trunk dialling rules by something like 3+4|XX – that matches a three digit number starting with four, takes off the leading four, and adds a three to the start – basically, replacing the 4 with a 3. That would let you call 312 at office2 by dialling 412 at office1). You can also do ‘smart’ stuff like having office2 fail over to office1 if their connection to MyTel goes down, by having office2’s outbound route (which is currently 9|. with the only trunk being MyTel) have ‘office1’ after the mytel trunk, and in the ‘office1’ trunk on office2 add a 0 if the call being sent to it is longer than 3 digits – eg, 0+XXXX.
Another caveat is that this was written from a Hotel room in Toowoomba. I’m currently away from the office for the rest of the week, and this post was done from memory. Hopefully if there’s any errors, someone will leave a comment and I’ll fix it!
Update: There’s been a comment below about dialling out through an interconnect, when you just want the freepbx machine to pass the calls through blindly. Whilst we will be making a ‘to-trunk’ destination, which you can use to plumb routes together, there’s a solution on the Trixbox Forums that explain how to do it.
–Rob

12 thoughts on “Connecting two FreePBX machines together

  1. This post is very helpful in my implementation of multiple asterisks. Thanks.

    I would like to know how server B can access the trunks in server A, if server B only has extensions and IAX2 trunk connection to server A, and server A has other trunks connecting to international and zaptel?

  2. I have 2 freepbx boxes configured with 2 T1 cards each on different nodes on a WAN. (te220b from digium) for a total of 96 external lines to the PSTN. I have 12 locations in my company that place calls to and receive calls from the PSTN on these zap lines. I want the 2 boxes to load balance the PSTN as well as act as failovers in the event one of the PBX’s is not reachable. I will use this method to connect the dial plan but I am curious if the ZAP channels will failover. Specifically, if at office 1 all 48 zap channels are in use, can I specify the iax trunk to office2 as the secondary trunk and have office2 place calls on 1 of there zap channels?

    Comments appreciated

  3. Short answer is yes. It works fine if you out the trunk to the other office after the zap trunk in the outbound routing. One thing i found out is that if the call can not be completed becouse of "the number is not availble" etc, it will fall over to the next trunk and call the number again via the other office and then fail – But if you have the same failover at the other office it will loop back to te first and so on and on and on and on and on… Until you hangup becouse it never rings…

  4. although – with a little bit of custom work, I’m pretty sure there are ways to prevent the infinite loop issue. (I’ve done so interconnecting internal dialplans between legacy pbx systems).
  5. Thanks for the heads up on the loop. Will this method also preserve the original caller id if the source call is answered on a zap channel at server1 and the destination is an extension on on server2….
  6. i have 2 freepbx server. one with zap card and the other is without zap card. how can i use the zap channel from my freepbx that doest have zap card to the freepbx with zap card?
  7. Hello, there…i need a help from you and i trust that
    you will send me a solution
    I configured my Grandstream HT-386 ATA as a trunk in my asterisk as follow
    Peer details:
    allow=all
    context=from-internal
    host=192.168.16.27
    type=friend
    the problem is that i can call only the 1st FXS port of the ATA and the
    other one can’t be called ever even if the 1st one is busy..i need an option that is like a hunt group.if the 1st busy it redirects the call to another available….
    HINT:this ATA ‘s that i use to tie all branches Panasonic PBXs’ extensions
    to the VOIP extensions..i use many ATA’s 2 ports and many also of ATA’s 8 ports and each branch will have 2 ATA’s minimum and the total number of branches is 13

    and hint that in each branch PBX there are repeated extensions(for analog phones).

    so i want to put a prefix for each branch ATAs.

    please send me a solution if you can of course…

  8. Hi, I have successfully had two trixbox at two separate offices working as outlined above for nearly a year. However, I recently upgraded one site
    (call it site A) to the latest Freepbx (2.4.1) using module admin and also did a yum -y update so that the trixbox version is 2.2.3. Now I can make calls from site A to site B but not the other way. I have not changed any configuration and the log at site B shows the following:

    —————————————————————————————————————————————————————————
    Jun 10 21:10:07 DEBUG[2911] chan_sip.c: Setting NAT on RTP to 524288
    Jun 10 21:10:07 DEBUG[2911] chan_sip.c: Checking SIP call limits for device 4001
    Jun 10 21:10:07 DEBUG[2911] chan_sip.c: build_route: Contact hop:
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Expression result is ‘1’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Function result is ‘device’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Function result is ‘4001’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Expression result is ‘0’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Not taking any branch
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Expression result is ‘0’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Not taking any branch
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Function result is ‘4001’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Function result is ‘4001’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Function result is ‘blahblah’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Expression result is ‘0’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Not taking any branch
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Function result is ‘4001’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Expression result is ‘1’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Function result is ‘”blahblah” <4001>‘
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Function result is ‘4001’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Function result is ‘0’
    Jun 10 21:10:07 VERBOSE[15956] logger.c: recordingcheck|20080610-211007|1213128607.27304: Outbound recording not enabled
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Expression result is ‘1’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Expression result is ‘1’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Function result is ‘IAX2/InterOffice’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Expression result is ‘0’
    Jun 10 21:10:07 DEBUG[15956] pbx.c: Not taking any branch
    Jun 10 21:10:07 WARNING[2917] chan_iax2.c: Call rejected by 000.000.000.70: No such context/extension
    Jun 10 21:10:07 DEBUG[2917] chan_iax2.c: Immediately destroying 4, having received reject
    Jun 10 21:10:07 DEBUG[15956] chan_iax2.c: We’re hanging up IAX2/InterOffice-4 now…
    Jun 10 21:10:07 DEBUG[15956] chan_iax2.c: Really destroying IAX2/InterOffice-4 now…
    Jun 10 21:10:07 DEBUG[15956] app_dial.c: Exiting with DIALSTATUS=CHANUNAVAIL.
    Jun 10 21:10:07 DEBUG[15956] channel.c: Scheduling timer at 160 sample intervals
    Jun 10 21:10:09 DEBUG[2911] chan_sip.c: Auto destroying call ‘418830037-1547926746@000.000.000.222’
    Jun 10 21:10:09 DEBUG[2911] chan_sip.c: Stopping retransmission on ‘5e10e09029bb17770baf11641d99d74f@000.000.000.43’ of Request 102: Match Found
    Jun 10 21:10:09 DEBUG[15956] channel.c: Scheduling timer at 0 sample intervals
    Jun 10 21:10:09 DEBUG[15956] channel.c: Scheduling timer at 0 sample intervals
    Jun 10 21:10:09 DEBUG[15956] channel.c: Scheduling timer at 160 sample intervals
    Jun 10 21:10:11 DEBUG[2911] chan_sip.c: Stopping retransmission on ‘2bf26095602b672f33257cf74f702a00@000.000.000.43’ of Request 102: Match Found
    Jun 10 21:10:11 DEBUG[15956] channel.c: Scheduling timer at 0 sample intervals
    Jun 10 21:10:11 DEBUG[15956] channel.c: Scheduling timer at 0 sample intervals
    Jun 10 21:10:11 DEBUG[15956] cdr_addon_mysql.c: cdr_mysql: inserting a CDR record.
    Jun 10 21:10:11 DEBUG[15956] cdr_addon_mysql.c: cdr_mysql: SQL command as follows: INSERT INTO cdr (calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid) VALUES (‘2008-06-10 21:10:07’,’\”blahblah\” <4001>‘,’4001′,’4026′,’from-internal’, ‘SIP/4001-b7623310′,’IAX2/InterOffice-4′,’ResetCDR’,’w’,4,0,’FAILED’,3,”,’1213128607.27304′)

    ——————————————————————————————————————————————————————————————-
    It seems that the context from-internal is no longer valid?

    Any help would be appreciated.

    Alisterg

Leave a Reply