This question already has answers here:
Enable TLS 1.2 only in apache-tomcat-9 and Java 8
(3 answers)
Closed 1 year ago.
I'm new to tomcat. I've seen many links regarding changing the tls version in tomcat. All of them do one thing in common (ie) to configure the sslProtocol field in the below connector (in server.xml):
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLSv1.2" />
However I've changed this line to so many times to different versions. But whenever I test this using openssl, the server works only on TLSv1.2 and not any other versions. It seems that the field sslProtol in connector takes no effect on changing the TLS version. Is there anything that one needes to configure other than changing the version in the connector ? I've searched all over the web and stackoverflow and numerous answers. All seems to change the connector.
Is there anything other than configuring the connector to change the ssl/tls version like adding any external libraries or configuring the jdk or something like that .
Tomcat doesn't implemented SSL/TLS itself. Instead it relies on something external.
If you are using APR connectors, it uses on the OpenSSL engine installed on your platform.
If you are using BIO or NIO connectors, it uses the JSSE provider that your JVM is configured to use. That could either be the JSSE provider distributed as part of Java SE, or it could be a 3rd-party provider such as BounceCastle.
So ... if you can't get the "sslProtocol" parameter to actually select what you want, check that your JVM, JSSE provider or OpenSSL implementation actually supports the version you are trying to use.
Note that if you are using a "stack" that doesn't support (say) TLSv1.3, specifying that in the Connector config is not going to magically make it work. The SSL implementation code has to support it.
References:
How to find what SSL/TLS version is used in Java
Note that the above says what versions of SSL / TLS are supported by older versions of Java. It also provides some tips one figuring out what version is actually being used.
If you had told us clearly ...
what versions of SSL / TLS you were trying to use,
what Tomcat Connector class you were using, and
what versions of the respective software you were using ...
then I might have been able to give you more specific advice.
Related
As per the below link
https://github.com/spring-projects/spring-boot/issues/6164, the following features are removed from tomcat 8.5
a) Class org.apache.tomcat.util.net.ServerSocketFactory no longer exists
b) Class org.apache.tomcat.util.net.jsse.JSSESocketFactory no longer exists
c) Method JSSEImplementaton.getServerSockerFactory(AbstractEndpoint) no longer exists
d) Method JSSEImplementaton.getSSLUtil(AbstractEndpoint) no longer exists
These make our upgrade from tomcat 8.0 to tomcat 8.5.x difficult.
We have two requirements
Tomcat AJP protocol receives encrypted content coming from the HTTP server and gives an encrypted response. This was possible with tomcat 8, by using custom classes implementing tomcat's ServerSocketFactory interface.
Store certificates file for tomcat https in a custom keystore (an XML file)
How these can be achieved in tomcat 8.5? Any suggestions appreciated. (We were doing it in Tomcat 8 using custom SocketFcatory implementing tomcat's interface)
After the connector refactoring the JIoEndpoint that allowed to specify arbitrary ServerSocketFactory is no longer available.
However the AJP connector is almost ready to accept SSL connections if you allow some changes to Tomcat's codebase: the AbstractAjpProtocol class just lacks an implementation of the addSslHostConfig and findSslHostConfigs or better it has implementations that don't store or return anything with a very explicit comment:
SSL is not supported in AJP
If you change them as in AbstractHttp11Protocol, you'll be able to configure an AJP connector the same way you configure a HTTP/1.1 connector:
<Connector SSLEnabled="true" port="8009" protocol="AJP/1.3">
<SSLHostConfig ...>
<Certificate ... />
</SSLHostConfig>
</Connector>
Regarding the certificate storage you can implement your own KeyStoreSpi and security provider and use:
<Certificate certificateKeystoreProvider="your_provider"
certificateKeystoreType="your_type"
... />
Setting up the context:
In java 8 (precisely 8b98), in order to deal with Client-Initiated Renegotiation causing vulnerability to Denial of Service attack, an un-documented flag was rolled out named jdk.tls.rejectClientInitiatedRenegotiation as a part of Transport Layer Security which could disable client initiated renegotiations.
jdk.tls.rejectClientInitiatedRenegotiation = true
Server which i'm using is JBoss 7.1.1 which supports 7. However java 8 supporting servers are JBoss EAP & Wildfly. I'm reluctant to switch to these new server.
Now My challenge is to implement this property somehow in Java 7. Any sort of guidance will be highly appreciated.
Indeed Java 7 doesn't support this option. Maybe an acceptable behavior could be the Interoperable mode as in Description of Phase 2 Fix of the JSSE 7, which means enabling renegotiation for "good" clients ?
My exact answer is to switch to OpenSSL implementation, particularly the one with the hard-coded renegotiation denial, then you get rid of the JSSE implementation which doesn't support your hard-to-find option.
First, you need OpenSSL 0.9.8l which just denies all client renegotiations.
After that enable the Native Connectors on JBOSS 7.1 and configure as said in this documentation.
web archive links :
http://web.archive.org/web/20201019212829/https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html
http://web.archive.org/web/20201027040002/https://www.openssl.org/news/secadv/20091111.txt
http://web.archive.org/web/20201123225554/https://docs.jboss.org/author/display/AS71/Admin%20Guide.html
I have built a JAVA web application which uses SOAP to fetch data from an external database server. This works fine until a few days ago. Now, the connection to the database server is terminated while establishing them.
In my JAVA log file, I found the following sequence of exceptions:
javax.net.ssl.SSLException: Server key
at sun.security.ssl.Handshaker.throwSSLException(Handshaker.java:1260)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:283)
...
Caused by: java.security.spec.InvalidKeySpecException: Unknown KeySpec type: java.security.spec.ECPublicKeySpec
at org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory.engineGeneratePublic(Unknown Source)
at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
Maybe the provider of the database server has changed their SSL certificate and got another CA chain.
I noticed that the intermediate CA use SHA384withRSA as signature algorithm. (see COMODO, Domain Validation (SHA-2)).
So, what can I do to to make my system running again?
Please ask, if you need further information.
Remark: The same SOAP request from a Windows 7 client works fine. There I noticed, that the Windows 7 client uses TLSv1.2 to establish the SSL connection. The Linux system of my server (see below) uses TLSv1 ,
The configuration of my Java WebServer:
Debian Wheezy
Java: OpenJDK 1.7.0u111
Tomcat 7.0.28
https connector uses JSSE with sslProtocol="TLS"
BIRT Runtime V4.5.0
DTP V1.12.0
org.eclipse.datatools.enablement.oda.ws V1.2.6
Thanks
Friedbert
Solved!
Apparently, the configuration of the tomcat connector did no longer match current security standards.
I had set up the system 2 years ago. But the security requirements have increased in the meantime.
Now I took a recent appliance from turnkey, compared the settings and found a few differences:
JAVA: java.security
security.provider.10=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.cfg
Tomcat7: server.xml /Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
sslProtocol="TLSv1.2" sslEnabledProtocols="TLSv1.2,TLSv1.1,TLSv1"
server="Secret" URIEncoding="UTF-8" (may be, these does not matter)
With these changes, my system works again!
1/
Install the latest version of tomcat (8.0.28) and run it on java 8 (I'm using the 1.8.0_45 / 64-Bit version).
I'm running the Tomcat on a Windows 7 64-Bit
2/ Enable SSL on Tomcat:
Activate SSL by creating a keystore and uncommenting the https connector in the server.xml file, add
keystoreFile="" keystorePass=""
to the connector.
FYI: here is my connector:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystorePass="password"
keystoreFile="/path/to/my/keystore" />
3/ Install Fiddler (www.telerik.com/fiddler) or any other tool to sniff the traffic between your host and the server, the fiddler should run on your host. I did my screen shots with Fiddler.
4/
Go to tools/options/https and check "enable decrypt".
5/
Using Internet explorer 11 (chrome also works but as it compresses the websocket traffic it makes it harder to reach 8KB of data), access your tomcat remotely using https and open the example app at https://server:8443/examples/websocket/echo.xhtml
choose "Programmatic API", hit "Connect", then send a small test message
on fiddler, double click on the websocket session and look at the result in the websocket tab.
Now, try to send a large text of say 20KB, you'll see that the reply is split in frames of 8KB marked "Continuation". There should be a frame marked "Final" which is missing at this point.
Send another small message so that the missing frame is flushed.
Important:
If I connect to a Tomcat running locally on my host I do not reproduce this issue.
If I do not use SSL, I do not reproduce this issue.
Questions:
- why such behavior, did anyone experience the same thing ?
- how to properly troubleshoot this issue ?
- I tried to enable the Tomcat logging but nothing interesting in the logging: org.apache.tomcat.websocket.level = FINE
The issue is apparently OS related:
When Tomcat is on Windows 7 it does not work
When Tomcat is on Windows 10 it works
When Tomcat is on Windows Server 2012 R2 it works
In short this issue a combination of OS (some versions of windows) / SSL and WebSockets.
The "dirty" workaround I found for now is to send a last message to flush the buffer since I have access to the code of the server side.
please let me knwo if you faced such issue as this could be something related to the SSL handshake for some specific windows versions and I don't knwo how to trouble shoot that.
I have recently discovered XCA tool to manage certificates, keys and so on related to cryptography or security (check it out here ).
So far, I've created a self-signed CA certificate, with which I've signed my server and client certificates:
Now, what I want to do is configure Tomcat with the exported files of XCA so as to make use of SSL:
<Connector
port="8443"
protocol="org.apache.coyote.http11.Http11AprProtocol"
maxThreads="150"
SSLEnabled="true"
scheme="https"
secure="true"
clientAuth="true"
sslProtocol="TLSv1.2"
SSLVerifyClient="require"
SSLCipherSuite="ALL"
SSLCertificateFile="??"
SSLCertificateKeyFile="??"
SSLCertificateChainFile="??"
SSLCACertificateFile="??" />
So my question comes here: which files must I export and where to place them in the Tomcat Connector? (PEM, pem with certificate chain file, pem with all trusted certificates, pem with all certificates...).
Thanks for your help!
EDIT:
I've followed this tutorial to set all up (this guide is in spanish). I've tested it on Firefox, Chrome, Internet Explorer and Safari. The unique browser in which it's working is Firefox... I'm getting the following error: ERR_CERT_INVALID
I've realised what might be causing this issue... I've used sometimes SHA-1 alg to make these certificates. I'll repeat the process using another algorithm.
EDIT 2
After changing the hashing algorithm from SHA-1 to SHA-512, nothing has changed...
EDIT 3
It seems that Chrome, Internet Explorer or Safari are more strict than Firefox on terms of security. I've tried a client in Java which connects to my web service using HTTPS and works fine :).
Since you are using the APR connector, you are correct that you should be using PEM files (the other connectors use Java keystores). Just be aware that a "PEM file" just describes the file type and not its contents.
You will need two artifacts to get TLS configured:
The server's private key
The server's certificate
There are ways to configure these artifacts in a single file, but it's a bit easier to understand if you have each one in a separate file. It's somewhat traditional to have a file called [servername].key for the key and another file called [servername].crt for the certificate.
It will be easier to verify that TLS is configured properly first without using client certificates, so try that first and then add the client-cert configuration on top of that.
Now that you have these files, the SSL-related attribute values are somewhat obvious:
SSLCertificateFile="[servername].crt"
SSLCertificateKeyFile="[servername].key"
You will not need either of these attributes to be set to anything:
SSLCertificateChainFile
SSLCACertificateFile
Don't set the cipher suite to "ALL"... that will enable ciphers with essentially zero security. Try something like SSLCipherSuite="HIGH". You'll want to read online a bit about how to configure a decent set of cipher suites for a modern deployment.