Как захватить https с помощью скрипача, в java

Я запускаю следующую java-программу в Eclipse IDE:

import java.net.*;
import java.io.*;

 public class HH
 {
    public static void main(String[] args)throws Exception
    {
      //if i comment out the system properties, and don't set any jvm arguments, the program runs and prints out the html fine.
            System.setProperty("http.proxyHost", "localhost"); 
            System.setProperty("http.proxyPort", "8888"); 
            System.setProperty("https.proxyHost", "localhost"); 
            System.setProperty("https.proxyPort", "8888"); 

            URL x=new URL("https://www.google.com");
            HttpURLConnection hc=(HttpURLConnection)x.openConnection();

            hc.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.0)
            AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2");


            InputStream is=hc.getInputStream();

            int u=0;
            byte[] kj=new byte[1024];
            while((u=is.read(kj))!=-1)
           {
                System.out.write(kj,0,u);
            }
           is.close();
          }



        }

Это приводит к следующему исключению: если fiddler является RUNNING, как во время захвата, так и без захвата:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown ...

Если я закрываю fiddler, программа работает нормально без каких-либо исключений, создавая html на url, к которому я подключаюсь.

в качестве альтернативы, если я укажу System.setProperty("https.proxyPort", "443");, а не: System.setProperty("https.proxyPort", "8888");, он запускает и выводит все html без исключений, даже если скрипт открыт, в режиме захвата, но до сих пор нет захвата от скрипача вообще.

Затем, если я установил эти системные свойства через аргументы eclipse jvm, такие как: -DproxySet=true -DproxyHost=127.0.0.1 -DproxyPort=8888, то же точное исключение произойдет снова, пока приложение fiddler запущено, как в режиме захвата, так и без захвата. Если я закрываю fiddler, программа будет работать отлично.

Если я использую: System.setProperty("http.proxyHost", "127.0.0.1"); вместо: System.setProperty("http.proxyHost", "localhost");, он отлично работает с запущенным приложением fiddler, как в режиме кэширования, так и без захвата, но также и с отсутствием захваченного трафика.

Есть ли кто-нибудь, способный захватить свой собственный https-трафик с помощью скрипача, а не через веб-браузер, а через java-программу? Каковы аргументы jvm, как вы это настроили? спасибо

Ответ 1

Создайте хранилище ключей, содержащее сертификат Fiddler. Используйте это хранилище ключей как доверенное хранилище для JVM вместе с настройками прокси.

Вот как это сделать:

  • Экспорт корневого сертификата Fiddler

Инструменты → Параметры Fiddler... → HTTPS → Экспорт корневого сертификата на рабочий стол

  • Создайте хранилище ключей с этим сертификатом

Откройте командную строку как администратор (keytool не работает иначе)

< JDK_Home > \bin\keytool.exe -import -file C:\Users\<Username> \Desktop\FiddlerRoot.cer -keystore FiddlerKeystore -alias Fiddler

Введите пароль при появлении запроса. Это должно создать файл под названием FiddlerKeystore.

  • Теперь запустите JVM с помощью Fiddler в качестве прокси-сервера, и это хранилище ключей в качестве доверенного магазина. Вам понадобятся эти vmargs:

-DproxySet = истина

-DproxyHost = 127.0.0.1

-DproxyPort = 8888

-Djavax.net.ssl.trustStore = < путь\к\FiddlerKeystore >

-Djavax.net.ssl.trustStorePassword = < Пароль ключa >

Используйте эти vmargs в конфигурации запуска eclipse, и вам должно быть хорошо идти.

Я могу записывать HTTPS-запросы из JVM без каких-либо проблем с этой настройкой.

Ответ 2

Создайте хранилище ключей, содержащее сертификат fiddler, и используйте его:

java -DproxySet=true -DproxyHost=127.0.0.1 -DproxyPort=8888 -Dhttps.proxyPort=8888 -Dhttps.proxyHost=127.0.0.1 -Djavax.net.ssl.trustStore=<path to FiddlerKeystore> -Djavax.net.ssl.trustStorePassword=<password> -jar test.jar

Если вы используете сторонние HTTP-библиотеки, вам нужно установить прокси-соединения. Пример с Apache Commons HttpClient:

HttpClient httpClient = new HttpClient();
httpClient.getHostConfiguration().setProxy("localhost", 8888);

Ответ 3

Я обнаружил, что мне также необходимы следующие параметры командной строки java

-Dhttps.proxyPort=8888 
-Dhttps.proxyHost=127.0.0.1

Ответ 4

Вы также можете импортировать ключ fiddler в хранилище доверенных сертификатов java:

  • Экспорт корневого сертификата Fiddler

    Инструменты → Параметры Fiddler... → HTTPS → Действия → Экспорт корневого сертификата на рабочий стол

  • Запуск от имени администратора:

"keytool.exe" -import -noprompt -trustcacerts -alias FiddlerRoot -file c:\work\FiddlerRoot.cer -keystore "C:\Program Files\Java\jdk1.7.0_79\jre\lib\security\cacerts" -storepass changeit

Также у меня возникла проблема с расшифровкой https-трафика клиента API Google с помощью Fiddler. Проблема заключалась в том, что по умолчанию он использует собственный хранилище cert:

InputStream keyStoreStream = GoogleUtils.class.getResourceAsStream("google.jks");
SecurityUtils.loadKeyStore(certTrustStore, keyStoreStream, "notasecret");

И вот как я исправил это:

 HttpTransport transport = new NetHttpTransport() 
 //istead of transport = GoogleNetHttpTransport.newTrustedTransport();