Turning your OBi200 and OBi202 into an ITSP for Google Voice

Robert Stampfli — r5519@cboh.org — last updated Sunday, 17 June 2018

Please Note: Although I believe the instructions below to be accurate, I still view this as a work in progress and will likely make changes to this document as we gain more experience. While these notes worked for me, they have yet to be tested in the field. So check back here frequently for any additions and/or corrections, and feel free to contact me if you have any questions or problems so that not only can we get them resolved, but also so that we can make these notes more clear and bullet-proof. Finally, let us know if you follow the instructions below and are successful, so that we can tell if they are usable by the typical reader.

Introduction

Many VoIP hobbyists and experimenters have come to rely on Google Voice for their trunking needs. While it's certainly not a perfect fit, it can be made to work reasonably well and free offsets a multitude of sins. Recently, Google announced it will be shutting down its XMPP servers — the protocol the Asterisk PBX uses to access GV. Polycom (neé OBiHAI) makes the only non-Google devices which currently have access to the new GV network with Google's blessing, and this got me thinking: The OBi 200 and 202 devices are themselves a feature-rich ATA — some might even say a mini-PBX in themselves — capable of handling four trunks and/or endpoint devices. Could they be pulled into service to provide a SIP-to-GV bridge? Think of this as a small localized version of Bill Simon's Google Voice Gateway. After some experimentation I came to the conclusion that, yes, they can.

I was able to interface an OBi202 to an Asterisk 13 server such that (1) outgoing calls from Asterisk would flow into the 202 using the SIP protocol, where they would be bridged to a corresponding GV line to complete the call. And (2) incoming GV calls would be automatically translated into SIP and delivered to Asterisk. In essence, the OBi200 or 202 ATA look like an ITSP to the Asterisk server and make it possible for Asterisk to continue to support up to three GV lines per OBi.

The OBi200 can be had for around $50 and as low as $35 on sale. The 202 costs a bit more. However, many of us already use these OBi units as ATAs in which case the additional functionality can often be added without any additional hardware costs.

What follows is a description of how to configure Asterisk and the OBi device to accomplish this task. Every configuration option described herein is based on publicly available published documentation. I will address two scenarios: The first, and simpler, implementation presumes that the Asterisk server and OBi device are on the same local LAN. The second, more involved, approach will work with an Asterisk server with a static IP address on the Internet interfacing with an OBI sitting behind a firewall that has a dynamic IP. (Think Asterisk on a VPS here.)

These notes presume the reader is familiar with programming the FreePBX Asterisk server, including how to add a trunk and make it functional. My personal testing was performed on a FreePBX 13 system running Asterisk 13. A Debian 8 system supported the first implementation and a CentOS 6 system the second.

There are several ways make the changes we will be making below. One way involves disabling all OBiTalk updates and making the changes via the OBi's built-in web server. Although I rather dislike dealing with programming the OBi via OBiTalk.com, it's probably easier overall to bite the bullet use the OBiTalk Expert interface. If you are not familiar with how to do this, take the time to learn how it works before you begin.

Preliminaries...

Verify your OBi firmware is current:
You must be on a firmware load that supports the new GVsip protocol or GV will not work. The firmware ("Software Version") can be found under Product Information on the status page, from either the device's internal server or the OBiTalk.com website. The version must be 3.2.2 Build 5859EX or later.
Program the GV service(s) into your OBi:
This is normally done using the OBiTalk.com interface. Refer to the instructions on the website.

Make a note of the site-specific data you'll need:

Method 1: Your OBi and Asterisk are on the same LAN

If your Asterisk server and OBi are located on the same LAN and both have static IP addresses, then this method should work and is the simplest way to proceed. No registrations or authentications are needed; instead, the IP addresses themselves provide the necessary authentication. For the OBi, a static IP address can either be assigned manually, or by setting up your DHCP server to always serve the same IP address when presented with the OBi's MAC address. The latter is often the easier way to make this happen.

The OBi20X boxes have support for four Voice Services, named SP1 - SP4. It also has provisions for handling four Service Provider ITSP Profiles. By convention, SP1 is linked to ITSP Profile A, SP2 to Profile B, etc., but this is not a requirement.

In addition to the GV Service(s) you already have programmed (via OBiTalk.com), you'll need at least one unencumbered Voice Service for the SIP-side interface. In the description below, I use SPx to denote the Sip-side SP and SPgv for the Google Voice side. The "x" and "gv" should be replaced by the appropriate numeric voice service designator for your setup.

Now, before we begin, raise your right hand and repeat after me: "I will NOT change any parameter under any Google Voice Service or its ITSP Profile except for X_InboundCallRoute". If you do accidentally change a GV parameter it may break your GV or cause odd problems which are hard to diagnose.

On the OBi, here are the changes I made to the default settings, or in the case of SPgv, the settings OBiTALK made when setting up the Google Voice Service:

*** Changes to the OBi SIP-side service:

Using the ITSP profile you previously assigned to your SIP Voice Service:
Service Providers > ITSP Profile X > SIP > ProxyServer          [Set to the IP-addr of your A* Server]
Service Providers > ITSP Profile X > SIP > ProxyPort            [Set to the listening SIP port on your A* server (typically 5060 or 5160)]
Service Providers > ITSP Profile X > SIP > X_SpoofCallerID      (check)

Voice Services > SPx Service > X_ServProvProfile                [The ITSP profile you selected and modified above]
Voice Services > SPx Service > X_InboundCallRoute               {SPgv}
Voice Services > SPx Service > X_RegisterEnable                 (uncheck)
Voice Services > SPx Service > AuthUserName                     OBi202 *
Voice Services > SPx Service > X_EnforceRequestUserID           (must be unchecked)
–––––––––––––––
* – AuthUserName can be anything, but it must match username below.

*** Changes to the OBi GV-side service:

(This will be the only change you should make to the GV Service.)
Voice Services > SPgv Service > X_InboundCallRoute       {SPx(6145551212)} ¹
–––––––––––––––
¹ – Substitute your GV DID for 6145551212.

A word about the choice of a DID number above: Any number will work here as long as it does not conflict with another number on your server, but your GV DID is a good choice because it is logical as well as unique. You can prepend a leading '1' to it or not; just make sure it matches the DID you code in the Inbound Route below.

*** Changes on your Asterisk/FreePBX server:

Create a SIP trunk:
Creation is straightforward and left as an exercise for the reader. I set Maximum Channels to '2' to avoid abusing GV. The Incoming SIP Settings should all be left blank. The Outgoing Peer Details should contain something like:
host=192.168.1.202 *
port=5060 *
username=OBi202 *
type=peer
context=from-pstn
insecure=invite,port
qualify=yes
directmedia=no
disallow=all
allow=ulaw,opus ²
–––––––––––––––
* – replace with whatever is appropriate in your environment
² – Remove ,opus if your server does not support this codec.
Create an Outbound Route
No special configurations are required here.
Create an Inbound Route
No special configurations are required here. Use your GV number, the one you substituted for 6145551212 above, as the DID.

Method 2: An exposed Asterisk server with an OBi behind a firewall

Notice that the above implementation was done without any registrations. Registrations exist (1) to inform the far end of an endpoint's IP address when it is dynamic, and (2) to circumvent NAT issues. On local LANs, neither is typically a problem and thus registrations are rarely required or desired — you can just code the applicable IPs and Port numbers directly. However, VPSes don't have local LANs — at least not LANs that can do us any good. So, can we use our OBis to provide GV access to VPS PBXes? The answer is again yes, we just need to situate the OBi at a convenient spot on the Internet that we control, and hopefully one "close" (in Internet terms) to the VPS to avoid latency issues.

Here's the tricky part: If the convenient spot of choice is served by a dynamic IP address or located behind a firewall then you'll probably have to resort to using registrations. Normally, we are familiar with registrations in two contexts: (1) registering extensions (our VoIP phones), and (2) registering with ITSPs to gain access to trunks. In this case, however, we are dealing with something rarely encountered — here it's the OBi box (the ITSP) that has the labile IP address, so it needs to register with Asterisk (the client) as opposed to the other way around. So let's see how we can make this happen.

To be honest, I never could make this happen with SIP. I could get as far as answering a ringing phone, but never could get the audio. Hence, I abandoned SIP on the Asterisk server and went with PJsip.

*** Changes to the OBi SIP-side service

Service Providers > ITSP Profile A > SIP > ProxyServer          [Set to the IP addr of your A* server]
Service Providers > ITSP Profile A > SIP > X_SpoofCallerID      (make sure this is UNchecked)

Voice Services > SPx Service > X_ServProvProfile                [The ITSP profile selected above]
Voice Services > SPx Service > X_InboundCallRoute               {SPgv}
Voice Services > SPx Service > X_AcceptsSipFromRegistrarOnly    (check – why not?)
Voice Services > SPx Service > X_NoRegNoCall                    (check – why not?)
Voice Services > SPx Service > AuthUserName                     OBi200 *
Voice Services > SPx Service > AuthPassword                     (set passwd)
Voice Services > SPx Service > X_EnforceRequestUserID           (must be unchecked)
–––––––––––––––
* – Name at your discretion, but should match Trunk name below.

*** Changes to the OBi GV-side service:

Voice Services > SPgv Service > X_InboundCallRoute               SPx(6145551212) ¹
–––––––––––––––
¹ – Substitute your GV number for 6145551212.

*** Changes on the Asterisk/FreePBX server:

Create a PJsip trunk:
Under Connectivity > Trunks > Add Trunk > chan_pjsip
Trunk Name 							[same as AuthUserName above]
Secret								[same as AuthPassword above]
Authentication > Inbound					(select Inbound)
Registration > Receive						(select Receive)
Codecs								ulaw (+ opus if you have it)
Create an Inbound and Outbound route:
(Refer to the Inbound/Outbound documentation above.)

Troubleshooting:

If everything to this point has gone according to plan, you should now be able to call in and out on your new trunk. But, what do you do if your setup doesn't work? Here are some pointers:

The Icing on the Cake: Passing Inbound CallerID (Method 2):

