LittleProxy: прокси-сервер для анализа запросов и манипуляции контентом
LittleProxy — это высокопроизводительный HTTP-прокси, написанный на Java с использованием отличной библиотеки Trustin Lee Netty для работы с событиями в сети. Он отличается стабильностью, хорошей производительностью и простотой интеграции в проекты.
Один из способов использования LittleProxy — клонировать его и запустить из командной строки. Это просто:
$ git clone git://github.com/adamfisk/LittleProxy.git
$ cd LittleProxy
$ ./run.bash
Также можно внедрить LittleProxy в свои проекты через Maven:
<dependency>
<groupId>org.littleshoot</groupId>
<artifactId>littleproxy</artifactId>
<version>1.1.2</version>
</dependency>
После включения LittleProxy сервер можно запустить следующим образом:
HttpProxyServer server =
DefaultHttpProxyServer.bootstrap()
.withPort(8080)
.start();
Для перехвата и манипулирования HTTPS-трафиком LittleProxy использует менеджер «человек посередине» (MITM). По умолчанию в LittleProxy используется реализация SelfSignedMitmManager с довольно ограниченным набором функций. Для большего контроля над олицетворением сертификатов, доверием браузера, рукопожатием TLS и т. д. можно использовать совместимое с LittleProxy расширение MITM:
Чтобы фильтровать HTTP-трафик, можно добавить фильтры запросов и ответов с помощью HttpFiltersSource(Adapter), например:
HttpProxyServer server =
DefaultHttpProxyServer.bootstrap()
.withPort(8080)
.withFiltersSource(new HttpFiltersSourceAdapter() {
public HttpFilters filterRequest(HttpRequest originalRequest, ChannelHandlerContext ctx) {
return new HttpFiltersAdapter(originalRequest) {
@Override
public HttpResponse clientToProxyRequest(HttpObject httpObject) {
// TODO: implement your filtering here
return null;
}
@Override
public HttpObject serverToProxyResponse(HttpObject httpObject) {
// TODO: implement your filtering here
return httpObject;
}
};
}
})
.start();
Пожалуйста, обратитесь к Javadoc org.littleshoot.proxy.HttpFilters, чтобы увидеть методы, которые вы можете использовать.
Чтобы включить агрегатор и инфлятор, необходимо вернуть значение больше 0 в методах HttpFiltersSource#get(Request/Response)BufferSizeInBytes(). Это предоставит вам FullHttp(Request/Response) с полным содержимым в вашем фильтре без сжатия. В противном случае вам придётся обрабатывать фрагменты самостоятельно.
@Override
public int getMaximumResponseBufferSizeInBytes() {
return 10 * 1024 * 1024;
}
Этот предел размера применяется к каждому соединению. Чтобы отключить агрегирование по URL, например, для файлов *.iso или *dmg, вы можете вернуть в своих фильтрах источник фильтр, подобный этому:
return new HttpFiltersAdapter(originalRequest, serverCtx) {
@Override
public void proxyToServerConnectionSucceeded(ChannelHandlerContext serverCtx) {
ChannelPipeline pipeline = serverCtx.pipeline();
if (pipeline.get("inflater") != null) {
pipeline.remove("inflater");
}
if (pipeline.get("aggregator") != null) {
pipeline.remove("aggregator");
}
super.proxyToServerConnectionSucceeded(serverCtx);
}
};
Это позволяет выполнять огромные загрузки в приложении, которое обычно обрабатывает ограниченные по размеру FullHttpResponse для изменения своего содержимого, например HTML. Литтл прокси всегда содержит веб-сервер. Если вы получаете URI без схемы, хоста и порта в originalRequest
, это прямой запрос к вашему прокси. Вы можете вернуть реализацию HttpFilters
, которая отвечает на запросы ответами с HTML-контентом или перенаправляет в clientToProxyRequest
следующим образом:
public class AnswerRequestFilter extends HttpFiltersAdapter {
private final String answer;
public AnswerRequestFilter(HttpRequest originalRequest, String answer) {
super(originalRequest, null);
this.answer = answer;
}
@Override
public HttpResponse clientToProxyRequest(HttpObject httpObject) {
ByteBuf buffer = Unpooled.wrappedBuffer(answer.getBytes("UTF-8"));
HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, buffer);
HttpHeaders.setContentLength(response, buffer.readableBytes());
HttpHeaders.setHeader(response, HttpHeaders.Names.CONTENT_TYPE, "text/html");
return response;
}
}
При ответе на перенаправление следует добавить заголовок Connection: close, чтобы избежать блокирующего поведения:
HttpHeaders.setHeader(response, Names.CONNECTION, Values.CLOSE);
С помощью этого трюка можно легко реализовать пользовательский интерфейс для вашего приложения.
Если вы хотите создать дополнительные прокси-серверы с аналогичной конфигурацией, но прослушивающие разные порты, вы можете клонировать существующий сервер. Клонированные серверы будут совместно использовать циклы событий для снижения использования ресурсов, и когда один клон будет остановлен, все они также будут остановлены.
existingServer.clone().withPort(8081).start()
Примеры настройки ведения журнала см. в src/test/resources/log4j.xml.
Если у вас есть вопросы, посетите нашу группу Google здесь:
https://groups.google.com/forum/#!forum/littleproxy
Чтобы подписаться, отправьте электронное письмо по адресу mailto:LittleProxy+subscribe@googlegroups.com. Просто ответив, не нажимая кнопку, вы обойдёте процесс регистрации Google. Вы станете участником.
Инструкции и результаты бенчмаркинга можно найти здесь.
Большое спасибо The Measurement Factory за использование Co-Advisor для тестирования соответствия стандартам HTTP.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )