-
Notifications
You must be signed in to change notification settings - Fork 423
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
The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "Unexpected rethrowing". #879
Comments
Hi @martinm1000, could you share your connection string that you're using to produce this error? |
@peterbae Its the most simple one:
by rapidly reloading data in my app I just got the exception again (even with encrypt=false which I just added). |
I can confirm I also can get this exception using mssql-jdbc-7.0.0.jre10. |
I think I'll try to write a small test class that could reproduce it. I'm having a hard time reproducing it, but right now by best way to do it is by running my app from a java 11 runtime image with everything on the module path. Not sure if this is really a factor or not. I need to quickly reload stuff in my app to trigger new sql connection in a quick succession and then I might get the exception. |
I'm attaching a text log of reproducing the problem with the jvm option -Djavax.net.debug=ssl:handshake if this can be helpfull. |
I believe this kind of error should have a internal retry as some other type of internal ssl errors are retried in the driver (SQLServerException.DRIVER_ERROR_INTERMITTENT_TLS_FAILED), but it doesn't looks like this one get another chance on the first fail, unless I'm mistaken. (SQLServerException.DRIVER_ERROR_SSL_FAILED) |
Hi @martinm1000 , |
Hi @ulvii
I'm about to post a "working" test case that sometimes reproduce the problem (a simple loop). I am currently trying to find out why I sometimes can't get it to crash... and well... its a bizarre one. Right now I can only have it trigger when I running on a JLINKED runtime and not from the complete JDK runtime. Anyways, I'm running some more tests before posting it. But that would match what I see since yesterday and why I havent seen that problem before my tests under Java 11. |
Could you use connection property |
So far so good with TLSv1. At least we have that ;-) |
Great, now we confirmed that you are seeing the failures because of intermittent TLS1.2 issues. Please take a look at this article, which explains the cause of the issue (changes to Windows ciphers) and also possible resolution/workarounds. I would also like to explain why the driver is unable to retry when there is a logic implemented for this. Intermittent TLS1.2 issue is "guessed" by the driver based on the error message from the server. See this line. For some reason, your JDK version wraps the actual and expected exception message
Notice how Please let me know if you have any other questions. |
Thanks, I'll have a look at this. But I'm not sure it answer it all... Right now, I can reproduce the problem using a jlinked java runtime... which is what we're supposed to do now... I'll do tests with Oracle's JDK tomorrow. Here's my test caseDirectory Layoutmssql-jdbc-7.1.2.jre11-preview.jar Instructions
The test file contains arguments for the program (sql url, etc) When executing with the full JDK I never (not yet anyway) got the exception :
I only might get the exception when running from a jlinked minimal java runtime. (that's what bothering me for now). Look at used modules
Generate a runtime for our app
run the test program with this runtime. I sometimes get the exception...
|
Question: how did you get the stacktraces without it just retrying and silencing them since you do have the expected exception message (and not the Unexpected rethrowing) ? edit: can I see your Issue849.java ? |
When executing with the full JDK I never (not yet anyway) got the exception
If retry actually happens, you will see a line: Another possibility is that DHE suites are disabled for the JDK as mentioned in this article. How did you get the stacktraces without it just retrying and silencing them since you do have the expected exception message (and not the Unexpected rethrowing) ? |
Ok, I'll try that Thursday. I've already looked at that article earlier today. Its really bizarre because I don't get why java would not use fixed key sizes, which this article state might be the source of the intermittent failure (when less than 1024). Still I'll do more tests, we need to find the source of the "Unexpected rethrowing" because since this bypass the driver retry logic, this problem might become bigger in the future... |
I could not get the retry logged message when running on the full jdks, I don't get why, its like it never needed to retry ? I tested Oracle commercial jdk and Oracle open jdk build. Its all the same as for AdoptOpenJDK. I'm going to have a look at finding more about that "Unexpected rethrowing". But it does look like the current retry logic won't work on jlinked jdk 11 runtimes. |
Well I have no idea. I suppose I'll go with SSLv1 and hope its support never goes away... java.base/sun.security.ssl TransportContext:293 // Note: close_notify is not delivered via fatal() methods.
void fatal(Alert alert, String diagnostic,
boolean recvFatalAlert, Throwable cause) throws SSLException {
// If we've already shutdown because of an error, there is nothing we
// can do except rethrow the exception.
//
// Most exceptions seen here will be SSLExceptions. We may find the
// occasional Exception which hasn't been converted to a SSLException,
// so we'll do it here.
if (closeReason != null) {
if (cause == null) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
SSLLogger.warning(
"Closed transport, general or untracked problem");
}
throw alert.createSSLException(
"Closed transport, general or untracked problem");
}
if (cause instanceof SSLException) {
throw (SSLException)cause;
} else { // unlikely, but just in case.
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
SSLLogger.warning(
"Closed transport, unexpected rethrowing", cause);
}
throw alert.createSSLException("Unexpected rethrowing", cause);
}
} Caused by: javax.net.ssl.SSLProtocolException: Unexpected rethrowing
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:126)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:293)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:259)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:137)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1756) |
You can generate a debugable image using the following command. Running on this java image will allow you to get the real TLS 1.2 issue sometimes, which I always get using a <2000 connections. I even once got the issue at the first connection !
I can see that in debug that the Exception (Unexpected) has the IOException (incomplete response) as a cause. Persharps adding a new if branch for this case here would be a safe way to support what I see (but don't fully understand why this happen). As for running on the full JDK, I can't get that same breakpoint to trigger, so its like we don't even have the TLS 1.2 issue... |
Possible explanation I'm currently looking at:
What do you think ? |
Hi @martinm1000 , I am pretty sure the retry logic still works, as long as the actual error message does not get wrapped into something else in the middle. I also think it is fair to also check for the error message of the |
I'm not so sure about this. But difficult to prove as the problem is not easy to reproduce (well if you forgot my case here). Ok, so I found out that if someone generate a runtime image with the additional modules below, the jlinked image will advertise for TLS the same algorithms that the full runtime do. And I guess we will have an algo used that won't be subject to the intermittent issue. So this might be a solution (we're shoving the real problem under the carpet but....)
|
As for the code that wrap the exception, I think the current sun.security.ssl.TransportContext implementation that does this changed in the last couple of JDK releases. If I check for Java 8 jsse.jar for sun.security.ssl.TransportContext it doesn't exists. So it might really be the case that the non-wrapped exception stopped working a while ago, but changes in ciphers available for TLS masked this. I think it should be assumed that this is the current way the exception would happen. Thank you for the help ! |
@martinm1000 , if you take a look at the stack trace I have posted above, you can see that
If you completely want to be sure, you can put a breakpoint in I built a jar that also checks for the |
@ulvii that's interesting. In my case A real test with your build did correctly retry ! This time I can see This was done with:
|
Hi @martinm1000 , Thank you for testing the build. I created a PR, please feel free to review it. |
#882 merged. |
I am having same problem too.
|
@muhammedOzbilici I don't think this is the same problem; Yours is "SQL Server did not return a response" which means something else (not sure what!) |
But, is it not related to SSL ? If it's not then, which configuration I have to check on Database side ? |
Hi @muhammedOzbilici , |
I have the same problem |
янв 16, 2020 8:00:01 PM com.microsoft.sqlserver.jdbc.SQLServerDriver:1 connect |
|
thanks, I will look into it. |
This is an older thread but I wanted to leave this here in case it helps somebody scouring the Internet.... I was getting this error in an AWS Lambda function and found it was caused by giving the function too little memory. I bumped it up from 128MB to 512MB (probably overkill) and it works now. "The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption" was pretty misleading but it turned out to be too little memory. |
Currently I am getting this issue com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: No appropriate protocol (protocol is disabled or cipher suites are inappropriate). I am trying to connect to mssql server from java dynamic web project.Any help is appreciable |
We fixed this issue by enforcing |
most likely the local version of sql server is not supported. like I fixed it by going from version 12.0.2000 to 12.0.5000 |
Driver version
mssql-jdbc-7.1.2.jre11
mssql-jdbc-7.0.0.jre10 ( i think I got the problem with this one too)
Problem / Question
I've been refactoring my database connection code, and I probably have a new non-oblivious problem since but I need some pointers on what is going on in the mssql driver.
I seem to have random problems creating SQL connections that otherwise would work ok. I get the following stacktraces while connecting to a NON-ENCRYPTED sql server 2017 database.
Can someone explain the TDS Prelogin negociations vs SSL vs any other encryption scheme that might explain why I get this exception sometimes ? Or is this wrong exception message ? Is there some SSL going on to login even if we don't have encrption setup on the sql server side ?
The text was updated successfully, but these errors were encountered: