Docker login to ghcr.io denied from behind a proxy

Hi there.
I’ve got no problem logging in to ghcr.io from a direct connection (from a linux GCP vm, for example). But behind my company’s proxy this is what I receive:

Error response from daemon: Get https://ghcr.io/v2/: denied

I’m using Windows 10 with Docker Desktop installed, which has the proxy configuration (with user and pass) set. This configuration is working, given that any pull works, even from ghcr dot io. Problem is only when trying to login.

Any idea why this can be failing?

I’m facing the same issue. I tested to access the endpoint - https://ghcr.io/v2/ by using curl in both environments where proxy is needed and not, and noticed something difference in their output.
When docker login behind a proxy, it follows HTTP1.1 protocol, and gets denied. But when it logs in directly without a proxy, it follows HTTP2.

Here is what I get when going through a proxy.

# curl -v -u xxxx:xxxx https://ghcr.io/v2/
* Uses proxy env variable https_proxy == 'http://<proxyuser>:<proxypass>@<proxy-server>:80/'
*   Trying <proxy-ip>:80...
* TCP_NODELAY set
* Connected to proxy-server (<proxy-ip>) port 80 (#0)
* allocate connect buffer!
* Establish HTTP proxy tunnel to ghcr.io:443
* Proxy auth using Basic with user '<proxyuser>'
* Server auth using Basic with user 'xxxx'
> CONNECT ghcr.io:443 HTTP/1.1
> Host: ghcr.io:443
> Proxy-Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==
> User-Agent: curl/7.68.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 Connection established
<
* Proxy replied 200 to CONNECT request
* CONNECT phase completed!
* 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):
* CONNECT phase completed!
* CONNECT phase completed!
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: C=US; ST=California; L=San Francisco; O=GitHub, Inc.; CN=*.ghcr.io
*  start date: Aug 31 00:00:00 2020 GMT
*  expire date: Sep  8 12:00:00 2021 GMT
*  subjectAltName: host "ghcr.io" matched cert's "ghcr.io"
*  issuer: <xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
*  SSL certificate verify ok.
* Server auth using Basic with user 'xxxx'
> GET /v2/ HTTP/1.1
> Host: ghcr.io
> Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
< Content-Type: application/json
< docker-distribution-api-version: registry/2.0
< www-authenticate: Bearer realm="https://ghcr.io/token",service="ghcr.io",scope="repository:user/image:pull"
< Date: Mon, 19 Apr 2021 04:57:35 GMT
< Content-Length: 73
< X-GitHub-Request-Id: 4FDA:2A9B:1976A:5B95C:607D0DBE
< Cache-Control: proxy-revalidate
< Proxy-Connection: Keep-Alive
< Connection: Keep-Alive
< Set-Cookie: BCSI-CS-0da1226ae99f4856=1; Path=/
< Proxy-support: Session-based-authentication
<
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required"}]}
* Connection #0 to host <proxy-server> left intact

When I test this on another server where a proxy is not needed, the output is quite different.

# curl -v -u xxxx:xxxx https://ghcr.io/v2/
*   Trying 192.30.255.165...
* TCP_NODELAY set
* Connected to ghcr.io (192.30.255.165) 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/pki/tls/certs/ca-bundle.crt
  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=California; L=San Francisco; O=GitHub, Inc.; CN=*.ghcr.io
*  start date: Aug 31 00:00:00 2020 GMT
*  expire date: Sep  8 12:00:00 2021 GMT
*  subjectAltName: host "ghcr.io" matched cert's "ghcr.io"
*  issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 High Assurance Server CA
*  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
* Server auth using Basic with user 'xxxx'
* Using Stream ID: 1 (easy handle 0x1d6bd10)
> GET /v2/ HTTP/2
> Host: ghcr.io
> Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
> User-Agent: curl/7.61.1
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200
< content-type: application/json
< docker-distribution-api-version: registry/2.0
< date: Mon, 19 Apr 2021 05:02:28 GMT
< content-length: 0
< x-github-request-id: D15C:30BE:D3AA:80BCC:607D0EE4
<
* Connection #0 to host ghcr.io left intact

The above output indicates the server supports multi-use, and follows HTTP2 protocol.

Does that mean HTTP1.1 is not support by https://ghcr.io/v2?

Thanks,
Weiping

@weipingxia Actually I receive a differrent error:

  • schannel: next InitializeSecurityContext failed: Unknown error (0x80092012) - The revocation function was unable to check revocation for the certificate.
  • Closing connection 0
  • schannel: shutting down SSL/TLS connection with ghcr.io port 443
  • schannel: clear security context handle

I don’t know which certificate (if any) is causing the problem though.

I’m facing the same issue too! I also tested to access the same endpoint with and without proxy and my result was the same:

# curl -v -u xxxx:xxxx https://ghcr.io/v2/
* Uses proxy env variable https_proxy == 'http://<proxyuser>:<proxypass>@<proxy-server>:80/'
*   Trying <proxy-ip>:80...
* TCP_NODELAY set
* Connected to proxy-server (<proxy-ip>) port 80 (#0)
* allocate connect buffer!
* Establish HTTP proxy tunnel to ghcr.io:443
* Proxy auth using Basic with user '<proxyuser>'
* Server auth using Basic with user 'xxxx'
> CONNECT ghcr.io:443 HTTP/1.1
> Host: ghcr.io:443
> Proxy-Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==
> User-Agent: curl/7.68.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 Connection established
<
* Proxy replied 200 to CONNECT request
* CONNECT phase completed!
* 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):
* CONNECT phase completed!
* CONNECT phase completed!
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: C=US; ST=California; L=San Francisco; O=GitHub, Inc.; CN=*.ghcr.io
*  start date: Aug 31 00:00:00 2020 GMT
*  expire date: Sep  8 12:00:00 2021 GMT
*  subjectAltName: host "ghcr.io" matched cert's "ghcr.io"
*  issuer: <xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
*  SSL certificate verify ok.
* Server auth using Basic with user 'xxxx'
> GET /v2/ HTTP/1.1
> Host: ghcr.io
> Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
< Content-Type: application/json
< docker-distribution-api-version: registry/2.0
< www-authenticate: Bearer realm="https://ghcr.io/token",service="ghcr.io",scope="repository:user/image:pull"
< Date: Mon, 19 Apr 2021 04:57:35 GMT
< Content-Length: 73
< X-GitHub-Request-Id: 4FDA:2A9B:1976A:5B95C:607D0DBE
< Cache-Control: proxy-revalidate
< Proxy-Connection: Keep-Alive
< Connection: Keep-Alive
< Set-Cookie: BCSI-CS-0da1226ae99f4856=1; Path=/
< Proxy-support: Session-based-authentication
<
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required"}]}
* Connection #0 to host <proxy-server> left intact

Do you have any idea why does HTTP1.1 not supported by the endpoint?
Thanks in advance,
John Riviera
My inbox: nonpqlolzx@gmail.com
My site: https://azoft.com

I receive that same error if I add --ssl-no-revoke to the curl command.

No idea why HTTP1.1 is being used. Is there any way to force the use of HTTP2?