feat(proxy): negotiate SDES-SRTP on SIP legs (secure in -> secure out)#226
Merged
Conversation
The proxy media layer only ever selected a binary WebRTC-vs-RTP transport, so an inbound SDES-SRTP offer (RTP/SAVP + a=crypto, e.g. a Twilio Elastic SIP Trunk with Secure Media) was answered with plain RTP/AVP. The trunk rejects the downgraded answer and tears the call down immediately after it is answered, while the callee leg stays up. Introduce a three-way transport selection on the anchored/media-proxy path: - sdp_transport_mode(): classify a peer SDP as WebRtc (ICE+DTLS), Srtp (RTP/SAVP or a=crypto, no DTLS), or plain Rtp. - caller_transport_mode(): answer the caller (UAS) leg with a profile that matches its offer, so an RTP/SAVP offer is answered with RTP/SAVP. - callee_transport_mode(): for SIP callees, mirror SDES-SRTP from the caller leg so anchored SIP<->SIP media stays encrypted end to end; WebRTC and plain-RTP calls are unchanged. build_rtp_track_builder now takes a rustrtc::TransportMode and applies it (SDES-SRTP reuses the plain-RTP port range). Leg transport metadata is set from the same helpers. Adds unit coverage for the SDP classification. Requires rustrtc with the SDES-SRTP RTP/SAVP profile fix (restsend/rustrtc#31). Co-authored-by: Claude <noreply@anthropic.com>
ce65772 to
4f479c4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The proxy media layer selects a binary WebRTC-vs-RTP transport for each leg. There is no path that picks SDES-SRTP, so an inbound SDES-SRTP offer (
m=audio … RTP/SAVP+a=crypto, e.g. a Twilio Elastic SIP Trunk with Secure Media enabled) is answered with plainRTP/AVPand no crypto.That is an invalid answer — you can't downgrade an
RTP/SAVPoffer toRTP/AVP— so the trunk drops its leg immediately after the call is answered while the callee leg stays up. Observed against Twilio:Change
Introduce a three-way transport selection on the anchored /
media_proxypath:sdp_transport_mode(sdp)— classify a peer SDP asWebRtc(ICE + DTLS),Srtp(RTP/SAVPprofile or ana=cryptoline, without DTLS), or plainRtp.caller_transport_mode()— answer the caller (UAS) leg with a profile that matches its offer, so anRTP/SAVPoffer is answered withRTP/SAVP+a=crypto.callee_transport_mode(callee_is_webrtc)— for SIP callees, mirror SDES-SRTP from the caller leg ("secure in → secure out") so anchored SIP↔SIP media stays encrypted end to end. WebRTC and plain-RTP calls are unchanged.build_rtp_track_buildernow takes arustrtc::TransportModeand applies it viawith_mode(SDES-SRTP reuses the plain-RTP port range, not the WebRTC range). Leg transport metadata (set_transport) is populated from the same helpers; the existing WebRTC↔RTP media-bridge/transcoding path is intentionally left untouched.Tests
test_sdp_transport_mode_classification(plain RTP,RTP/SAVP, crypto-only, and WebRTC precedence).proxy::proxy_call::sip_session::tests(78) andmedia::(318) suites pass; no behavioral change for WebRTC or plain-RTP calls.Dependency
Requires rustrtc to actually emit a valid SDES-SRTP offer/answer (
RTP/SAVPprofile, no DTLS attributes). That fix is restsend/rustrtc#31; this PR should land after a rustrtc release containing it (then bump therustrtcdependency). Verified locally by patchingrustrtcto that branch.Validation status
Built and unit-tested locally against the patched rustrtc. Live end-to-end validation against a Twilio trunk with Secure Media is still recommended before release.