envoyproxy / envoy

Cloud-native high-performance edge/middle/service proxy
https://www.envoyproxy.io
Apache License 2.0
24.53k stars 4.73k forks source link

Any way to route specific traffic to a external proxy #34651

Closed ChrWeissDe closed 1 month ago

ChrWeissDe commented 2 months ago

Dear Community,

We have got the requirement to route specific traffic - based on the domain name via an additional external proxy.

Example client request 01: https://my-api.internal.com/hello --> should be routed directly
client request 02: https://other-api.external.com/hello --> should be routed via an additional (external) proxy

Is there any way to achieve this with Envoy?

We already tried to use "extensions.filters.network.tcp_proxy.v3.TcpProxy" - but failed as it seems that it allows only one entry (so one proxy for all TCP Traffic - or not proxy at all)

nbaws commented 2 months ago

For this you want two virtual hosts, and two static clusters. vhost 1 is for my-api vhost 2 is for other-api You will reach each vhost depending on the Host/Authority header your client sends. You can test this with curl like follows curl localhost:8099 -H "Host: other-api.internal.com" -v

cluster 1 and 2 is effectively statically routed from each vhost.

This is using cleartext http, converting to tls is left as an exercise for the reader :)

Example config is here:

static_resources:
  listeners:
  - name: http_connect
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 8099
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: "ingress_http"
          route_config:
            name: test
            virtual_hosts:
            - name: my-api
              domains:
              - "my-api.internal.com"
              routes:
              - match:
                  prefix: '/'
                route:
                  cluster: my-api
            - name: other-api
              domains:
              - "other-api.internal.com"
              routes:
              - match:
                  prefix: '/'
                route:
                  cluster: other-api
          http_filters:
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
  - name: my-api
    connect_timeout: 0.25s
    type: STATIC
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: my-api
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 1.2.3.4
                port_value: 80
  - name: other-api
    connect_timeout: 0.25s
    type: STATIC
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: other-api
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 2.3.4.5
                port_value: 80
ChrWeissDe commented 2 months ago

Hi @nbaws:
Thanks for the quick reply! Highly appreciated!

One thing were I still struggle:

At the end of the day I would like to do a 'standard curl' - and thus use the 443 port. E.g.: curl https://www.google.com

I tried to add your filter shown above to an exiting 'listeners' (have a standard Istio installation) - but somehow I failed.
Can you give me a hint where I need to place / add the filter ? (to which listener / to which context?)

nbaws commented 2 months ago

Take a look at this set of configurations for TLS: https://www.envoyproxy.io/docs/envoy/latest/start/sandboxes/tls

Your main issue will be how you want envoy to be presented to the client. Either it is presented as a http proxy, or as the real host (with appropriate certificate/s). The previous configuration is only dependent on the Host:/Authority: header being correct when it lands on Envoy. However TLS will complicate this as it will not validate correctly on your client unless the certificate being presented matches what your client is expecting to connect to.

ChrWeissDe commented 2 months ago

@nbaws:

Thanks a lot!

github-actions[bot] commented 1 month ago

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 "no stalebot" or other activity occurs. Thank you for your contributions.

github-actions[bot] commented 1 month ago

This issue has been automatically closed because it has not had activity in the last 37 days. If this issue is still valid, please ping a maintainer and ask them to label it as "help wanted" or "no stalebot". Thank you for your contributions.