CFNetwork SSLHandshake failed (-9806) intermittently - ssl

I am using an iOS app and I get the below error when testing in iOS 9.
CFNetwork SSLHandshake failed (-9806)
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9806)
I found a number of links saying this could be due to the NSAppTransportSecurity suggesting to add exception for my domain or to disable ATS. But my server does support TLS1.2 and I get this issue only intermittently. Had this been due to the NSTransportSecurity I assume that the issue should be consistent.
Whats strange is that this is not consistent. The app works fine and is able to connect to server in most cases. But after a while I get the above error. I use NSURLCONNECTION. Most of the app interaction is like click on a button and it makes a network call to server(tomcat). Once the SSL failed error occurs, the only way to get the app to send requests successfully to server is by killing the app and starting again. I have tried changing the connection from wifi to 3g during the issue, and even restarting the server once the issue happens but I could find no luck. I am able to work fine with safari and other apps. I have been trying to find a solution for this for some time now. The server is not forward secrecy enabled.
To check the issue deeply I verified the SSL packets from the client.
When the issue occurs the client is sending a different list of ciphers compared to when the connection is working good.
When the connection is working good I could see the below list of ciphers being sent.
It was also seen that during the issue the client hello packet was shown as SSL where as when the connection is good the client hello packet is shown as TLS1.2
During issue
When there is no issue
I am using the same NSurlconnetion class to connect to server throughout the app. I am confused why and how there could be such a discrepancy and how the same server call that works once is not working later. Does the above data suggest that during the issue the client is trying to connect via tls1.0 or lower? The server supports TLS 1.1 and TLS 1.2 only. The issue is found only in iOS 9. Any help is much appreciated.

The app will probably start with TLS 1.2 and a will offer ciphers which are new with TLS 1.2 too (the ones with GCM in the name). Then I guess there is some handshake problem, maybe cause by temporary server problems, some middlebox (firewall) in between or something else. From then on the app assumes that there are problems with TLS 1.2 and will attempt to use a downgraded connection, i.e TLS 1.0. and stay this way because "it knows" that TLS 1.2 will not work.
This kind of downgrades is often seen in browsers too but usually they remember to do the downgrade only if it was at least once successful. Could there be some SSL intercepting middlebox (firewall) involved which causes the original TLS 1.2 to fail and the downgrade to succeed? I.E. does the problem happens only after the device connected once through this middlebox and then later tries to reconnect to your site?

Related

The TLS protocol defined fatal alert code is 70

I'm trying to access an SSL URL from a Windows browser to another machine running Tomcat and I am seeing error 36887 from Schannel in the System event log on the Windows machine with this description:
The TLS protocol defined fatal alert code is 70
According to MS documentation:
I've turned up Schannel logging (max=7) on the Windows machine and I can see that an SSL handshake was negotiated correctly, this from the event log:
An SSL server handshake completed successfully. The negotiated cryptographic parameters are as follows.
Protocol: TLS 1.2
CipherSuite: 0xC028
Exchange strength: 256
This seems to contradict the code 70 error.
Cipher suite 0xC028 is TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384. I've checked on the Tomcat machine and can see that this is available, and TLS1.2 is also enabled on both machines so the successful handshake makes sense.
The process ID associated with the code 70 error belonged to lsass.exe - my Windows knowledge is quite limited so I have no idea what that does.
I can find nothing in the catalina.out log on the Tomcat machine, the code 70 seems to be happening before the request is actuall sent. I am certain that the certs are all configured correctly as I can access the URL successfully from other machines.
How can I progress from here?
The issue turned out to be that one of our client apps was using .NET 4.5.2 and defaulting to TLS1.1, which had been disabled at the server end by some patching. Ultimately a .NET update to 4.7.2 fixed the issue.
It means communication with the server was attempted using a recognized but unsupported TLS version. If your server is set to accept only communications using TLS 1.2 or newer, for example, then anything that tries to communicate via TLS 1.1 or lower will throw this error.
Two computers have to agree on a method of communication before they can actually do the communication. That is why this error message can occur and then the computers appear to communicate just fine... the first method was tried and rejected, and then a newer one was tried and succeeded, that's all.

How to customize ssl handshake routine?

Recently, I tried to access one special bizarre https server with python requests library and it always reported handshake_failure. However, I can access it with browser.
After some debugging with wireshark, I found the server refused the first clientHello directly. I knew there may be some bizarre behavior for that server.
What i ask is that how to customize ssl handshake routine to identify what exactly caused the server to refuse my clientHello?
For example,
I want to add some extensions as the browser does during ssl handshake.
Thanks!

SSL/TLS error with website

I have a website using tls1.2,1.1 and 1.0(ssllabs) . I am using websense proxy to access it. Have enabled tls1.1 and tls1.2 on the WCG. I am still getting Peer disconnected error. The website worked once and is giving the error randomly. I have websense 8 and the URL in question is https://rem2.piiapps.com/site/login. It works fine with websense 7. I dont have a ssl bypass option due to security restrictions. Sometimes the browser indicates that the certificate is broken and sometimes it is healthy.
I did some analysis and found that this URL was using a real time communication protocol which is not supported by deafult in websense. It has to be tunneled in the incident list.

gnutls and openssl handshake in NGINX

I'm testing SSL/TLS stream proxying within NGINX that will connect to a web server using gnutls as the underlying TLS API. Using the command line test tool in gnutls (gnutls-serv) the entire process works, but I can't understand the logic:
the NGINX client (proxying HTTP requests from an actual client to the gnutls server) seems to want to handshake the connection multiple times. In fact in most tests it seems to handshake 3 times without error before the server will respond with a test webpage. Using wireshark, or just debugging messages, it looks like the socket on the client side (in the perspective of the gnutls server) is being closed and reopened on different ports. Finally on the successful connection, gnutls uses a resumed sessions, which I imagine is one of the previously mentioned successful handshakes.
I am failing to find any documentation about this sort of behaviour, and am wondering if this is just an 'NGINX thing.'
Though the handshake eventually works with the test programs, it seems kind of wasteful (to have multiple expensive handshakes) and implementing handshake logic in a non-test environment will be tricky without actually understanding what the client is trying to do.
I don't think there are any timeouts or problems happening on the transport, the test environment is a few different VMs on the same subnet connected between 1 switch.
NGINX version is the latest mainline: 1.11.7. I was originally using 1.10.something, and the behaviour was similar though there were more transport errors. Those errors seemed to get cleaned up nicely with upgrading.
Any info or experience from other people is greatly appreciated!
Use either RSA key exchange between NGINX and the backend server or use SSLKEYLOGFILE LD_PRELOAD for NGINX to have the necessary data for Wireshark to decrypt the data.
While a single incoming connection should generate just one outgoing connection, there may be some optimisations in NGINX to fetch common files (favicon.ico, robots.txt).

SSL handshake issue while java client talking to SSLv3 ONLY server

We are facing a problem and I am sure this is the right place. We have a load balancer (cisco's) and for various reasons the SSL configuration on the load balancer (the server) side is set to use "SSLv3" protocol version. Now after setting the same, when I access the load balancer in CHROME browser, I am able to access the pages but I do see the below message when I click on their security icon.
"connection had to be retried using ssl 3.0" - I looked at the packet capture using wireshark and I see that browser tries TLSv1 and receives a "fatal alert" from the server saying "protocol_version" and then immediately browser tries SSLv3 version and finishes the handshake. So browser is able to negotiate this as a client.
However when I set up a stand alone java (tried using 1.6 as well as 1.7) client from eclipse and try connecting to the server I am getting the below exception.
: Received fatal alert: protocol_version javax.net.ssl.SSLException: Received fatal alert: protocol_version
As per various documentations, I saw two options I have
to set https.protocol system property to SSLv3. [this works for us, but the problem is it is affects the outbound SSL calls globally. I have another outbound SSL call to another server which does not work with SSLv3]
setEnabledprotocols() - this works as well but sometimes, we dont have access to the socket directly (sometime we generates stubs using third party and the stub takes care of the low level connection stuff, so no access to that socket).
But my actual question is, If by default TLSv1/SSLv3 and SSLv2Hello(just the format I believe) are enabled in java, why is JSSE implementation not able to negotiate like how chrome browser is able to negotiate. Is this expected? If browser is doing it, I believe it should be part of some SSL RFC and if that is the case, same functionality of this "negotiation" should be provided by java itself right?
I did go through this http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/security/ssl/SSLSocketImpl.java and was not able to find any part for this negotiation during handshake.
Is there a possibility of issue from the server side (load balancer) that i. I see that server sends fatal alert but that being cisco I believe the ssl implementation should be perfect and that is expected. Am I wrong?
Issue happens both in java 1.6 and 1.7. Do let me know if more information would be required to answer, will be happy to help.