[prev in list] [next in list] [prev in thread] [next in thread] 

List:       helix-server-cvs
Subject:    [Server-cvs] engine/netio http_listenresp.cpp, 1.16,
From:       dcollins () helixcommunity ! org
Date:       2008-07-28 22:30:47
Message-ID: 200807282233.m6SMXOaa010453 () mailer ! progressive-comp ! com
[Download RAW message or body]

Update of /cvsroot/server/engine/netio
In directory cvs01.internal.helixcommunity.org:/tmp/cvs-serv9927/engine/netio

Modified Files:
      Tag: SERVER_12_1
	http_listenresp.cpp mms_listenresp.cpp rtsp_listenresp.cpp 
	servsockimp.cpp 
Log Message:
Synopsis
========
Fixes PR 208796 - DoS: Connections to most/all TCP ports never idle timeout (updated)

Branches: SERVER_12_0, SERVER_12_1, HEAD
Reviewers: Atin, JJ


Description
===========

Problem:
~~~~~~~~
If a client connects to the server but does not transmit any data, there
is no mechanism in place to time out the connection.  This allows for an
easy DoS attack, consuming resources on the server and eventually
causing a server restart.

Solution:
~~~~~~~~~
Fix and use the built-in timeout mechanism in CHXSocket.  This timer
causes an EventPending() callback to occur when the timeout fires with
the event HX_SOCK_EVENT_ERROR and the error code HXR_SOCK_TIMEDOUT.

In the server core, we enable the above timeout as soon at the new socket
is established, and disable the timeout when the socket is handed-off to
the relevant protocol object.  IHXSocket::SetOption() is used to enable
and disable it, with the HX_SOCKOPT_APP_IDLETIMEOUT option.

It is disabled because the protocol object will have a better
understanding of what type of activity is appropriate for the specific
connection.  For example, RTSP uses Ping messages rather than timing out
the socket itself.  If the protocol wants to rely on the same CHXSocket
mechanism it is free to re-enable it at any time using SetOption().

A message is logged to the server's error log when this abnormal activity
occurs.  An example of this message is:

15-Jul-2008 09:24:42.228 tmplgpln(20940): HXR_SOCK_TIMEDOUT: A connection to local \
port 1554 was established from host 'n.n.n.n' but it never sent any data.


The default timeout is 30 seconds.  This default may be overidden
by adding the variable <Var ClientConnectionTimeout="nnn"> to 
the top-level of your server config file.

The CHXSocket::Func() callback had an incorrect conversion from ms to sec
causing incorrect behavior.  This is also fixed as part of this.

While debugging this, it was noted that the CHXSocket call to time()
for setting m_tLastPacket was only necessary if the timeout mechanism
was being used.  This per-packet call to time() was causing noticable
and unnecessary overhead in a heavily loaded server (especially given
the one-second resolution!)  I wrapped this in an if() check and now
only set this when the timeout is enabled.


Files Affected
==============

common/netio/platform/posix/sockimp.cpp
server/admin/monitor/smonnet.cpp
server/admin/monitor/smonnet.h
server/engine/core/aliveprot.cpp
server/engine/core/hxprotmgr.cpp
server/engine/core/pub/hxprotmgr.h
server/engine/netio/http_listenresp.cpp
server/engine/netio/mms_listenresp.cpp
server/engine/netio/rtsp_listenresp.cpp
server/engine/netio/servsockimp.cpp


Testing Performed
=================

Unit Tests:
- None

Integration Tests:
- Ran the repro scenario described in the PR and verifid sockets now go
    away after the timeout period.
- Ran in a v12-style uptime in servlab for one day on RHEL4.
- Tested with both IPv6 and IPv4 connections.
- Tested with a short timeout period set in the config file.

Leak Tests:
- Not explicitly tested yet

Performance Tests:
- None

Platforms Tested: linux-rhel4-i686
Build verified: linux-rhel4-i686, sunos-5.10-sparc-server, win32-i386-vc7


QA Hints
========
- An uptime test is recommended.
- Regress the PR:
    + Verify the config flag works.
    + Verify the error log message occurs.



Index: servsockimp.cpp
===================================================================
RCS file: /cvsroot/server/engine/netio/servsockimp.cpp,v
retrieving revision 1.54
retrieving revision 1.54.12.1
diff -u -d -r1.54 -r1.54.12.1
--- servsockimp.cpp	30 Aug 2007 17:31:15 -0000	1.54
+++ servsockimp.cpp	28 Jul 2008 22:30:44 -0000	1.54.12.1
@@ -47,8 +47,11 @@
 #include "iresolv.h"
 #include "servresolvimp.h"
 #include "resolvcache.h"
+#include "writequeue.h"
+#include "servertrace.h"
 #include "servsockimp.h"
 
+
 #include "core_proc.h"
 
 #include "listenresp.h"
@@ -68,6 +71,7 @@
 
 static const UINT32 DEFAULT_TCP_SNDBUF_SIZE = 32768;
 static const UINT32 DEFAULT_UDP_SNDBUF_SIZE = 16834;
+static const UINT32 DEFAULT_CONNECT_TIMEOUT_SEC = 30;
 
 CServSockCB::CServSockCB(CHXServSocket* pSock, UINT32 event) :
     m_nRefCount(0),
@@ -261,12 +265,14 @@
     return HXR_OK;
 }
 
+
 void
 CHXServSocket::OnEvent(UINT32 ulEvent)
 {
     CHXSocket::OnEvent(ulEvent);
 }
 
+
 STDMETHODIMP
 CHXServSocket::Init(HXSockFamily f, HXSockType t, HXSockProtocol p)
 {
@@ -460,7 +466,18 @@
 	m_pProc->pc->error_handler->Report(HXLOG_ERR, 0, 0, szErr, NULL);
     }
     else
+    {
 	(*g_pSocketAcceptCount)++;
+        INT32 nConnectTimeout = DEFAULT_CONNECT_TIMEOUT_SEC;
+        m_pProc->pc->registry->GetInt("config.ClientConnectionTimeout", \
&nConnectTimeout, m_pProc); +        if (nConnectTimeout)
+        {
+            // Set the inactivity timer on this socket.  Note that this will
+            // be reset back to zero in HXSocketConnection::EventPending() 
+            // when handing the socket off to the protocol object.
+            (*ppNewSock)->SetOption(HX_SOCKOPT_APP_IDLETIMEOUT, \
(UINT32)nConnectTimeout); +        }
+    }
 
     return hxr;
 }
@@ -477,11 +494,11 @@
 
     if (!m_bDontDispatch && HX_SOCK_VALID(m_sock))
     {
-	if (!m_bRemovedCallbacks)
-    {
-	m_pProc->pc->engine->callbacks.remove(HX_READERS, m_sock.sock);
-	m_pProc->pc->engine->callbacks.remove(HX_WRITERS, m_sock.sock);
-	m_pProc->pc->engine->UnRegisterSock();
+        if (!m_bRemovedCallbacks)
+        {
+            m_pProc->pc->engine->callbacks.remove(HX_READERS, m_sock.sock);
+            m_pProc->pc->engine->callbacks.remove(HX_WRITERS, m_sock.sock);
+            m_pProc->pc->engine->UnRegisterSock();
 	    m_bRemovedCallbacks = TRUE;
 	}
 

Index: http_listenresp.cpp
===================================================================
RCS file: /cvsroot/server/engine/netio/http_listenresp.cpp,v
retrieving revision 1.16
retrieving revision 1.16.64.1
diff -u -d -r1.16 -r1.16.64.1
--- http_listenresp.cpp	25 Jan 2005 22:55:21 -0000	1.16
+++ http_listenresp.cpp	28 Jul 2008 22:30:44 -0000	1.16.64.1
@@ -79,7 +79,7 @@
 HTTPListenResponse::OnConnection(IHXSocket* pNewSock, IHXSockAddr* pSource)
 {
     HXSocketConnection* pConn;
-    pConn = new HXSocketConnection(pNewSock, HXPROT_UNKNOWN);
+    pConn = new HXSocketConnection(pNewSock, HXPROT_UNKNOWN, m_pMessages);
     // NB: We do not AddRef the connection, the socket does
 
     return HXR_OK;

Index: rtsp_listenresp.cpp
===================================================================
RCS file: /cvsroot/server/engine/netio/rtsp_listenresp.cpp,v
retrieving revision 1.14
retrieving revision 1.14.64.1
diff -u -d -r1.14 -r1.14.64.1
--- rtsp_listenresp.cpp	25 Jan 2005 22:55:21 -0000	1.14
+++ rtsp_listenresp.cpp	28 Jul 2008 22:30:44 -0000	1.14.64.1
@@ -79,7 +79,7 @@
 RTSPListenResponse::OnConnection(IHXSocket* pNewSock, IHXSockAddr* pSource)
 {
     HXSocketConnection* pConn;
-    pConn = new HXSocketConnection(pNewSock, HXPROT_UNKNOWN);
+    pConn = new HXSocketConnection(pNewSock, HXPROT_UNKNOWN, m_pMessages);
     // NB: We do not AddRef the connection, the socket does
 
     return HXR_OK;

Index: mms_listenresp.cpp
===================================================================
RCS file: /cvsroot/server/engine/netio/mms_listenresp.cpp,v
retrieving revision 1.9
retrieving revision 1.9.64.1
diff -u -d -r1.9 -r1.9.64.1
--- mms_listenresp.cpp	25 Jan 2005 22:55:21 -0000	1.9
+++ mms_listenresp.cpp	28 Jul 2008 22:30:44 -0000	1.9.64.1
@@ -56,7 +56,7 @@
 MMSListenResponse::OnConnection(IHXSocket* pNewSock, IHXSockAddr* pSource)
 {
     HXSocketConnection* pConn;
-    pConn = new HXSocketConnection(pNewSock, HXPROT_MMS);
+    pConn = new HXSocketConnection(pNewSock, HXPROT_MMS, m_pMessages);
     // NB: We do not AddRef the connection, the socket does
 
     return HXR_OK;


_______________________________________________
Server-cvs mailing list
Server-cvs@helixcommunity.org
http://lists.helixcommunity.org/mailman/listinfo/server-cvs


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic