> > I agree that drafts running into such issues have to address this -
> > but this seems possible and is just a design detail that has to be
> > solved.
>
> I think we are basically in agreement. This has to be added to the
> list
> of things to check in any tcpinc draft, but we should anticipate that
> it
> is a tractable problem.
>
> > I still don't understand how this can be an issue if the actual
> buffer
> > and possibly RWND considers the encoding overhead.
>
> It doesn't have to be an issue, but it can be an issue if a protocol is
> not properly designed. And naively attempting to address the problem
> could lead to other issues (such as exceeding the receive buffer size).
Sorry, I still don't understand what buffer problem you refer to, assuming the
protocol design is bug-free. Could you please expand a bit?
> For example, one naive way to solve the problem is to implement payload
> integrity entirely on top of TCP, almost at a different level of
> abstraction. Something like TLS already works over TCP, so intuitively
> one might expect this to work.
What deadlock is caused when we would use something like TLS for
confidentiality and something like TCP-AO integrity (or TCP-AO for both)?
> Well obviously not because now the MACs
> are going to consume options space and cause deadlock in situations
> where TCP would have been fine. Okay, so the next thing one might try
Maybe it would help to me to better understand the deadlock if I had a concrete
example.
> to do is increase the effective send buffer size to be SO_SNDBUF plus
> the size of all buffered MACs. But this still doesn't solve the
As far as I know, SO_SNDBUF/SO_RCVBUF is the *socket* buffer size, which should
not be affected if tcpinc offers a socket interface to the app, as far as I
understand it.
But the socket buffer may not be the buffer TCP uses - if they were the same,
this would be a specific implementation choice.
The TCP buffer can be larger. For instance, I think Linux uses for TCP
buffering a buffer significantly larger than the socket buffer:
SO_SNDBUF
Sets or gets the maximum socket send buffer in bytes. The
kernel doubles this value (to allow space for bookkeeping
overhead) when it is set using setsockopt(2), and this doubled
value is returned by getsockopt(2). The default value is set
by the /proc/sys/net/core/wmem_default file and the maximum
allowed value is set by the /proc/sys/net/core/wmem_max file.
The minimum (doubled) value for this option is 2048.
SO_RCVBUF
Sets or gets the maximum socket receive buffer in bytes. The
kernel doubles this value (to allow space for bookkeeping
overhead) when it is set using setsockopt(2), and this doubled
value is returned by getsockopt(2). The default value is set
by the /proc/sys/net/core/rmem_default file, and the maximum
allowed value is set by the /proc/sys/net/core/rmem_max file.
The minimum (doubled) value for this option is 256.
Thus, as far as I understand it, the value of SO_RCVBUF is by and large
decoupled from the TCP receiver advertised window. An application cannot expect
that the receiver advertised window is equal to SO_RCVBUF etc.
> problem, because now what if the MAC is computed over more data than
> the
> receive window size? Now the receiver will have a bunch of data whose
> integrity is unknown, and will not have buffer space to receive the
> MAC.
If the MAC for header fields is added in a TCP option (e.g., TCP-AO), I don't
understand why buffer space would be a problem.
I understand that securing certain TCP header fields from within the TCP byte
stream may be challenging. But buffer space is by far not the only challenge
for this, as far as I can see.
> Okay so now allow sender to exceed the receive window and have the
> receiver buffer data until the next MAC. Okay, but now an ill-behaved
> sender could create a giant message that massively exceeds the receive
> buffer size.
I don't understand why one would have to allow a sender to exceed the receive
window. Could you please explain why this would be required? It violates the
TCP specs.
> These are all obvious straw-men. But the point is that the real
> solution is a bit more complicated. Since as far as I know none of the
> sequence-number-stretching tcpinc proposals has even been implemented,
> it's an open question how exactly flow control interacts with such
> proposals.
tcpcrypt seems to have to violate TCP flow control for INIT1/INIT2 (well, using
EDO could possibly solve this problem).
Again, please help me better understanding why flow control would be an issue
in any other solution. We don't need an implementation to understand whether
protocol semantics are violated or not. But you have to explicitly state your
assumptions and reason why there is no alternative to them.
> > I think most TCP stacks don't run a static, fixed TCP buffer of size
> > SO_SNDBUF or SO_RCVBUF anyway. In particular packet-based stacks
> seems
> > to work differently internally.
>
> I haven't tested recently, but in my experience SO_RCVBUF definitely
> impacted the receive window. More importantly, though, even
> applications that don't set SO_RCVBUF can reasonably assume they get
> some sane default value, meaning at least 4 MSS and less than infinity.
As far as I can tell, the IETF does not mandate how a TCP stack allocates
buffer internally, nor how it sets the TCP receive window.
> If tcpinc changes this so the effective receive buffer is tiny, it
> could
> cause deadlock. If tcpinc changes it so the effective receive buffer
> is
> infinity, this breaks flow control. And obviously, while greater than
> the buffer size, we want some kind of limit on how much buffer space
> the
> kernel needs on the sender or receiver.
Sorry, I cannot follow. It is up to the TCP stack to decide how much buffer to
allocate, and what receive window to announce. A TCP stack does not have to
use SO_RCVBUF for calculating the receive window, as far as I know.
The tcpinc WG may have to specify that a stack has to ensure that the TCP
buffer is larger than the socket buffer, or the tcpinc WG may specify that a
TCP endpoint using tcpinc must allocate X additional bytes e.g. to store
out-of-band key/MAC data, and fall back to vanilla TCP if no RAM us available.
Why is this a problem?
> > There may be (legacy) middleboxes (PEPs) that send such Pre-ACKs if
> > they know/assume that the path between the middlebox and the receiver
> > is entirely reliable. This is a violation of TCP end-to-end semantics
> > and probably not a PEP behavior that the IETF recommends. But, in
> > particular in satellite environments, this could be a mechanism used
> > for traffic engineering or performance optimization (I've read about
> > it one decade ago, maybe those PEPs went away in the mean time). If
> > used for performance tuning, these ACKs would not be a malicious
> > attack.
>
> Probably better just to terminate the TCP connection, no? Particularly
> given the prevalence of transparent proxies. If there's a choice
> between breaking flow control and slightly diminishing the throughput
> of
> legacy devices that are new enough to use tcpcrypt but not to increase
> their receive buffer size, I would prefer the latter.
Pre-ACKs have been suggested in the past because of the huge RTT in satellite
networks. This large RTT also affects congestion control (e.g., during
Slow-Start). The performance difference could be significant.
I agree that a transparent TCP proxy may end up in less issues. Also, I have no
data whether there are indeed middleboxes in the Internet not terminating the
connection but faking ACKs. And none of these middleboxes are desirable
regarding end-to-end TCP semantics. But we have toaccept that people may deploy
middleboxes e.g. in satellite networks without having attacks in mind.
> > If an attacker that can inject ACKs into the connection, that
> attacker
> > could also send RST or other segments with more impact than a faked
> > ACK, right? So, this is basically a variant of the question whether
> to
> > protect against RST (e.g., with TCP-AO)?
>
> Well, you can say it's a variant of RST, but the consequences of the
> attack are different and the defenses are different, so it doesn't seem
> that useful to lump them together. RST protection can be implemented
> locally and unilaterally for a variety of TCP modifications. Checking
> the integrity of ACKs requires specific support from the wire format.
>
> Also, RST kills the connection, so it's basically a DoS attack. ACK
> forgery causes the application to think things are okay, but return
> incorrect values for things like percent complete and bytes/second.
TCP does not guarantee that data indeed arrives at the receiving application.
TCP only guarantees delivery to the receiving TCP stack. Thus, an application
that cares about payload integrity (in your example: complete upload) has to
verify the byte stream at application level for standard TCP already. In that
case, one can detect that attack already at application level, right? So, I
really wonder faking a complete upload at TCP level is a real problem.
In addition, one could very easily detect this attack in many scenarios. If an
application reports an upload rate of 42 Gbit/s on a 4 Mbit/s DSL uplink, that
would certainly be strange, right? In other words: ACK forgery would have to
detect the real path capacity in order to keep the displayed throughput without
reasonable limits of the true value. Getting this right would be quite some
effort; it seems basically equivalent to an active on-path attacker. Is this
really what a tcpinc solution should focus on?
Michael
_______________________________________________
Tcpinc mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/tcpinc