[sr-dev] Websocket module
Peter Dunkley
peter.dunkley at crocodile-rcs.com
Wed Aug 8 00:44:49 CEST 2012
Hi,
I have just committed a couple of updates to the WebSockets module.
There is an event_route[websocket:closed] that is run whenever a
connection is closed, and the ws_handle_handshake() function now returns 1
when it is successful. This will enable a hash table to be added to when
a connection is created and cleaned up when the connection is closed.
All 5 of the use cases described below should be supportable in
kamailio.cfg now.
Hope this helps,
Peter
> Hi Inaki,
>
>> 1) A callback (i.e. a script "route[X]" in kamailio.cfg) that is called
>> when a new WebSocket connection is requested by a client, by providing
>> access to the HTTP GET request (so the admin, based on local policy can
>> inspect the HTTP request and allow/dissalow the connection after
>> checking
>> the Cookie header, the Origin header, the Host header or whatever).
>>
>
> All new WebSocket connections are handled by an
> event_route[xhttp:request]. This allows any inspection of the headers you
> want, and you can perform HTTP digest authentication using this
> event_route. Once you are happy that the connection should be allowed you
> call the ws_handle_handshake() function to do some further checks,
> generate the handshake response, and upgrade the connection in Kamailio
> core. So, for example:
>
> event_route[xhttp:request] {
> set_reply_close();
> set_reply_no_connect();
>
> if ($Rp != 80 && $Rp != 443) {
> xlog("L_WARN", "HTTP request received on $Rp\n");
> xhttp_reply("403", "Forbidden", "", "");
> exit;
> }
>
> xlog("L_DBG", "HTTP Request Received\n");
>
> if ($hdr(Upgrade)=~"websocket"
> && $hdr(Connection)=~"Upgrade"
> && $rm=~"GET") {
> xlog("L_DBG", "WebSocket\n");
> xlog("L_DBG", " Host: $hdr(Host)\n");
> xlog("L_DBG", " Origin: $hdr(Origin)\n");
>
> if ($hdr(Host) == $null || !is_myself($hdr(Host))) {
> xlog("L_WARN", "Bad host $hdr(Host)\n");
> xhttp_reply("403", "Forbidden", "", "");
> exit;
> }
>
> # Optional... validate Origin
> # Optional... perform HTTP authentication
>
> # ws_handle_handshake() exits (no further configuration
> file
> # processing of the request) when complete.
> ws_handle_handshake();
> }
>
> xhttp_reply("404", "Not found", "", "");
> }
>
>> 2) A mechanism to associate custom attributes for each WebSocket
>> connection
>> (i.e. an authorized user identifier, which has been authorized by means
>> of
>> the previous HTTP GET request inspection in step 1).
>>
>
> You can do this by creating a hash table using the htable module
> (http://kamailio.org/docs/modules/stable/modules_k/htable.html). This
> table can be filled in as part of the event_route[xhttp:request] above.
> If required ws_handle_handshake() could easily be updated to return
> success/failure instead of exiting on completion to help with this (but
> that change may not be needed).
>
> The hash table should be indexed on the source address and port of the
> connection.
>
>> 3) A mechanism to retrieve, in the kamailio.cfg script, the attributes
>> of
>> the WebSocket connection from which a SIP request arrives to Kamailio
>> (i.e.
>> useful to enforce that the From URI matches the connection user
>> identifier
>> retrieved in any custom way in step 1).
>>
>
> This information can be put in the hash table and retrieved on demand.
> You can always get the source address and port (which the hash table would
> be indexed on) of a request in the Kamailio configuration.
>
>> 4) A mechanism to close an existing WebSocket connection from the
>> kamailio.cfg script (i.e: during the WebSocket handshake we decided,
>> somehow, that the user identifier is "alice", but at some point we
>> receive
>> an INVITE from that WS connection with From user "bob", so it could be
>> an
>> attacker and we want to close the connection).
>>
>
> I believe that calling the existing "set_reply_close()" function and then
> sending a SIP reply to the INVITE will kill the connection. Adding an API
> to explicitly kill the WebSocket connection immediately wouldn't be hard -
> but shouldn't be needed.
>
>> 5) A callback that is called when a previously accepted WebSocket
>> connection is closed (by passing as argument the terminator of the
>> connection: the client or kamailio.cfg).
>>
>
> There is no support for this at the moment, but it would be relatively
> easy to add an event_route[] to the WebSocket module (probably just a few
> lines in ws_conn.c:wsconn_close_now() or ws_conn.c:wsconn_rm()). If the
> event_route[] makes sure appropriate pseudo-vars (containing information
> like source address and port of the terminated connection and so on) are
> provided then this can be used to clean-up the hash-table (otherwise
> entries will just have to time-out).
>
>>
>> Said that, WWW people WON'T like the idea of providing a SIP username
>> and
>> SIP password in the JavaScript code retrieved by the user when visiting
>> the
>> web page, and for sure most of WWW people will prefer to
>> validate/authenticate/authorize the WebSocket connections by inspecting
>> the
>> HTTP GET request (Origin, Cookie, some custom API_KEY in the request-URI
>> of
>> the GET method or whatever).
>>
>
> Yes I thought that. That is one of the reasons I decided to use the xhttp
> module to handle the WebSocket handshake instead of coding it all in the
> module.
>
> Regards,
>
> Peter
>
> --
> Peter Dunkley
> Technical Director
> Crocodile RCS Ltd
>
>
> _______________________________________________
> sr-dev mailing list
> sr-dev at lists.sip-router.org
> http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
>
--
Peter Dunkley
Technical Director
Crocodile RCS Ltd
More information about the sr-dev
mailing list