Fix Calls Dropping After 30 Seconds

Why Asterisk calls disconnect after exactly 30 seconds and how to fix NAT, session timer, and ACK delivery issues

The Problem

One of the most frustrating Asterisk issues: calls connect successfully, you hear ringing, the callee answers, but the call disconnects exactly 30-32 seconds later. This is so specific that it almost always points to one of a few well-known causes.

The 30-Second Rule: In SIP, the default Timer B (transaction timeout) is 32 seconds (64 * T1 where T1 = 500ms). When a critical SIP message like ACK cannot be delivered, the call is torn down after this timeout.

Cause 1: SIP ACK Not Reaching Asterisk (NAT)

This is the most common cause. The SIP call flow is: INVITE → 100 Trying → 180 Ringing → 200 OK → ACK. The ACK confirms the call is established. If the ACK cannot reach Asterisk (blocked by NAT/firewall), Asterisk keeps retransmitting the 200 OK. After ~32 seconds, it gives up and terminates the call.

Why NAT Blocks the ACK:

  • The 200 OK is sent from Asterisk's private IP (Contact header has 192.168.x.x)
  • The remote side tries to send ACK to this private IP — which is unreachable
  • The NAT translation entry may have expired between INVITE and ACK

Fix (chan_sip):

[general]
; Tell Asterisk your public IP
externaddr=203.0.113.50
localnet=192.168.1.0/255.255.255.0
localnet=10.0.0.0/255.0.0.0

; NAT traversal settings
nat=force_rport,comedia
directmedia=no

; Per-peer settings
[my-trunk]
type=peer
nat=force_rport,comedia
qualify=yes
directmedia=no

Fix (PJSIP):

[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
external_signaling_address=203.0.113.50
external_media_address=203.0.113.50
local_net=192.168.1.0/24

[my-endpoint]
type=endpoint
force_rport=yes
rewrite_contact=yes
rtp_symmetric=yes
direct_media=no

Cause 2: SIP Session Timers (RFC 4028)

SIP session timers (RFC 4028) are a mechanism to detect dead calls. If one side supports session timers and the other does not respond to re-INVITE/UPDATE refreshes correctly, the call is terminated. This can cause drops at various intervals (often 30 seconds, 90 seconds, or 1800 seconds).

Fix (chan_sip):

[general]
; Option 1: Refuse session timers entirely (simplest fix)
session-timers=refuse

; Option 2: Accept but let remote side refresh
session-timers=accept
session-refresher=uas
session-minse=90
session-expires=1800

Fix (PJSIP):

[my-endpoint]
type=endpoint
; Disable session timers
timers=no

; Or configure with longer intervals:
; timers=yes
; timers_min_se=90
; timers_sess_expires=1800

Cause 3: Qualify/OPTIONS Timeout

When qualify=yes is set, Asterisk sends periodic OPTIONS messages to check if the peer is alive. If the peer does not respond within the qualify timeout (default 2000ms), Asterisk marks it as UNREACHABLE and may terminate active calls.

; chan_sip: increase qualify timeout
[my-peer]
qualify=yes
qualifyfreq=60       ; Check every 60 seconds (default 60)
; qualifytimeout=5000  ; Not available in all versions

; PJSIP:
[my-aor]
type=aor
qualify_frequency=60
qualify_timeout=5.0   ; 5 seconds timeout (default 3.0)
Note: If the peer has high latency (e.g., international trunk), increase the qualify timeout to 5-10 seconds to prevent false UNREACHABLE status.

Cause 4: RTP Timeout (No Media Flowing)

Asterisk can be configured to hang up calls if no RTP (audio) packets are received for a specified time. If the firewall is blocking RTP in one direction, this timeout triggers and the call drops.

; In sip.conf or pjsip.conf endpoint:
; These settings control RTP timeout behavior:

; chan_sip:
[general]
rtptimeout=60        ; Hang up if no RTP for 60 seconds (0=disable)
rtpholdtimeout=300   ; Hang up if no RTP while on hold for 300 seconds
rtpkeepalive=10      ; Send RTP keepalive every 10 seconds

; PJSIP:
[my-endpoint]
type=endpoint
rtp_timeout=60
rtp_timeout_hold=300
rtp_keepalive=10

The rtp_keepalive setting is crucial — it sends comfort noise packets to keep NAT translations alive and prevent RTP paths from being closed by firewalls.

Cause 5: SIP ALG on Router

A SIP Application Layer Gateway (ALG) on the router rewrites SIP messages in transit. It often corrupts the Contact header, Via header, or SDP, causing the ACK to be sent to the wrong address. This is one of the most common and hardest-to-diagnose causes of 30-second call drops.

How to Disable SIP ALG:

# On Linux routers (iptables/netfilter):
modprobe -r nf_nat_sip nf_conntrack_sip
echo "blacklist nf_nat_sip" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nf_conntrack_sip" >> /etc/modprobe.d/blacklist.conf

# On consumer routers:
# Login to router admin panel
# Look for "SIP ALG", "SIP Passthrough", or "SIP Helper"
# DISABLE it
# Reboot the router

# Common router brands:
# - Netgear: Advanced > WAN Setup > Disable SIP ALG
# - TP-Link: Advanced > NAT > ALG > Uncheck SIP
# - Ubiquiti: Services > NAT > Disable SIP module
# - pfSense: System > Advanced > Firewall > Disable pf scrub

Debugging the 30-Second Drop

# Step 1: Enable SIP debug
asterisk -rx "sip set debug on"

# Step 2: Make a test call and watch for:
# - 200 OK being retransmitted (means ACK not received)
# - Look at the Contact header in 200 OK:
#   Contact: <sip:100@192.168.1.100:5060>  <-- BAD (private IP)
#   Contact: <sip:100@203.0.113.50:5060>   <-- GOOD (public IP)

# Step 3: Check for session timer negotiation
# Look for "Session-Expires:" and "Require: timer" headers

# Step 4: Check RTP flow
asterisk -rx "rtp set debug on"
# Look for RTP packets flowing in both directions

# Step 5: Use sngrep for visual SIP ladder diagram
sngrep -d eth0 port 5060

Key Indicators:

SymptomLikely CauseFix
200 OK retransmitted multiple timesACK not reaching AsteriskFix NAT (externaddr, force_rport)
“Session-Expires” in SIP headersSession timer mismatchSet session-timers=refuse
Peer shows UNREACHABLE during callQualify timeout too lowIncrease qualifytimeout
RTP packets flow one way onlyFirewall/NAT blocking return RTPOpen UDP 10000-20000, set comedia
Contact header has wrong IPSIP ALG rewriting packetsDisable SIP ALG on router
← Back to All Asterisk Solutions|Asterisk Complete Guide →