If you've played around with your new trunk at all, you've probably noticed that it does not pass the proper CallerID. Instead, it substitutes the name of the trunk. This is because we did not set X_SpoofCallerID above. But, unfortunately, our hands are tied, as PJsip relies on the trunk name being passed to match the incoming call to the proper trunk. If we spoof the CallerID, we get a PJsip error and the call never completes. Fortunately, though, there is a way to work around this, and I'm sure you want to know who's calling, so lets make it happen!

It turns out PJsip implements several algorithms of matching an incoming call to a PJsip trunk, but only two are activated by default. The first uses the SIP INVITE's IP address, but this doesn't work for us because (among other reasons) our address is dynamic. The second uses the first part of the FROM field of INVITE, the same as what we need to spoof, so this won't work either. However, there is a third option that uses the AUTHENTICATE field of the INVITE, and since we always authenticate our incoming GV calls, this looks like an excellent alternative for us. But, since tha AUTHENTICATE option is not active by default we need to activate it via a PJsip configuration change. Unfortunately, it is is beyond the capabilities of FreePBX to do this, so we'll have to modify the Asterisk config files directly.

Insert the following line at the very top of /etc/asterisk/pjsip_custom_post.conf, which is probably empty:
endpoint_identifier_order=ip,username,auth_username,anonymous
Next, add the following to /etc/asterisk/pjsip.endpoint_custom_post.conf
[OBi200](+)
trust_id_inbound=true
identify_by=auth_username
where OBi200 above is the name of your trunk. Finally, reload PJsip to allow the above changes to take effect:
asterisk -rx "module reload res_pjsip.so"

Now you should be able to go back and check X_SpoofCallerID on the SIP-side SPx to have the original ID passed to Asterisk.

Optional Enhancements:

One Google Voice Line, Multiple Endpoints

There is no reason why multiple endpoints cannot use the same GV line. Provided you have a remaining unassigned Voice Service, it can be pressed into service as a second SIP-side interface. Just configure it as described above, as if it were the sole user of the GV trunk. In this case it would be prudent to set Maximum Channels so as to avoid overloading the GV channel should both endpoints attempt to use the GV line at the same time.

Of course, incoming calls will be routed according to the GV channel's X_InboundCallRoute (which, incidentally, does not need to be set to one of the outgoing endpoints). Typically, these calls will be routed to only one destination, but here is an example of an X_InboundCallRoute which will ring two endpoints simultaneously and dispatch the call to the first one answered:
X_InboundCallRoute			 {sp3(6145551212),sp4(6145551212)}

Multiple Google Voice Lines, one Asterisk Trunk

In a similar vein, one Asterisk trunk can be made to control all the GV lines assigned to an OBi. You can direct a call to a specific GV line based on several criteria such as the called number, a prefix code, or the passed CallerID. (Since GV will always opt to use its own number for the CallerID when making a call, this makes the passed CallerID a good candidate for selecting between GV lines.) This post from dslreports, https://www.dslreports.com/forum/r31956002-, describes in greater detail how this is done.
The following route will direct a call to SP1 if the passed CallerID matches 6145551212, else the call will go to SP2:
X_InboundCallRoute				{6145551212>:sp1},{:sp2}

Installing the Opus Codec on Asterisk

GVsip uses two codecs, ulaw and opus. While theoretically only ulaw is needed on the SIP side, it's handy to have to have the opus codec on Asterisk so no transcoding is necessary. Unfortunately, all my systems already had opus installed, so these instructions have never been tested in a opus-free environment.

I believe opus is installed by default in Asterisk 14, but must be explicitly built into Asterisk 13. There are two ways to accomplish this: The preferred method is to build and install opus as part of the Asterisk build. However, there is a quick and dirty alternative for Intel-based servers which involves downloading the libraries from Digicom and manually copying them into the Asterisk directories. This latter method worked fine for me. I used the notes from https://gist.github.com/worldadventurer/757bf4b10af2356d83d57a8a6bb3e4e8 to do the install on my system. Just make sure when you are done that you perform an " asterisk -rx 'core show translation' " to verify the codec is indeed loaded and usable.

Final Thoughts and Observations:

The OBi solution for adding Google Voice lines as trunks on an Asterisk system is viable and if OBi20x boxes are already in use as ATAs the additional functionality can often be added to them at no additional hardware cost. The implementation appears robust and, especially if everything resides on the same LAN, adds only minimal latency compared to the existing XMPP solution.

These instructions are designed for and were tested with a FreePBX/Asterisk server. However, they probably could be updated to apply to any VoIP PBX, or even the OBi100 series devices.

Although the OBi solution has worked well for me, it is only one of several options available to Asterisk users. One should also take a look at Bill Simon's Google Voice Gateway and twincloud's How to make and receive calls using Google Voice without XMPP paper, to name a few, before making a decision.

Finally, understand that it was never Google's intent for Google Voice to become a provider of free PBX trunks. As we alluded to in the first paragraph, these notes are mainly directed towards hobbyists and experimenters. The OBis may be the equivalent of a Swiss army knife for VoIP interconnections, but that doesn't alter the fact that if you run afoul of "the Gospel according to Google, available to only a select few" (to paraphrase from a recent Bill Simon post), you may well find your service suspended.