I finally gave up chan_sip for chan_pjsip and it was fine

This is a brief tale about an upgrade from Debian 8 / Asterisk 11 / FreePBX 13 using exclusively chan_sip to Debian 10 / Asterisk 16 / FreePBX 15 using exclusively chan_pjsip.

The old PBX was running happily but I decided it was time to bring it to a more modern state. While I could have easily loaded chan_sip and brought all that cruft over I decided to start fresh and remake the dozen extensions and three trunks (not a big PBX) with pjsip, leaving chan_sip out altogether. I wasn’t sure where I’d run into challenges. Here were the ones I encountered.


  • TLS: The FreePBX-generated config points to the wrong cert file, at least in my scenario where I am using Letsencrypt. (Bug [FREEPBX-20610] PJSIP TLS transport points to wrong certificate file - Sangoma Issue Tracker) Also, old endpoints seem to have a really hard time negotiating with modern TLS and even though I worked at it for a long time, I couldn’t come up with a TLS configuration on FreePBX that was acceptable to an Obi 110. Globally, in Asterisk SIP Settings / pjsip, I had to turn off verify_client because otherwise endpoints that don’t present a client certificate are rejected.

  • IPv6: Not configurable in FreePBX yet for pjsip. I used the custom_post.conf files to add IPv6 transports, for example (in pjsip.transports_custom_post.conf):


    To allow my extensions to use IPv6 I had to add settings for them not available in the GUI: (in pjsip.endpoint_custom_post.conf) (Not needed with current Asterisk 16)


    You don’t need to tell extensions to use the ipv6 transport; Asterisk figures this out when they initially register over IPv6.

  • NAT: for endpoints behind NAT you choose from these options, which look a little different from the old chan_sip NAT options:


  • IPv6: To use the IPv6 transport here I had to put in an override in the pjsip.endpoint_custom_post.conf file:

  • Registration, authentication, etc.: This is all easier with FreePBX’s pjsip trunk screen than the chan_sip trunk screen, in my opinion. Just fill in the blanks. I have a Vitelity trunk where I register to one server and send outbound calls to a different one. No problem but you have to know which fields to use:


    Registrar: (on Advanced tab)

    and to receive calls from that server,

    Here’s the whole config for an IP-authenticated outbound only trunk…

Other than dealing with IPv6 and TLS, which many people won’t use, I didn’t really find anything difficult about moving from chan_sip to chan_pjsip. I don’t know how long it’s been the case, but I am happy that by default the extensions are set up for NAT handling. Just wanted to share my experience and “I survived!” even though folks often post about their troubles using the newer SIP driver.


Did you confirm you need “rtp_ipv6”? Recent versions of Asterisk should use the signalling transport IP protocol version to then choose RTP automatically. I worked on it at SIPit ages ago after talking to various other vendors on what they do and how the industry does it.

Thanks, I will test that. I added it because it was noted as a “must” on the Asterisk wiki: https://wiki.asterisk.org/wiki/display/AST/Configuring+res_pjsip+for+IPv6

If after testing it works as expected for you I’ll update the wiki page!

Ah, so you can configure one trunk that works for in and outbound even though the IP addresses of the in and outbound servers are different. Didn’t know that.
Can the same thing be done when using IP authentication and not registration?

Sure, that’s what the Match field is for. Just list all the IPs or subnets that will be sending traffic to you.

Sorry if this is obvious question. I have been using chan_SIP trunk with my chan_SIP extensions. Can I use chan_PJSIP with chan_SIP trunk or do I need to make a chan_PJSIP trunk?

My other question is, I have one DID account with my SIP provider. Can I use that account to build two trunks (chan_SIP and chan_PJSIP)?

Thanks in advance.

Yes. There is nothing preventing you from having both chan_sip and pjsip trunks and extensions in any combination.

Probably not. If you are registering trunks, you must use different credentials for each trunk. If your provider allows you to create sub-accounts, you could probably do this, but I can’t think of any benefit to doing so.

1 Like

Thank you, @lgaetz.

1 Like

I do exactly this with Skyetel. I send calls to term.skyetel.com and in the match field I have all the networks they send calls from.

For those relying on the Match field for pjsip trunks, know that the Firewall module does not whitelist these IPs automatically as is done for the SIP Server. I have an open feature request for this: https://issues.freepbx.org/browse/FREEPBX-18741

Oh, I’d also check whether you actually do need to specify the transport on the endpoint. Asterisk 16 DNS resolution prefers IPv6, so the resolution should result in AAAA records being used and thus the IPv6 transport chosen. If that’s not happening then I can take a gander and see why.

In FreePBX you have to choose a transport for trunk endpoints. Sounds like another feature request: an “auto” choice that omits the transport= line from the endpoint definition.

1 Like

Ah, yeah, in Asterisk it’s not required unless you have multiple competing transports and want to force it. For most people it’ll choose the right one based on the target of the SIP message.

It’s nice that we now have the “config files!” people collaborating with the “web GUI!” people here on the same forum. :smiley:

I just say things. Sometimes people listen, sometimes people do things.

1 Like

Today I found that the WebRTC phone doesn’t work over IPv6, but does work over IPv4. Investigating. I’m mentioning it in this thread because the error generated is:

[2019-10-04 10:01:46] ERROR[29983]: res_pjsip.c:3662 ast_sip_create_dialog_uas: Could not create dialog with endpoint 991101. Invalid URI (PJSIP_EINVALIDURI)

May be due to this issue[1] which has had a fix merged in recently[2].

[1] https://issues.asterisk.org/jira/browse/ASTERISK-28544
[2] https://gerrit.asterisk.org/c/asterisk/+/12986

Might be the same or a fresh new bug:

[2019-10-04 10:33:14] DEBUG[32275]: res_pjsip_transport_websocket.c:448 websocket_on_rx_msg: Request msg INVITE/cseq=9908 (rdata0x7fae503937b8) re-writing Contact URI from ibef549gpid8.invalid:0;transport=wss to [2601:xxx:xxx:xxx:xxx:xxx:xxx:yyy]:55257;transport=ws

I’m suspicious of how ;transport=wss becomes ;transport=ws

That should be okay. That logic is updating the received Contact to enforce connection reuse, and due to the way things work internally being "ws’ is pefectly fine. If it were “wss” it wouldn’t actually work. The spec also states that the transport parameter should be “ws” for URIs[1]. WSS is only valid in the Via header.

[1] https://tools.ietf.org/html/rfc7118#page-6

1 Like