Это действительно важный для меня проект.Я хотел бы создать прокси в 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).
Спасибо за ответы и сообщите, если вам нужна дополнительная информация.