2014-02-20 60 views
0

我發現下面有用的程序來下載證書。但我的問題是,主持人(帶證書)只能通過我們的公司代理訪問。 我如何教這個程序通過我們的代理進行連接?通過代理建立套接字連接

/** 
* Originally posted at: (not available now) 
* http://blogs.sun.com/andreas/resource/InstallCert.java 
* Use: 
* java InstallCert hostname 
* Example: 
*% java InstallCert ecc.fedora.redhat.com 
*/ 

import javax.net.ssl.*; 

import java.io.*; 
import java.net.Socket; 
import java.security.KeyStore; 
import java.security.MessageDigest; 
import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 

/** 
* Class used to add the server's certificate to the KeyStore with your trusted 
* certificates. 
*/ 
public class InstallCert { 

    public static void main(String[] args) throws Exception { 
     String host; 
     int port; 
     char[] passphrase; 
     if ((args.length == 1) || (args.length == 2)) { 
      String[] c = args[0].split(":"); 
      host = c[0]; 
      port = (c.length == 1) ? 443 : Integer.parseInt(c[1]); 
      String p = (args.length == 1) ? "changeit" : args[1]; 
      passphrase = p.toCharArray(); 
     } else { 
      System.out.println("Usage: java InstallCert [:port] [passphrase]"); 
      return; 
     } 

     File file = new File("jssecacerts"); 
     if (file.isFile() == false) { 
      char SEP = File.separatorChar; 
      File dir = new File(System.getProperty("java.home") + SEP + "lib" 
        + SEP + "security"); 
      file = new File(dir, "jssecacerts"); 
      if (file.isFile() == false) { 
       file = new File(dir, "cacerts"); 
      } 
     } 
     System.out.println("Loading KeyStore " + file + "..."); 
     InputStream in = new FileInputStream(file); 
     KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 
     ks.load(in, passphrase); 
     in.close(); 

     SSLContext context = SSLContext.getInstance("TLS"); 
     TrustManagerFactory tmf = TrustManagerFactory 
       .getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
     tmf.init(ks); 
     X509TrustManager defaultTrustManager = (X509TrustManager) tmf 
       .getTrustManagers()[0]; 
     SavingTrustManager tm = new SavingTrustManager(defaultTrustManager); 
     context.init(null, new TrustManager[] { tm }, null); 
     SSLSocketFactory factory = context.getSocketFactory(); 

     System.out 
       .println("Opening connection to " + host + ":" + port + "..."); 
     SSLSocket socket = (SSLSocket) factory.createSocket(host, port); 
     socket.setSoTimeout(10000); 
     try { 
      System.out.println("Starting SSL handshake..."); 
      socket.startHandshake(); 
      socket.close(); 
      System.out.println(); 
      System.out.println("No errors, certificate is already trusted"); 
     } catch (SSLException e) { 
      System.out.println(); 
      e.printStackTrace(System.out); 
     } 

     X509Certificate[] chain = tm.chain; 
     if (chain == null) { 
      System.out.println("Could not obtain server certificate chain"); 
      return; 
     } 

     BufferedReader reader = new BufferedReader(new InputStreamReader(
       System.in)); 

     System.out.println(); 
     System.out.println("Server sent " + chain.length + " certificate(s):"); 
     System.out.println(); 
     MessageDigest sha1 = MessageDigest.getInstance("SHA1"); 
     MessageDigest md5 = MessageDigest.getInstance("MD5"); 
     for (int i = 0; i < chain.length; i++) { 
      X509Certificate cert = chain[i]; 
      System.out.println(" " + (i + 1) + " Subject " 
        + cert.getSubjectDN()); 
      System.out.println(" Issuer " + cert.getIssuerDN()); 
      sha1.update(cert.getEncoded()); 
      System.out.println(" sha1 " + toHexString(sha1.digest())); 
      md5.update(cert.getEncoded()); 
      System.out.println(" md5  " + toHexString(md5.digest())); 
      System.out.println(); 
     } 

     System.out 
       .println("Enter certificate to add to trusted keystore or 'q' to quit: [1]"); 
     String line = reader.readLine().trim(); 
     int k; 
     try { 
      k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1; 
     } catch (NumberFormatException e) { 
      System.out.println("KeyStore not changed"); 
      return; 
     } 

     X509Certificate cert = chain[k]; 
     String alias = host + "-" + (k + 1); 
     ks.setCertificateEntry(alias, cert); 

     OutputStream out = new FileOutputStream("jssecacerts"); 
     ks.store(out, passphrase); 
     out.close(); 

     System.out.println(); 
     System.out.println(cert); 
     System.out.println(); 
     System.out 
       .println("Added certificate to keystore 'jssecacerts' using alias '" 
         + alias + "'"); 
    } 

    private static final char[] HEXDIGITS = "abcdef".toCharArray(); 

    private static String toHexString(byte[] bytes) { 
     StringBuilder sb = new StringBuilder(bytes.length * 3); 
     for (int b : bytes) { 
      b &= 0xff; 
      sb.append(HEXDIGITS[b >> 4]); 
      sb.append(HEXDIGITS[b & 15]); 
      sb.append(' '); 
     } 
     return sb.toString(); 
    } 

    private static class SavingTrustManager implements X509TrustManager { 

     private final X509TrustManager tm; 
     private X509Certificate[] chain; 

     SavingTrustManager(X509TrustManager tm) { 
      this.tm = tm; 
     } 

     public X509Certificate[] getAcceptedIssuers() { 
      throw new UnsupportedOperationException(); 
     } 

     public void checkClientTrusted(X509Certificate[] chain, String authType) 
       throws CertificateException { 
      throw new UnsupportedOperationException(); 
     } 

     public void checkServerTrusted(X509Certificate[] chain, String authType) 
       throws CertificateException { 
      this.chain = chain; 
      tm.checkServerTrusted(chain, authType); 
     } 
    } 
} 

我已經嘗試添加以下內容,但它並不能幫助:

/* Proxy settings */ 
System.setProperty("http.proxyHost", "proxy.abc.com"); 
System.setProperty("http.proxyPort", "80"); 

也沒有類似的東西,有什麼好處:

Socket proxy = new Socket("proxy.abc.com", 80); 
SSLSocket socket = (SSLSocket) factory.createSocket(proxy, host, port, false); 

我總是得到以下異常:

Exception in thread "main" java.net.ConnectException: Connection timed out: connect 
    at java.net.PlainSocketImpl.socketConnect(Native Method) 
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333) 
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195) 
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182) 
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366) 
    at java.net.Socket.connect(Socket.java:529) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:550) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.<init>(SSLSocketImpl.java:353) 
    at com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl.createSocket(SSLSocketFactoryImpl.java:71) 
    at InstallCert.main(InstallCert.java:72) 

Ac通過瀏覽器打開遠程主機也僅適用於主動代理。這就是爲什麼我認爲我也需要InstallCert程序的代理。

回答

1

我得到了它在internetz工作,但我修改/砍死的代碼位。

我得到了同樣的錯誤「連接超時:連接」,當我試圖用型HTTP(S)的代理。當我使用SOCKS類型的代理時,此錯誤消失了。但是當我使用代理服務器176.9.240.109:1080時(我從列表here中選擇了該代理服務器),我收到了錯誤「連接重置」。當你不發送類似瀏覽器的用戶代理時,會發生這種情況,所以我也更新了它。

你提到隨系統啓動特性「HTTP」。或「https。」,這意味着它們只能用於HTTP(S)連接,而不是純粹的套接字連接。

在下面我修改/破解代碼使用HttpsURLConnection,所以系統性能可能會正常工作。

public class InstallCert { 

public static void main(String[] args) throws Exception { 

    String httpsUrl = null; 
    String host; 
    int port; 
    char[] passphrase; 
    if (args.length == 0) { 
     httpsUrl = "https://www.google.com/"; 
     port = 443; 
     host = "www.google.com"; 
     passphrase = "changeit".toCharArray(); 
    } else if ((args.length == 1) || (args.length == 2)) { 
     String[] c = args[0].split(":"); 
     host = c[0]; 
     port = (c.length == 1) ? 443 : Integer.parseInt(c[1]); 
     String p = (args.length == 1) ? "changeit" : args[1]; 
     passphrase = p.toCharArray(); 
    } else { 
     System.out.println("Usage: java InstallCert [:port] [passphrase]"); 
     return; 
    } 

    File file = new File("jssecacerts"); 
    if (file.isFile() == false) { 
     char SEP = File.separatorChar; 
     File dir = new File(System.getProperty("java.home") + SEP + "lib" 
       + SEP + "security"); 
     file = new File(dir, "jssecacerts"); 
     if (file.isFile() == false) { 
      file = new File(dir, "cacerts"); 
     } 
    } 
    System.out.println("Loading KeyStore " + file + "..."); 
    InputStream in = new FileInputStream(file); 
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 
    ks.load(in, passphrase); 
    in.close(); 

    SSLContext context = SSLContext.getInstance("TLS"); 
    TrustManagerFactory tmf = TrustManagerFactory 
      .getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
    tmf.init(ks); 
    X509TrustManager defaultTrustManager = (X509TrustManager) tmf 
      .getTrustManagers()[0]; 
    SavingTrustManager tm = new SavingTrustManager(defaultTrustManager); 
    context.init(null, new TrustManager[] { tm }, null); 
    SSLSocketFactory factory = context.getSocketFactory(); 

    System.out.println("Opening connection to " + host + ":" + port + "..."); 

    URL url = new URL(httpsUrl); 
    Proxy p = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("176.9.240.109", 1080)); 
    HttpsURLConnection conn = (HttpsURLConnection)url.openConnection(p); 
    conn.setSSLSocketFactory(factory); 
    conn.setConnectTimeout(3000); // 3 seconds. 
    conn.setReadTimeout(3000); // 3 seconds 
    conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0"); 
    try { 
     System.out.println("Starting SSL handshake..."); 
     conn.connect(); 
     System.out.println(); 
     System.out.println("No errors, certificate is already trusted"); 
    } catch (SSLException e) { 
     System.out.println(); 
     e.printStackTrace(System.out); 
    } finally { 
     conn.disconnect(); 
    } 

    X509Certificate[] chain = tm.chain; 
    if (chain == null) { 
     System.out.println("Could not obtain server certificate chain"); 
     return; 
    } 

    BufferedReader reader = new BufferedReader(new InputStreamReader(
      System.in)); 

    System.out.println(); 
    System.out.println("Server sent " + chain.length + " certificate(s):"); 
    System.out.println(); 
    MessageDigest sha1 = MessageDigest.getInstance("SHA1"); 
    MessageDigest md5 = MessageDigest.getInstance("MD5"); 
    for (int i = 0; i < chain.length; i++) { 
     X509Certificate cert = chain[i]; 
     System.out.println(" " + (i + 1) + " Subject " 
       + cert.getSubjectDN()); 
     System.out.println(" Issuer " + cert.getIssuerDN()); 
     sha1.update(cert.getEncoded()); 
     System.out.println(" sha1 " + toHexString(sha1.digest())); 
     md5.update(cert.getEncoded()); 
     System.out.println(" md5  " + toHexString(md5.digest())); 
     System.out.println(); 
    } 

    System.out 
    .println("Enter certificate to add to trusted keystore or 'q' to quit: [1]"); 
    String line = reader.readLine().trim(); 
    int k; 
    try { 
     k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1; 
    } catch (NumberFormatException e) { 
     System.out.println("KeyStore not changed"); 
     return; 
    } 

    X509Certificate cert = chain[k]; 
    String alias = host + "-" + (k + 1); 
    ks.setCertificateEntry(alias, cert); 

    /* 
    OutputStream out = new FileOutputStream("jssecacerts"); 
    ks.store(out, passphrase); 
    out.close(); 
    */ 
    System.out.println(); 
    System.out.println(cert); 
    System.out.println(); 
    System.out 
    .println("Added certificate to keystore 'jssecacerts' using alias '" 
      + alias + "'"); 
} 

private static final char[] HEXDIGITS = "abcdef".toCharArray(); 

private static String toHexString(byte[] bytes) { 
    StringBuilder sb = new StringBuilder(bytes.length * 3); 
    for (int b : bytes) { 
     b &= 0xff; 
     sb.append(HEXDIGITS[b >> 4]); 
     sb.append(HEXDIGITS[b & 15]); 
     sb.append(' '); 
    } 
    return sb.toString(); 
} 

private static class SavingTrustManager implements X509TrustManager { 

    private final X509TrustManager tm; 
    private X509Certificate[] chain; 

    SavingTrustManager(X509TrustManager tm) { 
     this.tm = tm; 
    } 

    public X509Certificate[] getAcceptedIssuers() { 
     throw new UnsupportedOperationException(); 
    } 

    public void checkClientTrusted(X509Certificate[] chain, String authType) 
      throws CertificateException { 
     throw new UnsupportedOperationException(); 
    } 

    public void checkServerTrusted(X509Certificate[] chain, String authType) 
      throws CertificateException { 
     this.chain = chain; 
     tm.checkServerTrusted(chain, authType); 
    } 
} 
} 

運行代碼顯示了javax.net.ssl.SSLException: java.lang.UnsupportedOperationException,但更重要的是,這表明它已經收到3個證書:-)

+0

謝謝,我不得不改變代理類型爲'Proxy.Type.HTTP'那麼它的工作 – user3193317

+0

再次感謝!我加入這個我[javabox(https://github.com/boly38/javabox/)項目:爲[InstallCertProxy.java](https://github.com/boly38/javabox/blob/master/src/main /java/InstallCertProxy.java)。在我的示例中,「https.proxyHost」和「https.proxyPort」用於設置https代理。只是一句話:添加「主機」到您的用法打印:「用法:java InstallCert [主機:端口] [密碼]」 – boly38