Re: [tcpm] TCP zero window timeout?

John Heffner <jheffner@psc.edu> Tue, 29 August 2006 18:41 UTC

Received: from [127.0.0.1] (helo=stiedprmman1.va.neustar.com) by megatron.ietf.org with esmtp (Exim 4.43) id 1GI8Wn-0004Fi-Mv; Tue, 29 Aug 2006 14:41:37 -0400
Received: from [10.91.34.44] (helo=ietf-mx.ietf.org) by megatron.ietf.org with esmtp (Exim 4.43) id 1GI8Wl-0004FR-RB for tcpm@ietf.org; Tue, 29 Aug 2006 14:41:35 -0400
Received: from mailer2.psc.edu ([128.182.66.106]) by ietf-mx.ietf.org with esmtp (Exim 4.43) id 1GI8Wj-00026R-Hi for tcpm@ietf.org; Tue, 29 Aug 2006 14:41:35 -0400
Received: from [128.182.160.132] (ice.psc.edu [128.182.160.132]) (authenticated bits=0) by mailer2.psc.edu (8.13.5.20060308/8.13.3) with ESMTP id k7TIfOEV018883 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 29 Aug 2006 14:41:24 -0400 (EDT)
Message-ID: <44F48A55.2030304@psc.edu>
Date: Tue, 29 Aug 2006 14:41:25 -0400
From: John Heffner <jheffner@psc.edu>
User-Agent: Thunderbird 1.5.0.5 (Macintosh/20060719)
MIME-Version: 1.0
To: Mahesh Jethanandani <mahesh@cisco.com>
Subject: Re: [tcpm] TCP zero window timeout?
References: <D87D0DFD1BEB364D8E528F28527DD6130240571D@bcs-mail2.internal.cacheflow.com> <7.0.1.0.0.20060722170818.05a59eb8@gont.com.ar> <44EF8F0D.7030803@cisco.com>
In-Reply-To: <44EF8F0D.7030803@cisco.com>
Content-Type: text/plain; charset="ISO-8859-1"; format="flowed"
Content-Transfer-Encoding: 7bit
X-Spam-Score: 0.0 (/)
X-Scan-Signature: 41c17b4b16d1eedaa8395c26e9a251c4
Cc: "Mahdavi, Jamshid" <jamshid.mahdavi@bluecoat.com>, tcpm@ietf.org, "Anantha Ramaiah (ananth)" <ananth@cisco.com>, Fernando Gont <fernando@gont.com.ar>
X-BeenThere: tcpm@ietf.org
X-Mailman-Version: 2.1.5
Precedence: list
List-Id: TCP Maintenance and Minor Extensions Working Group <tcpm.ietf.org>
List-Unsubscribe: <https://www1.ietf.org/mailman/listinfo/tcpm>, <mailto:tcpm-request@ietf.org?subject=unsubscribe>
List-Post: <mailto:tcpm@ietf.org>
List-Help: <mailto:tcpm-request@ietf.org?subject=help>
List-Subscribe: <https://www1.ietf.org/mailman/listinfo/tcpm>, <mailto:tcpm-request@ietf.org?subject=subscribe>
Errors-To: tcpm-bounces@ietf.org

I was looking at a similar problem a while ago as a result of a 
conversation with Stanislav Shalunov about his netkill 
(http://www.internet2.edu/~shalunov/netkill/) attack tool.  The netkill 
problem is different than the zero window problem (and simpler for the 
attacker, requiring less state), but the end result is essentially the 
same: the sender is forced to maintain data in the send buffer for a 
large number of connections, running the server out of memory.

Thinking about possible solutions, I didn't like the strictly TCP or 
strictly application solutions, for reasons already described on this 
list.  My favored approach was to write a daemon that accesses TCP state 
through instrumentation, applies a policy if memory is running low, and 
kills connections as appropriate by using the deleteTCB(12) state 
defined in the TCP MIB.  This does not require any additional protocol 
standardization.

I wrote a simple proof-of-concept python script (below) that utilizes 
the Web100 implementation of the TCP ESTATS MIB.  What it does 
essentially is if the system TCP send buffer memory is over some 
threshold value (100 MB), then it kills all connections that are over 
their fair share, and haven't made any forward progress in the last 
second.  There's clearly room for improvement, like more complicated 
policy (protect or favor certain applications, etc.), but it does defend 
against netkill, and should work for the zero-window attack as well.

   -John



import Web100
import time

agent = Web100.Web100Agent()

THRESH = 100 * 1024 *1024

omem = 0
conns = {}
while True:
     cmem = 0

     cl = agent.all_connections()
     for c in cl:
         state = c.read('State')
         try:
             old = conns[c.cid]
             if state == 1:
                 del(conns[c.cid])
             else:
                 cur = c.readall()

                 cmem = cmem + cur['CurAppWQueue']

                 if omem > THRESH and \
                    cur['SndUna'] == old['SndUna'] and \
                    cur['CurAppWQueue'] > THRESH / len(conns):
                     print("Deleting connection %d."%c.cid)
                     c.write('State', 12)

                 conns[c.cid] = cur

         except:
             # New connection.  Ignore if it's already closed.
             if state != 1:
                 conns[c.cid] = c.readall()
                 cmem = cmem + c.read('CurAppWQueue')

     omem = cmem
     time.sleep(1)

_______________________________________________
tcpm mailing list
tcpm@ietf.org
https://www1.ietf.org/mailman/listinfo/tcpm