SIP Session Timers (RFC 4028) Deep Dive: Preventing Ghost Calls and Dead Leg Removal
Overview
RFC 4028 defines an essential keepalive mechanism for active SIP dialogs using periodic re-INVITE or UPDATE transactions. Without session timers, unexpected network failures, unhandled NAT drops, or silent endpoint crashes leave orphaned calls open indefinitely on carriers, SBCs, and media servers. This guide explores the negotiation mechanics, header rules, refresher assignment logic, and operational best practices required to ensure robust dead leg removal across VoIP networks.

Key takeaways
- Session timers periodically validate that both SIP endpoints and intermediate stateful proxies are alive during an established call.
- Negotiation uses the Session-Expires and Min-SE headers, establishing a minimum allowable interval and a maximum time before a call is torn down.
- The refresher parameter (uac or uas) explicitly dictates which endpoint must send periodic re-INVITE or UPDATE requests.
- Keepalive messages are sent at half the negotiated expiration interval (SE / 2) to allow retransmission attempts before hard expiration.
- Session timers prevent billing discrepancies, exhausted channel licenses, and memory leaks caused by ghost calls.
Prerequisites
- Fundamental knowledge of SIP call setup and dialog state management (RFC 3261)
- Understanding of SIP proxies, Back-to-Back User Agents (B2BUAs), and Session Border Controllers (SBCs)
- Familiarity with reading raw SIP message traces via Wireshark, sngrep, or Homer
Guide
- section #1
The Anatomy of Ghost Calls and Dead Legs In a standard SIP architecture, a call is established with a 200 OK and ACK, and terminated when one party sends a BYE request. However, real-world IP networks experience silent packet loss, router reboots, physical cable disconnections, and dynamic NAT binding timeouts. When a network connection drops mid-call without producing a BYE message, stateful SIP entities—such as Session Border Controllers (SBCs), core softswitches, and billing engines—remain unaware that the media stream and dialog have ceased. These un-terminated sessions are referred to as 'ghost calls' or 'dead legs'. They consume active channel licenses, hold media processing ports, inflate customer billing, and cause memory retention issues on softswitches unless a proactive keepalive mechanism actively monitors dialog state.
- section #2
RFC 4028 Mechanics and Core Headers RFC 4028 solves the ghost call problem by extending SIP to allow endpoints and proxies to negotiate a session expiration timer. This extension introduces key headers: 'Session-Expires' (specifies the session lifetime in seconds and designates the refresher), 'Min-SE' (defines the absolute minimum session expiration period acceptable to an entity), and option tags 'timer' in 'Supported' or 'Require' headers. When a User Agent Client (UAC) supports session timers, it includes 'Supported: timer' and an optional 'Session-Expires' header in the initial INVITE. Intermediate proxies or the User Agent Server (UAS) can inspect, alter, or require these timers during dialog establishment.
- section #3
Negotiation Logic: Min-SE and Refresher Assignment The negotiation flow enforces bounds to prevent network flooding while allowing flexible role assignment. If a UAC requests a 'Session-Expires' interval that is too small, a receiving proxy or UAS can reject the INVITE with a '422 Session Interval Too Small' response containing a 'Min-SE' header specifying the minimum allowable value (typically 90 seconds). The UAC must then retry with a higher value. During a successful 200 OK response, the UAS returns the final 'Session-Expires' value along with a mandatory 'refresher' parameter ('refresher=uac' or 'refresher=uas'). If the UAS does not support RFC 4028, a timer-aware proxy or the UAC itself can assume responsibility for sending refreshers.
- section #4
SIP Message Exchange Trace Example Below is an annotated trace of an initial INVITE and 200 OK negotiation where the UAC proposes a 1800-second (30-minute) session timer and the UAS accepts, assigning the UAC as the refresher. Periodic refreshes will occur every 900 seconds using UPDATE or re-INVITE requests.
INVITE sip:alice@example.com SIP/2.0 Via: SIP/2.0/UDP 192.168.1.100:5060;branch=z9hG4bK776asdhds From: <sip:bob@example.com>;tag=12345 To: <sip:alice@example.com> Call-ID: c3031200-a012@192.168.1.100 CSeq: 1 INVITE Supported: timer Session-Expires: 1800 Min-SE: 90 Content-Type: application/sdp SIP/2.0 200 OK Via: SIP/2.0/UDP 192.168.1.100:5060;branch=z9hG4bK776asdhds;received=192.168.1.100 From: <sip:bob@example.com>;tag=12345 To: <sip:alice@example.com>;tag=abcde Call-ID: c3031200-a012@192.168.1.100 CSeq: 1 INVITE Require: timer Session-Expires: 1800;refresher=uac Content-Type: application/sdp - section #5
Keepalive Timing and Dead Leg Teardown Rules To prevent accidental call teardown due to transient network delay or packet loss, RFC 4028 dictates that the active refresher MUST send a session refresh request (preferably UPDATE, or re-INVITE if UPDATE is unsupported) at half the negotiated expiration interval ($SE / 2$). For example, if $SE = 1800$, the refresher sends an UPDATE at 900 seconds. If the refresher fails to send a refresh request or receives no 2xx response before $SE$ seconds elapses, both sides—and any monitoring stateful proxies—MUST consider the session expired and immediately terminate the dialog by sending a BYE or internal tear-down signal.
- section #6
Configuring Session Timers in Asterisk (pjsip.conf) Modern Asterisk instances using chan_pjsip allow administrators to fine-tune session timer behavior per endpoint or globally. The configuration options control whether session timers are forced, preferred, or disabled, as well as setting custom Min-SE and Session-Expires values.
; pjsip.conf endpoint configuration example [carrier-trunk] type=endpoint context=from-carrier disallow=all allow=ulaw,alaw ; Enable RFC 4028 Session Timers timer=yes timer_min_se=90 timer_sess_expires=1800 ; Options for timer_refresher: uac, uas, or auto timer_refresher=auto ; Preference when negotiating session timers: accept, prefer, required, forced ; 'forced' requires all incoming call legs to enforce session timers session_timers=accept - section #7
Session Timers in Kamailio / OpenSIPS Proxies SIP proxies operating as stateful dialog managers (such as Kamailio or OpenSIPS) can enforce session timers on behalf of uncooperative endpoints. Using Kamailio's `dialog` and `sst` (SIP Session Timer) modules, the proxy can inspect incoming requests, insert `Session-Expires` headers if missing, and monitor whether refreshes arrive in time. If a endpoint crashes and stops sending refreshes, the proxy's dialog module reaches its timeout and generates internal BYE messages sent in both directions to cleanly tear down media paths on downstream SBCs and carriers.
- section #8
Best Practices, Common Pitfalls, and Interoperability When implementing session timers, set reasonable values based on network infrastructure; setting `Session-Expires` too low (e.g., 90 seconds) creates unnecessary SIP signaling load on core switches, whereas setting it too high (e.g., 7200 seconds) leaves ghost calls alive for hours. Always prefer UPDATE over re-INVITE for refreshes because UPDATE does not require SDP re-negotiation, reducing CPU overhead and avoiding unintended media glare conditions (RFC 3311). Lastly, ensure that stateful firewalls and NAT routers have UDP timeouts aligned with or greater than half the session timer interval to prevent mid-call firewall pinhole closure.
Further reading
- RFC 4028: Session Timers in the Session Initiation Protocol (SIP)
- RFC 3261: SIP: Session Initiation Protocol
- RFC 3311: The Session Initiation Protocol (SIP) UPDATE Method
- Asterisk PJSIP Endpoint Configuration Reference