This discussion is archived
13 Replies Latest reply: Oct 17, 2012 7:22 AM by 850701 RSS

Freeze/Hang when connecting using SSLSocket

850701 Newbie
Currently Being Moderated
Hi

I have a client/server connection using a SSLSocket. The SSL stuff is using a certificate inside a keystore with a public key which is stored in a signed .jar file, as part of the set of jars obtained by the client using Java Web Start (jars are signed, of course).

In the server side I have estabished the javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword properties with the right values, and are pointing to the keystore where I have the private key wired to the public key inside the certificate stored in the client's keystore. This way I can use the default SSLServerSocketFactory to get a SSLServerSocket (and then SSLSockets from the ssocket.accept() method).

In the client side I do this:
char[] passwordKeystore = "keyForTheKeystore".toCharArray();

KeyStore ks = KeyStore.getInstance("JKS");

ks.load(CommManager.class.getResourceAsStream("/path/to/the/keystore/inside/the/jar/file"), passwordKeystore);

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
trustManagerFactory.init(ks);

KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(ks, passwordKeystore);

SSLContext sslContext = SSLContext.getInstance("TLSv1");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
SSLContext.setDefault(sslContext);

sslSocketFactory = sslContext.getSocketFactory();
I'm exchanging data exchanging serialized Objects through this SSLSocket. I've tried to "startHandshake()" in the client right after "connect()" (also in the server with the SSLSocket I get from "ssocket.accept()"), before getting the reference to the streams, but I've also tried to skip this step. Then I get first the ObjectOutputStream and then the ObjectInputStream in both sides.

Here is the problem:
This code works fine in a computer, but in another (both Linux, only different versions of Ubuntu, and always using the oracle JVM; this happens with both java6 and java7) there is a strange delay when I try to get the ObjectOutputStream, and I tried to exchange the order (first OOS in one side and OIS in the other, just to test) but the problem is still there. After 25/30 seconds the connection is finally established and everything works.

By enabling debug in the java.net stack (I don't remember the exact name of the property) I've seen both VM's loading the known certificates, but everything is paused when it's going to obtain the reference to the streams, and finally works after this 25/30 seconds delay (I can see the helloClient and helloServer steps, and the algorithm negotiation).

What might be going on here? Is it really using the certificate I created (self-signed), or this delay is related with some timeout because of not being using the proper key pair, which finally forces the connection to use a default key pair provided by the server, as long as client autenthication is not required?

Regards

Edited by: 847698 on 08-oct-2012 13:33
  • 1. Re: Freeze/Hang when connecting using SSLSocket
    EJP Guru
    Currently Being Moderated
    1. If the javax.net.debug trace gets past the ChangeCipherSpec messages the handshake is complete and you are speaking SSL.

    2. You need to construct to OOS first. Strictly speaking you only need to do that at one end, OOS-OIS and OS-OOS will work, but its easiest to do it first at both ends (OOS-OIS and OOs-OIS) so that you don't run any risk of doing OIS-OOS and OIS-OOS, which will deadlock.

    3. Whether you call startHandshake() before the first I/O or not is immaterial, as it will happen anyway during the first I/O, which in this case is during the construction of the OOS.
  • 2. Re: Freeze/Hang when connecting using SSLSocket
    850701 Newbie
    Currently Being Moderated
    Hmm by checking my code I've seen everything ok, compared to your suggestions, and with some tests I have discovered something interesting:
    It works fine if the server is listening in localhost or if you have internet connection, but it fails if your machine doesn't have access to internet. In fact in my tests I was using a fake network for both server and client (192.168.x.x, same PC for server and client) where there was no working default GW (it was configured in the network settings, but the router was offline), but if I use a public address or localhost there is no such delay.

    Because of this I expect this problem to be related with some security stuff, as long as the certificate in the client is self-signed and the VM might be trying to authenticate it outside as long as it doesn't match any of the internal well known CA's. But again it's strange, once I've been sniffing network traffic with wireshark and there's no packet exchange with the outside during the handshake process (when using the 192.168.x.x network).

    Regards
  • 3. Re: Freeze/Hang when connecting using SSLSocket
    EJP Guru
    Currently Being Moderated
    As I said, if it gets to the end of the handshake, SSL is working, so it isn't the certificate. It sounds like a DNS problem to me.
  • 4. Re: Freeze/Hang when connecting using SSLSocket
    850701 Newbie
    Currently Being Moderated
    It seems so. Only for testing I've removed the DNS servers in the network configuration and/or the default GW, and the delay is now close to 5 seconds, so there is some relation there, indeed. Besides it only happens with SSLSockets and not whith non-SSLSockets, so I think the SSL stack does some internal work which need DNS "for something".

    It would be interesting to know what is this extra stuff, but the main goal was to detect the source of the problem :)

    Regards
  • 5. Re: Freeze/Hang when connecting using SSLSocket
    jtahlborn Expert
    Currently Being Moderated
    to state the obvious, which i haven't seen mentioned/confirmed yet in the thread. you need to immediately flush the OOS after you instantiate it. maybe you already do this, just wanted to make sure it wasn't something "simple".
  • 6. Re: Freeze/Hang when connecting using SSLSocket
    EJP Guru
    Currently Being Moderated
    I've been saying that for years too but I don't think it's correct. I think there's an automatic flush, if one is needed. Anyway it wouldn't explain the symptoms, which are occasional, not every time.
  • 7. Re: Freeze/Hang when connecting using SSLSocket
    850701 Newbie
    Currently Being Moderated
    It can't be done. I can't flush the OOS as long as both client and server are blocked at socket.getOutputStream() at the same time. The program flow continues with the next line of code after the delay.
  • 8. Re: Freeze/Hang when connecting using SSLSocket
    EJP Guru
    Currently Being Moderated
    I think you still need to clarify here when exactly the delay occurs, i.e. at what point with respect to the output of -Djava.net.ssl.debug.
  • 9. Re: Freeze/Hang when connecting using SSLSocket
    jtahlborn Expert
    Currently Being Moderated
    847698 wrote:
    It can't be done. I can't flush the OOS as long as both client and server are blocked at socket.getOutputStream() at the same time. The program flow continues with the next line of code after the delay.
    you should get a stack dump of your program at the point when it is hanging.
  • 10. Re: Freeze/Hang when connecting using SSLSocket
    jtahlborn Expert
    Currently Being Moderated
    EJP wrote:
    I've been saying that for years too but I don't think it's correct. I think there's an automatic flush, if one is needed.
    I don't see any obvious "flush" call in ObjectOutputStream after the header is written.
    Anyway it wouldn't explain the symptoms, which are occasional, not every time.
    good point.
  • 11. Re: Freeze/Hang when connecting using SSLSocket
    850701 Newbie
    Currently Being Moderated
    Ok, here it goes the output with debug enabled.

    Output in client side:
    keyStore is : 
    keyStore type is : jks
    keyStore provider is : 
    
    --------------- At some point here my SSL stuff is initialized, using the code of my first post
    
    init keystore
    init keymanager of type SunX509
    trustStore is: /path/to/keystore
    trustStore type is : jks
    trustStore provider is : 
    init truststore
    adding as trusted cert:
      MY CERT ------------------------------
    
    trigger seeding of SecureRandom
    done seeding SecureRandom
    Allow unsafe renegotiation: false
    Allow legacy hello messages: true
    Is initial handshake: true
    Is secure renegotiation: false
    
    --------------- Ok establishing the TCP connection
    SSLSocket socket = (SSLSocket)sslSocketFactory.createSocket();
    
    socket.connect(new InetSocketAddress("192.168.x.x", port));
    
    --------------- Ok before calling getOutputStream()
    ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
    
    --------------- 25/30 SECONDS DELAY HERE (blocked in this method call / constructor)
    
    %% No cached client session
    *** ClientHello, TLSv1
    RandomCookie:  GMT: 1349860735 bytes = { 181, 153, 31, 19, 148, 94, 0, 4, 123, 73, 50, 89, 135, 12, 124, 102, 190, 129, 104, 241, 115, 235, 116, 107, 28, 130, 24, 194 }
    Session ID:  {}
    Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
    Compression Methods:  { 0 }
    ***
    Thread-0, WRITE: TLSv1 Handshake, length = 81
    Thread-0, WRITE: SSLv2 client hello message, length = 110
    Thread-0, READ: TLSv1 Handshake, length = 1008
    *** ServerHello, TLSv1
    RandomCookie:  GMT: 1349860735 bytes = { 117, 97, 0, 132, 86, 132, 98, 105, 137, 207, 30, 190, 224, 236, 92, 225, 159, 242, 115, 138, 144, 160, 243, 209, 43, 175, 221, 23 }
    Session ID:  {80, 117, 61, 127, 222, 181, 192, 12, 239, 17, 207, 187, 229, 245, 12, 138, 24, 56, 91, 245, 142, 29, 26, 188, 233, 49, 50, 71, 61, 68, 149, 16}
    Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
    Compression Method: 0
    Extension renegotiation_info, renegotiated_connection: <empty>
    ***
    %% Created:  [Session-1, SSL_RSA_WITH_RC4_128_MD5]
    ** SSL_RSA_WITH_RC4_128_MD5
    *** Certificate chain
    Output in server side:
    keyStore is : /path/to/keystore
    keyStore type is : jks
    keyStore provider is : 
    init keystore
    init keymanager of type SunX509
    ***
    found key for : keyjnlp
    chain [0] = [
    [
      MY CERT ------------------------------
    
    ]
      Algorithm: [MD5withRSA]
      Signature:
        ----
    
    ]
    ***
    trustStore is: /usr/lib/jvm/java-6-sun-1.6.0.26/jre/lib/security/cacerts
    trustStore type is : jks
    trustStore provider is : 
    init truststore
    adding as trusted cert:
      Subject: CN=SwissSign Platinum CA - G2, O=SwissSign AG, C=CH
      Issuer:  CN=SwissSign Platinum CA - G2, O=SwissSign AG, C=CH
      Algorithm: RSA; Serial number: 0x4eb200670c035d4f
      Valid from Wed Oct 25 10:36:00 CEST 2006 until Sat Oct 25 10:36:00 CEST 2036
    
    adding as trusted cert:
     LOTS OF CERTS ---------------------
    
    trigger seeding of SecureRandom
    done seeding SecureRandom
    ------- ServerSocket created OK
    ------- Before ssocket.accept()
    Allow unsafe renegotiation: false
    Allow legacy hello messages: true
    Is initial handshake: true
    Is secure renegotiation: false
    matching alias: keyjnlp
    Thread-0, called closeSocket()
    Allow unsafe renegotiation: false
    Allow legacy hello messages: true
    Is initial handshake: true
    Is secure renegotiation: false
    --------------- Now I have a SSLSocket from accept()
    --------------- Ok before calling getOutputStream()
    ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
    
    --------------- 25/30 SECONDS DELAY HERE (blocked in this method call / constructor)
    
    
    Thread-1, READ:  SSL v2, contentType = Handshake, translated length = 81
    *** ClientHello, TLSv1
    RandomCookie:  GMT: 1349860735 bytes = { 181, 153, 31, 19, 148, 94, 0, 4, 123, 73, 50, 89, 135, 12, 124, 102, 190, 129, 104, 241, 115, 235, 116, 107, 28, 130, 24, 194 }
    Session ID:  {}
    Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
    Compression Methods:  { 0 }
    ***
    %% Created:  [Session-1, SSL_RSA_WITH_RC4_128_MD5]
    *** ServerHello, TLSv1
    RandomCookie:  GMT: 1349860735 bytes = { 117, 97, 0, 132, 86, 132, 98, 105, 137, 207, 30, 190, 224, 236, 92, 225, 159, 242, 115, 138, 144, 160, 243, 209, 43, 175, 221, 23 }
    Session ID:  {80, 117, 61, 127, 222, 181, 192, 12, 239, 17, 207, 187, 229, 245, 12, 138, 24, 56, 91, 245, 142, 29, 26, 188, 233, 49, 50, 71, 61, 68, 149, 16}
    Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
    Compression Method: 0
    Extension renegotiation_info, renegotiated_connection: <empty>
    ***
    Cipher suite:  SSL_RSA_WITH_RC4_128_MD5
    I hope that's enough

    Regards

    Edited by: 847698 on 11-oct-2012 18:47
  • 12. Re: Freeze/Hang when connecting using SSLSocket
    EJP Guru
    Currently Being Moderated
    @jwenting: I don't see any buffering to flush either. It has a buffering mode but I think it's only used when writing custom serialisation data. You'd need a flush if there was a BufferedOutputStream.

    @OP: this is really odd. The connection seems to exist, which appears to rule out DNS, and the handshake hasn't even started, which appears to rule out the certificates.

    I still think its DNS, or reverse DNS: Java does that in the SecurityManager for accepted connections. Can you add -Djava.security.debug=access,failure?
  • 13. Re: Freeze/Hang when connecting using SSLSocket
    850701 Newbie
    Currently Being Moderated
    Yeah, I also think it might be related to DNS. It's a bit strange why it needs DNS or reverse DNS when the TCP connection is already established, but for whatever reason it might be doing some DNS-related work.

    Anyway, using -Djava.security.debug=access,failure there's no output at all in terms of debug information.

    Regards

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points