envoyproxy/envoy

route match with tls client certificate does not work with session resumption

Open

#21.235 aperta il 11 mag 2022

Vedi su GitHub
 (18 commenti) (0 reazioni) (0 assegnatari)C++ (5373 fork)batch import
area/tlsbughelp wanted

Metriche repository

Star
 (27.997 star)
Metriche merge PR
 (Merge medio 8g) (378 PR mergiate in 30 g)

Descrizione

Title: route match with tls client certificate does not work with session resumption

Description: I configured optional mutual TLS (mTLS) based on the path using RouteMatch.TlsContextMatchOptions with Envoy 1.22.0. However, when cURL/OpenSSL client resumes TLS session, Envoy fails to route and client gets 404 (NR -- no route configured). A fresh (TLS) connection works as expected (Envoy routes with client certificate and returns 404 without client certificate).

When the client resumes the TLS session, from Envoy accesslog, I can see it has %DOWNSTREAM_PEER_SUBJECT% logged correctly. I suspect that TlsContextMatchOptions does not take resumed session when validating the certificate presented and validated conditions (which was done when the original session was first created).

Repro steps: Envoy 1.22.0 with cURL 7.83.0 + OpenSSL 1.1.1n on MacOS. Use the test.py in https://gist.github.com/rafan/b5474d575d69346b3abcc3b7d381a6b1 to let cURL send request in 3 seconds apart. For the 2nd request, cURL will re-create the connection (as CURLOPT_MAXAGE_CONN is 1 second) and attempt TLS session resumption. Then, Envoy returns 404 :

* Too old connection (3 seconds idle), disconnect it
* Connection 0 seems to be dead                                                                   
* Closing connection 0                           
* Hostname 127.0.0.1 was found in DNS cache
*   Trying 127.0.0.1:29443...                                                                     
* Connected to 127.0.0.1 (127.0.0.1) port 29443 (#1)
* ALPN: offers h2
* ALPN: offers http/1.1
*  CAfile: /tmp/cacert
*  CApath: none
* SSL re-using session ID
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
*  subject: C=US; ST=Denial; L=Springfield; O=Dis; CN=mysite.com
*  start date: May 11 09:27:36 2022 GMT
*  expire date: May 11 09:27:36 2023 GMT
*  issuer: C=US; ST=Denial; L=Springfield; O=Dis; CN=mysite.com
*  SSL certificate verify ok.
> GET /test_service HTTP/1.1
Host: 127.0.0.1:29443
User-Agent: PycURL/7.45.1 libcurl/7.83.0 (SecureTransport) OpenSSL/1.1.1n zlib/1.2.11 brotli/1.0.9 zstd/1.5.2 libidn2/2.3.2 libssh2/1.10.0 nghttp2/1.47.0 librtmp/2.3 OpenLDAP/2.6.1
Accept: */*
Content-type: application/json

* old SSL session ID is stale, removing
* old SSL session ID is stale, removing
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found 
< date: Wed, 11 May 2022 09:44:02 GMT
< server: envoy
< content-length: 0
< 
* Connection #1 to host 127.0.0.1 left intact

Admin and Stats Output: https://gist.github.com/rafan/b5474d575d69346b3abcc3b7d381a6b1

Config: https://gist.github.com/rafan/b5474d575d69346b3abcc3b7d381a6b1

Logs: https://gist.github.com/rafan/b5474d575d69346b3abcc3b7d381a6b1, access log:

[2022-05-11T09:29:18.761Z] "GET /test_service HTTP/1.1" 200 - 0 19 4 1 "-" "PycURL/7.45.1 libcurl/7.83.0 (SecureTransport) OpenSSL/1.1.1n zlib/1.2.11 brotli/1.0.9 zstd/1.5.2 libidn2/2.3.2 libssh2/1.10.0 nghttp2/1.47.0 librtmp/2.3 OpenLDAP/2.6.1" "bec7c827-ad10-452d-bf0d-66327bca2b6a" "127.0.0.1:29443" "172.27.0.2:8080" "CN=mysite.com,O=Dis,L=Springfield,ST=Denial,C=US" "-"
[2022-05-11T09:29:21.791Z] "GET /test_service HTTP/1.1" 404 NR 0 0 0 - "-" "PycURL/7.45.1 libcurl/7.83.0 (SecureTransport) OpenSSL/1.1.1n zlib/1.2.11 brotli/1.0.9 zstd/1.5.2 libidn2/2.3.2 libssh2/1.10.0 nghttp2/1.47.0 librtmp/2.3 OpenLDAP/2.6.1" "48f1133e-15c2-442e-8641-8441baf97791" "127.0.0.1:29443" "-" "CN=mysite.com,O=Dis,L=Springfield,ST=Denial,C=US" "-"

Call Stack: n/a

Guida contributor