Diagnose one-way audio in the order sipnab ranks the causes
Steps to work through a one-way audio complaint with sipnab: what the capture missed, network error reports, NAT, STUN and TURN relays, and finally a call set up to send audio one way.
In short
“One-way audio” means one person on a call can hear the other. The other person cannot hear them. Several different faults cause it:
- a network device rejecting the audio,
- an address rewritten by a router,
- a relay server that stopped forwarding,
- a call set up to carry audio in one direction only.
sipnab’s --analyze report lists the problems it finds in a recorded call.
The most serious come first. This how-to follows that order. It is also the
order of the troubleshooting guide.
Who this is for
Anyone handling a one-way audio complaint who has a packet capture (pcap file) of the call.
Know the order of the checks
Work through the causes in this order:
- What sipnab could not read.
--analyzelists theseBLINDfindings above every other finding.
- ICMP errors against the audio.
- An ICMP error is a message a router or host sends back when it cannot deliver a packet.
--analyzeratesICMP: media undeliverableas critical.
- NAT.
- NAT (network address translation) is the router function that rewrites private addresses into public ones.
--analyzeratesRTP source no SDP advertisedas major.
- STUN and TURN.
- STUN lets a phone learn its public address.
- TURN relays audio through a server.
--analyzerates an unanswered STUN request and a lapsed TURN allocation as major. It rates an SDP address that STUN contradicts as critical.
- The call’s own setup, comfort noise and codecs.
- The one-way finding rests only on the audio packets seen in each direction.
- It does not read the audio direction the call’s SDP asked for.
- So a call set up to send audio one way is also reported as one-way audio.
Within one severity level, --analyze lists first the finding that occurred
most often.
The captures used below ship in the sipnab repository.
-qhides informational log lines.--no-cli-printsuppresses the per-message output.- The output below has the trailing spaces at the ends of table lines removed.
Steps
- Run the analysis and read it from the top:
sipnab -N -q -I tests/fixtures/stun_sdp_mismatch.pcap --analyze --no-cli-print
Capture analysis: 4 finding(s) across 1 dialog(s), 2 stream(s), 69 frame(s) read.
1. [CRITICAL] One-way audio — 1 call(s)
RTP flowed in one direction only: one party heard the other and was not heard back. The usual causes are a NAT that never opened the return pinhole, an SDP advertising an address the far end cannot route to, or a firewall dropping inbound media.
Evidence:
- Call-ID stun-sdp-mismatch-1@192.168.10.50 | 192.168.10.50:5060 -> 198.51.100.30, SDP 198.51.100.30, RTP from 203.0.113.7 | 2023-11-14 22:13:21.000 UTC | rtp_packets=60 streams=2 | 203.0.113.7:41000 -> 192.168.10.50:40000 carried 30 packet(s); nothing came back the other way
2. [CRITICAL] SDP advertises an address STUN contradicts — 1 call(s)
The client's SDP names an address that STUN is on record either replacing with a different, reachable one, allocating on a TURN relay, or never answering about at all: the far end is sending media to an address that cannot receive it. Where the STUN exchange and the call coincide this is the cause of one-way audio rather than an inference from it; evidence seen well outside the call is matched by client IP alone and says so in its notes.
Evidence:
- Call-ID stun-sdp-mismatch-1@192.168.10.50 | 192.168.10.50:5060 -> 198.51.100.30, STUN client 192.168.10.50:5060, SDP advertises 192.168.10.50 | 2023-11-14 22:13:21.000 UTC | stun_requests=2 | 2 request(s) drew no STUN response, so the client never learned a public address and advertised 192.168.10.50
3. [MAJOR] RTP source no SDP advertised — 1 call(s)
Media arrived from an address that no SDP in the dialog named — the signature of a NAT rewriting the media source. Frequently benign on its own (symmetric RTP through a NAT looks exactly like this); read it together with any one-way audio on the same call.
Evidence:
- Call-ID stun-sdp-mismatch-1@192.168.10.50 | 192.168.10.50:5060 -> 198.51.100.30, SDP 198.51.100.30, RTP from 203.0.113.7 | 2023-11-14 22:13:21.000 UTC | rtp_packets=60 streams=2
4. [MAJOR] STUN Binding Request unanswered — 1 transaction(s)
A client asked a STUN server what its public address was and nothing came back, so it never learned one and will advertise its private address in any SDP it later sends. RFC 5389 §7.2.1 retransmits only on timeout, so a repeated request is itself proof the earlier ones drew silence.
Evidence:
- client 192.168.10.50:5060, server 198.51.100.20:3478 | 2023-11-14 22:13:20.000 UTC | requests=2 | retransmitted, which by itself proves the first request went unanswered
On this capture all four findings concern one call:
-
The phone’s STUN requests got no answer (finding 4).
-
So it put its private address 192.168.10.50 in its SDP (finding 2).
-
Its audio reached the far side from a different address (finding 3).
-
If the report starts with a BLIND finding, fix the capture or the options before reading anything else.
- Every count below it is a lower bound.
- This run deliberately restricts the SIP ports to 5070 on a capture whose SIP uses 5060.
2>/dev/nulldiscards two warning lines that repeat the same fact:
sipnab -N -q -I tests/pcap-samples/sip-rtp-g711.pcap --analyze --no-cli-print --portrange 5070-5070 2>/dev/null
Capture analysis: 1 finding(s) across 0 dialog(s), 0 stream(s), 852 frame(s) read.
THIS ANALYSIS IS INCOMPLETE — sipnab did not read all of this capture. The findings below describe what it UNDERSTOOD, so their counts are floors and the ABSENCE of a finding is not evidence that the problem is absent. The blind finding(s) are listed first.
1. [BLIND] SIP discarded by --portrange — 10 message(s)
sipnab recognized these as SIP and then threw them away because neither port was inside --portrange. They are in no dialog and no count. Widen the range (--portrange 1-65535 analyzes everything) and read the capture again.
Evidence:
- port 5060 | messages=10
-
Look for an ICMP finding against the audio.
- None of the captures in the repository contains one. So this step shows no output.
- The troubleshooting guide’s section “First: check whether the network already answered” shows what sipnab prints.
- Such a finding names the address and port that rejected the audio. It also names the device that reported it.
-
Check NAT.
--nat-issuesselects calls whose audio arrived from an address that no SDP in the call advertised:
sipnab -N -q -I tests/fixtures/stun_sdp_mismatch.pcap --nat-issues --report --no-cli-print
Call-ID From To State Code Duration Msgs PDD Tags
-------------------------------------------------------------------------------------------------------------------------
stun-sdp-mismatch-1@192.168... alice bob Completed 200 7s 7 0.2s -
RTP Streams:
SSRC PT Codec Clock Source Destination Pkts Lost Loss% Jitter Dur Kbps
--------------------------------------------------------------------------------------------------------------------------
0x11223344 0 PCMU 8000 192.168.10.50:40000 198.51.100.30:41000 30 0 0.0% 0ms 1s 66
0x55667788 0 PCMU 8000 203.0.113.7:41000 192.168.10.50:40000 30 0 0.0% 0ms 1s 66
A NAT match on its own can be normal. Read it together with a one-way finding on the same call. Finding 3 in the first step says this.
- Check STUN and TURN.
- Unanswered STUN requests already appear in the analysis (first step, finding 4).
- For a call that went silent partway through, check whether a TURN relay allocation expired.
- A TURN server grants an allocation for a lifetime.
- It removes the allocation if the phone does not renew (Refresh) it in time.
- That stops the relayed audio with no SIP message:
sipnab -N -q -I tests/fixtures/turn_relay.pcap --stun --no-cli-print
STUN Transactions (7 packet(s), 3 transaction(s)):
Transaction Method Client Server Reqs Response RTT Mapped Address Relayed Address
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
2b3c4d5e6f708192a3b4c5d6 Allocate 192.0.2.10:50000 198.51.100.20:3478 1 success 12.0ms 203.0.113.5:12262 198.51.100.77:49160
112233445566778899aabbcc CreatePermission 192.0.2.10:50000 198.51.100.20:3478 1 success 8.0ms - -
0102030405060708090a0b0c ChannelBind 192.0.2.10:50000 198.51.100.20:3478 1 success 8.0ms - -
TURN Allocations (1):
Client Server Relayed Address Lifetime Refreshes Status
---------------------------------------------------------------------------------------------------
192.0.2.10:50000 198.51.100.20:3478 198.51.100.77:49160 60s 0 LAPSED
152 relayed ChannelData frame(s), 25864 byte(s) of application data, crossed these allocations. Those bytes are also analyzed as ordinary media: the frame is unwrapped and the RTP inside it reaches the stream store, so a relayed call appears in the stream list rather than as a call with no media.
192.0.2.10:50000 -> 198.51.100.20:3478: 152 frame(s) on channel 0x4001, carrying 2 stream(s) (SSRC 0x11223344, 0x55667788)
channel 0x4001 is bound to peer 203.0.113.9:16000
1 allocation(s) were still carrying traffic after the lifetime they were last granted had run out, with no Refresh seen in between. A TURN server tears an allocation down when its lifetime lapses, and the relayed media stops with it — mid-call, with no SIP message to say why.
192.0.2.10:50000 -> 198.51.100.20:3478: 60s lifetime, 0 refresh(es) seen, traffic continued 1s past expiry
media on it: 152 frame(s) on channel 0x4001, carrying 2 stream(s) (SSRC 0x11223344, 0x55667788)
LAPSED marks the allocation that ran past its lifetime. sipnab reports
that it saw no Refresh. That can also mean the capture missed it.
- If none of the above applies, check whether the endpoints set the call up
to send audio one way.
tests/pcap-samples/sip-rtp-g711.pcapholds two calls that--analyzereports as one-way audio:
sipnab -N -q -I tests/pcap-samples/sip-rtp-g711.pcap --analyze --no-cli-print
Capture analysis: 1 finding(s) across 2 dialog(s), 2 stream(s), 852 frame(s) read.
1. [CRITICAL] One-way audio — 2 call(s)
RTP flowed in one direction only: one party heard the other and was not heard back. The usual causes are a NAT that never opened the return pinhole, an SDP advertising an address the far end cannot route to, or a firewall dropping inbound media.
Evidence:
- Call-ID 1-1966@10.0.2.20 | 10.0.2.20:5060 -> 10.0.2.15, SDP 10.0.2.20 | 2016-11-26 14:52:59.666 UTC | rtp_packets=425 streams=1 | 10.0.2.15:27942 -> 10.0.2.20:6000 carried 425 packet(s); nothing came back the other way
- Call-ID 1-1968@10.0.2.20 | 10.0.2.20:5060 -> 10.0.2.15, SDP 10.0.2.20 | 2016-11-26 14:53:08.286 UTC | rtp_packets=414 streams=1 | 10.0.2.15:28102 -> 10.0.2.20:6000 carried 414 packet(s); nothing came back the other way
--nat-issues selects neither call on this capture. Select the one-way
calls whose SIP messages contain an SDP direction other than sendrecv
(two-way):
sipnab -N -q -I tests/pcap-samples/sip-rtp-g711.pcap --filter "one_way == true AND payload =~ 'a=(sendonly|recvonly|inactive)'" --report --no-cli-print
Call-ID From To State Code Duration Msgs PDD Tags
-------------------------------------------------------------------------------------------------------------------------
1-1966@10.0.2.20 sipp test Completed 200 8s 6 - -
1-1968@10.0.2.20 sipp test InCall 200 0s 4 - -
RTP Streams:
SSRC PT Codec Clock Source Destination Pkts Lost Loss% Jitter Dur Kbps
--------------------------------------------------------------------------------------------------------------------------
0x343da99b 0 PCMU 8000 10.0.2.15:27942 10.0.2.20:6000 425 0 0.0% 0ms 8s 64
0x343ffa34 8 PCMA 8000 10.0.2.15:28102 10.0.2.20:6000 414 0 0.0% 0ms 8s 64
In both calls:
- The INVITE’s SDP carries
a=recvonly. - The
200 OK’s SDP carriesa=sendonly. - Both ends agreed that audio flows one way, and it did.
The MCP tool get_sdp_timeline shows the same thing per offer and answer.
On call 1-1966@10.0.2.20 it shows "mode":"recvonly" for the offer and
"mode":"sendonly" for the answer.
The payload field matches any message in the call. So a call put on hold
with a re-INVITE also matches this filter. Read the matching messages before
concluding.
- Check comfort noise and codecs last.
- Some trunks send comfort noise (generated background noise) instead of
audio during silence.
- sipnab does not report one-way audio when comfort noise exceeds a share of a call’s packets.
--cn-suppression-ratiosets that share. The default is 0.3.- Raising it can hide real one-way calls. Lowering it reports more.
sip-rtp-g711.pcapcarries no comfort noise. On it,--cn-suppression-ratio 0.5produces output identical to the previous step.
- The MCP tool
check_codec_negotiationlists the codecsoffered,answeredandcommonto both.- For call
1-1966@10.0.2.20,commonholds PCMU. - So the two ends shared a codec.
- For call
- Some trunks send comfort noise (generated background noise) instead of
audio during silence.
Terms used here
- SIP: the protocol that sets up, changes and ends phone calls over IP.
- SDP: the part of a SIP message that describes the audio: address, port,
codecs and direction (
sendrecv,sendonly,recvonly,inactive). - Offer / answer: the SDP one side proposes and the SDP the other side
replies with; in the captures above, the INVITE and the
200 OK. - RTP: the protocol that carries the audio packets.
- Stream: the RTP packets sent in one direction, identified by an SSRC number.
- Dialog: one SIP conversation, such as one call.
- pcap: a file format for recorded network traffic.
- ICMP error: a message a router or host sends back when it cannot deliver a packet.
- NAT: network address translation, which rewrites private addresses into public ones at a router.
- STUN: a protocol a phone uses to ask a server which public address it appears from.
- TURN: a protocol for relaying audio through a server; an allocation is the relay address the server grants for a limited lifetime.
- Comfort noise: low-level generated noise sent instead of audio during silence.
- Codec: the audio encoding, such as PCMU (G.711 µ-law).
- MCP: Model Context Protocol, the interface AI assistants use to call sipnab’s tools.
Related guides
- Troubleshooting: one-way audio
- First: check whether the network already answered
- NAT traversal issues
- NAT discovery went unanswered
- A relayed call that went quiet halfway through
- Cookbook 4. Diagnose a one-way audio complaint and 45. Check whether comfort noise explains a one-way finding
- STUN / TURN JSON (
--json-stun) get_sdp_timelineandcheck_codec_negotiation