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

GCM diagnose partially fails with System.Net.Http.HttpRequestException #1215

Closed
yozachar opened this issue Apr 24, 2023 · 14 comments · Fixed by #1339
Closed

GCM diagnose partially fails with System.Net.Http.HttpRequestException #1215

yozachar opened this issue Apr 24, 2023 · 14 comments · Fixed by #1339
Assignees
Labels
network Related to networking (VPN, TCP/IP, etc)

Comments

@yozachar
Copy link

Version: 2.0.886+ea93cb5158
OS: ArchLinux (on VM - minimal Arch install with BSPWM and Alacritty)

$ git-credential-manager diagnose
Running diagnostics...

 [ OK ] Environment
 [ OK ] File system
 [FAIL] Networking

    [!] Encountered an exception [!]
    System.Net.Http.HttpRequestException: An error occurred while sending the request.
     ---> System.IO.IOException: Unable to read data from the transport connection: Connection reset by peer.
     ---> System.Net.Sockets.SocketException (104): Connection reset by peer
       --- End of inner exception stack trace ---
       at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
       at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
       at System.Net.Http.HttpConnection.InitialFillAsync(Boolean async)
       at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
       --- End of inner exception stack trace ---
       at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
       at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
       at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
       at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
       at GitCredentialManager.Diagnostics.NetworkingDiagnostic.RunInternalAsync(StringBuilder log, IList`1 additionalFiles)
       at GitCredentialManager.Diagnostics.Diagnostic.RunAsync()

    [*] Diagnostic test log [*]
    Checking networking and HTTP stack...
    Creating HTTP client... OK
    IsNetworkAvailable: True
    Sending HEAD request to http://example.com...

 [ OK ] Git
[ OK ] Credential storagee
 [ OK ] Microsoft authentication (AAD/MSA)
 [ OK ] GitHub API

Diagnostic summary: 6 passed, 0 skipped, 1 failed.
Log files:
  /home/user-name/gcm-diagnose.log

Caution: Log files may include sensitive information - redact before sharing.

Diagnostics indicate a possible problem with your installation.
Please open an issue at https://aka.ms/gcm/bug and include log files.
/home/user-name/gcm-diagnose.log
Diagnose log at 2023-04-24T01:19:54Z

AppPath: /usr/bin/git-credential-manager
InstallDir: /usr/share/git-credential-manager-core/
Version: 2.0.886+ea93cb5158

------------
Diagnostic: Environment
Skipped: False
Success: True
Exception: None
Log:
OSType: Linux
OSVersion: Linux archvm 6.2.12-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 20 Apr 2023 16:11:55 +0000 x86_64 GNU/Linux
Reading environment variables... OK
 Variables:
_=/usr/bin/git-credential-manager
XDG_SEAT=seat0
STARSHIP_SESSION_KEY=2018714487163012
USER=user-name
XDG_VTNR=1
ALACRITTY_LOG=/tmp/Alacritty-353.log
XAUTHORITY=/home/user-name/.Xauthority
XDG_SESSION_ID=1
ASDF_DIR=/home/user-name/.znap/repos/asdf
SHLVL=2
MAIL=/var/spool/mail/user-name
WINDOWPATH=1
TERM=alacritty
XDG_SESSION_CLASS=user
COLORTERM=truecolor
LANG=en_US.UTF-8
ALACRITTY_SOCKET=/run/user/1000/Alacritty-:0-353.sock
XDG_CONFIG_HOME=/home/user-name/.config
SYSTEMD_EXEC_PID=295
DISPLAY=:0
EDITOR=micro
XDG_RUNTIME_DIR=/run/user/1000
XDG_CACHE_HOME=/home/user-name/.cache
ALACRITTY_WINDOW_ID=8388610
XDG_SESSION_TYPE=tty
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
DEBUGINFOD_URLS=https://debuginfod.archlinux.org 
XDG_DATA_HOME=/home/user-name/.local/share
STARSHIP_SHELL=zsh
GCM_CREDENTIAL_STORE=gpg
INVOCATION_ID=abbd61c334a54b3a9a96641f51459029
XDG_STATE_HOME=/home/user-name/.local/state
WINDOWID=8388610
OLDPWD=/home/user-name
MOTD_SHOWN=pam
PATH=/home/user-name/.asdf/shims:/home/user-name/.znap/repos/asdf/bin:/home/user-name/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
HOME=/home/user-name
LOGNAME=user-name
SHELL=/usr/bin/zsh
PWD=/home/user-name


------------
Diagnostic: File system
Skipped: False
Success: True
Exception: None
Log:
Temporary directory is '/tmp/'...
Checking basic file I/O...
Writing to temporary file '/tmp/ac774831afb2254052bc1b64'... OK
Reading from temporary file '/tmp/ac774831afb2254052bc1b64'... OK
Deleting temporary file '/tmp/ac774831afb2254052bc1b64'... OK
Testing IFileSystem instance...
UserHomePath: /home/user-name
UserDataDirectoryPath: /home/user-name/.gcm
GetCurrentDirectory(): /home/user-name

------------
Diagnostic: Networking
Skipped: False
Success: False
Exception:
System.Net.Http.HttpRequestException: An error occurred while sending the request.
 ---> System.IO.IOException: Unable to read data from the transport connection: Connection reset by peer.
 ---> System.Net.Sockets.SocketException (104): Connection reset by peer
   --- End of inner exception stack trace ---
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
   at System.Net.Http.HttpConnection.InitialFillAsync(Boolean async)
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at GitCredentialManager.Diagnostics.NetworkingDiagnostic.RunInternalAsync(StringBuilder log, IList`1 additionalFiles)
   at GitCredentialManager.Diagnostics.Diagnostic.RunAsync()
Log:
Checking networking and HTTP stack...
Creating HTTP client... OK
IsNetworkAvailable: True
Sending HEAD request to http://example.com...
------------
Diagnostic: Git
Skipped: False
Success: True
Exception: None
Log:
Getting Git version... OK
Git version is '2.40.0'
Locating current repository... OK
Not inside a Git repository.
Listing all Git configuration... OK
Git configuration:
file:/home/user-name/.gitconfig	core.editor=micro
file:/home/user-name/.gitconfig	maintenance.repo=/home/user-name/.znap/repos/asdf
file:/home/user-name/.gitconfig	maintenance.repo=/home/user-name/.znap/repos/asdf-direnv
file:/home/user-name/.gitconfig	maintenance.repo=/home/user-name/.znap/repos/zsh-autosuggestions
file:/home/user-name/.gitconfig	maintenance.repo=/home/user-name/.znap/repos/zsh-syntax-highlighting
file:/home/user-name/.gitconfig	credential.helper=
file:/home/user-name/.gitconfig	credential.helper=/usr/bin/git-credential-manager
file:/home/user-name/.gitconfig	credential.https://dev.azure.com.usehttppath=true


------------
Diagnostic: Credential storage
Skipped: False
Success: True
Exception: None
Log:
ICredentialStore instance is of type: CredentialStore
Writing test credential... OK
Reading test credential... OK
Deleting test credential... OK

------------
Diagnostic: Microsoft authentication (AAD/MSA)
Skipped: False
Success: True
Exception: None
Log:
Broker not supported.
Flow type is: Auto
Gathering MSAL token cache data... OK
CacheDirectory: /home/user-name/.local/.IdentityService
CacheFileName: msal.cache
CacheFilePath: /home/user-name/.local/.IdentityService/msal.cache
KeyringCollection: 
KeyringSchemaName: 
KeyringSecretLabel: 
KeyringAttribute1: (,)
KeyringAttribute2: (,)
Creating cache helper... OK
Verifying MSAL token cache persistence... OK

------------
Diagnostic: GitHub API
Skipped: False
Success: True
Exception: None
Log:
Using 'https://github.com/' as API target.
Querying '/meta' endpoint... OK
@mjcheetham
Copy link
Collaborator

Thanks for opennning the issue @joe733.

Diagnostic: Networking
Skipped: False
Success: False
Exception:
System.Net.Http.HttpRequestException: An error occurred while sending the request.
 ---> System.IO.IOException: Unable to read data from the transport connection: Connection reset by peer.
 ---> System.Net.Sockets.SocketException (104): Connection reset by peer
   --- End of inner exception stack trace ---
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
   at System.Net.Http.HttpConnection.InitialFillAsync(Boolean async)
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at GitCredentialManager.Diagnostics.NetworkingDiagnostic.RunInternalAsync(StringBuilder log, IList`1 additionalFiles)
   at GitCredentialManager.Diagnostics.Diagnostic.RunAsync()
Log:
Checking networking and HTTP stack...
Creating HTTP client... OK
IsNetworkAvailable: True
Sending HEAD request to http://example.com...

The exception is being thrown after we try a simple HEAD call to http://example.com. Please could you try running the below curl command to see if this is a problem specific to the networking stack in .NET or your machine?

curl --head 'http://example.com'

Example output:

% curl --head 'http://example.com'
HTTP/1.1 200 OK
Content-Encoding: gzip
Accept-Ranges: bytes
Age: 388970
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Mon, 24 Apr 2023 15:52:51 GMT
Etag: "3147526947"
Expires: Mon, 01 May 2023 15:52:51 GMT
Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
Server: ECS (sec/96ED)
X-Cache: HIT
Content-Length: 648

@mjcheetham mjcheetham added the network Related to networking (VPN, TCP/IP, etc) label Apr 24, 2023
@yozachar
Copy link
Author

$ curl --head "http://example.com"
curl: (56) Recv failure: Connection reset by peer

whereas

$ curl --head "https://example.com"
HTTP/2 200 
accept-ranges: bytes
age: 599256
cache-control: max-age=604800
content-type: text/html; charset=UTF-8
date: Mon, 24 Apr 2023 16:09:04 GMT
etag: "3147526947"
expires: Mon, 01 May 2023 16:09:04 GMT
last-modified: Thu, 17 Oct 2019 07:18:26 GMT
server: ECS (oxr/8310)
x-cache: HIT
content-length: 1256

Can't reach over http but can reach over https.

@ldennington
Copy link
Contributor

What happens if you try to visit http://www.example.com in your browser? Do you have any network settings or firewalls that are set up to prevent http (non-https) connections?

@yozachar
Copy link
Author

It's unreachable.

Do you have any network settings or firewalls that are set up to prevent http (non-https) connections?

No I do not think so.

image

http://httpforever.com is accessible

$ curl --head "http://httpforever.com"
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Tue, 25 Apr 2023 01:34:00 GMT
Content-Type: text/html
Content-Length: 5124
Last-Modified: Wed, 22 Mar 2023 14:54:48 GMT
Connection: keep-alive
ETag: "641b16b8-1404"
Referrer-Policy: strict-origin-when-cross-origin
X-Content-Type-Options: nosniff
Feature-Policy: accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'
Content-Security-Policy: default-src 'self'; script-src cdnjs.cloudflare.com 'self'; style-src cdnjs.cloudflare.com 'self' fonts.googleapis.com 'unsafe-inline'; font-src fonts.googleapis.com fonts.gstatic.com cdnjs.cloudflare.com; frame-ancestors 'none'; report-uri https://scotthelme.report-uri.com/r/d/csp/enforce
Accept-Ranges: bytes

image

@mjcheetham
Copy link
Collaborator

What happens if you try to visit http://www.example.com in your browser?

It's unreachable.

Interesting. GCM uses example.com to test if GCM can reach the wider Internet in the network diagnostic test. The fact you cannot reach http://example.com in a browser or via the curl command line is evidence enough that this isn't a GCM specific issue per-se.

I'm interested as to why example.com over HTTP is not working however.

  • Do you have any processes running that are listening on all addresses for port :80?
    lsof -i -P -n | grep LISTEN

  • What happens if you do nslookup example.com or curl --http1.1 -I 'http://example.com'?

  • What about if you try visiting the IP address for example.com over HTTP that you get back from the nslookup command?

% nslookup example.com
Server:		127.0.0.1
Address:	127.0.0.1#53

Non-authoritative answer:
Name:	example.com
Address: 93.184.216.34

% curl --http1.1 -I -H 'Host: example.com' 'http://93.184.216.34'
HTTP/1.1 200 OK
Content-Encoding: gzip
Accept-Ranges: bytes
Age: 484610
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Tue, 25 Apr 2023 18:26:51 GMT
Etag: "3147526947"
Expires: Tue, 02 May 2023 18:26:51 GMT
Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
Server: ECS (sec/96ED)
X-Cache: HIT
Content-Length: 648

@yozachar
Copy link
Author

$ lsof -i -P -n | grep LISTEN
 # adb, vscode and pantsd did listen, but I've killed them all

$ nslookup example.com
Server:		9.9.9.9
Address:	9.9.9.9#53

Non-authoritative answer:
Name:	example.com
Address: 93.184.216.34
Name:	example.com
Address: 2606:2800:220:1:248:1893:25c8:1946

$ curl --http1.1 -I -H 'Host: example.com' 'http://93.184.216.34'   
curl: (56) Recv failure: Connection reset by peer

What about if you try visiting the IP address for example.com over HTTP that you get back from the nslookup command?

404 on IPv4, Unreachable on IPv6

image

@ldennington
Copy link
Contributor

The fact that curl and access via browser don't work on http indicates that this is not a GCM issue. Closing.

@ldennington ldennington closed this as not planned Won't fix, can't repro, duplicate, stale May 1, 2023
@yozachar
Copy link
Author

yozachar commented May 2, 2023

I've a suggestion, GCM can attempt more than one site for network check.

Also why not use HTTPS?

I'd recommend the FOSS one at http://http.badssl.com

$ curl --head "http://http.badssl.com"                                  
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 02 May 2023 04:46:04 GMT
Content-Type: text/html
Content-Length: 483
Last-Modified: Mon, 24 Apr 2023 00:02:00 GMT
Connection: keep-alive
ETag: "6445c6f8-1e3"
Cache-Control: no-store
Accept-Ranges: bytes

From superuser/q#1213116 there are plenty of other HTTP sites that GCM can use for testing network.

@jimmychu0807
Copy link

I actually encounter the same issue...

Screenshot 2023-05-17 at 19 14 34 Screenshot 2023-05-17 at 19 14 43

@ldennington
Copy link
Contributor

I'll re-open this. I'm open to changing to http://httpforever.com/ since multiple users are running into it.

@ldennington ldennington reopened this May 17, 2023
@yozachar
Copy link
Author

@ldennington, any objections to use multiple URLs, and preferably FOSS http://http.badssl.com?

@ldennington
Copy link
Contributor

ldennington commented May 18, 2023

@joe733 - I'm curious what the advantage is of using multiple URLs? I'm also unsure of purposefully putting something titled badssl into the product - I worry it could come off as odd or even a security risk to those who don't know what it is.

@yozachar
Copy link
Author

yozachar commented May 19, 2023

I'm curious what the advantage is of using multiple URLs?

You'll have a fallback mechanism which would trigger, if the primary network check fails due reasons including, but not limited, to ISP / region wide blocking / inaccessibility.

I'm also unsure of purposefully putting something titled badssl into the product - I worry it could come off as odd or even a security risk to those who don't know what it is.

That is a just concern. So you can have this URL (https://github.com/chromium/badssl.com) in a short explainer comment.
Or I'd go for http://detectportal.firefox.com/success.txt from Mozilla.

The reason for not going for non-FOSS URLs is, you won't know when they'll be taken down. With http://http.badssl.com/, you'll have some indicators / activity at least on its corresponding GitHub repository.

@ldennington ldennington self-assigned this May 22, 2023
@ldennington
Copy link
Contributor

We (the maintainers) discussed this and have decided on the following:

  1. We will no longer fail in this scenario, but will instead print a warning and attempt a backup URL. If that URL also fails we will simply print another warning and move on.
  2. We're going to stick with http://example.com as the primary URL, since it's hosted by IANA. We will use http://httpforever.com/ as the backup.

ldennington added a commit that referenced this issue Jul 17, 2023
Currently, failure to access http://example.com causes failure of the
Networking Diagnostic portion of the `diagnose` command. To improve the
experience for users who are unable to access http://example.com, this
change:

1. Adds a fallback URI - if accessing http://example.com throws an
exception, we now try http://httpforever.com.
2. Prints a warning when either the primary or both the primary and
fallback uris throw an exception (instead of failing the Networking
Diagnostic).

Fixes #1215
ldennington added a commit that referenced this issue Aug 1, 2023
**Changes since 2.2.2:**

- Fix a GCM/Git Trace2 file locking issue
  - Issue: #1323 
  - PR: #1340
- Remove symlinks to `git-credential-manager-core` exe
  - Issue: #1322
  - PR: #1327 
- Add fallback http uri to `diagnose` command
  - Issue: #1215
  - PR: #1339
- Workaround MSAL tenant issue with silent auth
  - Issue: #1297
  - PR: #1321
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
network Related to networking (VPN, TCP/IP, etc)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants