We have a server with a windows service that calls an web api over https in other server (both servers internals) and it was working normal, until they were changed their TLS configuration.
I coded a simple console app for test the call and reproduced the error. I tested from Firefox from the machine acting as client and is respoding ok (this discard any firewall or port blocks issue) More strange is I tested from my laptop (win7) and worked ok.
As can be seen in the Exception details fails "at System.Net.TlsStream.EndWrite(...)
" so seems to be related with changed configuration. After a lot of research I found some changes done in Registry (not done by me, because I can't but for support area), and change my code adding ServicePointManager.SecurityProtocol for support Tls.
Any Ideas?
Following almost all instructions on: https://blogs.msdn.microsoft.com/dataaccesstechnologies/2016/07/12/enable-tls-1-2-protocol-for-reporting-services-with-custom-net-application/
- Development: Visual Studio: 2013
- .Net Framework: version 4.5
- Operation System: Windows Server 2008 R2 Service Pack 1
Registry found (made by support personal, these are some of them)
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Client] "Enabled"=dword:00000000 "DisabledByDefault"=dword:00000001 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server] "Enabled"=dword:00000001 "DisabledByDefault"=dword:00000000
Sample Console app for testing:
public async Task<string> TestApiCall() { const string uri = "https://myserver/api/blahblah"; try { using (var client = new HttpClient()) { //client.DefaultRequestHeaders.Accept.Clear(); //client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*")); client.DefaultRequestHeaders.Add("Connection", "close"); // Keep Alive = false (tested with & without this line) ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; // tested with almost all combinations since only Tls12 ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3; // Disable SSL3 //ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; // Accept possible invalid certificates (not recomended, only for test), tested without this line too var response = await client.GetAsync(uri).ConfigureAwait(false); // <-- Exception thrown here response.EnsureSuccessStatusCode(); var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false); return result; } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } }
Exception thrown:
System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state) at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) --- End of inner exception stack trace --- at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult) at System.Net.PooledStream.EndWrite(IAsyncResult asyncResult) at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar) --- End of inner exception stack trace --- at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult) at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar) --- End of inner exception stack trace --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() at TestHttp.Program.<TestApiCall>d__2.MoveNext()
1 Answers
Answers 1
You can try adding a certificate file send to server. Usually this certificate file is open by the certificate CA ROOT.
ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate; HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url); X509Certificate cer = new X509Certificate("F:\\csharp2.cer"); //adding your client certificate. httpWebRequest.ClientCertificates.Add(cer); httpWebRequest.BeginGetResponse(CallBack(), httpWebRequest); private void CallBack() { AsyncCallback ac = (result) => { HttpWebRequest webRequest = (HttpWebRequest)result.AsyncState; using (HttpWebResponse response = (HttpWebResponse)webRequest.EndGetResponse(result)) { //response } }; } private static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return (sslPolicyErrors == SslPolicyErrors.None); }
0 comments:
Post a Comment