Re: [tcpm] Handling of FIN in the reassembly queue

Andre Oppermann <> Sun, 24 February 2008 01:00 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 311BB28C1E1; Sat, 23 Feb 2008 17:00:02 -0800 (PST)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -0.249
X-Spam-Status: No, score=-0.249 tagged_above=-999 required=5 tests=[AWL=-0.412, BAYES_00=-2.599, FH_RELAY_NODNS=1.451, HELO_MISMATCH_ORG=0.611, J_CHICKENPOX_33=0.6, RDNS_NONE=0.1]
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id 4AgF+xr0iT9O; Sat, 23 Feb 2008 17:00:00 -0800 (PST)
Received: from (localhost []) by (Postfix) with ESMTP id CD3303A6BD6; Sat, 23 Feb 2008 17:00:00 -0800 (PST)
Received: from localhost (localhost []) by (Postfix) with ESMTP id C68803A6B9A for <>; Sat, 23 Feb 2008 16:59:58 -0800 (PST)
X-Virus-Scanned: amavisd-new at
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id jSbKMU+Vin5r for <>; Sat, 23 Feb 2008 16:59:57 -0800 (PST)
Received: from ( []) by (Postfix) with ESMTP id 356A63A6AC5 for <>; Sat, 23 Feb 2008 16:59:57 -0800 (PST)
Received: (qmail 83259 invoked from network); 24 Feb 2008 00:15:23 -0000
Received: from localhost (HELO []) ([]) (envelope-sender <>) by (qmail-ldap-1.03) with SMTP for <>; 24 Feb 2008 00:15:23 -0000
Message-ID: <>
Date: Sun, 24 Feb 2008 01:59:50 +0100
From: Andre Oppermann <>
User-Agent: Thunderbird (Windows/20071210)
MIME-Version: 1.0
To: David Borman <>
References: <> <> <> <> <>
In-Reply-To: <>
Cc:, "Anantha Ramaiah (ananth)" <>
Subject: Re: [tcpm] Handling of FIN in the reassembly queue
X-Mailman-Version: 2.1.9
Precedence: list
List-Id: TCP Maintenance and Minor Extensions Working Group <>
List-Unsubscribe: <>, <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit

David Borman wrote:
> On Feb 22, 2008, at 1:38 PM, Anantha Ramaiah (ananth) wrote:

David, Anantha,

>> David,
>>   Pl see inline..
>>> For any TCP connection, in each direction there can be only
>>> one FIN, it will never move, and there will never be any
>>> valid data transmitted after the FIN.  So, if you get into
>>> this situation, you already have a problem, you just don't
>>> know what the problem is.  Either the previously received
>>> out-of-sequence data is bad, or the current packet with the
>>> FIN is bad, but you don't know which.
>>> As to what to do if this scenario should actually happen:  If
>>> these packets were received in sequence, the packet with the
>>> FIN would put us into CLOSE-WAIT state.  The data in the
>>> packets with SEG.SEQ after the FIN would then be ignored, see
>>> page 75 in RFC 793.  So, it seems that the thing to do would
>>> be to integrate the data with the FIN, and flush the
>>> previously received data that is after the FIN.
>> Agreed. Just to be clear, the rationale for me suggesting to drop the
>> segment with FIN in this case is :
>> If this is a genuine FIN, it would get retransmitted again. So you know
>> what to do the next time, ie., So just give it a chance one time, I
>> think this is more safer and robust but YMMV.
> Well, now you have to remember that you previously got this FIN, so that 
> if it shows up again out of sequence you can do something different.  I 
> don't like that additional complexity.  Keep it simple.  (Or are you 
> saying just keep ignoring the out-of-sequence FIN until the holes are 
> filled and it shows up in sequence?)
>>>>> 2. FIN was already received and another one arrives pointing
>>>>>    into the middle of already queue data (or hole);
>>>>>      Ignore the FIN and integrate the data?
>>>>>      Ignore the whole segment with the bogus FIN?
>>>>>      Integrate the data, move the FIN and flush excess data?
>>>> In the regular case (in-order) if the data is already
>>> consumed by the
>>>> application and the window has slided, TCP simply ignores the
>>>> duplicate data. Now for data sitting in the retransmission
>>> queue, we
>>>> should probably do the same, I would ignore the whole segment. [ I
>>>> know in this case FIN is extra]
>>> You should be consistent.  Once again, I'd say integrate the
>>> data and FIN into the resequencing queue, and flush the
>>> excess data beyond this FIN.
>> Well, we have already received a FIN, which means that ( going by your
>> CLOSEWAIT state example) we don't want to accept any data beyond this as
>> per RFC. Now we got a FIN which is way before the current sequence
>> number, in which case I would think it makes sense to ignore it. My
>> consistency reasons are :-
>> - if it would have been received in-order, we would have moved to
>> CLOSEWAIT and would have discarded the new FIN as duplicate ( the
>> receive window already slided, app might have already the data). TCP
>> window slides forward and in this and there is no provision for data
>> "overwrite".
> But we haven't processed that data & FIN yet, because they came out of 
> order.  They are to be processed in SEG.SEQ order, which means the 
> earlier FIN is processed first (unless you received something like 
> SEG1.SEQ=100,LEN=100,FIN and then SEG2.SEQ=150,LEN=0,FIN, in which case 
> the later sequenced FIN would be processed first...)
> The bottom line is that if you have two FINs, or data beyond a FIN, the 
> connection is screwed up and it probably isn't worth putting much effort 
> into dealing with this scenario.  Certainly it is not worth trying to 
> optimize.  Your safest bet is to go to a fallback position and toss all 
> the suspect data.  So, I'll stick with my original suggestion that all 
> the out of sequence data after the earlier (sequence numbered) FIN be 
> thrown away.  But we should probably also throw away the earlier FIN 
> (and any data that it arrived with).  Then we've tossed all the suspect 
> data, and the other side can retransmit what it thinks is the correct 
> data, assuming it is able to do so.

After reading and sleeping one night over this excellent discussion I realized
that we are unsafe at any speed here.

We may get hit with a FIN attack just as we may get hit with a RST attack.
A FIN anywhere in the window is valid and gets queued in the reassembly
queue for later processing.  This wrecks a TCP session by either ending
it prematurely in one direction (accepting the FIN closest to left edge),
or by preventing its legitimate ending (accepting only the first FIN and
waiting for data that never comes).  This is a serious threat.  Maybe even
more so than a pure RST attack with the same complexity.  It is much more
subtle and can cause long hangs for TCP based protocols that do not have
their own keepalive ping exchange.  tcpsecure doesn't even mention it.
I guess nodoby thought of the reassembly and its effects yet.  FIN deserves
its own section as well.

The solution I've come up with is to only accept a FIN when it matches the
left edge (rcv_nxt) either perfectly or accompanied by data that advances
rcv_nxt (the missing segment).  All data beyond that point in the reassembly
queue is then to be flushed.  All FINs that do not fulfill this condition are
to be ignored and not queued.  The only remaining question then is whether to
ignore the whole segment data that came with the FIN.  Probably not.  We can't
say if this is real FIN or not and consequently we can't say whether the
segment data is real or not.  We however have to assume it is real because
we don't have any evidence to the contrary (provided all tcp input validity
checks have been done previously).  This is a quite simple solution and it
avoids a lot of complexity in FIN handling in the reassembly queue.

If my reasoning and rationale is agreed with I can write up a FIN section
for tcpsecure over the next few days.


tcpm mailing list