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

support HTTP/1.1 CONNECT for proxied upstreams #3664

Closed
bdecoste opened this issue Sep 24, 2020 · 7 comments · Fixed by #4358
Closed

support HTTP/1.1 CONNECT for proxied upstreams #3664

bdecoste opened this issue Sep 24, 2020 · 7 comments · Fixed by #4358
Labels
Type: Enhancement New feature or request

Comments

@bdecoste
Copy link
Contributor

Is your feature request related to a problem? Please describe.
I am unable to connect from envoy to an internet upstream through corporate proxy

Describe the solution you'd like
support HTTP/1.1 CONNECT for proxied upstreams

envoyproxy/envoy#11308

@bdecoste bdecoste added the Type: Enhancement New feature or request label Sep 24, 2020
@kdorosh
Copy link
Contributor

kdorosh commented Dec 1, 2020

upstream envoy issue, not a gloo one

@kdorosh kdorosh closed this as completed Dec 1, 2020
@kdorosh
Copy link
Contributor

kdorosh commented Feb 19, 2021

documenting config for HTTP request -> envoy (encapsulate in HTTP Connect) -> HTTP Connect-enabled proxy -> upstream.

this is useful, for example, if the HTTP Connect enabled proxy is in a DMZ with internet access, but envoy and your other services are not on the internet.

put the following envoy config on clipboard:

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address:
      protocol: TCP
      address: 0.0.0.0
      port_value: 9903
static_resources:
  listeners:
    - name: listener_0
      address:
        # use an in memory pipe here instead, see example in following comment below
        socket_address:
          protocol: TCP
          address: 0.0.0.0
          port_value: 10000
      filter_chains:
        - filters:
            - name: tcp
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
                stat_prefix: tcp_stats
                cluster: "cluster_0"
                tunneling_config:
                  hostname: host.com:443
    - name: listener_1
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 9999
      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
                codec_type: AUTO
                stat_prefix: prefix
                http_filters:
                  - name: envoy.filters.http.router
                route_config:
                  name: demo_route
                  virtual_hosts:
                    - name: demo_host
                      domains:
                        - "*"
                      routes:
                        - match:
                            prefix: "/"
#                            headers:
#                              - name: ":method"
#                                exact_match: GET
                          route:
                            cluster: tcp_self_cluster
  clusters:
    - name: cluster_0
      type: LOGICAL_DNS
      connect_timeout: 5s
      # This ensures HTTP/1.1 CONNECT is used for establishing the tunnel.
      typed_extension_protocol_options:
        envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
          "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
          explicit_http_config:
            http_protocol_options: {}
      load_assignment:
        cluster_name: cluster_0
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      # in this example, this is the address of the proxy in DMZ (supports HTTP Connect)
                      address: host.docker.internal
                      port_value: 9876
    - name: tcp_self_cluster
      connect_timeout: 5.000s
      load_assignment:
        cluster_name: tcp_self_cluster
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: 127.0.0.1
                      port_value: 10000
      upstream_connection_options:
        tcp_keepalive: {}
      type: STATIC

and run envoy:

docker run -p 10000:10000 -p 9903:9903 -p 9999:9999 --rm envoyproxy/envoy-dev:b77157803df9a1e6dff53cc616b32ddbf79f83f2 --config-yaml "$(pbpaste)" -l trace

Then start a fake "echo server" as the upstream:

(printf "HTTP/1.1 200 OK\n\n";cat) | nc -l 9876

And make an HTTP request:

curl -v 127.0.0.1:9999

The flow here is:

  • HTTP request to envoy at port 9999 -> envoy forwards to itself at port 10000 (so TCP filter can match for HTTP Connect) -> envoy treats the HTTP request as TCP, sends everything after the headers as raw TCP in new encapsulated HTTP Connect request to upstream cluster (e.g., proxy in a DMZ)

Reopening because we need to expose some envoy config to support this flow

edit: upon further review, the second cluster and listener aren't necessary for POC. curl -v 127.0.0.1:10000 would have worked, although the "loopback" is still necessary to get matching for this tunneling config at the route level.

@kdorosh kdorosh reopened this Feb 19, 2021
@kdorosh
Copy link
Contributor

kdorosh commented Feb 23, 2021

If you want to test using SSL:

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address:
      protocol: TCP
      address: 0.0.0.0
      port_value: 9903
static_resources:
  listeners:
    - name: listener_0
      address:
        pipe:
          path: "@/cluster_0"
      filter_chains:
        - filters:
            - name: tcp
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
                stat_prefix: tcp_stats
                cluster: "cluster_0"
                tunneling_config:
                  hostname: host.com:443
    - name: listener_1
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 9999
      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
                codec_type: AUTO
                stat_prefix: prefix
                http_filters:
                  - name: envoy.filters.http.router
                route_config:
                  name: demo_route
                  virtual_hosts:
                    - name: demo_host
                      domains:
                        - "*"
                      routes:
                        - match:
                            prefix: "/"
                          route:
                            cluster: tcp_self_cluster
  clusters:
    - name: cluster_0
      type: LOGICAL_DNS
      connect_timeout: 5s
      # This ensures HTTP/1.1 CONNECT is used for establishing the tunnel.
      typed_extension_protocol_options:
        envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
          "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
          explicit_http_config:
            http_protocol_options: {}
      transport_socket:
        name: envoy.transport_sockets.tls
        typed_config:
          '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
          common_tls_context:
            tls_certificates:
              - certificate_chain:
                  # base64 encoded
                  inline_bytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNsakNDQVg0Q0NRQ2ZPMXBKcXdQLzZEQU5CZ2txaGtpRzl3MEJBUXNGQURBTk1Rc3dDUVlEVlFRR0V3SlYKVXpBZUZ3MHlNVEF5TWpNeU1URTNNVEJhRncweU1UQXpNalV5TVRFM01UQmFNQTB4Q3pBSkJnTlZCQVlUQWxWVApNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXIxYUY2TWJwb2ZDOWVyODBHazloClJ5RlYyQjBEM1RkOVJ1VUYxYTFYNFhCVGdGYUxvN0RQbFlDSFVBSWRvUmRpSlVqeDZ2by8vY1h4TmcxRDRGMy8KY1owazFpTVROL0pvQm9QVitpa3RCMGJCUURFSGVWV2p4a0J4S1pFSGE0aEgrUyt2alhmSXRBSEJrY2tTcFZQcApBRmJzU0kvbi9XREZBbTlvNUlBZXR5eTJKdEhXbVlKa0IrSU90dFNtN2RZazRnMmVxS0lVSWh3dE5acTRZeU9SCkoyQ2g2aXV4VEtmb3Y4OEF5SDJxZEd5TkVlVlhVNndtNWdhek1XUXo4SmsvMExyYW1PVlVldGcxTEVBLys1VVEKZXJqU2NNWFhPQW5OaGpPdjBqdEJhWUhod25FVlg4R2NwWGFZc1ZETElhSWphMDVrODFqazFOcWtUbTFLc0Z2dQpUUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQXVNSFEyVTE5SlA3d1d1VFdYS0NjenRtb1JWT2dDCmxLMlJQZzJYSWNPQjRMWXdkV2ExR3dSQkhLYVFDNWh5ME0rSEhhRTVSMVI5SURPaFJzblZTWGUzZTJucjZFRFIKRmUwdEtYWE5yL2pzNXhFR0xHV2xFYmZ6SFVEQWxtRU9SVXhuUFlFMU52eHBVVVVCMFg4c04zMTlPaG1uRDZkTApMZ25Pcy9LZXpJZFgwV2lrakZmR1c2d0lYZDBORmNmSjI0YjVJbHdDdHVSUW81cG5UVS9FWWM4SXZpaFdhL2VjCjBuM3R1WVlwMjBNUGxhY0JxQ2pQbU1QM1VnaEY2ZE1UMnFrRGtVcFkyc05Nc0JMVkZyYXh0L2lBMlhkbUlqdVMKMU8xRVBlZWludDlaQUNUcmVaQ2Rzblk3b0JJUzdwaWkva210U1BSV2lSMlNqWlRiMXZlcHFyMmYKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
                private_key:
                  # base64 encoded
                  inline_bytes: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2QUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktZd2dnU2lBZ0VBQW9JQkFRQ3ZWb1hveHVtaDhMMTYKdnpRYVQyRkhJVlhZSFFQZE4zMUc1UVhWclZmaGNGT0FWb3Vqc00rVmdJZFFBaDJoRjJJbFNQSHErai85eGZFMgpEVVBnWGY5eG5TVFdJeE0zOG1nR2c5WDZLUzBIUnNGQU1RZDVWYVBHUUhFcGtRZHJpRWY1TDYrTmQ4aTBBY0dSCnlSS2xVK2tBVnV4SWorZjlZTVVDYjJqa2dCNjNMTFltMGRhWmdtUUg0ZzYyMUtidDFpVGlEWjZvb2hRaUhDMDEKbXJoakk1RW5ZS0hxSzdGTXAraS96d0RJZmFwMGJJMFI1VmRUckNibUJyTXhaRFB3bVQvUXV0cVk1VlI2MkRVcwpRRC83bFJCNnVOSnd4ZGM0Q2MyR002L1NPMEZwZ2VIQ2NSVmZ3WnlsZHBpeFVNc2hvaU5yVG1UeldPVFUycVJPCmJVcXdXKzVOQWdNQkFBRUNnZ0VBR3FSRStKZXd6RUJ1S2daL2ZqZnRpZ2RRcWVQT3dJQTc4dGU5eVRmcmtIK20KMEd0V0VHcy9QM0ltSFV3VkFITXpJSU15N3dkVFRkWVR6cWk1VlpBeXppcVlmRWtjRkhZcXhFS244cmpxOUo0VgpveEZRRjJtaDF1L1h3ZjhkWjROdm5EZFlyMkF5Q05memQ1bGIwZThzQ2pjcTgrT1oxbkFydnpENmVTM1dmUEozCjFWQkVadUVNUCtsWnZqMmdkQWJWVTkrTURzS2hRUm44dS9kcnByby80NG5FbmFSNkpaQmNiRkZtYmJtOVNKODIKSjRHTy82YXllWCs0UnYrOHducTloQVpDY2tIR3JFWkNBUGxJUE9aY1pTMkRZYUxsZTRBeElFSS9CRjh6dkx0OApJTFRTY3cwZUFTc0J3TkMveEJkWUk4S0JjSklWWDk1Z2E3cHJIYlJ3NlFLQmdRRGIxZ3cyUWdVeFNhckV1YzNKCjlxUnpFRk90SURWY2d2alJ3NE9aVHNTZTlKdnc1YmFVRDRMVzFIODNMT2g3T01PZmlvQ3ZUUGJSUm1IRHRvWEUKMXp6dnRXdnBaWUtLUXVLQlRzcm5VSmtLQWZoS0x0QkVTOGFHVEhIaGQ4S3MvazlXMGcvNHY3M3ZuQUowelBHegp6VU9mQWJmN0JHRnMzWVdscERERi9GOUU1d0tCZ1FETUxvYkFmNmkzNytUZ3pVY1FWc3R4NUJ4YStxYzZia0xUCjkwRHVzWUFsR3dYaUNDN0lXWjIrV2M4Z0tjdUJWY1Exc3N1dVVidGwrQVgyam8rUmNIalpVUERqN0JEMmx0bUUKL2xUZkt0Y3RuRy9semh5c05aY2ZIQTRGNnd3SnMwQk0wdGVZaW01SkU3WDYrRFNBOTcyVVVyRGN0N1R3RXpTeQp1STlUNS9yWXF3S0JnQkxmS3lrMVBiRGZmQk5yUitsQWpSbDdtMU5QWW9WUWtQK2c0eGswRTlqNWNyR1paclVMCko5WTlZN1plMm81SmJ6R3crQjhVWWxQUTBPKzJLWUdlWUpMTFpqb2hCclhMekJvQm81Vjc2OGRhSi9CbVdHYWsKZ3FSZ3g1M3RZLzdwemZITUVxYnQvdVlrNUdrV2R1RlNpNjJJdmp5RVFjRFF1M3Bldi9rZkV5YWRBb0dBYjhhRQpwRHIrZlB0SjI3cmt6VkFHZmFtMzBDSnBpN1l5eFdFVTNkYXo1UncvQXpjaGpUSnFCWHVheE91OGFXZ3ZTb28vCnNJVXp4cVdaZGhrakJTYUNNYzE2b2Z0b2FlVzQzSEp5dWR6MUFSWWp0N1Uyd3h0dlNHdU9UYlVYMlBPVkhybEoKcDBzWkJzNVFrRHh5V2F2Rno3M1k3bXR2RlFJZWxqd3MwbTByU0pNQ2dZQitMeUM1andrMElNNEpaMXZ2SVFLMApROGExWFNQUUhXVytSNDZpL295QzRFdEN6QmE0M0d2dTh5Q2F3ZFozam5rS2Fuc1hOTko1ZlRDdlhsak1aV0p6CjdEODQvNVZxMWJMTXdLY1ZpamRScFVrMWh3MEdHTFVUZy9sUy9STmJ5Vk16Wm1yaUVoY1NQaGR5a292ZHhmSWQKSE9ub2RhdmthSmw0YmtnSWxyTk1Fdz09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K
      load_assignment:
        cluster_name: cluster_0
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      # in this example, this is the address of the proxy in DMZ (supports HTTP Connect)
                      address: host.docker.internal
                      port_value: 9876
    - name: tcp_self_cluster
      connect_timeout: 5.000s
      load_assignment:
        cluster_name: tcp_self_cluster
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    pipe:
                      path: "@/cluster_0"
      upstream_connection_options:
        tcp_keepalive: {}
      type: STATIC

