Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proxy TCP connections over HTTP2 connection pools #1630

Closed
simonsj opened this issue Sep 13, 2017 · 20 comments · Fixed by #11146
Closed

Proxy TCP connections over HTTP2 connection pools #1630

simonsj opened this issue Sep 13, 2017 · 20 comments · Fixed by #11146
Assignees
Labels
enhancement Feature requests. Not bugs or questions. help wanted Needs help!

Comments

@simonsj
Copy link

simonsj commented Sep 13, 2017

I'd like to use Envoy as something like a stunnel replacement, but leveraging long-lived HTTP2 connection pools, like this:

client <-----> E1 <-----------> E2 <-----> server
         raw       encrypted         raw
         TCP       conn. pooled      TCP
                   HTTP2 tunnel

^ where neither the client nor server speaks any HTTP.

Clients use servers' IP addresses directly, so no DNS is involved.

I was thinking it should be possible to map TCP flows like that over long-lived HTTP2 tunnels.

After reading over issues and the mailing lists and experimenting a bit locally, it's not clear to me that this kind of mode exists today as-is. But I could have missed something.

Is it possible to configure Envoy for something like this? Would it be feasible to add such a mode?

@mattklein123 mattklein123 added the question Questions that are neither investigations, bugs, nor enhancements label Sep 13, 2017
@mattklein123
Copy link
Member

This is not supported out of the box. What does the HTTP/2 tunneling give you exactly? Are the TCP connections short lived? If this is needed a custom protocol is required. The best bet is probably some type of bi-directional gRPC streaming API that gets converted back to raw TCP on either side. You could build Envoy filters fairly easily to accomplish this.

@simonsj
Copy link
Author

simonsj commented Sep 14, 2017

What does the HTTP/2 tunneling give you exactly?

What I'm after to is multiplex multiple streams over the single encrypted HTTP/2 connection, trying to avoid needing to set up one new connection per raw TCP flow. I'd ideally be able to reuse that connection for lots of flows over time.

Are the TCP connections short lived?

Yes, in general; at most these connections could last up to 2 hours but most would fall into the seconds range.

If this is needed a custom protocol is required. The best bet is probably some type of bi-directional gRPC streaming API that gets converted back to raw TCP on either side. You could build Envoy filters fairly easily to accomplish this.

Thanks, this is helpful, and good to know there wasn't something in-the-box that I missed. I'll study up on the filter code.

@mattklein123
Copy link
Member

@simonsj if you potentially want to implement I can provide tips / rough overview. If this is something that the community would find useful we can upstream also.

@simonsj
Copy link
Author

simonsj commented Sep 14, 2017

@simonsj if you potentially want to implement I can provide tips / rough overview. If this is something that the community would find useful we can upstream also.

@mattklein123 that would be awesome, I'd love to give this a try.

@mattklein123
Copy link
Member

@simonsj here is a rough outline:

  1. I would define a gRPC streaming API that basically passes a trivial message back and forth. Each message would just contain raw bytes (you might potentially want to carry some kind of routing data along with the bytes but that's separate).

  2. You could follow along with tcp_proxy filter: https://github.com/envoyproxy/envoy/blob/master/source/common/filter/tcp_proxy.h. Specifically here: https://github.com/envoyproxy/envoy/blob/master/source/common/filter/tcp_proxy.cc#L207. Instead of making a raw TCP connection, you could instantiate a typed gRPC client following along with here: https://github.com/envoyproxy/envoy/blob/master/source/common/config/grpc_subscription_impl.h#L24

The above would give you the egress side of the equation. Then for ingress, you would write an HTTP filter which basically does tcp_proxy filter but in reverse.

  1. Parse gRPC incoming stream using grpc codec.
  2. Make TCP connection to local host or wherever.
  3. Feed bytes.

@mattklein123 mattklein123 added enhancement Feature requests. Not bugs or questions. and removed question Questions that are neither investigations, bugs, nor enhancements labels Oct 16, 2017
@mattklein123 mattklein123 changed the title Envoy as stunnel replacement for raw TCP using HTTP2 connection pools? Proxy TCP connections over HTTP2 connection pools Oct 16, 2017
@mattklein123
Copy link
Member

Switching this to a feature request. I think Google needs this also so they might implement. cc @alyssawilk

@PiotrSikora
Copy link
Contributor

Please don't reinvent the wheel. This should use extended CONNECT method proposed in https://tools.ietf.org/html/draft-mcmanus-httpbis-h2-websockets, and proxy TCP stream as a HTTP/2 stream without any extra gRPC encapsulation.

client <-----> E1 <-----------------> E2 <-----> server
         raw       HTTP/2 connection       raw
         TCP       :method = CONNECT       TCP
                   :protocol = tcp

@mattklein123
Copy link
Member

@PiotrSikora agreed. I was not aware of this proposal. Yes, let's implement this for sure.

@songole
Copy link

songole commented Feb 15, 2018

@PiotrSikora @mattklein123 We are also interested in this solution. However, the rfc is a draft and I guess the preferred solution may not be available anytime soon. Do you still recommend the previous approach in the mean time? Or, is there an easier solution with Websocket and avoid HTTP/2 ? The payload to tunnel for us is HTTP/1.1.

@PiotrSikora
Copy link
Contributor

@songole I don't have cycles to work on it right now, but I do recommend implementing the draft, the final version won't differ much from it (if at all).

@josdotso
Copy link

Is this kind of thing (multiplexed-TCP-proxy-over-one-upstream-listener) possible today in Envoy regardless of HTTP2? I'm trying to tunnel a bunch of TCP stuff to a single ELB port with mTLS and demux/terminate TLS on the backend.

Very loose idea of my use case:

screen shot 2018-04-20 at 12 00 35 pm

@mattklein123
Copy link
Member

@josdotso no, not possible today to multiplex TCP out of the box. This issue tracks developing some solution to the general problem.

@stale
Copy link

stale bot commented Jun 19, 2018

This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in the next 7 days unless it is tagged "help wanted" or other activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Jun 19, 2018
@alyssawilk alyssawilk added help wanted Needs help! and removed wontfix labels Jun 19, 2018
alyssawilk added a commit that referenced this issue Aug 28, 2018
)

