freeswitch
freeswitch copied to clipboard
Stuck calls on inbound 'parked' voice call leg
Description of the problem Termination of the client (accidentally or due to a local failure) who is the originator of the inbound 'parked' (but not answered) voice call leg causes the call to get stuck, consequently leading to call/channel allocated resources leaking and eventually possible termination of service and catastrophic failure of the FreeSWITCH. Voice service which is the most prone to the failure scenario described above is the WebRTC voice call originated by the browser and 'parked' on the FreeSWITCH side based on the dialplan instructions. UAC on the browser side sends an INVITE, which gets processed by the FreeSWITCH and FreeSWITCH replies with SIP/2.0 100 Trying. Since, based on the SIP spec, the timer to terminate the 'stuck' call is on the client side, if the user will accidentally close the browser - the call on the FreeSWITCH side gets stuck, consequently tieing all the allocated resources indefinitely. Looks like a vulnerability for a 'perfect' DoS attack. I sample SIP trace plus debug console output of the FreeSWITCH for the call which demonstrates such failure scenario is attached. In this case, SIPP has been used to generate the call.
To Reproduce There are multiple ways to reproduce the problem:
Using WebRTC client
- Originate inbound WebRTC call using the browser.
- Get the call 'parked' by the FreeSWITCH by dialplan instructions. For example (I had to strip xml tags)
extension name="park and await instructions"
condition field="${direction}" expression="^inbound$"
action application="park"
condition
extension
- Quit the browser once FreeSWITCH replies with '100 Trying' to the INVITE from the client.
- Observe that call on the FreeSWITCH gets stuck using 'show calls' and 'show channels' commands.
Using SIPP client
The same failure scenario described above can be achieved using the SIPP client and basic UAC script. Sample uac.xml file attached (with .txt extension for upload compatibility). In the case of the SIPP client there is no need to quit or terminate anything observe the failure of stuck calls.
Expected behavior Interestingly enough, the observed behavior is the expected one, based on the SIP spec. But, since it's a clear vulnerability issue, which potentially can easily lead to the denial of service and catastrophic failure - it should be addressed.
Package version or git hash HEAD of the master branch
Trace logs Attached.
backtrace from core file N/A
@figaro2015 If you uuid_kill <uuid> then show calls, is the same uuid there?
Killing those stuck calls is not an issue. uuid_kill, hupall, or anything else will work fine and terminate them. Isn't the problem that terminating them requires intervention from the console.
Can you provide the output from a gcore thread apply all bt ?
One theory is you have MEDIA_TIMEOUT set to a high value and the calls dont end until that value is reached
Since the SIP session hasn't been established yet the MEDIA_TIMEOUT timer hasn't been armed yet. The call is 'parked' on the server: the client sent INVITE and the server only replied with 100 Trying. In this particular case, the timeout to break the call and release resources is on the client side. But the client is gone (for example browser which originated WebRTC call got closed, accidentally). This issue is not really a bug in the code, but rather an architecture/design issue.