Zuul Connections not kept alive when using a Client Cert - java

To be able to support a client cert, I extended
ProxyHttpConnectionManager extends DefaultApacheHttpClientConnectionManagerFactory and have overridden newConnectionManager
if (disableSslValidation) {
try {
final SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial((new File(keystore)), keyStorePass.toCharArray(), keyStorePass.toCharArray())
.loadTrustMaterial(new File(trustStore)).build();
registryBuilder.register(HTTPS_SCHEME, new SSLConnectionSocketFactory(
sslContext, NoopHostnameVerifier.INSTANCE));
}
catch (Exception e) {
LOG.warn("Error creating SSLContext", e);
}
Thats the only customization I have done. Zuul does not keep the HttpConnections alive for servers that need a client cert. For all other servers on Https, previous connections are reused.
Summary for SSL Logs and TCP Dumps
No Client Cert requried
SYN , Client Hello
Server Hello
Data Exchange
Request 2- Data Exchange
Close after timeout
Servers with Client Cert Required
SYN CLient Hello
Server Hello
Data Exchange
FIN
Request 2 - SYN
Hello's again
Data Exchange
Fin

Related

Force client or server to restart SSL handshake (or expire SSL session)

I have a java client which connects to an HTTPS server (the server written in Java also). Here is the HttpClient setting in the client:
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
keyManagers = ...; // Created from a PKIX KeyManagerFactory
trustManagers = ...; // Created from a PKIX TrustManagerFactory
ctx.init(keyManagers, trustManagers, new SecureRandom());
SSLContext.setDefault(ctx);
RequestConfig defaultRequestConfig = RequestConfig.custom()//
.setSocketTimeout(5000)//
.setConnectTimeout(5000)//
.setConnectionRequestTimeout(5000)//
.build();
httpClient = HttpClients.custom()//
.setSSLContext(ctx)//
.setDefaultRequestConfig(defaultRequestConfig)//
.setSSLHostnameVerifier(new NoopHostnameVerifier())//
.build();
The client certificate and trusted certificates are stored in a PKI token.
The client sends some HTTP requests to the server continuously. All things work fine. Now I want to force client (or server) to restart handshaking. In other words, I want to refresh SSL connection which causes to check server certificate periodically. Is there any way to do this?
I know about SSLSessionContext.setSessionTimeout(). But this will not refresh the current connection(s). It will force only new connections to do handshaking again.
For future readers.
I ask a similar question on security.stackexchange.com without details about programming. I had thought that the question may be a security issue. However, that question now is migrated from security.stackexchange.com to stackoverflow.com and has a convincing answer for me. I suggest referring to that: https://stackoverflow.com/a/55004572/5538979
You can clear the ssl caches with the following code snippet:
SSLContext sslContext = ...; // your initialised SSLContext
SSLSessionContext sslSessionContext = sslContext.getClientSessionContext();
Collections.list(sslContext.getClientSessionContext().getIds()).stream()
.map(sslSessionContext::getSession)
.filter(Objects::nonNull)
.forEach(SSLSession::invalidate);

FTP4j fails to use FTPES (TLS session of data connection has not resumed or the session does not match the control connection)

I am trying to use ftp4j lib to get list of files from FileZilla FTP servcer with TLS.
import it.sauronsoftware.ftp4j.FTPClient;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.Arrays;
public class FTP {
public static void main(String args[]) throws Exception {
System.setProperty("http.protocols", "TLSv1,TLSv1.1,TLSv1.2");
//tried to avoid closing connection during the handshake
//load and set certificate
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream("mykeystore.jks"), "root12".toCharArray());
FTPClient client = new FTPClient();
SSLContext sslContext = null;
try {
javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory
.getInstance(javax.net.ssl.KeyManagerFactory
.getDefaultAlgorithm());
tmf.init(keyStore);
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
} catch (Exception e) {
e.printStackTrace();
}
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
client.setSSLSocketFactory(sslSocketFactory);
client.setSecurity(FTPClient.SECURITY_FTPES);
client.setCharset("UTF-8");
client.setPassive(true);
String[] arg = client.connect("localhost", 21);
System.out.println(Arrays.toString(arg));
client.login("admin", "pass"); //OK
client.noop(); // aka Ping is OK
String s = client.currentDirectory(); //OK
client.changeDirectory("/"); //OK
String[] files = client.listNames(); //Exception here
System.out.println(Arrays.toString(files));
client.disconnect(true);
}
}
I got an exception
Exception in thread "main" it.sauronsoftware.ftp4j.FTPException
[code=450, message= TLS session of data connection has not resumed or
the session does not match the control connection] at
it.sauronsoftware.ftp4j.FTPClient.listNames(FTPClient.java:2407) at
FTP.main(FTP.java:49)
I tried to use active mode, but it doesn't help also (failed after ping command)
Exception in thread "main" it.sauronsoftware.ftp4j.FTPException
[code=421, message= Rejected command, requested IP address does not
match control connection IP.]
Could you please answer me what I've done wrong or does ftp4j library actually support FTPES & TLS?
Screenshots with FileZilla server TLS configuration:
ftp4j library does support FTPS/TLS. Were it not, you would not get the error in the first place.
FileZilla FTP server is one of FTP servers, which require the clients to reuse the TLS/SSL session from FTP control connection for data connections:
https://svn.filezilla-project.org/filezilla?view=revision&revision=6661
This increases security by making it a way harder for an attacker to hijack a data connection.
I do not know, if ftp4j supports the reuse this though.
Alternative solutions are:
Use Java FTP client from Apache Commons Net library. While it does not support the reuse on its own, it's easy to add the support. See How to connect to FTPS server with data connection using same TLS session?
As you own the FTP server, you can disable the requirement for reuse. See the Require TLS session resumption on data connection when using PROT P option (on your screenshot). Though as mentioned above, it has some impact of security.
Try to remove this checkbox it helped me.

