Subject: Re: [tcpm] SYN's in draft-ietf-tcpm-tcpsecure.txt :-)

From: Sandy Murphy <[email-masked]>
Date: Thu, 20 May 2004 10:55:26 -0400 (EDT)

>> There's been a lot of discussion about the modifications to the RST
>> processing, but not much about the modifications to the SYN processing.
>>
>> NOTE: All of the following is predicated on an assumption of just what
>> exactly is meant by "send an ACK segment to the peer but before
>> sending the ACK segment subtract one from value being acknowledged."
>> and "send an ACK segment to the peer."  I'm presuming this means send
>> <SEQ=SND.NXT><ACK=RCV.NXT-1><CTL=ACK> and
>> <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>.
>
>sorry for late reply. somehow missed it earlier. The
>suggestion is to only send rcv.nxt-1 and not 2 ACKs if that
>is what you are saying above. Similar points as below were
>brought to light on the first day of the draft itself
>(April 20 tcpm archive).

Gack!

Sorry, I did check the archive, honest.  I obviously just did not go
back far enough.  I actually sat on my writeup for two weeks,
thinking that surely someone was going to mention this.  Sanjay's
message of Apr 20 addresses exactly my concern of needing to rely on
timeouts.

And, no, of course I don't mean sending two ACK's at the same time.
The paragraph mentions sending ACK's in two different situations
without specifics, I was trying to be specific about what those two
ACK's might be.

[So any chance that the draft could spell out the packets exactly, as
in RFC793:
    <SEQ=SND.NXT><ACK=RCV.NXT-1><CTL=ACK>
or whatever?]

>Although as you have mentioned above, for the case where we send rcv.nxt-1
>ack and the SYN side then sends us a RST with rcv.nxt-1 might not be
>acceptable in some implementations that do not have keepalive mechanism. 

Sending an ACK with a value less than RCV.NXT, whether prompted by
a <SEQ=RCV.NXT> SYN or a <SEQ=RCV.NXT-1> SYN, means that any resultant
RST will be dropped.

If the SYN is an old duplicate, you don't really need to do anything.
And if the SYN is a current SYN (with SEQ=RCV.NXT-1), then sending the
ACK with RCV.NXT is undesirable (maybe - see my comment below) and
sending the ACK with anything less than RCV.NXT results in a livelock
until timeout.

So here's a radical suggestion: how about doing nothing?

And then there are the revised suggestions for dealing with the
SEQ=RCV.NXT-1 case:

From [email-masked]:
>   B) If the SYN bit is set and the sequence number is exactly one less
>      than the next expected sequence (SEG.SEQ == (RCV.NXT - 1)) then
>      send an ACK segment to the peer but before sending the ACK segment
>      subtract one from the value being acknowledged i.e. the value
>      being acknowledged should be (RCV.NXT - 2) or (SEG.SEQ - 1).

And from [email-masked]
>What we are trying to avoid is send an ACK which will be valid to the
>remote end. Hence if we send an ACK with value RCV.NXT in response to
>an ISN of RCV.NXT-1, this ACK will be acceptable which we are trying
>to avoid.

Why not just rely on the "out of the window" mechanism of case A?

I believe that the motivation for adjusting the ACK is to prevent a
restarted peer in state SYN-SENT from believing that it's SYN was
being ACK'd - and declaring the connection ESTABLISHED.  But it seems
to me that the behavior in state SYN-SENT will drop the segment if
there is no SYN on the segment, even if the ACK is acceptable.  So
that's not really a problem.  Right?  Or maybe I've missed the point.

--Sandy

_______________________________________________
tcpm mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/tcpm

---

From: Anantha Ramaiah <[email-masked]>
Date: Thu, 20 May 2004 10:39:46 -0700

Sandy,
    See inline for my comments..
> message of Apr 20 addresses exactly my concern of needing to rely on

You are encouraged to see my reply to that too :)

Anyways,

One of the corner cases is when the incoming sequence # ( ie ISN
chosen happens to be RCVNXT  -1 ) happens
to be SEG.SEQ = SEG.RCVNXT - 1 which would imply that the ACK would 
contain the SEG.ACK = RCVNXT, which the other end would treat it as
acceptable and drop it since it is in SYNSENT state expecting a
SYN+ACK and not just ACK. For this the suggestion was, 

"To send the ACK with RCVNXT -1, which would generate the RST but
 only on some systems ( RST with RCVNXT -1 is treated as a RST
 of a keepalive packet) it is acceptable, but on others it is 
  dropped"

" worst case is do nothing. This will force the restarted peer to 
  give up and the next time it tries to establish the connection
  the ISN chosen would be random and hence different from the 
  older one ( which was RCVNXT -1)"

But someone (Allwyn) pointed the case for packets (kamikaze like packets) 
where the SYN would contain the data,
in which case I am not sure what would be the consequences of partial
ACK's (which is again rare since why would anybody chose to do a partial
ACK for SYN segment with data) and how they need to be processed. 

Are there any other issues which we should be considering?

thanks,
-Anantha

---

From: Don Lewis <[email-masked]>
Date: Thu, 20 May 2004 13:38:55 -0700 (PDT)

> ACK for SYN segment with data) and how they need to be processed. 

This particular case motivated me to move the SYN handling code from
after the segment is trimmed to fit the window to before the segment is
trimmed to fit the window in the vulnerability fix that I am proposing
to implement in FreeBSD.

If the SYN flag is set and either SEG.SEQ != IRS or SEG.SEQ >= RCV.NXT,
the segment will get special handling.  The last condition is meant to
be a cheap way of detecting that sequence space must have wrapped and
the SYN flag could be in the window.  The normal case of a duplicate SYN
will fall through and will be trimmed off when the segment is trimmed to
fit the window.

If the segment qualifies for special handling, there are five cases:

    The TIME-WAIT case, which is handled elsewhere in the FreeBSD
    implementation.
    
    RCV.NXT < SEG.SEQ || RCV.NXT >= SEG.SEQ+SEG.LEN
        Just send an ACK and drop the segment.  If we received a
        legitimate SYN, the ACK will trigger a RST response.  If this
        was a spoofed SYN, our peer will accept the ACK and not respond.

    RCV.NXT == SEG.SEQ && !ACK
        For simplicity, just drop the connection.  An ACK challenge
        could be done to guard against the unlikely case of an attacker
        guessing just the right sequence number to tear down the
        connection.

    ACK flag is set
        Drop the segment since this must not be a legitimate request to
        set up a new connection.

    SEG.SEQ < RCV.NXT && SEG.SEQ+SEG.LEN > RCV.NXT
        Drop the segment.  The segment includes a data payload and
        straddles RCV.NXT.  There is no reason to send a normal ACK,
        since no response will be generated, no matter whether the
        segment was a legitimate new SYN or it was spoofed.  It might be
        possible though to distinguish these two cases by doing
        something like a TCP keepalive test, which would cause an
        ESTABLISHED peer to respond.