title: WebRequest on .NET Core 3.0 fails the second time due to SSL handshake exception
body: <p>The problem is that the code below succeeds if you run it once but fails if you run it twice during the same lifetime of a program.</p>
  
  <pre class="lang-cs prettyprint-override"><code>var request = (HttpWebRequest)WebRequest.Create("https://google.com");
  var response = (HttpWebResponse)await request.GetResponseAsync();
  </code></pre>
  
  <p>I have <strong>.NET Core 3.0</strong> and <strong>SDK Version 3.0.100</strong>.</p>
  
  <h1>Reproduce:</h1>
  
  <ol>
  <li><code>dotnet new console -n test-ssl</code> <code>cd test-ssl</code>.</li>
  <li>Open <code>Program.cs</code>.</li>
  <li>Replace content with:</li>
  </ol>
  
  <pre class="lang-cs prettyprint-override"><code>using System;
  using System.IO;
  using System.Net;
  using System.Threading.Tasks;
  
  namespace test_ssl
  {
      class Program
      {
          static async Task Main(string[] args)
          {
              await CallGoogle();
              await CallGoogle();
          }
  
          private static async Task CallGoogle()
          {
              var request = (HttpWebRequest)WebRequest.Create("https://google.com");
              var response = (HttpWebResponse)await request.GetResponseAsync();
              var jsonResponse = new StreamReader(response.GetResponseStream()).ReadToEnd();
              Console.WriteLine(jsonResponse);
          }
      }
  }
  </code></pre>
  
  <ol start="4">
  <li><code>dotnet run</code>.</li>
  </ol>
  
  <p>This will crash with the exception:</p>
  
  <pre><code>Unhandled exception. System.Net.WebException: The SSL connection could not be established, see inner exception. The handshake failed due to an unexpected packet format.
   ---&gt; System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
   ---&gt; System.IO.IOException: The handshake failed due to an unexpected packet format.
     at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
     at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
  --- End of stack trace from previous location where exception was thrown ---
     at System.Net.Security.SslStream.ThrowIfExceptional()
     at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
     at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)
     at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
     at System.Net.Security.SslStream.&lt;&gt;c.&lt;AuthenticateAsClientAsync&gt;b__65_1(IAsyncResult iar)
     at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
  --- End of stack trace from previous location where exception was thrown ---
     at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
     --- End of inner exception stack trace ---
     at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
     at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
     at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
     at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
     at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
     at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
     at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
     at System.Net.HttpWebRequest.SendRequest()
     at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
     --- End of inner exception stack trace ---
     at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
     at System.Net.WebRequest.&lt;&gt;c.&lt;GetResponseAsync&gt;b__68_2(IAsyncResult iar)
     at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
  --- End of stack trace from previous location where exception was thrown ---
     at test_ssl.Program.CallGoogle() in C:\Users\me\source\Workspaces\tests\test-ssl\Program.cs:line 19
     at test_ssl.Program.Main(String[] args) in C:\Users\me\source\Workspaces\tests\test-ssl\Program.cs:line 13
     at test_ssl.Program.&lt;Main&gt;(String[] args)
  </code></pre>
  
  <p>Why would it fail the second time?</p>
  
  <p>This issue is posted in .NET Core on github also since it seems related to that: <a href="https://github.com/dotnet/core/issues/3847" rel="nofollow noreferrer">https://github.com/dotnet/core/issues/3847</a></p>
  
  <h1>Further tests to narrow down the problem</h1>
  
  <h3>.NET Framework 4.8 - WORKING</h3>
  
  <p>Using <strong>.NET Framework 4.8 Console app</strong> does work however. So using the original <code>Program.cs</code> file works here. Seems like the real problem is in <strong>.NET Core 3.0</strong></p>
  
  <h3>.NET Core 3.0 in Docker - WORKING</h3>
  
  <pre><code>docker run --rm -it mcr.microsoft.com/dotnet/core/sdk:3.0
  dotnet new console -n test-ssl
  cd test-ssl
  // Replace content of Program.cs again.
  dotnet run
  // Everything works.
  </code></pre>
  
  <p>This leads me to believe that there is something on my machine that is broken and perhaps not a firewall problem either since in the end the docker container will go through the same firewall as my computer to reach google.</p>
  
  <h3>Powershell Test - WORKING</h3>
  
  <p><em>test-ssl.ps1</em></p>
  
  <pre><code>Invoke-WebRequest -Uri 'https://google.com'
  Invoke-WebRequest -Uri 'https://google.com'
  </code></pre>
  
  <h3>HttpClient .NET Core 3.0 - NOT WORKING</h3>
  
  <p>Using <code>HttpClient</code> gives the same error. So replacing the content of <code>CallGoogle</code> with the below doesn't work:</p>
  
  <pre><code>var client = new HttpClient();
  await client.GetStringAsync("https://google.com");
  </code></pre>