Как правильно перехватывать запросы HTTP и HTTPS с помощью сокетов в Java (HTTP / HTTPS Proxy)? - PullRequest
0 голосов
/ 23 июня 2019

Это действительно важный для меня проект.Я хотел бы создать прокси в Java, который позволит мне перехватывать все запросы HTTP и HTTPS, сделанные пользователем из его браузера (после того, как этот будет настроен, указывая, что прокси будет использоваться в адресе localhost и порту 8080).После перехвата я бы хотел иметь возможность манипулировать определенными частями запросов (например, заголовком User-agent) и, как только они будут отправлены на соответствующие хосты, получить ответ, также иметь возможность манипулировать им иотправьте его в браузер пользователя.

Я добился вышеуказанного с помощью сокетов (ServerSocket и Socket).Однако существует серьезная проблема:

Когда я перехватываю запрос к серверу, на котором включен SSL (то есть HTTPS), я вижу только те запросы, которые используют метод CONNECT, а не запросы, которые используютметод GET или POST, как показано ниже:

CONNECT img.youtube.com:443 HTTP / 1.1 User-Agent: Mozilla / 5.0 (Windows NT 10.0; Win64; x64; rv: 67.0) Gecko / 20100101Firefox / 67.0 Proxy-Connection: keep-alive Соединение: keep-alive Хост: img.youtube.com:443

Выше приведено то, что мое приложение показывает из информации о сокетах.С другой стороны, инструмент Burp Suite также показывает следующую информацию:

GET /image.jpeg HTTP / 1.1 Хост: img.youtube.com Пользовательский агент: Mozilla / 5.0 (Windows NT 10.0; Win64;x64; rv: 67.0) Gecko / 20100101 Firefox / 67.0 Accept: * / * Accept-language: en-us, en: q = 0.5 Accept-encoding: gzip, deflate Cache-control: no-cache Pragma: no-cache

Проблема с вышесказанным заключается в том, что мой прокси-сервер должен также показывать то, что показывает инструмент Burp Suite, но это не так.Это может быть проблема с необходимостью SSL-сертификатов или что-то в этом роде?Мой прокси-сервер использует только Socket и ServerSocket, а не SSLSocket.

Вот некоторые фрагменты кода, где:

Шаг 1 - я создаю ServerSocket, прослушивающий порт:


ServerSocket serverSocket=null;
        try {
            serverSocket = new ServerSocket( ProxyConfig.getInstance().getLocalPort() );
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        Socket socket;
        Connection connectionCreator;
        try {
            while ( (socket = serverSocket.accept() ) != null) {
                connectionCreator = new ConnectionImpl( new ClientConnectionImpl(socket) );
                connectionCreator.start();
            }
        } catch (IOException e) {
            e.printStackTrace(); 
        }

Шаг 2 - Я печатаю содержимое сокета (следующий код просто печатает первую строку, что-то вроде «CONNECT img.youtube.com:443 HTTP / 1.1»):

int characterRead;
        boolean endOfLine = false;
        ByteArrayOutputStream contentClientRequest = new ByteArrayOutputStream();

        while (( (characterRead = getClientSocket().getInputStream().read()) != -1) && !endOfLine) {
            switch (characterRead)
            {
                case '\n':
                    endOfLine=true;
                    break;
                case '\r':
                    endOfLine=true;
                    break;
                default:
                    contentClientRequest.write( characterRead );
                    break;
            }
        }

        System.out.println( contentClientRequest.toString() );

        return contentClientRequest.toString( getISO() );

ПРИМЕЧАНИЕ:В приведенном выше коде «getClientSocket ()» представляет сокет, принятый на шаге 1 («socket = serverSocket.accept ()»)

Шаг 3 - Отправьте ответ в браузер пользователя (запись байтов в сокетепоказано в шагах 1 и 2).

Спасибо за ответы и сообщите, если вам нужна дополнительная информация.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...