This allows tunneling over H2, unfortunately only enabled via nghttp2_option_set_no_http_messaging until nghttp2/nghttp2#1181 is sorted out. See the big warnings about not using (at least without knowing you're going to have a roll-out that may break backwards-compatibility some time in the not too distant future)

Risk Level: Medium (changes are contained behind H2-with-Upgrade header which doesn't work today)
Testing: unit tests, and turned up the full H1/H2 upstream/downstream in the integration test
Docs Changes: for now, though I may take them out. I think they're useful for review.
Release Notes: not added since we don't want folks using it (outside of testbeds) yet.
#1630

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk alyssawilk self-assigned this Oct 17, 2018
alyssawilk added a commit that referenced this issue Oct 25, 2018
The main difference between what we had and official nghttp2 support is lack of support for upgrade-with-bodies (on request or response path). Adjusted header munging, tests, and docs accordingly.

Risk Level: Low (changes code on a "hidden" code path)
Testing: updated tests, new unit tests
Docs Changes: updated
Release Notes: noted H2 websocket support
Fixes #1630

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
alyssawilk added a commit that referenced this issue Apr 22, 2020
This should result in all Path() calls not altered in #10720 being safe for path-less CONNECT.
The major change for this PR is that requests without a path will not be considered gRPC requests. They're still currently rejected at the HCM, but when they are allowed through they will simply not be gRPC rather than causing crashes.

Risk Level: medium (L7 code refactor)
Testing: new unit tests
Docs Changes: n/a
Release Notes: n/a
Part of #1630 #1451

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
penguingao pushed a commit to penguingao/envoy that referenced this issue Apr 22, 2020
…oxy#10851)

This should result in all Path() calls not altered in envoyproxy#10720 being safe for path-less CONNECT.
The major change for this PR is that requests without a path will not be considered gRPC requests. They're still currently rejected at the HCM, but when they are allowed through they will simply not be gRPC rather than causing crashes.

Risk Level: medium (L7 code refactor)
Testing: new unit tests
Docs Changes: n/a
Release Notes: n/a
Part of envoyproxy#1630 envoyproxy#1451

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: pengg <pengg@google.com>
alyssawilk added a commit that referenced this issue Apr 28, 2020
CONNECT won't be very useful without proxy protocol support, and needs some pausing for security reasons, both coming soon.

Risk Level: Medium (router refactor)
Testing: unit tests and integration tests
Docs Changes: some
Release Notes: n/a (still hidden)
Part of #1630 #1451

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk
Copy link
Contributor

As said over on 1451 Envoy connect support is ready to play with.
I've got a couple of PRs in flight improving docs and cleaning up internal code flow, but feel free to start playing around with it!

alyssawilk added a commit that referenced this issue May 11, 2020
Risk Level: n/a
Testing: n/a
Docs Changes: connect docs improved
Release Notes: n/a
Part of #1451 and #1630

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
alyssawilk added a commit that referenced this issue May 13, 2020
Un-hiding CONNECT docs and config, now that it is implemented.

Risk Level: low (docs only)
Testing: in prior PRs
Docs Changes: yes
Release Notes: yes
Fixes #1630 and #1451

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
jpsim pushed a commit that referenced this issue Nov 28, 2022
Signed-off-by: Rafal Augustyniak <raugustyniak@lyft.com>
Signed-off-by: JP Simard <jp@jpsim.com>
jpsim pushed a commit that referenced this issue Nov 29, 2022
Signed-off-by: Rafal Augustyniak <raugustyniak@lyft.com>
Signed-off-by: JP Simard <jp@jpsim.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature requests. Not bugs or questions. help wanted Needs help!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants