TLS Handshake failure in WSL but not in Windows

Hi,

Having a funny issue with Docker-desktop running in WSL2 and Ubuntu.

Within WSL i am getting the error Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: TLS handshake timeout. I have a corporate VPN/filter as well (Fortinet). This was working before, but has stopped in the last week or two.

I’ve tried hunting down the common items (setting MTU to a lower value in docker config, setting DNS to VPN via resolv.conf) but i keep hitting the error and am right stumped now. I have reinstalled both docker desktop and Ubuntu fresh, but still have the error.

Within Ubuntu i’m able to ping websites, clone git repos, use curl etc., so the network seems to be working, but what i’m not able to do is pull docker images. From windows i am able to pull images just fine via docker pull hello-world, but when i go to WSL it throws that error up. Additionally, when i hit that error in WSL all my outgoing connections in windows stop working, but i’m still able to use curl and git clone repos after that error and ping websites as well. Its resolved with a reboot to get back to normal conditions.

Any guess to why i’d be able to pull via windows, but have it fail in WSL? Additionally, why would this failure cause the TLS error as well. I’m stumped!

You might want to ask your helpdesk/admins whether your company uses TLS/SSL inspection/Interception
If this is the case, they should be able to tell you what needs to be done in your WSL distro.

While the Windows Host has the certificates used from the security appliance in its certificate store, the WSL distro doesn’t.

See: TLS interception - ORG Wiki

Any guess why other actions like curl and git cloning from WSL would still work? Odd that it was working, then failed as well.

I’ll check in with them and see what they say as well.

Actually you can check it easily with curl inside our wsl distro:
If you execute the command curl -iv https://registry-1.docker.io/v2/ the output should look like this (maybe it resolves to different ip due to geo location) :

*   Trying 44.205.64.79:443...
* TCP_NODELAY set
* Connected to registry-1.docker.io (44.205.64.79) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: CN=*.docker.com
*  start date: Oct 31 00:00:00 2022 GMT
*  expire date: Nov 30 23:59:59 2023 GMT
*  subjectAltName: host "registry-1.docker.io" matched cert's "*.docker.io"
*  issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
*  SSL certificate verify ok.
> GET /v2/ HTTP/1.1
> Host: registry-1.docker.io
> User-Agent: curl/7.68.0
> Accept: */*

If TLS inspection is used, the issuer will be different.

Seems successful(ish). On/off vpn returns the same result as well.

Not sure what the handshake failure would be still. Perhaps related my internet properties has TLS 1.3 unchecked, but it looks like its getting 1.2 which is checked.

*   Trying 44.205.64.79:443...
* Connected to registry-1.docker.io (44.205.64.79) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: CN=*.docker.com
*  start date: Oct 31 00:00:00 2022 GMT
*  expire date: Nov 30 23:59:59 2023 GMT
*  subjectAltName: host "registry-1.docker.io" matched cert's "*.docker.io"
*  issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
*  SSL certificate verify ok.
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET /v2/ HTTP/1.1
> Host: registry-1.docker.io
> User-Agent: curl/7.81.0
> Accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
HTTP/1.1 401 Unauthorized
< content-type: application/json
content-type: application/json
< docker-distribution-api-version: registry/2.0
docker-distribution-api-version: registry/2.0
< www-authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io"
www-authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io"
< date: Mon, 23 Jan 2023 21:30:13 GMT
date: Mon, 23 Jan 2023 21:30:13 GMT
< content-length: 87
content-length: 87
< strict-transport-security: max-age=31536000
strict-transport-security: max-age=31536000

<
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}
* Connection #0 to host registry-1.docker.io left intact

Seems I was wrong. Your handshake looks different, because I used a custom generated Ubuntu 20.04 WSL distro. Though, if I use the official Ubuntu 22.04 distro, the output looks exactly like yours.

I would have said, maybe your vpn connection alters the route table… but then this curl request would have been affected as well.

The last thing that comes to mind is: does your wsl distro use a http proxy to access the registry?

looking at the env it doesn’t look like it. Docker just uses the standard settings as well, without the proxy set.

One thing that jumped out to me is OpenSSH is on the path from windows, but I don’t see how that would interfere with pull requests from WSL and not from windows, unless there is some form of conflict.