I have a client/server process with one server and one client.
The connect setup looks like:
System.setProperty("javax.net.ssl.trustStore", "path/to/store");
System.setProperty("javax.net.ssl.trustStorePassword", "passwd");
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
sslsocket = (SSLSocket) sslsocketfactory.createSocket(InetAddress.getLocalHost(), port);
1:1, this works fine. Now I am expanding it such that the server is listening on multiple ports for multiple clients. Each client that connects to the server should do so on a specific port with a specific truststore.
If I register two trust stores on the server side, when I try to make the client connection I get the error:
javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown Received fatal alert: certificate_unknown
I've been looking through stack overflow for an example, but everything seems overly complicated. Is there a simple way to manage this? Or a compelling reason that one process shouldn't use multiple key stores?
I don't think using your method this is possible. Since you are setting a system property (which is a hashtable), the last one you write will overwrite the earlier ones.
But also, I do not understand the usecase. In general truststore is a client side concept. It is about determining what server to trust. Most of the time (unless you are using certificate based authentication) a client's trustworthiness is not relevant.
Having said this, it is possible to set different keystores for different ports. In tomcat, for instance
<Connector port="443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
keystoreFile="${user.home}/.keystore1"
keystorePass="changeit"
clientAuth="false" sslProtocol="TLS" />
The above snippet states that on port 443 ~/.keystore1 should be used. On another port, keystore2 could be used.
Should you want to use client authentication, you can force the client to send a certificate, in the above example by setting clientAuth to true, and adding truststoreFile and truststorePass.
Digging in tomcat's source code may help you in setting up your environment. In particular the file java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java will perhaps have exactly what you want.
Related
I have an application which is hosted on AWS instance and we used elastic load balancer with AWS SSL certificate. We used tomcat server. As we used AWS SSL certificate we have not configured 443 port on tomcat. Now we want to implement two way SSL certificate. I have searched for the same but most of the information is saying use SSLEnable=true in tomcat's server.xml but this will not work in my case. Can someone please help me in this situation to implement Two way SSL.
This is how i've setup it,
(server.xml)
<Connector
port="8081"
protocol="HTTP/1.1"
proxyPort="443"
scheme="https"
secure="true"
proxyName="mydomain.com"
connectionTimeout="50000"
URIEncoding="UTF-8"
redirectPort="8443" />
I have a Java app deployed in tomcat 6. The app sends messages to another service via socket and it needs to use ONLY TLSv1.2 protocol.
In my tomcat6.conf file I put this configuration:
JAVA_HOME=/usr/lib/jvm/jre1.7.0_75
JAVA_OPTS="${JAVA_OPTS} -Djavax.sql.DataSource.Factory=org.apache.commons.dbcp.BasicDataSourceFactory -Dhttps.protocols=TLSv1.2"
But stll use the older tls version.
It there any configuration to apply in java or tomcat to force use TLSv1.2?
Edit 1:
The answer provided by #Peter Walser is good and could work. The problem is I can't modify the code because is a jar provided by third party, and I can only configure the enviroment, not the code.
The https.protocols system property is only considered for HttpsURLConnection and URL.openStream(), as stated in Diagnosing TLS, SSL, and HTTPS
Controls the protocol version used by Java clients which obtain https connections through use of the HttpsURLConnection class or via URL.openStream() operations. ...
For non-HTTP protocols, this can be controlled through the SocketFactory's SSLContext.
You can configure the SSLSocket as follows:
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
socket.setEnabledProtocols(new String[] {"TLSv1.2"});
When working with REST-clients, most of them support configuring the protocols over the SSLContext. Example (JAX-RS client):
Client client = ClientBuilder.newBuilder()
.sslContext(SSLContext.getInstance("TLSv1.2"))
// more settings, such as key/truststore, timeouts, logging
.build();
If you are trying to force the server to use TLSv1.2 the following link may provide what you need.
The Apache Tomcat 5.5 Servlet/JSP Container - SSL Configuration HOW-TO
As the doc specifies edit the Tomcat Configuration File as below,
The implementation of SSL used by Tomcat is chosen automatically unless it is overridden as described below. If the installation uses APR - i.e. you have installed the Tomcat native library - then it will use the APR SSL implementation, otherwise it will use the Java JSSE implementation.
To avoid auto configuration you can define which implementation to use by specifying a classname in the protocol attribute of the Connector.
To define a Java (JSSE) connector, regardless of whether the APR library is loaded or not do:
<Connector protocol="org.apache.coyote.http11.Http11AprProtocol" port="8443" .../>
Configure the Connector in the $CATALINA_BASE/conf/server.xml file, where $CATALINA_BASE represents the base directory for the Tomcat 6 instance. An example <Connector> element for an SSL connector is included in the default server.xml file installed with Tomcat. For JSSE, it should look something like this:
<!--
<Connector
port="8443" maxThreads="200"
scheme="https" secure="true" SSLEnabled="true"
SSLCertificateFile="/usr/local/ssl/server.crt"
SSLCertificateKeyFile="/usr/local/ssl/server.pem"
clientAuth="optional" SSLProtocol="TLSv1"/>
-->
You will note that the example SSL connector elements are commented out by default. You can either remove the comment tags from around the the example SSL connector you wish to use or add a new Connector element of your own. In either case, you will need to configure the SSL Connector for your requirements and environment.
The port attribute (default value is 8443) is the TCP/IP port number on which Tomcat will listen for secure connections. You can change this to any port number you wish (such as to the default port for https communications, which is 443). However, special setup (outside the scope of this document) is necessary to run Tomcat on port numbers lower than 1024 on many operating systems.
After completing these configuration changes, you must restart Tomcat as you normally do, and you should be in business. You should be able to access any web application supported by Tomcat via SSL.
Try changing the SSLProtocol attribute in <Connector> element to SSLProtocol="TLSv1.2".
<Connector
port="8443" maxThreads="200"
scheme="https" secure="true" SSLEnabled="true"
SSLCertificateFile="/usr/local/ssl/server.crt"
SSLCertificateKeyFile="/usr/local/ssl/server.pem"
clientAuth="optional" SSLProtocol="TLSv1.2"/>
I have configured Tomcat Server (apache-tomcat-9.0.1) with self-signed certificate. On this added required configuration on server.xml, and copied .jks file on conf folder.
Create Self Signed Certificate
Configure Tomcat with SSL Stuff
HTTPS Works on browser as expected.
disableSSL Verification while making HttpsURLConnection call to fetch an REST API
Certificate Exception Stuff
Disable Certificate Exception
It works ! -
On Server.xml -= only 8443 port configured.
On Web Application Security Constraint Configured:
<security-constraint>
<web-resource-collection>
<web-resource-name>OVS</web-resource-name>
<!-- all URLs are protected -->
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<!-- redirect all requests to HTTPS -->
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
Tomcat Server starts without showing any exception on anywhere.
But SSL/TLS communication not happening with Tomcat Server on using self-signed certificate ? . Wireshark captured the packets , expected to see TLS Packets or SSL Handshake But nothing, Only TCP Packets.
Why SSL Handshake not happening ?, Its like because Its verifying only SSL server certificate ? ( as Client Authentication is false )
<Connector SSLEnabled="true" acceptCount="100" clientAuth="false"
disableUploadTimeout="true" enableLookups="false" maxThreads="150"
port="8443" keyAlias="london" keystoreFile="conf/londonkey.jks" keystorePass="sumit123"
protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https"
secure="true" sslProtocol="TLS" />
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
Have you ever tested after configuring the self-signed certificate etc stuff to see If SSL/TLS Communication take place ?
Edit
AS Far as I know that to have SSL Communication between two network entity say A and B, both must have their own private key and public certificate, but on above we have configured only Server with Certificate and Private Key stuff nothing with Client ?, Please correct ?
I have checked various example : posts , but all talking about the generating the key and only configuring the Tomcat Server. For Test, Its talking like browser would be showing certificate exception , accept that exception and all would be set, No Where I found discussion about the actual TLS/SSL handshaking for which we actually configuring the Tomcat Server.
No, ssl cert in tomcat is not enough if non browser
Clients
Do two way ssl:
Import the cert of tomcat on client side and import
Client ‘s cert in tomcat
This way u can achieve 2way ssl
You just have to either create proper ssl context
or override javax.ssl.* which includes keystore
Keystore password and key password if any
That’s it
I'm having regarding a java web app running on apache.
One of the pages is invoking an applet which code is an external server.
The company responsible of the applet told us to use HTTPS when invoking the page showing the applet as we had problems when we invoked the page using HTTP.
The problem is that when I browse the page in HTTPS , I have an ssl_error_rx_record_too_long error.
The address I want to browse looks like :
https://www.myurl.com:8084/myWebApp/pageContainingApplet.jsp?parameter1=value1¶meter2=value2
I looked for the server.xml file under /conf and added this tag:
<Connector port="8084" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
Still nothing
Error code: ssl_error_rx_record_too_long
This usually means the implementation of SSL on your server is not correct. The error is usually caused by a server side problem which the server administrator will need to investigate. Below are some things we recommend trying.
Ensure that port 443 is open and enabled on your server. This is the
standard port for https communications.
If SSL is using a non-standard port then FireFox 3 can sometimes give
this error. Ensure SSL is running on port 443.
If using Apache2 check that you are using port 443 for SSL. This can
be done by setting the ports.conf file as follows
Listen 80 Listen 443 https Make sure you do not have more than one
SSL certificate sharing the same IP. Please ensure that all SSL
certificates utilise their own dedicated IP.
If using Apache2 check your vhost config. Some users have reported
changing to default resolved the error.
Make sure that your SSL certificate is not expired
Try to specify the Cipher:
SSLCipherSuite
ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM:+SSLv3
Also check this : https://support.servertastic.com/error-code-ssl-error-rx-record-too-long/
I have developed a proxy servlet under Tomcat, the servlet receive the request from client and and forward to another proxy server, before forwarding, it will authenticate with the proxy server. Now it can process the HTTP request very well but can not receive the HTTPS request. So this proxy servlet is not perfect.
I have searched google and read many posts in this forum, esp this one:
Developing a proxy servlet that can handle HTTPS connections
I configured the Tomcat to listen on port 8443, as follows:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true"
keystoreFile="${user.home}/.keystore" keystorePass="changeit"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" redirectPort="8080"/>
I deployed the servlet within eclipse, locally, and I set the browser proxy to 127.0.0.1:8080, but bypass it for localhost.
When I browse https:// localhost:8443/ I can see the https request received in servlet log(by calling request.getScheme() and request.isSecure()). But if i browse https://www.google.com, it can not get connected and my proxy servlet didn't catch the request.
I also override the service() method and print the request.getMethod() and still failed to catch the HTTPS request.
What should I do?
All I want is get the HTTPS request and add the authentication and forward to the next proxy server.
Thanks
That's not the way SSL proxies work. If you set your HTTPS proxy to localhost:8080, then your browser will dutifully connect to localhost:8080 and use the CONNECT verb to tunnel SSL traffic through the HTTP proxy connection. Without doing this, SSL wouldn't be particularly secure and any proxy server administrator could trivially read one's credit card details next time someone decided to buy something from Amazon or check their bank balance or sign up for a recurring-payment adult entertainment web site or whatever it is that people do that requires SSL these days.
It doesn't appear that you've told your browser anything about this new SSL proxy on port 8443, so I'm not sure why you think it would be used. It won't. You may be able to tell your browser to use an SSL-based proxy server - ie, set your proxy ashttps://localhost:8443, but even then it will use CONNECT-based SSL tunneling, so there's really no point except still slower connections.
If all you really need to do is forward this request on to another proxy, you need to forward the CONNECT method to the upstream proxy and include the appropriate authentication information.