Write this as tls.key file:

-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCvVoXoxumh8L16
vzQaT2FHIVXYHQPdN31G5QXVrVfhcFOAVoujsM+VgIdQAh2hF2IlSPHq+j/9xfE2
DUPgXf9xnSTWIxM38mgGg9X6KS0HRsFAMQd5VaPGQHEpkQdriEf5L6+Nd8i0AcGR
yRKlU+kAVuxIj+f9YMUCb2jkgB63LLYm0daZgmQH4g621Kbt1iTiDZ6oohQiHC01
mrhjI5EnYKHqK7FMp+i/zwDIfap0bI0R5VdTrCbmBrMxZDPwmT/QutqY5VR62DUs
QD/7lRB6uNJwxdc4Cc2GM6/SO0FpgeHCcRVfwZyldpixUMshoiNrTmTzWOTU2qRO
bUqwW+5NAgMBAAECggEAGqRE+JewzEBuKgZ/fjftigdQqePOwIA78te9yTfrkH+m
0GtWEGs/P3ImHUwVAHMzIIMy7wdTTdYTzqi5VZAyziqYfEkcFHYqxEKn8rjq9J4V
oxFQF2mh1u/Xwf8dZ4NvnDdYr2AyCNfzd5lb0e8sCjcq8+OZ1nArvzD6eS3WfPJ3
1VBEZuEMP+lZvj2gdAbVU9+MDsKhQRn8u/drpro/44nEnaR6JZBcbFFmbbm9SJ82
J4GO/6ayeX+4Rv+8wnq9hAZCckHGrEZCAPlIPOZcZS2DYaLle4AxIEI/BF8zvLt8
ILTScw0eASsBwNC/xBdYI8KBcJIVX95ga7prHbRw6QKBgQDb1gw2QgUxSarEuc3J
9qRzEFOtIDVcgvjRw4OZTsSe9Jvw5baUD4LW1H83LOh7OMOfioCvTPbRRmHDtoXE
1zzvtWvpZYKKQuKBTsrnUJkKAfhKLtBES8aGTHHhd8Ks/k9W0g/4v73vnAJ0zPGz
zUOfAbf7BGFs3YWlpDDF/F9E5wKBgQDMLobAf6i37+TgzUcQVstx5Bxa+qc6bkLT
90DusYAlGwXiCC7IWZ2+Wc8gKcuBVcQ1ssuuUbtl+AX2jo+RcHjZUPDj7BD2ltmE
/lTfKtctnG/lzhysNZcfHA4F6wwJs0BM0teYim5JE7X6+DSA972UUrDct7TwEzSy
uI9T5/rYqwKBgBLfKyk1PbDffBNrR+lAjRl7m1NPYoVQkP+g4xk0E9j5crGZZrUL
J9Y9Y7Ze2o5JbzGw+B8UYlPQ0O+2KYGeYJLLZjohBrXLzBoBo5V768daJ/BmWGak
gqRgx53tY/7pzfHMEqbt/uYk5GkWduFSi62IvjyEQcDQu3pev/kfEyadAoGAb8aE
pDr+fPtJ27rkzVAGfam30CJpi7YyxWEU3daz5Rw/AzchjTJqBXuaxOu8aWgvSoo/
sIUzxqWZdhkjBSaCMc16oftoaeW43HJyudz1ARYjt7U2wxtvSGuOTbUX2POVHrlJ
p0sZBs5QkDxyWavFz73Y7mtvFQIeljws0m0rSJMCgYB+LyC5jwk0IM4JZ1vvIQK0
Q8a1XSPQHWW+R46i/oyC4EtCzBa43Gvu8yCawdZ3jnkKansXNNJ5fTCvXljMZWJz
7D84/5Vq1bLMwKcVijdRpUk1hw0GGLUTg/lS/RNbyVMzZmriEhcSPhdykovdxfId
HOnodavkaJl4bkgIlrNMEw==
-----END PRIVATE KEY-----

