Registration succeeding tells you almost nothing about audio. A softphone can hold a valid binding with the office PBX for hours and still deliver silence. The tunnel carries only the packets someone deliberately sends into it, and a call uses three separate paths: binding, dialog setup, and the RTP stream. Once you split those apart, the failure lands on one path instead of on the word VPN.

Picture a laptop on home Wi-Fi dialing an office extension through an approved tunnel. The PBX authenticates the user, accepts the REGISTER, and the extension shows as available, yet the call connects with dead air in one direction.

Registration binds a contact, not a media path

A REGISTER request asks the registrar to store a mapping between an address-of-record and one or more contact URIs. That mapping answers a narrow question about where a new dialog should be sent right now. It says nothing about where media belongs, and an accepted registration does not prove that a later INVITE carries a reachable media address. Registrations also expire on a timer, so a phone that stops refreshing loses incoming calls while its tunnel still looks healthy. Watch the contact expiry rather than the tunnel status.

When the softphone sits behind the tunnel, the contact header may carry a private address. A PBX that forwards it to another endpoint creates a dialog aimed at a network the callee cannot reach. Setting rewrite_contact=yes on the PJSIP endpoint makes the PBX substitute the source address it observed, which is often the difference between a ring and a timeout.

What the INVITE offers and who can use it

An INVITE with an SDP body proposes where the caller wants to receive media: an address, a port, and a codec list. The callee answers with its own address and port, and each side then sends RTP to what the other proposed. If the caller proposed a 192.168.x.x address that exists only inside its home network, the callee has nowhere to send audio no matter how clean the signaling was. Masquerading rewrites IP headers as packets leave a router, but it never rewrites the text inside an SDP body.

That gap explains the classic one-way call: signaling works because both endpoints can reach the PBX, and audio fails because one endpoint was told to send to an address that only exists behind a different NAT.

PathWho picks the addressTypical failure
REGISTERSoftphone, rewritten by the registrar if configuredBinding expires or points at a private address
INVITE and SDPEach endpoint in its own offer or answerOffer names a media address nobody can route to
RTPPBX relay policy or the two endpointsPort range blocked, or no return path

Who carries the audio is a configuration choice

Signaling and media are separate roles. A proxy can stay on the signaling path for an entire call and never touch a single RTP packet. Whether the PBX becomes a media relay depends on configuration, not on the presence of a tunnel.

With direct media the endpoints exchange RTP themselves, which works well on one LAN and badly when one side sits behind a narrow port range.

Setting direct_media=no forces the PBX into the media path so both legs terminate on an address it controls, trading bandwidth and CPU for predictable addressing. When it relays, the PBX still has to advertise a reachable address. On a multi-homed host, external_media_address and external_signaling_address in pjsip.conf decide what appears in SDP and in Via headers. Leave them unset and the PBX may offer its LAN address to a caller whose only route is the tunnel's far side.

Trace each direction before touching settings

Start with the socket table on the PBX while a call is up: ss -uanp | grep -E '5060|10000' shows whether RTP ports are bound and which local address they use. If nothing is bound in the media range, the relay is not engaged and the endpoints are talking directly. Then capture on the softphone side with tcpdump -ni any -s0 udp portrange 10000-20000 -w rtp.pcap. Outbound packets with no inbound packets narrow the problem to the return path or to the address the far end was told to use, and an empty capture means media never reached the tunnel interface at all. A signaling capture with sngrep answers the other half by showing the SDP connection line as sent.

Compare the address in that connection line with the address the far end can actually route to. That one comparison resolves most one-way audio reports faster than any configuration review.

Encryption stops at the tunnel edge

SIP over TLS protects the signaling hop it was configured for, SRTP protects media when both ends negotiate it, and the tunnel protects traffic between its own endpoints. None of those grants the others. A call that is encrypted inside the tunnel can leave the gateway in cleartext toward the PBX, which is a design decision rather than a defect.

Before closing the ticket, confirm three things in order: the registration is fresh, the SDP carries an address the far end can reach, and packets flow both ways on the media ports. If any of those is false, the tunnel is not where the problem lives. Fix the path that failed, then re-run the same capture to confirm the change. Keeping the captures from before and after makes the next one-way report a five-minute check instead of an afternoon.

Makomi ya ndenge moko