[asterisk-dev] SRTP and Dialplan control

Terry Wilson twilson at digium.com
Thu Jan 8 17:27:56 CST 2009


I've been working on getting the SRTP branch ready for review.  My  
latest bit of work has centered around trying to get enough  
information available to the dialplan to be able to properly notify  
both sides of the call whether or not the call is secure (as defined  
by the user via the information that is available).

To do this, I have made "secure_signalling" and "secure_media" fields  
available to ${CHANNEL()}, and added MACRO_RESULT (for Dial option  
M()) values of PLAY_CALLER:prompt_name and  
PLAY_BOTH:prompt_name_caller^prompt_name_callee (with callee being  
optional as it will play the first prompt to both if there isn't a  
second one listed).  WIth these options you can play a notification to  
the caller, or notify the caller and callee simultaneously, as to the  
state of the call (i.e. "Channel secured!").  I couldn't think of  
another way to get this information, since the only way to be able to  
run ${CHANNEL(secure_media)} to get the status of the callee's channel  
would be through the M() or U() options to dial.

I've come up with some sample configs and use cases that I will post  
below that show  how everything should work.  What I would like is  
some feedback as to whether or not people think this is the right way  
to go about things, and if there are some cases that you think that  
this information won't be sufficient.  There are cases that you just  
can't handle solely in the dialplan right now, like if the call is  
initially set up as secure, but one party reinvites to make the call  
insecure, for instance.  These types of issues will probably require a  
significant amount of work to overcome, and I would like to at least  
get a bare minimum set of SRTP features implemented and merged.   
Examples and use cases follow.

Example configs
---------------
__sip.conf__
[phone](!)
type=friend
host=dynamic
context=default
secret=test

[6001](phone)
srtpcapable=yes  ; maybe should be encryption=yes like chan_iax?
[6002](phone)
srtpcapable=yes
[6003](phone)
srtpcapable=no

__iax.conf__
[phone](!)
type=friend
host=192.168.1.100
secret=test
context=default

[6004](phone)
username=6004
encryption=yes
[6005](phone)
username=6005
encryption=no

__extensions.conf__
[globals]
6001_tech = SIP
6002_tech = SIP
6003_tech = SIP
6004_tech = IAX2
6005_tech = IAX2

Use Cases
---------
1. All phones are SIP, support encryption, and are forced to use it  
for every call.  No offers will be made or accepted that don't support  
encryption.  If the caller does not support SRTP we will get either a  
response back from the phone that it doesn't support SRTP, or it will  
improperly ignore our request for encryption and respond with a normal  
RTP offer.  In either case, the call will fail.

__extensions.conf__
[default]
exten => _600X,1,NoOp(All calls must be secured!)
exten => _600X,n,Set(_SIPSRTP=1)
exten => _600X,n,Dial(SIP/${EXTEN})
exten => _600X,n,Hangup

2. There is mix of SIP and IAX phones and only some of them support or  
need to be encrypted.  In this case, it would be best to set the  
srtpcapable=yes config option for all SIP phones that you would like  
calls to be encrypted to and encryption=yes for any IAX phones that  
should use encryption (these two options should probably both be  
"encryption").  Asterisk will encrypt calls that come in from a caller  
automatically if the request contains encryption information.  Whether  
or not the outbound offer requires encryption is determined by the  
value of ${SIPSRTP}.  We can set this value based on the output of the  
result of ${SIPPEER(peer,srtpcapable)}.  If the callee is not SIP,  
SIPSRTP will be empty, so there is no problem there.

__extensions.conf__
[default]
exten => _600X,1,NoOp(Everyone that supports encryption will have it!)
exten => _600X,n,Set(_SIPSRTP=${SIPPEER(${EXTEN},srtpcapable)})
exten => _600X,n,Dial(${${EXTEN}_tech}/${EXTEN})
exten => _600X,n,Hangup

In this case, we will potentially have only one side of the  
conversation encrypted, but everyone who supports encryption will have  
their leg encrypted.  If you would like to let everyone know the  
status of the encryption across both legs of the call, you could do  
the following:

__extensions.conf__
[default]
exten => _600X,1,NoOp(Everyone that supports encryption will have it!)
exten => _600X,n,Set(_SIPSRTP=${SIPPEER(${EXTEN},srtpcapable)})
exten => _600X,n,Gosub(set-secure,s,1)
exten => _600X,n,Dial(${${EXTEN}_tech}/${EXTEN},,M(check-secure^$ 
{secure}))
exten => _600X,n,Hangup

[macro-check-secure]
exten => s,1,NoOp(Checking for secure signalling and media)
exten => s,n,Gosub(set-secure,s,1)
exten => s,n,Set(announce=${IF($[${secure} & ${ARG1}]?channel- 
secure:channel-insecure-warn)})
exten => s,n,Set(MACRO_RESULT=PLAY_BOTH:${announce})

[set-secure]
exten => s,1,Set(secure=$[${CHANNEL(secure_signalling)} & $ 
{CHANNEL(secure_media)}])
exten => s,n,Return

Here, we define secure as a call that has both secure signalling and  
secure media.  In SIP, this would mean both the transport being TLS  
and the media being encrypted with SRTP.  For IAX, this would be both  
Asterisk and the IAX phone (or other Asterisk box) having negotiated  
encryption.

3. You have a call that you would like to force encryption for, but  
instead of just rejecting the call if encryption is negotiated across  
both parties, you would like to play a message to both stating that  
the call will be terminated because it is not secure.  All phones are  
set to offer encryption, but you need to check the callee.

__extensions.conf__
[default]
exten => _600X,1,NoOp(Warn before disconnecting insecure calls)
exten => _600X,n,Set(_SIPSRTP=${SIPPEER(${EXTEN},srtpcapable)})
exten => _600X,n,Gosub(set-secure,s,1)
exten => _600X,n,GotoIf($[!{secure}]?insecure)
exten => _600X,n,Dial(${${EXTEN}_tech}/${EXTEN},,M(check-secure))
exten => _600X,n,Hangup
exten => _600X,n(insecure),Playback(disconnect-channel-was-insecure)
exten => _600X,n,Hangup

[macro-check-secure]
exten => s,1,NoOp(Checking for secure signalling and media)
exten => s,n,Gosub(set-secure,s,1)
exten => s,n,GotoIf($[!${secure}]?insecure)
exten => s,n,Set(MACRO_RESULT=PLAY_BOTH:channel-secure)
exten => s,n,MacroExit
exten => s,n(insecure),Set(MACRO_RESULT=GOTO:${MACRO_CONTEXT}^$ 
{MACRO_EXTEN}^insecure)
exten => s,n,Playback(disconnect-channel-was-insecure)

[set-secure]
exten => s,1,Set(secure=$[${CHANNEL(secure_signalling)} & $ 
{CHANNEL(secure_media)}])
exten => s,n,Return

After working these examples up, I think that it would be nice if the  
channel specific SIPSRTP variable and srtpcapable=yes/no config option  
could made more generic like "OFFER_ENCRYPTION" and encryption=yes/no  
(to match chan_iax).  Anyway, I look forward to any ideas,  
suggestions, criticisms that you all can offer.  Thanks.



More information about the asterisk-dev mailing list