Conversation
Opaque protocol hints on endpoints
The outbound proxy handles endpoints with the `opaque_transport` flag by opening a direct connection to the inbound proxy's inbound listener port, and sending a ProtoBuf `TransportHeader` including the target port of the originating outbound connection and an (optional) `SessionProtocol` describing the protocol used on that connection. Currently, outbound proxies initiating direct connections will *always* send `SessionProtocol` values communicating the protocol as understood by the outbound proxy. However, this is not always the desired behavior. Direct connections with `TransportHeader`s are used in two cases: for gateway connections, and for ports which are marked as opaque. When the inbound port is marked as opaque, the presence of a `SessionProtocol` tells the inbound proxy to handle that connection as the indicated protocol, which results in incorrect behavior when the inbound proxy's ServerPolicy configures the target port as opaque (see #9888). Therefore, the `Destination` proxy API has been updated to add a new `ProtocolHint`, `Opaque`, which indicates that an outbound proxy should _not_ send a `SessionProtocol` when initiating a direct connection, even if the outbound proxy handled the connection as HTTP. This hint was added to the proxy API in linkerd/linkerd2-proxy-api#197, and released in `linkerd2-proxy-api` v0.8.0. This branch updates the Destination controller's dependency on `linkerd2-proxy-api` to v0.8.0, and changes the controller to send an `Opaque` protocol hint when the target port is marked as opaque on the destination pod. This should override the `H2` protocol hint that is added when the destination is meshed. I've also added a new test for this behavior. Fixes #9888 (along with linkerd/linkerd2-proxy#2209, which changes the proxy to actually handle the `Opaque` protocol hint).
mateiidavid
left a comment
There was a problem hiding this comment.
Nice, it looks good to me.
olix0r
left a comment
There was a problem hiding this comment.
This is going to conflict with the other changes i have in flight so I'm going to have to be a little careful about merging this.
How can we make the change smaller? For instance, there's a lot of test infra change in this PR that i haven't really parsed.
| fn http_ep(metadata: Metadata, version: http::Version) -> crate::http::Connect { | ||
| let e = crate::http::Endpoint::from((version, ep(metadata))); | ||
| crate::http::Connect::from((version, e)) | ||
| } |
There was a problem hiding this comment.
This stuff is going to conflict with other work, especially. Can you decouple the tests from the specific target types used in the stack?
There was a problem hiding this comment.
Okay, 7557676 changes these tests so that they no longer use the actual target types --- is that sufficient?
IMO, this is somewhat unfortunate, as the target types' Param impls were part of the code being tested here, and now, we need to ensure that the targets used in the tests actually behave the same as the real targets. But, hopefully that reduces the conflict with other changes?
There was a problem hiding this comment.
Look at what's coming in
https://github.com/linkerd/linkerd2-proxy/pull/2210/files#diff-397930556d70c6560dae17b17cf26153f2b1398664e6e7b46112d5135a1ec4bb -- we don't have any reason to use Metadata at all.
IMO, this is somewhat unfortunate, as the target types' Param impls were part of the code being tested here,
This decoupling is intended to force this conversation. Why are these tests coupled to the caller context? Do we need tests in the caller module(s) that exercise how they set their parameters? Or does this indicate that the params are not factored properly so that the inputs to this stack are too fine grain?
We can remove the integration test changes if we don't care about having integration tests for this case; I wrote that initially while trying to reproduce the issue. If it's more desirable to have a smaller branch, I can back that out for now and we can consider merging those changes separately (or not at all)? |
Co-authored-by: Matei David <matei@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
My point was kind of the opposite: there are probably some parts of this that are relatively easy/uncontroversial to merge that don't actually touch the outbound stack. The outbound stack changes need to be considered in the scope of other changes, while much of the other changes (proxy-api bump, test infra stuff, etc) do not. |
Ooooh, gotcha. I'll pull that stuff out, then. |
|
#2226 includes some of those test changes |
Currently, updates sent by the mock destination controller used in integration tests are constructed by a number of free functions with names like `destination_add_tls` and `destination_add_h2_hinted` and so on. These functions determine different aspects of the generated destination updates, such as protocol hints, labels, and TLS identity. This works acceptably for the current integration tests. However, in order to add new tests, it may be desirable to add additional destination configurations. For example, for testing the handling of various protocol hints on direct connections, it's necessary to set both a protocol hint *and* a TLS identity (direct connections require TLS). The current approach has separate functions for constructing updates with a protocol hint and updates with TLS. In order to make the construction of test destinations more flexible, this PR replaces the current approach with a builder. This way, the logic for constructing updates with different attributes can be composed more easily, without having to implement separate constructors for the entire matrix of (protocol hint, TLS identity, addr labels, addr set labels) combinations. This was factored out of PR #2209 so that the test framework changes can be merged separately.
Depends on #2232 This branch adds a new integration test for direct connections transporting hinted HTTP/2. This was factored out from #2209. I did *not* add the test that actually reproduces linkerd/linkerd2#9888 in this PR, as it would fail.
Currently, updates sent by the mock destination controller used in integration tests are constructed by a number of free functions with names like `destination_add_tls` and `destination_add_h2_hinted` and so on. These functions determine different aspects of the generated destination updates, such as protocol hints, labels, and TLS identity. This works acceptably for the current integration tests. However, in order to add new tests, it may be desirable to add additional destination configurations. For example, for testing the handling of various protocol hints on direct connections, it's necessary to set both a protocol hint *and* a TLS identity (direct connections require TLS). The current approach has separate functions for constructing updates with a protocol hint and updates with TLS. In order to make the construction of test destinations more flexible, this PR replaces the current approach with a builder. This way, the logic for constructing updates with different attributes can be composed more easily, without having to implement separate constructors for the entire matrix of (protocol hint, TLS identity, addr labels, addr set labels) combinations. This was factored out of PR #2209 so that the test framework changes can be merged separately.
This branch adds a new integration test for direct connections transporting hinted HTTP/2. This was factored out from #2209. I did *not* add the test that actually reproduces linkerd/linkerd2#9888 in this PR, as it would fail.
|
Okay, I've opened a new PR for this change (#2237), which is updated to track the latest changes on |
Currently, when the outbound proxy makes a direct connection prefixed with a `TransportHeader` in order to send HTTP traffic, it will always send a `SessionProtocol` hint with the HTTP version as part of the header. This instructs the inbound proxy to use that protocol, even if the target port has a ServerPolicy that marks that port as opaque, which can result in incorrect handling of that connection. See linkerd/linkerd2#9888 for details. In order to prevent this, linkerd/linkerd2-proxy-api#197 adds a new `ProtocolHint` value to the protobuf endpoint metadata message. This will allow the Destination controller to explicitly indicate to the outbound proxy that a given endpoint is known to handle all connections to a port as an opaque TCP stream, and that the proxy should not perform a protocol upgrade or send a `SessionProtocol` in the transport header. This branch updates the proxy to handle this new hint value, and adds tests that the outbound proxy behaves as expected. Along with linkerd/linkerd2#10301, this will fix linkerd/linkerd2#9888. I opened a new PR for this change rather than attempting to rebase my previous PR #2209, as it felt a bit easier to start with a new branch and just make the changes that were still relevant. Therefore, this closes #2209.
The outbound proxy handles endpoints with the `opaque_transport` flag by opening a direct connection to the inbound proxy's inbound listener port, and sending a ProtoBuf `TransportHeader` including the target port of the originating outbound connection and an (optional) `SessionProtocol` describing the protocol used on that connection. Currently, outbound proxies initiating direct connections will *always* send `SessionProtocol` values communicating the protocol as understood by the outbound proxy. However, this is not always the desired behavior. Direct connections with `TransportHeader`s are used in two cases: for gateway connections, and for ports which are marked as opaque. When the inbound port is marked as opaque, the presence of a `SessionProtocol` tells the inbound proxy to handle that connection as the indicated protocol, which results in incorrect behavior when the inbound proxy's ServerPolicy configures the target port as opaque (see #9888). Therefore, the `Destination` proxy API has been updated to add a new `ProtocolHint`, `Opaque`, which indicates that an outbound proxy should _not_ send a `SessionProtocol` when initiating a direct connection, even if the outbound proxy handled the connection as HTTP. This hint was added to the proxy API in linkerd/linkerd2-proxy-api#197, and released in `linkerd2-proxy-api` v0.8.0. This branch updates the Destination controller's dependency on `linkerd2-proxy-api` to v0.8.0, and changes the controller to send an `Opaque` protocol hint when the target port is marked as opaque on the destination pod. This should override the `H2` protocol hint that is added when the destination is meshed. I've also added a new test for this behavior. Fixes #9888 (along with linkerd/linkerd2-proxy#2209, which changes the proxy to actually handle the `Opaque` protocol hint).
The outbound proxy handles endpoints with the `opaque_transport` flag by opening a direct connection to the inbound proxy's inbound listener port, and sending a ProtoBuf `TransportHeader` including the target port of the originating outbound connection and an (optional) `SessionProtocol` describing the protocol used on that connection. Currently, outbound proxies initiating direct connections will *always* send `SessionProtocol` values communicating the protocol as understood by the outbound proxy. However, this is not always the desired behavior. Direct connections with `TransportHeader`s are used in two cases: for gateway connections, and for ports which are marked as opaque. When the inbound port is marked as opaque, the presence of a `SessionProtocol` tells the inbound proxy to handle that connection as the indicated protocol, which results in incorrect behavior when the inbound proxy's ServerPolicy configures the target port as opaque (see #9888). Therefore, the `Destination` proxy API has been updated to add a new `ProtocolHint`, `Opaque`, which indicates that an outbound proxy should _not_ send a `SessionProtocol` when initiating a direct connection, even if the outbound proxy handled the connection as HTTP. This hint was added to the proxy API in linkerd/linkerd2-proxy-api#197, and released in `linkerd2-proxy-api` v0.8.0. This branch updates the Destination controller's dependency on `linkerd2-proxy-api` to v0.8.0, and changes the controller to send an `Opaque` protocol hint when the target port is marked as opaque on the destination pod. This should override the `H2` protocol hint that is added when the destination is meshed. I've also added a new test for this behavior. Fixes #9888 (along with linkerd/linkerd2-proxy#2209, which changes the proxy to actually handle the `Opaque` protocol hint).
The outbound proxy handles endpoints with the `opaque_transport` flag by opening a direct connection to the inbound proxy's inbound listener port, and sending a ProtoBuf `TransportHeader` including the target port of the originating outbound connection and an (optional) `SessionProtocol` describing the protocol used on that connection. Currently, outbound proxies initiating direct connections will *always* send `SessionProtocol` values communicating the protocol as understood by the outbound proxy. However, this is not always the desired behavior. Direct connections with `TransportHeader`s are used in two cases: for gateway connections, and for ports which are marked as opaque. When the inbound port is marked as opaque, the presence of a `SessionProtocol` tells the inbound proxy to handle that connection as the indicated protocol, which results in incorrect behavior when the inbound proxy's ServerPolicy configures the target port as opaque (see #9888). Therefore, the `Destination` proxy API has been updated to add a new `ProtocolHint`, `Opaque`, which indicates that an outbound proxy should _not_ send a `SessionProtocol` when initiating a direct connection, even if the outbound proxy handled the connection as HTTP. This hint was added to the proxy API in linkerd/linkerd2-proxy-api#197, and released in `linkerd2-proxy-api` v0.8.0. This branch updates the Destination controller's dependency on `linkerd2-proxy-api` to v0.8.0, and changes the controller to send an `Opaque` protocol hint when the target port is marked as opaque on the destination pod. This should override the `H2` protocol hint that is added when the destination is meshed. I've also added a new test for this behavior. Fixes #9888 (along with linkerd/linkerd2-proxy#2209, which changes the proxy to actually handle the `Opaque` protocol hint). Signed-off-by: Eric Anderson <eric@buoyant.io>
Currently, when the outbound proxy makes a direct connection prefixed
with a
TransportHeaderin order to send HTTP traffic, it will alwayssend a
SessionProtocolhint with the HTTP version as part of theheader. This instructs the inbound proxy to use that protocol, even if
the target port has a ServerPolicy that marks that port as opaque, which
can result in incorrect handling of that connection. See
linkerd/linkerd2#9888 for details.
In order to prevent this, linkerd/linkerd2-proxy-api#197 adds a new
ProtocolHintvalue to the protobuf endpoint metadata message. Thiswill allow the Destination controller to explicitly indicate to the
outbound proxy that a given endpoint is known to handle all connections
to a port as an opaque TCP stream, and that the proxy should not perform
a protocol upgrade or send a
SessionProtocolin the transport header.This branch updates the proxy to handle this new hint value, and adds
tests that the outbound proxy behaves as expected.
Once the Destination controller is updated to send this
ProtocolHintfor ports that are marked as opaque on the inbound side, this will fix
linkerd/linkerd2#9888.
This branch is currently a draft because the
linkerd2-proxy-apichanges have not been published yet. Once a new version of the proxy API
is published, we'll update this branch to depend on that, and this can
be merged.