NAT traversal is one of the hardest problems in SIP deployments. Kamailio uses RTPEngine (formerly RTPProxy) as a media proxy to anchor RTP streams and handle NAT. Here's how to configure it correctly and troubleshoot media path issues.
RTPEngine is a high-performance media proxy that Kamailio uses to anchor RTP streams. When endpoints behind NAT advertise private IP addresses in their SDP, RTPEngine rewrites the SDP to point to itself, proxies the media, and relays it to the correct endpoint. The underlying technique is described in symmetric RTP and latching.
RTPEngine advantages over RTPProxy: kernel-space packet forwarding (much higher performance), native SRTP support and transcoding, ICE support for WebRTC interworking, and active development. RTPProxy is deprecated for most use cases.
The key flags: replace-origin rewrites the SDP o= line, replace-session-connection rewrites the c= line. Both are needed to fix private IP addresses in the SDP.
No audio after rtpengine rewrite: Check that RTPEngine is running and reachable from Kamailio. Use rtpengine-ctl list to see active sessions. If sessions are created but no audio flows, check firewall rules — the RTP port range (10000-20000) must be open.
One way audio after rewrite: Usually means only the INVITE SDP was rewritten but not the 200 OK SDP. Verify your onreply_route calls rtpengine_manage() for 1xx and 2xx responses.
Check RTPEngine logs:
BYE not deleting RTPEngine session: Ensure rtpengine_delete() is called for BYE requests. Orphaned sessions accumulate and eventually exhaust the port pool.
RTPEngine is a high-performance media proxy used with Kamailio for NAT traversal. It rewrites SDP connection addresses, proxies RTP streams between endpoints, and handles SRTP transcoding and WebRTC-to-SIP bridging. It replaces the older RTPProxy with kernel-space packet forwarding for much better performance at scale.
One way audio with RTPEngine usually means the SDP was only rewritten in the INVITE but not in the 200 OK response. Verify your onreply_route calls rtpengine_manage() for all 1xx and 2xx responses. Also check that RTPEngine firewall ports 10000-20000 are open bidirectionally.
Use rtpengine_manage() with flags: ICE=remove DTLS=off SDES-off replace-origin replace-session-connection. This strips ICE candidates and converts DTLS-SRTP to plain RTP (or SDES-SRTP) for the SIP side. RTPEngine handles the media transcoding between the WebRTC and SIP legs.
Paste your Kamailio SIP trace into SIPSymposium. The analyzer checks SDP rewriting, detects private IPs in connection addresses, and identifies RTPEngine session failures.