Write TLS this as tls.crt file:

-----BEGIN CERTIFICATE-----
MIICljCCAX4CCQCfO1pJqwP/6DANBgkqhkiG9w0BAQsFADANMQswCQYDVQQGEwJV
UzAeFw0yMTAyMjMyMTE3MTBaFw0yMTAzMjUyMTE3MTBaMA0xCzAJBgNVBAYTAlVT
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr1aF6MbpofC9er80Gk9h
RyFV2B0D3Td9RuUF1a1X4XBTgFaLo7DPlYCHUAIdoRdiJUjx6vo//cXxNg1D4F3/
cZ0k1iMTN/JoBoPV+iktB0bBQDEHeVWjxkBxKZEHa4hH+S+vjXfItAHBkckSpVPp
AFbsSI/n/WDFAm9o5IAetyy2JtHWmYJkB+IOttSm7dYk4g2eqKIUIhwtNZq4YyOR
J2Ch6iuxTKfov88AyH2qdGyNEeVXU6wm5gazMWQz8Jk/0LramOVUetg1LEA/+5UQ
erjScMXXOAnNhjOv0jtBaYHhwnEVX8GcpXaYsVDLIaIja05k81jk1NqkTm1KsFvu
TQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAuMHQ2U19JP7wWuTWXKCcztmoRVOgC
lK2RPg2XIcOB4LYwdWa1GwRBHKaQC5hy0M+HHaE5R1R9IDOhRsnVSXe3e2nr6EDR
Fe0tKXXNr/js5xEGLGWlEbfzHUDAlmEORUxnPYE1NvxpUUUB0X8sN319OhmnD6dL
LgnOs/KezIdX0WikjFfGW6wIXd0NFcfJ24b5IlwCtuRQo5pnTU/EYc8IvihWa/ec
0n3tuYYp20MPlacBqCjPmMP3UghF6dMT2qkDkUpY2sNMsBLVFraxt/iA2XdmIjuS
1O1EPeeint9ZACTreZCdsnY7oBIS7pii/kmtSPRWiR2SjZTb1vepqr2f
-----END CERTIFICATE-----

Then set up TLS listener

(printf "HTTP/1.1 200 OK\n\n";cat) | ncat -l 9876 --ssl-cert test.crt --ssl-key test.key

And make requests:

curl -v 127.0.0.1:9999

@kdorosh
Copy link
Contributor

kdorosh commented Feb 24, 2021

In the customer env, the TLS context must go on tcp_self_cluster instead of cluster_0 for this to work

@gsustek
Copy link

gsustek commented Jan 21, 2022

for me above envoy config did not work, but following one does:

static_resources:
listeners:
- name: listener_0
address:
pipe:
path: "@/cluster_0"
filter_chains:
- filters:
- name: tcp
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
stat_prefix: tcp_stats
cluster: "cluster_0"
tunneling_config:
hostname: jwt.io:443
headers_to_add:
- header:
key: Proxy-Authorization
value: Basic dXNlcjpwYXNzd29yZA== # replace with your credentials
- header:
key: Proxy-Connection
value: Keep-Alive
append: false
- name: listener_1
address:
socket_address:
address: 0.0.0.0
port_value: 10000
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
codec_type: AUTO
stat_prefix: prefix
http_filters:
- name: envoy.filters.http.router
route_config:
name: demo_route
virtual_hosts:
- name: demo_host
domains:
- "*"
routes:
- match:
prefix: "/"
route:
host_rewrite_literal: jwt.io
cluster: tcp_self_cluster
clusters:
- name: cluster_0
type: LOGICAL_DNS
connect_timeout: 5s
# This ensures HTTP/1.1 CONNECT is used for establishing the tunnel.
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http_protocol_options: {}
load_assignment:
cluster_name: cluster_0
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
# in this example, this is the address of the proxy in DMZ (supports HTTP Connect)
address: 192.168.168.211
port_value: 8080
- name: tcp_self_cluster
connect_timeout: 5.000s
load_assignment:
cluster_name: tcp_self_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
pipe:
path: "@/cluster_0"
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
sni: jwt.io

      curl -v  127.0.0.1:10000

@scrocquesel
Copy link

for me above envoy config did not work, but following one:

static_resources: listeners: - name: listener_0 address: pipe: path: "@/cluster_0" filter_chains: - filters: - name: tcp typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy stat_prefix: tcp_stats cluster: "cluster_0" tunneling_config: hostname: jwt.io:443 headers_to_add: - header: key: Proxy-Authorization value: Basic dXNlcjpwYXNzd29yZA== # replace with your credentials append: false - name: listener_1 address: socket_address: address: 0.0.0.0 port_value: 10000 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 codec_type: AUTO stat_prefix: prefix http_filters: - name: envoy.filters.http.router route_config: name: demo_route virtual_hosts: - name: demo_host domains: - "*" routes: - match: prefix: "/" route: cluster: tcp_self_cluster clusters: - name: cluster_0 type: LOGICAL_DNS connect_timeout: 5s # This ensures HTTP/1.1 CONNECT is used for establishing the tunnel. typed_extension_protocol_options: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions explicit_http_config: http_protocol_options: {} load_assignment: cluster_name: cluster_0 endpoints: - lb_endpoints: - endpoint: address: socket_address: # in this example, this is the address of the proxy in DMZ (supports HTTP Connect) address: 192.168.168.211 port_value: 8080 - name: tcp_self_cluster connect_timeout: 5.000s load_assignment: cluster_name: tcp_self_cluster endpoints: - lb_endpoints: - endpoint: address: pipe: path: "@/cluster_0" transport_socket: name: envoy.transport_sockets.tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext sni: jwt.io

      curl -v --header 'Host: jwt.io' 127.0.0.1:10000

For improved perf, you may use a pipe loopback see https://gist.github.com/cortex93/6d7cd9738b077d0447ab891cbacd0d5e

@gsustek
Copy link

gsustek commented Jan 24, 2022

i adapted yaml once more time

this configuration supports only reaching https url's via forward proxy.
"curl --insecure -v -x http://user:password@localhost:8080 -L https://jwt.io "
looking in tcpdump we can see there is two http request:

  1. curl is using HTTP CONNECT VERB to connect jwt.io:443 via FW Proxy service by making Tunnel:
    "CONNECT jwt.io:443 HTTP/1.1
    Host: jwt.io:443
    Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==
    User-Agent: curl/7.77.0
    Proxy-Connection: Keep-Alive

HTTP/1.1 200 Connection established"

second:
TLS tunnel inside proxy-protocol TLS Client Hello
third: HTTP get jwt.io

so in gloo case
0. curl to locally exposed virtual service. curl -v localhost:10000

  1. HTTP/1.1 CONNECT is used for establishing the tunnel with proxy-auth and proxy-conn headers
  2. create TLS connection and rewrite hostname
  3. connect to jwt.io:443 via FW proxy

i assume that this structure would fit gloo virtualservice / upstream via FW proxy paradigm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants