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

David Borman <> Mon, 25 February 2008 17:32 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 152CA28C7BA; Mon, 25 Feb 2008 09:32:07 -0800 (PST)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: 0.021
X-Spam-Status: No, score=0.021 tagged_above=-999 required=5 tests=[AWL=-0.142, 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 wMacmM9h9j-a; Mon, 25 Feb 2008 09:32:05 -0800 (PST)
Received: from (localhost []) by (Postfix) with ESMTP id C26C928C7B3; Mon, 25 Feb 2008 09:26:54 -0800 (PST)
Received: from localhost (localhost []) by (Postfix) with ESMTP id 9A84E28C8B4 for <>; Mon, 25 Feb 2008 09:26:53 -0800 (PST)
X-Virus-Scanned: amavisd-new at
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id 5Rs50gVkfR9z for <>; Mon, 25 Feb 2008 09:26:52 -0800 (PST)
Received: from (frantic-dmz.weston.BORMAN.COM []) by (Postfix) with ESMTP id 238D828C8B8 for <>; Mon, 25 Feb 2008 09:22:46 -0800 (PST)
Received: from [] ( []) by (8.12.5/8.12.5) with ESMTP id m1PHMQ5G001596; Mon, 25 Feb 2008 11:22:27 -0600 (CST)
Message-Id: <>
From: David Borman <>
To:, Andre Oppermann <>
In-Reply-To: <>
Mime-Version: 1.0 (Apple Message framework v919.2)
Date: Mon, 25 Feb 2008 11:22:26 -0600
References: <> <> <> <> <> <> <>
X-Mailer: Apple Mail (2.919.2)
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

My comments are at the bottom.
			-David Borman

On Feb 23, 2008, at 8:00 PM, Jakob Heitz wrote:

> Andre Oppermann wrote:
>> 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.
> You are free to drop any received data (including FIN) that you
> have not yet acknowledged. The peer will retransmit. I suggest you
> drop any segment that contains a suspicious FIN, and I stress drop
> the whole segment. After all, if the FIN is suspicious, it will make
> the rest of the segment suspicious too. I would call a FIN suspicious
> if the resequencing queue contains any data (or another FIN) with a
> higher sequence number. I would then drop all of this data higher in
> the resequencing queue as well. All data in the resequencing queue
> has not been acknowledged (even if it's SACKed) and the peer will
> retransmit.

I agree with Jakob.  If you don't trust the FIN, you shouldn't trust  
the data, either.  Accept and queue any out-of-sequence FINs, and only  
worry about them if you get 1) a second FIN that doesn't match the  
first, 2) a FIN before data that you've already received, or 3) data  
after the FIN.  At that point, flush all the data from the first FIN  
to the end, including any data that came with that FIN.  Otherwise, if  
you reject all FINs until they show up right at the end of the  
connection, you are placing a penalty on all well-behaved TCP  
connections that just happen to have a packet loss or reordering of  
data packets just prior to the FIN.  Optimize for the common case, not  
the exception.  And keep in mind that there are perfectly legitimate  
reasons to get overlapping data (including the FIN), especially when  
retransmitting, but I won't go into the details here.

			-David Borman

tcpm mailing list