SOLVED auto-select correct transport/media_address for extension

silimms

New Member
Joined
Feb 18, 2016
Messages
27
Reaction score
1
Environment:

IncrediblePBX (FreePBX) / Asterisk 22.11.0, chan_pjsip
Server with multiple network interfaces:
192.168.22.209 (eth0) — external-facing NIC, port forwarding for remote/roaming extensions + IAX2
192.168.23.209 (eth1) — internal VLAN, all internal phones live here (isolated, no internet access by design)
10.0.10.10 — SIP trunk Providers
All PJSIP UDP transports bound on port 7666 (per-IP)
SIP trunk Providers on 5060

Problem:

I have a multi-homed FreePBX / Asterisk (chan_pjsip) server. When an extension's transport is left empty, Asterisk auto-selects a transport and, in this multi-homed setup, often picks the wrong one. As a result the media_address ends up as the wrong interface IP — e.g. a phone registered from 192.168.23.69 gets media_address = 192.168.22.209.

What I've found works (but only per-extension):

I've found two ways to fix it, but each one has to be done per extension:

Option 1 — edit pjsip.endpoint_custom_post.conf:

[<extension number>](+)
media_address=192.168.23.9

Option 2 — modify the extension (GUI Advanced tab):

transport = 192.168.23.209-udp (the correct interface)
media_use_received_transport = yes

My question:

Is there a way to make this happen globally / automatically for all extensions, instead of editing every single extension (via the GUI Advanced tab or pjsip.endpoint_custom_post.conf)?
 
Yes, one line per transport, no per-extension edits. What you are fighting is how "Auto" behaves in 22.11: when the endpoint has no transport, a PBX-originated request (INVITE, OPTIONS) is sent on whichever UDP transport pjsip finds first, not on the one the phone registered through. Responses to the phone's own INVITEs already go back on the arrival transport, which is why it only "often" fails.


The global fix is the transport option symmetric_transport. With it set, every request that arrives on that transport gets the transport name stored in the contact URI as an x-ast-txp parameter at registration, and any later outgoing request to that contact uses the same transport as long as the endpoint's transport is empty and the contact host is an IP. FreePBX includes pjsip.transports_custom_post.conf immediately after its generated transports, so append it there once:


192.168.22.209-udp symmetric_transport=yes


192.168.23.209-udp symmetric_transport=yes


10.0.10.10-udp symmetric_transport=yes


Use your actual transport section names from pjsip show transports. Reload and make the phones re-register, since the tag is written at REGISTER time. pjsip show contacts should then show x-ast-txp=192.168.23.209-udp on the internal phones, with the endpoint's Transport still on Auto.


For the media address, leave it blank on every extension. Without media_address the SDP is first built with the host's default address and the outbound filter rewrites the c= line to the interface the OS routes to that phone, keeping port 7666; RTP is bound to 0.0.0.0 so it receives on any interface. Setting media_address per extension is what switches that rewrite off. Two things must be true for it to hold: Local Networks in SIP Settings lists all three subnets (192.168.22.0/24, 192.168.23.0/24, 10.0.10.0/24) so the External Address rewrite never applies to an internal destination, and the routing table sends each phone subnet out of the right interface, with static routes via eth1 if any internal phones sit behind the VLAN router rather than on 192.168.23.0/24.


Your Option 2 works because of the transport line; media_use_received_transport is about honouring the RTP profile from the offer, not interfaces, so drop it.


If after this an internal phone still gets c=192.168.22.209, post the startup line "Local IPv4 address determined to be" and the output of pjsip show transport 192.168.23.209-udp, and it becomes a two-line answer.
 
You can set a default transport per endpoint group using the transport parameter in a template that all extensions inherit from. In FreePBX that usually means editing the endpoint template rather than each extension individually.
 
Environment:

IncrediblePBX (FreePBX) / Asterisk 22.11.0, chan_pjsip
Server with multiple network interfaces:
192.168.22.209 (eth0) — external-facing NIC, port forwarding for remote/roaming extensions + IAX2
192.168.23.209 (eth1) — internal VLAN, all internal phones live here (isolated, no internet access by design)
10.0.10.10 — SIP trunk Providers
All PJSIP UDP transports bound on port 7666 (per-IP)
SIP trunk Providers on 5060

Problem:

I have a multi-homed FreePBX / Asterisk (chan_pjsip) server. When an extension's transport is left empty, Asterisk auto-selects a transport and, in this multi-homed setup, often picks the wrong one. As a result the media_address ends up as the wrong interface IP — e.g. a phone registered from 192.168.23.69 gets media_address = 192.168.22.209.

What I've found works (but only per-extension):

I've found two ways to fix it, but each one has to be done per extension:

Option 1 — edit pjsip.endpoint_custom_post.conf:

[<extension number>](+)
media_address=192.168.23.9

Option 2 — modify the extension (GUI Advanced tab):

transport = 192.168.23.209-udp (the correct interface)
media_use_received_transport = yes

My question:

Is there a way to make this happen globally / automatically for all extensions, instead of editing every single extension (via the GUI Advanced tab or pjsip.endpoint_custom_post.conf)?
Following your method, we still had some calls with no audio. In the end, the fix was:

Modify pjsip.transports_custom_post.conf as follows:

[10.0.10.10-udp]
type=transport
protocol=udp
bind=10.0.10.10:5060
allow_reload=no
symmetric_transport=yes

Then in SIP Settings, just select udp-0.0.0.0 - All and fill in the External IP Address and Port to Listen On.

But the extension’s phone also needs NAT specifically enabled.
 
Glad it is stable. One thing worth pinning down so it survives the next upgrade: what you fixed at the end was the media path, not the transport. symmetric_transport settles which transport SIP leaves on and nothing in the SDP, so it was never going to touch the no-audio on its own.

The 0.0.0.0-All plus External IP plus per-phone NAT works, but by latching rather than by correcting the address. NAT on a chan_pjsip endpoint turns on rtp_symmetric, force_rport and rewrite_contact; rtp_symmetric makes Asterisk send RTP back to wherever the phone's RTP actually arrives from, so it overrides the wrong c= instead of fixing it. The limit is that it only latches after the first inbound packet, so anything that has to go out before the phone sends RTP, ringback or an announcement on early media, or a listen-only leg, can clip or stay silent until that packet lands.

The version without the per-phone NAT is the localnet route from earlier: keep the per-interface transports instead of 0.0.0.0-All, and the c= comes out right on its own, with no latch to carry it.

Quickest way to tell which one you are on:
rtp set debug on
place a call, and compare the c= Asterisk offers with where the RTP actually flows. Right with NAT off means the address is correct; right only with NAT on means it is still wrong and rtp_symmetric is covering for it.
 

Forum statistics

Threads
26,859
Messages
175,614
Members
20,397
Latest member
RaySugar
Get 3CX - Absolutely Free!

Link up your team and customers Phone System Live Chat Video Conferencing

Hosted or Self-managed. Up to 10 users free forever. No credit card. Try risk free.

3CX
A 3CX Account with that email already exists. You will be redirected to the Customer Portal to sign in or reset your password if you've forgotten it.
Back
Top