-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
listener/port sharing across protocols #527
Comments
Just jotting down notes from our Gitter discussion. There are a few ways we can go about this:
1 is the simplest, but probably less clean (though I could be convinced it is the right solution). |
I would also like to suggest that we keep this feature as a low priority until we see real use cases where there are no workarounds or workarounds are clunky (i.e., services with different protocols and colliding ports (e.g., mysql:8080, web:8080). ). Given the relatively large number of ports available, it might be far easier to impose the restriction on the end user that one cannot have two services of different layer-7 protocols listening on the same port, be it http, mongo, redis, custom TCP, udp, etc. How common is it for people to run their redis servers on port 8080, backend oracle database on port 8080, and their NodeJS frontend on port 8080 as well ? The state space of all possible configuration combinations in a generic distributed system framework is huge (be it kubernetes or mesos or some non container environment). Supporting all possible use cases (whether they are being really used by users) results in unnecessary complexity, instability and more potential for misconfiguration. All said, the one neat feature that might be related to this, is the ability to do (a) http and https on same port (similar to standard web servers), (b) tcp/udp on same port (e.g., DNS over UDP and DNS over TCP), targeting the same upstream cluster in both cases. These two are far more common, and there are several examples around the web. However, supporting these use cases does not involve complicated work arounds. We could get away with a generic L4 listener type that does tcp/udp for same upstream cluster, and a generic http conn man that supports no tls and tls on same port. |
This is going to be covered by the v2 configuration/API for LDS. There will be "routing rules" that will allow selecting different filter stacks within a listener. I'm going to close this in favor of that work. cc @htuch |
@kyessenov @mattklein123 I run into the same problem when trying to integrate istio into our product. If I put the http connection manager before the tcp filter, will http connection manager fail through to the tcp filter, or it just terminate the connection? |
@zhaohuabing HTTP connection manager will force L7 on the filter stack, there is no fallback behavior. Do you really need multiple protocols on the same port? If so, how would you like to see this fallback behavior work? |
@htuch Istio complains port conflict when building outbound listeners if there are TCP and HTTP services on the same port. It simply abandons TCP services, which causes unexpected behaviours for the application. Let's say we have a listener 0.0.0.0:9080, which only has an HTTP connection manager but will receive both HTTP and plain TCP traffic. Right now the plain TCP traffic is sent to the HTTP connection manager and then be terminated because it can't be handled as level 7. I would like the HTTP connection manager fail through to the next network filter in the chain, then it will be handled by original dst cluster, routing the traffic to its original destination.
|
@zhaohuabing how do you propose HTTP connection manager to detect that traffic is non-HTTP? At what point do you decide that this is a TCP connection vs. a badly formed HTTP request? Is this some heuristic on the first few bytes for example? |
@htuch it's a good point. I think rather than fail through form HTTP connection manager, a more reasonable solution is to use a listener filter to tell the protocol before passing the request to a filter chain. Then we can split HTTP and TCP to different filter to handle them. Is this possible? |
@zhaohuabing if we could allow listener filters to set arbitrary metadata and then add a metadata match criteria to the filter chain match, that would work as you describe. This seems like a good solution, I agree. |
We are trying to build a filter to identify the protocol and add other metadata such as HTTP host header, maybe we could override the protocol and servername metadata now using by TLS indication filter? However, it would be nice if this feature could be supported by envoy officially. |
When listener filters are run, the TLS handshake has not yet completed, so if this is a TLS connection, you cannot use any plaintext to set these values. If it's a plaintext connection, this would be feasible. It seems like what you may need is a network-filter which determines the protocol, and then has multiple sub-filter-chains, one of which can be selected for any given connection. |
Yes, that's exactly what I'm trying to achieve.
…On Tue, Jan 8, 2019, 3:28 AM Greg Greenway ***@***.*** wrote:
When listener filters are run, the TLS handshake has not yet completed, so
if this is a TLS connection, you cannot use any plaintext to set these
values. If it's a plaintext connection, this would be feasible.
It seems like what you may need is a network-filter which determines the
protocol, and then has multiple sub-filter-chains, one of which can be
selected for any given connection.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#527 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABQrItmN6jMWfWFejCpLMQzvtojoUloeks5vA5_qgaJpZM4MRm2j>
.
|
@ggreenway true. So, we want to set some metadata from arbitrary network filters and then match on this in HTTP connection manager... or we could have HCM still have a single filter chain and have a single match criteria which if not met make it pass-thru, allowing for multiple HCMs to be present at the end of a L4 filter chain. Actually, thinking about this, we could have a special "metadata match L4 filter" which does two things:
This would then make this kind of matching possible for any network filter, e.g. Redis. |
@htuch was something like what @zhaohuabing discussed ever implemented? I'm seeing a few issues about this like but all of them closed without a resolution. My goal is to expose an HTTP endpoint like /metrics and have all other TCP traffic go to the TCP proxy. (With the HTTP and TCP filters having different TLS contexts) |
See https://www.envoyproxy.io/docs/envoy/latest/configuration/listener_filters/http_inspector. I think you could use this to do ^. |
* Add support for all headers statuses returned by WASM. With this change, a WASM filter can return, say, StopAllIterationAndWatermark. This is useful when a WASM filter might want to call an external service and use the result to change an HTTP header before continuing processing the body. Signed-off-by: Gregory Brail <gregbrail@google.com>
Thanks that was very helpful. Achieved something similar with the following config.
|
Description: #498 did not fully solve #492. The reset cleanly destructed all objects. However, because destruction was posted in to the event dispatcher, the event dispatcher was left with bad accesses. This PR fixes the issue by issuing shutdown on the dispatcher, and only destructing once the event loop has exited and control has returned to the Engine's run function. Risk Level: med - fixing crash on shutdown Testing: local Fixes #492 Signed-off-by: Jose Nino <jnino@lyft.com> Signed-off-by: JP Simard <jp@jpsim.com>
Description: #498 did not fully solve #492. The reset cleanly destructed all objects. However, because destruction was posted in to the event dispatcher, the event dispatcher was left with bad accesses. This PR fixes the issue by issuing shutdown on the dispatcher, and only destructing once the event loop has exited and control has returned to the Engine's run function. Risk Level: med - fixing crash on shutdown Testing: local Fixes #492 Signed-off-by: Jose Nino <jnino@lyft.com> Signed-off-by: JP Simard <jp@jpsim.com>
Using iptables rules and
use_original_dst
causes issues since multiple protocols get combined in a single listener section in Envoy configuration. For example, consider two micro-services "mysql" and "web" that listen on the same port 9000 but use TCP and HTTP. In a third service egress proxy config, we capture packets by redirecting to another listener with iptables and recover the original port withuse_original_dst
to handle both service traffic in listener on port 9000. We can distinguish between the two services by their virtual IPs: MYSQL_SERVICE_IP:9000 and WEB_SERVICE_IP:9000. However, tcp_proxy and http_connection_manager cannot coexist in together since tcp_proxy always terminates connections and does not fall through.The text was updated successfully, but these errors were encountered: