projectcontour / contour

Contour is a Kubernetes ingress controller using Envoy proxy.
https://projectcontour.io
Apache License 2.0
3.73k stars 680 forks source link

Enabling passthrough on an HTTPProxy that has routes breaks TLS #2702

Closed alexbrand closed 9 months ago

alexbrand commented 4 years ago

What steps did you take and what happened:

TL;DR: HTTPS routing to an HTTPProxy with routes stops working when virtualhost.tls.passthrough: true

  1. Created the following HTTPProxy resource:

    apiVersion: projectcontour.io/v1
    kind: HTTPProxy
    metadata:
    name: tls-example
    namespace: default
    spec:
    routes:
    - conditions:
    - prefix: /
    services:
    - name: s1
      port: 80
    virtualhost:
    fqdn: example.com
    tls:
      passthrough: false
      secretName: testsecret
  2. Validated that the service is reachable

$ curl -m 5 -v -k https://example.com > /dev/null
* Rebuilt URL to: https://example.com/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 18.219.6.38...
* TCP_NODELAY set
* Connected to example.com (18.219.6.38) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
} [277 bytes data]
* TLSv1.2 (IN), TLS handshake, Server hello (2):
{ [96 bytes data]
* TLSv1.2 (IN), TLS handshake, Certificate (11):
{ [1114 bytes data]
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
{ [300 bytes data]
* TLSv1.2 (IN), TLS handshake, Server finished (14):
{ [4 bytes data]
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
} [37 bytes data]
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
} [1 bytes data]
* TLSv1.2 (OUT), TLS handshake, Finished (20):
} [16 bytes data]
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
{ [1 bytes data]
* TLSv1.2 (IN), TLS handshake, Finished (20):
{ [16 bytes data]
* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
* ALPN, server accepted to use h2
* Server certificate:
*  subject: O=mkcert development certificate; OU=abrand@branda-a01.vmware.com
*  start date: Jul 20 16:28:24 2020 GMT
*  expire date: Jul 20 16:28:24 2030 GMT
*  issuer: O=mkcert development CA; OU=abrand@Alexanders-MacBook-Pro.local; CN=mkcert abrand@Alexanders-MacBook-Pro.local
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fc94c80c800)
> GET / HTTP/2
> Host: example.com
> User-Agent: curl/7.54.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200
< content-length: 1753
< content-type: text/html
< date: Mon, 20 Jul 2020 18:22:28 GMT
< x-envoy-upstream-service-time: 0
< server: envoy
<
{ [1753 bytes data]
100  1753  100  1753    0     0   7917      0 --:--:-- --:--:-- --:--:--  7932
* Connection #0 to host example.com left intact
  1. Flip the passthrough flag to true in the HTTPProxy

  2. The service is no longer reachable over HTTPS:

$ curl -m 5 -v -k https://example.com > /dev/null
* Rebuilt URL to: https://example.com/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 18.219.6.38...
* TCP_NODELAY set
* Connected to example.com (18.219.6.38) port 443 (#0)
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
} [277 bytes data]
  0     0    0     0    0     0      0      0 --:--:--  0:00:04 --:--:--     0* Operation timed out after 5000 milliseconds with 0 out of 0 bytes received
* stopped the pause stream!
  0     0    0     0    0     0      0      0 --:--:--  0:00:04 --:--:--     0
* Closing connection 0
curl: (28) Operation timed out after 5000 milliseconds with 0 out of 0 bytes received

The service is available without TLS, however:

$ curl -m 5 -v -k example.com > /dev/null
* Rebuilt URL to: example.com/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 18.219.6.38...
* TCP_NODELAY set
* Connected to example.com (IP redacted) port 80 (#0)
> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-length: 1752
< content-type: text/html
< date: Mon, 20 Jul 2020 18:20:49 GMT
< x-envoy-upstream-service-time: 1
< server: envoy
<
{ [1296 bytes data]
100  1752  100  1752    0     0  17841      0 --:--:-- --:--:-- --:--:-- 17877
* Connection #0 to host example.com left intact

What did you expect to happen:

Based on prior conversations with @stevesloka, it seems like this HTTPProxy should be deemed invalid as there are is tcpproxy block.

With that said, it seems like there might be another issue where the TLS configuration is not being applied properly in this scenario.

Anything else you would like to add: [Miscellaneous information that will assist in solving the issue.]

Environment:

youngnick commented 4 years ago

I'm not one hundred percent sure, but I believe that the HTTPProxy routing insecure traffic to port 80 when passthrough: true is set was there at a customer request - to allow basically the same function as the insecure redirect does when terminating TLS.

I agree that a HTTPProxy with passthrough: true should have a tcpproxy block, or should be invalid.

github-actions[bot] commented 10 months ago

The Contour project currently lacks enough contributors to adequately respond to all Issues.

This bot triages Issues according to the following rules:

You can:

Please send feedback to the #contour channel in the Kubernetes Slack

github-actions[bot] commented 9 months ago

The Contour project currently lacks enough contributors to adequately respond to all Issues.

This bot triages Issues according to the following rules:

You can:

Please send feedback to the #contour channel in the Kubernetes Slack