2016-04-20 19 views
-1

我嘗試使用https連接到傳統思科IPS服務器。問題是此服務器僅接受某些條件下的握手:是否可以在Java中刪除SSL握手的擴展部分?

版本必須爲TLSv1.0,密碼套件必須爲SSL_RSA_WITH_RC4_128_MD5或SSL_RSA_WITH_RC4_128_SHA,且不得有任何擴展名。

我實現了一個手工製作「的ClientHello」,它發送下面的信息作爲握手(Wireshark的輸出):

Secure Sockets Layer 
TLSv1.2 Record Layer: Handshake Protocol: Client Hello 
    Content Type: Handshake (22) 
    Version: TLS 1.0 (0x0301) 
    Length: 45 
    Handshake Protocol: Client Hello 
     Handshake Type: Client Hello (1) 
     Length: 41 
     Version: TLS 1.0 (0x0301) 
     Random 
     Session ID Length: 0 
     Cipher Suites Length: 2 
     Cipher Suites (1 suite) 
     Compression Methods Length: 1 
     Compression Methods (1 method) 

服務器發送回服務器問候消息。

現在我想用Java的SSL實現發送,確切地說和ClientHello一樣。下面的代碼:

System.setProperty("https.protocols", "TLSv1"); 
    System.setProperty("javax.net.debug", "ssl:handshake"); 

    SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); 
    SSLSocket socket = (SSLSocket) factory.createSocket("ips-server", 443); 

    socket.setEnabledProtocols(new String[] {"TLSv1"}); 
    socket.setEnabledCipherSuites(new String[] {"SSL_RSA_WITH_RC4_128_MD5"}); 

    socket.startHandshake(); 

產生以下握手:

Secure Sockets Layer 
TLSv1.2 Record Layer: Handshake Protocol: Client Hello 
    Content Type: Handshake (22) 
    Version: TLS 1.0 (0x0301) 
    Length: 52 
    Handshake Protocol: Client Hello 
     Handshake Type: Client Hello (1) 
     Length: 48 
     Version: TLS 1.0 (0x0301) 
     Random 
     Session ID Length: 0 
     Cipher Suites Length: 2 
     Cipher Suites (1 suite) 
     Compression Methods Length: 1 
     Compression Methods (1 method) 
     Extensions Length: 5 
     Extension: renegotiation_info 
      Type: renegotiation_info (0xff01) 
      Length: 1 
      Renegotiation Info extension 

這會導致服務器發送回以下包:

TLSv1.2 Record Layer: Alert (Level: Fatal, Description: Handshake Failure) 

是否有可能使Java 發送數據包的「擴展」部分?

+0

除非您使用'HttpsURLConnection',否則設置'https.protocols'不起作用。 – EJP

回答

-1

如果有人想知道答案,則需要對https.protocols系統屬性使用SSLv2Hello。

System.setProperty("https.protocols", "TLSv1,SSLv2Hello"); 

我用下面的代碼連接到服務器:

SSLContext sslContext = SSLContext.getInstance("TLS"); 
sslContext.init(null, new TrustManager[] { new X509TrustManager() { 
    @Override 
    public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { 
    } 

    @Override 
    public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { 
    } 

    @Override 
    public X509Certificate[] getAcceptedIssuers() { 
     return null; 
    } 
} }, new SecureRandom()); 

SSLSocketFactory socketFactory = sslContext.getSocketFactory(); 
HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory); 

HttpsURLConnection conn = (HttpsURLConnection) new URL(url).openConnection(); 
conn.setHostnameVerifier(new HostnameVerifier() { 
    @Override 
    public boolean verify(String string, SSLSession ssls) { 
     return true; 
    } 
}); 

編輯更多的解釋 - @EJP提到這個代碼不回答標題中的問題。我寫了一個小測試來顯示SSL客戶端hello的擴展部分是否被刪除,作爲將客戶端hello改爲SSLv2的副作用。

public static void main(String[] args) throws NoSuchAlgorithmException, KeyManagementException, MalformedURLException, IOException { 
    System.setProperty("https.protocols", "TLSv1,SSLv2Hello"); 

    String url = "https://www.google.com"; 

    SSLContext sslContext = SSLContext.getInstance("TLS"); 
    sslContext.init(null, new TrustManager[]{new X509TrustManager() { 
     @Override 
     public void checkClientTrusted(X509Certificate[] xcs, String string) { 
     } 

     @Override 
     public void checkServerTrusted(X509Certificate[] xcs, String string) { 
     } 

     @Override 
     public X509Certificate[] getAcceptedIssuers() { 
      return null; 
     } 
    }}, new SecureRandom()); 

    SSLSocketFactory socketFactory = sslContext.getSocketFactory(); 
    HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory); 

    HttpsURLConnection conn = (HttpsURLConnection) new URL(url).openConnection(); 
    conn.setHostnameVerifier(new HostnameVerifier() { 
     @Override 
     public boolean verify(String string, SSLSession ssls) { 
      return true; 
     } 
    }); 

    BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); 

    Stream<String> lines = br.lines(); 
    lines.forEach(l -> { System.out.println(l);}); 
} 

這是我得到Wireshark的,如果我運行這個程序: enter image description here

如果我註釋掉SSLv2Client部分,我會得到這樣的: enter image description here

所以很明顯這達到了我的要求:刪除SSL握手的擴展部分。也許這不是最好的方法,因爲@EJP提到了很多安全漏洞(這裏不是我關心的問題,因爲我的CISCO IPS服務器是本地的,我只是想連接它,安全與否),但是我不能找到任何其他方式來做到這一點。

+0

你的問題沒有提到SSLV2ClientHello或HTTPS。有一種方法可以完全實現SSLSockets,但事實並非如此。根據你的問題測試,SSLV2ClientHello是沒有必要的。這裏沒有什麼能夠完成它在標題中所說的內容。你真正做的是設置TLS版本和密碼套件,並引入了幾個明顯的安全漏洞。 – EJP

+0

感謝您花時間閱讀和評論。我試圖在編輯中給出更多解釋。 – MNos