Java8 Secure WebSocket Handshake Problems (Tyrus and Jetty)

I'm attempting to implement a WebSocket Client in an application that supports secure transmissions through SSL. The application already supports standard SSL connections over HTTP, by implementing custom Key and Trust managers (these custom implementations are in place to prompt the user for a certificate when needed).
I'm having trouble getting a secure connection to our remote WebSocket endpoint. The failure is occurring during the handshake. I've tried two different implementations of the WebSocket API (both Tyrus and Jetty), and both fail in the same way, which, of course, leads me to point to our SSL implementation.
As I mentioned, the failure is occurring during the handshake. It seems that the connection cannot figure out that there are client certificates that are signed by the supported authorities returned from the server. I'm stumped to figure out if I haven't supplied the client certificates to the WebSocket API correctly, or if our custom Key/Trust managers are even getting used.
Here's a dump of the SSL Debug logs:
*** CertificateRequest
Cert Types: RSA, DSS
Cert Authorities:
(list of about 15 cert authorities supported by the server)
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** CertificateChain
<empty>
***
I've set breakpoints in our TrustManager implementation, to determine if they are ever getting called, and it seems that they are not being called at this point.
I've been attempting to debug this for a few days now, and am running out of things to try.
Any suggestions would be greatly appreciated!
Here's a snippet of the Jetty Code:
SSLContext context = SSLContext.getInstance("TLS");
// getKeyManagers / getTrustManagers retrieves an
// array containing the custom key and trust manager
// instances:
KeyManager[] km = getKeyManagers();
TrustManager[] tm = getTrustManagers();
context.init(km, tm, null);
SslContextFactory contextFactory = new SslContextFactory();
contextFactory.setContext(context);
WebSocketClient client = new WebSocketClient(contextFactory);
SimpleEchoClient echoClient = new SimpleEchoClient();
try {
client.start();
ClientUpgradeRequest request = new ClientUpgradeRequest();
Future<Session> connection = client.connect(echoClient, uri, request);
Session session = connection.get();
// if everything works, do stuff here
session.close();
client.destroy();
} catch (Exception e) {
LOG.error(e);
}
can you try with rejectUnAuthorized:false so that your certificates for which your browser is unable to authorize will skip the authorization.
var ws = new WebSocket('wss://localhost:xxxx', {
protocolVersion: 8,
origin: 'https://localhost:xxxx',
rejectUnauthorized: false
});

