From ec06b7e29a62d85505408320d416a952f484d784 Mon Sep 17 00:00:00 2001 From: lazedo Date: Sun, 17 Feb 2019 09:41:01 +0000 Subject: [PATCH] update ws connection count for proxied connections * adds allowed proxies * adds allowed connections per proxy --- kamailio/default.cfg | 4 -- kamailio/websockets-role.cfg | 76 ++++++++++++++++++++++-------------- 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/kamailio/default.cfg b/kamailio/default.cfg index 09fe902..5e7cd3b 100644 --- a/kamailio/default.cfg +++ b/kamailio/default.cfg @@ -341,10 +341,6 @@ route route(DOS_PREVENTION); #!endif - #!ifdef WEBSOCKETS_ROLE - route(HANDLE_WEBSOCKETS); - #!endif - #!ifdef NAT_TRAVERSAL_ROLE route(NAT_DETECT); #!endif diff --git a/kamailio/websockets-role.cfg b/kamailio/websockets-role.cfg index 83c337e..c31d4a0 100644 --- a/kamailio/websockets-role.cfg +++ b/kamailio/websockets-role.cfg @@ -24,6 +24,8 @@ loadmodule "xhttp.so" #!trydef WS_KEEPALIVE_INTERVAL 1 #!trydef WS_KEEPALIVE_DATA "Kazoo encourages you to keep alive" #!trydef WS_MAX_CONNECTIONS_PER_IP 50 +#!trydef WS_MAX_CONNECTIONS_PER_PROXY 0 +#!trydef WS_ALLOWED_PROXIES "0.0.0.0/0" ######## Websocket module ######## loadmodule "websocket.so" @@ -35,27 +37,10 @@ modparam("websocket", "ping_application_data", WS_KEEPALIVE_DATA) modparam("websocket", "sub_protocols", 1) ####### Websocket Logic ######## -route[HANDLE_WEBSOCKETS] -{ - # Do NAT traversal stuff for requests from a WebSocket - # connection - even if it is not behind a NAT! - # This won't be needed in the future if Kamailio and the - # WebSocket client support Outbound and Path. - - return(); - -} - -route[NAT_WEBSOCKETS_CORRECT] -{ - # Do NAT traversal stuff for replies to a WebSocket connection - # - even if it is not behind a NAT! - # This won't be needed in the future if Kamailio and the - # WebSocket client support Outbound and Path. - - return(); -} +kazoo.ws_allowed_proxies = WS_ALLOWED_PROXIES desc "comma separated list of allowed proxies in cidr notation" +kazoo.ws_max_connection_per_ip = WS_MAX_CONNECTIONS_PER_IP desc "max connections per ip" +kazoo.ws_max_connection_per_proxy = WS_MAX_CONNECTIONS_PER_PROXY desc "max connections per proxy" event_route[xhttp:request] { @@ -94,15 +79,42 @@ event_route[xhttp:request] } #!endif - if($sht(websockets=>$si::count) > WS_MAX_CONNECTIONS_PER_IP) { - xlog("L_WARN", "websocket|log|$si:$sp is at the maximum $def(WS_MAX_CONNECTIONS_PER_IP) allowable sockets per IP, rejecting request for another websocket\n"); + if ($hdr(X-Forwarded-For) == $null) { + $var(ws_orig_ip) = $si; + } else { + xlog("L_INFO", "websocket|log|request X-Forwarded-For $hdr(X-Forwarded-For) from $si\n"); + $var(ws_orig_ip) = $hdr(X-Forwarded-For); + } + + if($si != $var(ws_orig_ip)) { + if(!is_in_subnet($si, $sel(cfg_get.kazoo.ws_allowed_proxies))) { + xlog("L_WARNING", "websocket|log|request X-Forwarded-For $hdr(X-Forwarded-For) from invalid ip $si - allowed $sel(cfg_get.kazoo.ws_allowed_proxies)\n"); + xhttp_reply("403", "Forbidden", "", ""); + exit; + } + + if($sel(cfg_get.kazoo.ws_max_connection_per_proxy) > 0 && $sht(websockets=>$si::count) > $sel(cfg_get.kazoo.ws_max_connection_per_proxy)) { + xlog("L_WARN", "websocket|log|$si is at the maximum $sel(cfg_get.kazoo.ws_max_connection_per_proxy) allowable sockets per PROXY IP, rejecting request for another websocket\n"); + xhttp_reply("403", "Forbidden", "", ""); + exit; + } + } + + if($sel(cfg_get.kazoo.ws_max_connection_per_ip) > 0 && $sht(websockets=>$var(ws_orig_ip)::count) > $sel(cfg_get.kazoo.ws_max_connection_per_ip)) { + xlog("L_WARN", "websocket|log|$var(ws_orig_ip) is at the maximum $sel(cfg_get.kazoo.ws_max_connection_per_ip) allowable sockets per IP, rejecting request for another websocket\n"); xhttp_reply("403", "Forbidden", "", ""); exit; } if (ws_handle_handshake()) { - $var(count) = $shtinc(websockets=>$si::count); - xlog("L_INFO", "websocket|log|opened websocket $var(count) of $def(WS_MAX_CONNECTIONS_PER_IP) for $si:$sp\n"); + $var(count) = $shtinc(websockets=>$var(ws_orig_ip)::count); + if($si != $var(ws_orig_ip)) { + $var(proxy_count) = $shtinc(websockets=>$si::count); + xlog("L_INFO", "websocket|log|opened proxied websocket $ws_conid from $si for $var(ws_orig_ip):$sp\n"); + $sht(websockets=>$ws_conid::ws_orig_ip) = $var(ws_orig_ip); + } else { + xlog("L_INFO", "websocket|log|opened websocket $ws_conid from $var(ws_orig_ip):$sp\n"); + } exit; } @@ -110,12 +122,18 @@ event_route[xhttp:request] xhttp_reply("404", "Not Found", "", ""); } -event_route[websocket:closed] { +event_route[websocket:closed] +{ + $var(ws_orig_ip) = $sht(websockets=>$ws_conid::ws_orig_ip); + $sht(websockets=>$ws_conid::ws_orig_ip) = $null; + $var(count) = $shtdec(websockets=>$si::count); - if ($var(count) < 1) { - xlog("L_INFO", "websocket|log|$si:$sp closed last websocket to that IP\n"); - $sht(websockets=>$si::count) = $null; + if($var(ws_orig_ip) != $null && $si != $var(ws_orig_ip)) { + $var(countip) = $shtdec(websockets=>$var(ws_orig_ip)::count); + xlog("L_INFO", "websocket|log|$si closed proxied websocket $ws_conid for $var(ws_orig_ip):$sp\n"); + if ($var(countip) < 1) $sht(websockets=>$var(ws_orig_ip)::count) = $null; } else { - xlog("L_INFO", "websocket|log|closed websocket from $si:$sp, $var(count) remaining from that IP\n"); + xlog("L_INFO", "websocket|log|closed websocket $ws_conid from $var(ws_orig_ip):$sp\n"); } + if ($var(count) < 1) $sht(websockets=>$si::count) = $null; }