Mutual TLS and Static IP Requirements for Voice AI Carrier Integrations
Voice AI demos are about latency, interruption handling, and how natural the agent sounds. None of that is what stops a project. What stops a project is a carrier saying “we don’t accept traffic configured that way”, three weeks before go-live.
Two requirements come up again and again, and both are pass/fail. Either your platform can do it or the trunk cannot exist. There is no clever application logic that gets you around them.
What Is Mutual TLS and Why Do Carriers Require It?
Ordinary SIP over TLS proves the carrier’s identity to you. Mutual TLS also proves yours to them: during the handshake their SBC asks for a certificate, and you have to present one it trusts.
This is common in regulated work, like collections, healthcare, financial services. In our experience the carriers who require it treat it as a fixed property of their platform. They are not going to turn it off for one tenant, however nicely you ask.
Configuring Mutual TLS in jambonz 11.1.2
jambonz supports mutual TLS as of 11.1.2. You configure one identity per server and it is presented whenever a carrier asks for one, and nothing is sent to carriers that don’t ask, so it is harmless for the rest of your trunks. There is nothing to enable per carrier.
For full details on configuring mtls, check out this article on our docs page
The main configuration change is the addition of a <client> element in the <sip> section of /etc/drachtio.conf.xml:
<sip>
<contacts>
</contacts>
<tls>
<key-file>/etc/letsencrypt/live/sip.example.com/privkey.pem</key-file>
<cert-file>/etc/letsencrypt/live/sip.example.com/fullchain.pem</cert-file>
<chain-file>/etc/letsencrypt/live/sip.example.com/fullchain.pem</chain-file>
<!-- START OF NEW SECTION FOR mTLS -->
<client>
<key-file>/etc/drachtio/tls/carrier-client.key</key-file>
<cert-file>/etc/drachtio/tls/carrier-client.pem</cert-file>
<ca-file>/etc/ssl/certs/ca-certificates.crt</ca-file>
</client>
<verify-server-cert>true</verify-server-cert>
<verify-server-name>true</verify-server-name>
<sni>true</sni>
<!-- END OF NEW SECTION FOR mTLS -->
</tls>
<udp-mtu>8192</udp-mtu>
<reject-register-with-no-realm>true</reject-register-with-no-realm>
</sip>
Why You Cannot Reuse Your Existing SIP TLS Certificate
You cannot reuse the TLS certificate you already have for SIP.
Two reasons, and the second is recent enough that most people haven’t hit it yet.
First, a carrier requiring mutual TLS wants a certificate issued by an authority they trust. If they accepted the public authorities, anyone holding a Let’s Encrypt certificate could authenticate as you.
Second, a certificate has to carry the clientAuth extended key usage to work as a client certificate
at all — and the publicly trusted authorities are being taken out of that business entirely. Under
Chrome root program policy, subordinate CAs disclosed after 15 June 2026 may assert only server
authentication, and from 15 March 2027 every newly issued public TLS certificate will be
server-authentication only. Let’s Encrypt issued its last client-capable certificate on 8 July
2026. The stated migration path across the industry is that client authentication belongs in a
private or enterprise PKI.
So, the instinct to reach for a well-known public CA is the one thing that is actively being removed.
A certificate with only serverAuth is rejected outright, however well it is trusted, and the error
you get — unsupported certificate purpose — looks nothing like the actual cause.
Where to Get a Client Authentication Certificate
What works is a certificate from an authority the carrier trusts specifically: a small CA of your own that they load, a commercial client-authentication or industry PKI they already accept, or their own CA signing your request. We’ve documented all three, with the openssl commands, in Mutual TLS.
Why Carriers Require a Static IP Address for SIP Traffic
The second requirement is even less glamorous: many carriers allowlist by source address. They want to be told the IP your SIP traffic will come from, and they want it to stay that way.
This is where some managed platforms struggle. Running on shared infrastructure, the best they can usually offer is a published range of egress addresses. Sometimes a large one. A /21 and a /19 together are around ten thousand addresses.
A carrier that asks for your IP will not always accept that. A self-hosted jambonz runs on your own instance with your own address. One IP (or a couple, for redundancy), yours alone, stable across restarts, that you can put in an email and that will still be true next quarter. It is a boring answer to a boring question, and it closes the conversation.
The SBC Workaround and What It Costs
Neither of these is a secret. If you go looking, you will find customers of other self-hosted platforms being told the same thing by support: put a Kamailio or session border controller in front of their platform, manage that in addition to the rest of the voice infrastructure you’re dealing with, and let it “fix up” the carrier integration that way.
That’s not a solution. That’s punting the cost and complexity of solving the problem directly into your lap. And it’s not free. A back-to-back user agent sits in the signalling path, and usually the media path too, for the entire duration of every call. That is something else to scale, to make highly available, to monitor, and to pay for per minute. It lengthens the media path for every call, including the ones that never needed it.
Questions to Ask Before You Choose a Voice AI Platform
If you are evaluating platforms for production telephony, these are cheap questions to ask up front and expensive ones to discover during integration:
- Does it support mTLS for SIP?
- Can I give the carrier a single, stable IP address that I control?
We built jambonz so that the answer to both is yes.