2014-10-01 44 views
1

我們重新配置了我們的一臺服務器以更改其虛擬主機之一的主機名。爲什麼Java 6接收與Java 7不同的SSL證書鏈?

我們的服務器配置從去:

<VirtualHost *:443> 
    ServerName test.olddomain.com 

    SSLEngine on 
    SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL 

    SSLCertificateFile "D:/Security/wildcard/OLDDOMAIN.COM.crt" 
    SSLCertificateKeyFile "D:/Security/wildcard/OLDDOMAIN.COM.key" 
    SSLCertificateChainFile "D:/Security/wildcard/CertChain.crt" 

    ... 
</VirtualHost> 

到:

<VirtualHost *:443> 
    ServerName test.newdomain.com 
    ServerAlias test.olddomain.com 

    SSLEngine on 
    SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL 

    SSLCertificateFile "D:/Security/wildcard/NEWDOMAIN.COM.crt" 
    SSLCertificateKeyFile "D:/Security/wildcard/NEWDOMAIN.COM.key" 
    SSLCertificateChainFile "D:/Security/wildcard/CertChain.crt" 

    ... 
</VirtualHost> 

在任何瀏覽器,就可以訪問該網站就好了,我們沒有任何證書的問題。然而,當我嘗試從Java 6訪問某個網址,我得到這個錯誤:

java.security.cert.CertificateException: No subject alternative DNS name matching test.newdomain.com found 

我試圖運行Java與-Djavax.net.debug = SSL選項,奇怪的Java是越來越OLDDOMAIN證書:

*** Certificate chain 
chain [X] = [ 
[ 
    Version: VX 
    Subject: CN=*.olddomain.com, O=COMPANY, L=Place, ST=ST, C=US 
    Signature Algorithm: SHAXwithRSA, OID = X.X.XXX.XXXXXX.X.X.X 

    Key: Sun RSA public key, XXXX bits 
    modulus:  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 
XXXXXXXXXXXXXXXXXXXXXXXXXXXX 
    public exponent: XXXXX 
    Validity: [From: Tue Jan XX XX:XX:XX EST XXXX, 
       To: Fri Feb XX XX:XX:XX EST XXXX] 
    Issuer: CN=DigiCert High Assurance CA-X, OU=www.digicert.com, O=DigiCert Inc, C=US 
    SerialNumber: [ XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX] 

但是,如果我用java7替換java6。它正確讀取正確的證書,並且我可以訪問該URL。

我在這裏錯過了什麼?我看到從java6到java7的稍微不同的握手,但我不認爲這將解釋獲得不同的證書。

的Java6握手:

*** ClientHello, TLSv1 
*** 
pool-1-thread-1, WRITE: TLSv1 Handshake, length = 95 
pool-1-thread-1, WRITE: SSLv2 client hello message, length = 131 
pool-1-thread-1, READ: TLSv1 Handshake, length = 81 
*** ServerHello, TLSv1 
Cipher Suite: SSL_RSA_WITH_RC4_128_MD5 
Compression Method: 0 
Extension renegotiation_info, renegotiated_connection: <empty> 
*** 
%% Created: [Session-4, SSL_RSA_WITH_RC4_128_MD5] 
** SSL_RSA_WITH_RC4_128_MD5 
pool-1-thread-1, READ: TLSv1 Handshake, length = 4313 

java7握手:

*** ClientHello, TLSv1 
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1,sect233k1, sect23 
sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, se9k1,  secp256k1} 
Extension ec_point_formats, formats: [uncompressed] 
Extension server_name, server_name: [host_name: test.newdomain.com] 
*** 
pool-5-thread-2, WRITE: TLSv1 Handshake, length = 181 
pool-5-thread-2, READ: TLSv1 Handshake, length = 85 
*** ServerHello, TLSv1 
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA 
Compression Method: 0 
Extension server_name, server_name: 
Extension renegotiation_info, renegotiated_connection: <empty> 
*** 
%% Initialized: [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA] 
** TLS_RSA_WITH_AES_128_CBC_SHA 
pool-5-thread-2, READ: TLSv1 Handshake, length = 4312 

任何人都可以解釋爲什麼的Java6可能從java7和網絡瀏覽器不同的行爲,以及如何解決這一問題?

如果它有所作爲,這是我用來測試連接性的代碼。沒什麼特別的:

InputStream in = null; 
    try { 
     URL url = new URL("https://test.newdomain.com/myapp"); 
     URLConnection conn = url.openConnection(); 
     in = conn.getInputStream(); 
     System.out.println("OpenStream didn't fail!"); 
    } catch (IOException ex) { 
     System.out.println(ex.getClass().getName()+ex.getMessage()); 
     System.out.println("Connection failed"); 
    } finally { 
     try { 
      if (in != null) 
       in.close(); 
     } catch (IOException ex) { 
     } 
    } 

謝謝!

+1

這個區別無疑是因爲java7(Https)URLConn像所有主要瀏覽器一樣發送服務器名稱指示(SNI),但是java6沒有這樣做,因爲您的調試輸出已經確認。一個named-vhost服務器需要SNI來指定所需的主機和證書,並且沒有SNI必須做一些默認設置,這在你的情況下顯然是錯誤的,但是我不知道足夠的httpd來確切地說看看哪裏。 – 2014-10-01 23:34:12

+0

非常感謝您對戴夫的評論。我們正在思考這些問題,但我不瞭解SNI。至少我現在有什麼要調查。再次感謝! – loopkin 2014-10-02 02:43:11

回答

2

根據date_thompson_085提供的輸入回答我自己的問題。

問題是請求總是使用IP地址發送,並且主機名包含在http頭中。但是,使用SSL時,該主機名信息是加密的。所以當SSL握手發生時,它還不知道主機名。因此,它不知道請求應該到達哪個虛擬主機,並返回第一個(或默認)證書,在我們的案例中,olddomain.com是錯誤的。

瀏覽器和java7不受影響的原因是因爲他們發送服務器名稱指示(SNI)作爲SSL信息的一部分。這樣,apache在啓動SSL握手之前知道要使用哪個虛擬主機並返回適當的證書。 Java 6不支持SNI。