how to do connection pooling on a https server (to reduce time on ssl handshake)in java (Spring) [duplicate]

I am trying to communicate with a server using https service
I am able to communicate but it takes 2 Secs response time..
Now, I want to reduce time for SSL handshake for every request
So, I want to cache or keep the connection live or create pooling connection..
Any suggestions..
My Code:
static SslConfigurator sslConfig = SslConfigurator
.newInstance()
.securityProtocol("TLS")
.keyStoreFile("/path")
.keyStorePassword("password")
.keyStoreType("JKS")
.trustStoreFile(
"/path");
static SSLContext sslCtx = sslConfig.createSSLContext();
static Client client = ClientBuilder.newBuilder().sslContext(sslCtx).build();
Response response = client.target(target).path(path).request(MediaType.APPLICATION_JSON)
.post(Entity.entity(jsonRequest.toString(), MediaType.APPLICATION_JSON));

Using two key-pairs in SSL Socket Connection

I'd like to know how I can implement a server socket to let it able to identify and use
correct certificate according with the certificate being used by client to proceed
handshake communication with the server.
Explaining better, in the server side is:
AppServerSideSocket.jar
private keystore: privateKeyApp (type JKS, generated with keytool)
public keystore : publicKeyApp (type JKS, shared with all clients)
And in the client side ...
AppClientSideSocket.jar
- public keystore : publicKeyApp
The AppServerSideSocket.jar listening clients requests and once received proocess
information sent by clients
The AppClientSideSocket.jar connect with the server using SSL using publicKeyApp without
verify server hostname and after handshake send information for the AppServerSideSocket application.
Now I've another client application, AppClientSideSocketNEW.jar, and this verify server hostname to make
communication with the server. In this case, the CN used in the public certificate on the client side
must be match with the hostname where AppServerSideSocket.jar are.
Originaly the connection was configured in this way on the server side:
if (usingSSLConn) {
System.setProperty("javax.net.ssl.keyStore", "privateKeyApp");
System.setProperty("javax.net.ssl.keyStorePassword", "privateKeyAppPassword");
SSLServerSocketFactory sslServerSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
ServerSocket serverSocketApp = sslServerSocketFactory.createServerSocket(Port);
} else
serverSocketApp = new ServerSocket(Port);
}
All the clients received the same publicKeyApp and connect with the server without verify hostname, so doesn't matter
if the server where server socket application (AppServerSideSocket.jar) is installed in the server with hostname is
badServer1.com and the CN of key in privateKeyApp and publicKeyApp is setted with goodServer1.com, because all the clients don't verify hostname or the CN attribute of the key.
Bellow is showed a piece of this kind of connection:
private static final HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
System.setProperty("javax.net.ssl.trustStore", publicKey1);
System.getProperties().setProperty("java.protocol.handler.pkgs",
"javax.net.ssl.internal.www.protocol");
HttpsURLConnection.setDefaultHostnameVerifier(DO_NOT_VERIFY);
...
SOAPConnectionFactory soapConn = SOAPConnectionFactory.newInstance();
SOAPConnection connection = soapConn.createConnection();
...
URL endpoint = new URL(hostname + ":" + port);
But the new client (AppClientSideSocketNEW.jar) do this verification obrigatorily, now is necessary provide a new certificate
for this client with new value for CN attribute reflecting the correct hostname CN where the server socket is.
I don't have access to second client and I'm sure that it do hostname verification.
So I created two new key-pair ceritificates (privateKeyAppNew and publicKeyAppNew) and aparently the communications happened
with success between the server using this new key-pair and new client using this new public publicKeyAppNew key.
But I need continue to use the old key-pair for old clients. I'd like to know how can I deal with this.
Using a keymanager let me able to verify the client certificate on the server app when client try to connect and
choose the apropriate and do the handshake using the correct certificate?
Or I need disctinct ssl socket connection in different ports for which kind of clients?
You need to set a Hostname Verifier in the connection you want to verify the CN of the server certificate.
Plenty of examples if you google e.g.
Hostname verifier 1 this creates a trust all names but you can modify it as you need
HttpClient and SSL same in the answer her

Categories