modules/websocket: Updated example kamailio.cfg
authorPeter Dunkley <peter.dunkley@crocodile-rcs.com>
Tue, 18 Sep 2012 18:29:36 +0000 (19:29 +0100)
committerPeter Dunkley <peter.dunkley@crocodile-rcs.com>
Tue, 18 Sep 2012 18:29:36 +0000 (19:29 +0100)
- Now using corex and alias_subdomains.

  It is quite likely that a WebSocket server will be running on a host within
  the domain it is authoritative for and that the WebSocket client will
  address that host directly.  This means that the alias_subdomains modparam
  is a good way to get a domain and all of its sub-domains to match "myself".

  This is very useful for checking the Host: header in the WebSocket
  handshake.

- Added handling of OPTIONS pings.

- Fixed a problem with the Host: header check.

  When you connect to a WS or WSS socket in Google Chrome on the default ports
  (80 and 443 respectively) the Host: header will contain just a hostname
  (for example, "proxy.example.com") which works with is_myself().

  When you connect to a WS or WSS socket in Google Chrome on a non-default port
  (for example, 8080 or 8443 respectively) the Host: header will contain a
  hostname and port (for example, "proxy.example.com:8080") whoch does not work
  with is_myself().

  However, both "sip:proxy.example.com" and "sip:proxy.example.com:8080" will
  work, so simply adding "sip:" to the start of the contents of the Host:
  header before checking fixes the problem.

- Tidied up response reason texts.

- Tidied up some of the TLS specific checks in event_route[xhttp:request].

- Removed some DBG level log messages.

- Added a (commented out) example for checking the Origin: header in the
  WebSocket handshake.

modules/websocket/example/kamailio.cfg

index 5cc76ab..17ae075 100644 (file)
@@ -5,6 +5,7 @@
 
 #!substdef "!DBURL!sqlite:///etc/kamailio/db.sqlite!g"
 #!substdef "!MY_IP_ADDR!a.b.c.d!g"
+#!substdef "!MY_DOMAIN!example.com!g"
 #!substdef "!MY_WS_PORT!80!g"
 #!substdef "!MY_WSS_PORT!443!g"
 #!substdef "!MY_WS_ADDR!tcp:MY_IP_ADDR:MY_WS_PORT!g"
@@ -20,8 +21,6 @@
 fork=yes
 children=4
 
-alias="example.com"
-
 #!ifdef WITH_TLS
 enable_tls=1
 #!endif
@@ -65,6 +64,7 @@ loadmodule "auth.so"
 loadmodule "auth_db.so"
 loadmodule "kex.so"
 loadmodule "mi_rpc.so"
+loadmodule "corex.so"
 #!ifdef WITH_TLS
 loadmodule "tls.so"
 #!endif
@@ -105,6 +105,9 @@ modparam("auth_db", "calculate_ha1", yes)
 modparam("auth_db", "password_column", "password")
 modparam("auth_db", "load_credentials", "")
 
+# ----- corex params -----
+modparam("corex", "alias_subdomains", "MY_DOMAIN")
+
 #!ifdef WITH_TLS
 # ----- tls params -----
 modparam("tls", "tls_method", "SSLv23")
@@ -203,10 +206,15 @@ route[REQINIT] {
                exit;
        }
 
-       if(!sanity_check("1511", "7")) {
+       if (!sanity_check("1511", "7")) {
                xlog("Malformed SIP message from $si:$sp\n");
                exit;
        }
+
+       if (uri == myself && is_method("OPTIONS") && !(uri=~"sip:.*[@]+.*")) {
+               options_reply();
+               exit;
+       }
 }
 
 # Handle requests within SIP dialogs
@@ -239,7 +247,7 @@ route[WITHINDLG] {
                                        exit;
                                }
                        }
-                       sl_send_reply("404","Not here");
+                       sl_send_reply("404","Not Found");
                }
                exit;
        }
@@ -287,7 +295,7 @@ route[AUTH] {
        # if caller is not local subscriber, then check if it calls
        # a local destination, otherwise deny, not an open relay here
        if (from_uri!=myself && uri!=myself) {
-               sl_send_reply("403","Not relaying");
+               sl_send_reply("403","Forbidden");
                exit;
        }
 }
@@ -307,7 +315,11 @@ event_route[xhttp:request] {
        set_reply_close();
        set_reply_no_connect();
        
-       if ($Rp != MY_WS_PORT && $Rp != MY_WSS_PORT) {
+       if ($Rp != MY_WS_PORT
+#!ifdef WITH_TLS
+           && $Rp != MY_WSS_PORT
+#!endif
+       ) {
                xlog("L_WARN", "HTTP request received on $Rp\n");
                xhttp_reply("403", "Forbidden", "", "");
                exit;
@@ -318,17 +330,25 @@ event_route[xhttp:request] {
        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))) {
+               # Validate Host - make sure the client is using the correct
+               # alias for WebSockets
+               if ($hdr(Host) == $null || !is_myself("sip:" + $hdr(Host))) {
                        xlog("L_WARN", "Bad host $hdr(Host)\n");
                        xhttp_reply("403", "Forbidden", "", "");
                        exit;
                }
 
-               # Optional... validate Origin
+               # Optional... validate Origin - make sure the client is from an
+               # authorised website.  For example,
+               #
+               # if ($hdr(Origin) != "http://communicator.MY_DOMAIN"
+               #     && $hdr(Origin) != "https://communicator.MY_DOMAIN") {
+               #       xlog("L_WARN", "Unauthorised client $hdr(Origin)\n");
+               #       xhttp_reply("403", "Forbidden", "", "");
+               #       exit;
+               # }
+
                # Optional... perform HTTP authentication
 
                # ws_handle_handshake() exits (no further configuration file
@@ -341,7 +361,7 @@ event_route[xhttp:request] {
                }
        }
 
-       xhttp_reply("404", "Not found", "", "");
+       xhttp_reply("404", "Not Found", "", "");
 }
 
 event_route[websocket:closed] {