[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