Talk about a bad user experience.
You boot up your favourite device, launch your favourite VoIP client, and… encounter a connection failure.
But it worked just fine yesterday!
Software updates? Hmmm... nope, none recently. This version was working perfectly yesterday.
Time to dive in for some basic troubleshooting.
- Web browsing works
- The VoIP provider’s web site doesn’t indicate any kind of outage.
A little bird (or, OK, possibly the customer support department) tells you to run through some steps to figure out your current IP address.
And that’s it. You have an IPv6 address. And only an IPv6 address. Good luck connecting to your IPv4-only VoIP service with that…
Good news folks! The world is indeed moving to IPv6.
Check out the IPv6 adoption stats, in case there was any doubt.
Even better news for our customers is that the above “nightmare scenario”, being stuck on an IPv6-only network, with no connectivity to an IPv4-only VoIP service, is now a lot less likely to happen. This is particularly relevant for our Bria Mobile customers, who have started to encounter IPv6-only networks with their cellular data connections.
We’ve had some level of IPv6 support in our software for many, many years. The parsing of IPv6 addresses in our SIP stack has been there since before I joined CounterPath more than 10 years ago! However, to make for a great user experience, more is needed. We live in a world where:
- IPv4 and IPv6 dual stack clients and servers abound
- Network operators have gone IPv6-only, but VoIP services in particular are still IPv4-only
- Different operating systems provide different levels of support to applications
- Some hide the fact of your IPv6 connectivity behind local 4-to-6 and 6-to-4 address family translation services (e.g. Android CLAT)
- Some provide an easy way to do DNS64 lookups, others do not
- Users expect seamless connectivity, no matter if it’s an IPv4 network, IPv6, dual stack, or tunnels. That being said, it would be great to be able to switch between those on the fly too!
In general, our goal has been to make it as simple as possible to work on any device, with any network, without requiring the user to go into client configuration settings to make ‘tweaks’.
We added a couple of key features recently in order to help realize this goal.
On a dual-stack network, it might be the case that a VoIP service is reachable over both IPv4 and IPv6, or just one, or just the other.
- You are connected to a Wifi access point that provisions both IPv4 and IPv6 addresses, but the Internet service is IPv4 only.
- You have working IPv4 and IPv6 connectivity, and DNS configuration gives you both IPv4 and IPv6 addresses for your VoIP service, even though the VoIP service is only available with IPv4.
What happens if you attempt to connect using IPv6, but the server isn’t reachable? A long 32 second wait for a SIP transaction timeout (e.g. when using SIP over UDP) just isn’t a good user experience. Therefore, much as web browsers and other protocols do with TCP, some kind of connectivity probing is needed to quickly determine which IP version to go forward with, reducing the amount of time that the user has to wait.
In our case, connectivity probing is accomplished by sending SIP OPTIONS requests to the SIP proxy/registrar over both IPv4 and IPv6 simultaneously, before any other traffic (such as REGISTER, etc.). The first response back “wins”, and we use it as a hint to continue with that IP version.
A few notes on our use of OPTIONS:
- Strictly speaking, we don’t really need to send an OPTIONS for TCP. As with the browsers, the “happy eyeballs” TCP connection attempts defined in RFC 6555 would work just as well for SIP/TCP. However, the implementation as it currently stands will send OPTIONS no matter if TCP or UDP is required.
- We set the Max-Forwards header to 0 in the OPTIONS request, since we’re only interested in connectivity to the next-hop (i.e. the SIP proxy).
- We don’t require a “200 OK” response for the connectivity probe to succeed. In the case of TCP, a successful connection is enough; in the UDP case *any* response back is enough (even 4xx or 5xx responses).
- We allow only a short 2 second window for a response to the OPTIONS probes before we give up waiting and proceed with sending a REGISTER over the IP version that’s set as a preference in our configuration settings. (This REGISTER may still time out and we’d be required to try the other IP version after the requisite delay).
Connectivity probing is enabled by default in both the Android and iOS editions of Bria. However, as mentioned in point (3) above, we offer a way for the user to tweak the IP version preference. This is useful for cases where OPTIONS probing simply doesn’t work for interop reasons (e.g. there is no response to our OPTIONS requests). The naming is slightly different in the various Bria versions, however here is a quick summary of the new settings available:
- Auto (prefer IPv4) -- IPv4 connectivity probes are sent slightly before IPv6 ones, and if no response is received for the probes, IPv4 is attempted first
- Auto (prefer IPv6) -- IPv6 connectivity probes are sent slightly before IPv4 ones, and if no response is received for the probes, IPv6 is attempted first
- IPv4 -- only IPv4 is attempted, and no connectivity probing occurs; registration fails if there is no IPv4 interface on the device
- IPv6 -- only IPv6 is attempted, and no connectivity probing occurs; registration fails if there is no IPv6 interface on the device
In general, there is no need for a user to change this setting from it’s default “auto -- prefer IPv4” default value. Even when switching networks, e.g. between IPv6-only cellular data and IPv4-only wifi, this setting is appropriate, and will discover which IP version to use automatically (in a timely manner).
Network operators moving to IPv6-only networks do provide infrastructure to support connections to IPv4 services. This often takes the form of DNS64/NAT64. For more information on how this works, check out this link.
To leverage this support, software such as ours translates the configured address of the SIP proxy/registrar, which could be a hostname, or an IPv4 address, into an IPv6 address, which is provided by the DNS64/NAT64 machinery. The SIP traffic then routes via the NAT64 box, to and from the proxy/registrar.
However what about the SIP messages themselves, with their Via headers, Contact headers, and not to mention SDP, all of which contain the IP address of the local client, meaning an IPv6 address?
There’s no guarantee that an IPv4-only VoIP service on the other side will be able to auto-magically figure out what to do with SIP traffic bound for the UA, particularly if the various SIP headers point to the UA being on an IPv6 network. It might also choke completely if it sees an IPv6 address. So we need to “play nice”, and replace any IPv6 client address in both SIP and SDP with an IPv4 one.
Fortunately, NAT traversal in general for SIP (in a pure IPv4 setting) is something well understood and widely implemented. With an SBC in play, it turns out that we don’t even need to replace our IPv6 local address with the actual IPv4 address of the NAT64 middle box that our traffic appears to originate from (from the perspective of the VoIP service). It’s enough to pretend that we’re on a purely IPv4 network, behind a NAT, and use a ‘fake’ private IPv4 address instead, like “192.168.0.50”. The SBC’s usual NAT traversal abilities will ensure that SIP requests/responses destined for our UA will be sent to it.
For media, the situation is more complex. The IETF recommends using ICE to determine which IP version to use. However, ICE is simply not supported by many VoIP providers. More commonly, a VoIP service would rely on either an SBC, or on the clients to be configured with a STUN/TURN service.
In the case of an SBC, doing the same trick as for SIP works well -- replace any local IPv6 addresses in our SDP with a fake IPv4 address, and let the SBC do its magic re-writing of those addresses with its own, and perform latching as it normally would.
But wait, how was media from the UA’s IPv6 only network going to make it to an SBC on an IPv4 only network? This is where NAT64 comes in once again. The UA can use DNS64 to translate the IPv4 address provided by the SBC in the SDP into an IPv6 address (on the NAT64), so media ends up routing from the UA, to the NAT64 box, then to the SBC. This is an important point, since in my mind it’s also slightly controversial; is RTP media a valid usage of NAT64? On one hand, there’s no guarantee at all about quality of service. Think about thousands of VoIP UA’s using NAT64 for audio and video and competing for resources. On the other hand, this is carrier-grade NAT, presumably designed to handle such loads.
Another option would be to use a TURN server to relay the media between IPv6 and IPv4 networks. Certainly this approach could be used even where an SBC is present, instead of the approach with NAT64 mentioned above. However availability of a TURN server for this purpose is often a barrier for our retail customers; they get a VoIP service from company X, a softphone client from CounterPath, and a TURN server from who exactly? And then there’s the problem of needing to configure the TURN server itself, and configure the client -- a problem our stated “zero config” goal above strives to avoid. While TURN for this use case hasn’t been a focus for our client development team as yet, it is something we anticipate moving on as need arises.
Any Device, Any Network
There’s little doubt that supporting users during the IPv4-IPv6 transition period is no longer something that can be put off, in wait of standards yet to be written/debated/adopted. We believe that having connectivity probing and NAT64 support in our products today will make life easier for our customers. These features help to provide an “it just works” experience that doesn’t require manually tweaking configuration options depending on which Wifi or VoIP service you’re connected to today. For any device on any network, we want your user experience to be a great one.