#websocket #proxy #http2
#websocket #прокси #http2
Вопрос:
Я разрабатываю прокси-сервер https http / 2, как упоминалось здесь: https://chromium.googlesource.com/chromium/src / /HEAD/net/docs/proxy.md#HTTPS-proxy-scheme Там упоминается, что
Прокси HTTPS, использующие HTTP / 2, могут обеспечить лучшую производительность в Chrome, чем обычный HTTP-прокси, из-за более высоких ограничений на подключение (прокси HTTP / 1.1 в Chrome ограничены 32 одновременными подключениями во всех доменах).
Но когда пользователи пытаются перейти на веб-сайт, который использует websocket, через необработанное http-соединение, ответ содержит http-заголовок «Обновить», который запрещено использовать в http / 2, поскольку для HTTP / 2 нет websockets. https://daniel.haxx.se/blog/2016/06/15/no-websockets-over-http2/#:~:text=There is no websockets for HTTP/2.amp;text=That spec details how a,connection into a websockets connection.Проблема возникает из-за того, что когда трафик http1.1 проходит через прокси-сервер https, который реализует http / 2, заголовки должны быть переданы с http1.1 на http / 2. Конечно, когда веб-страница использует TLS, такой проблемы не возникает, поскольку весь трафик проходит через соединение, созданное методом http ‘CONNECT’. Проблема возникает, когда веб-сайт не использует TLS. Если нет решения этой проблемы, это означает, что прокси HTTPS не должны реализовывать протокол HTTP / 2.
Ответ №1:
Поскольку для HTTP / 2 нет веб-сокетов
Размещенная вами ссылка устарела, и с тех пор WebSocket через HTTP / 2 был указан в RFC 8441.
Поведение прокси-сервера HTTP / 2 указано в RFC 7540, раздел 8.3.
Когда клиент обменивается данными с прокси-сервером, используя безопасный HTTP / 2, каждый поток HTTP / 2 является «туннелем» к серверу.
Клиент и прокси обмениваются данными, используя безопасный HTTP / 2, и происходит «туннелирование», потому что каждый поток HTTP / 2 становится «бесконечным» запросом с «бесконечным» ответом, то есть «бесконечной» серией кадров HTTP / 2 DATA
в обоих направлениях, которые несут непрозрачную полезную нагрузку массива байтов.
Задача прокси-сервера состоит в том, чтобы разворачивать DATA
фреймы, полученные клиентом, и пересылать полезную нагрузку массива байтов на сервер, возможно, повторно оборачивая ее в фрейм HTTP / 2 DATA
, если связь между прокси-сервером и сервером также HTTP / 2 (возможно, можно оптимизировать процесс разворачивания и повторного-перенос, но это может быть сложно — например, нумерация потоков может отличаться).
Когда клиент пытается выполнить WebSocket через HTTP / 2, браузер будет выполнять действия, указанные в RFC 8441, и прокси-сервер получит CONNECT
запрос с :protocol
псевдо-заголовком, и прокси-сервер должен будет знать, что делать в этом случае, в зависимости от того, какой протокол он использует для связи с сервером.
То, что выше, описывает, что ваш прокси-сервер должен поддерживать, когда связь с клиентом осуществляется по протоколу HTTP / 2.
Если ваш прокси-сервер должен поддерживать клиентов, которые говорят на HTTP / 1.1, тогда вам нужно реализовать то, что требуется для прокси-сервера для поддержки HTTP / 1.1 и прокси-сервера WebSocket, и это обычно не сложно: первое — это просто переадресация HTTP / 1.1 или CONNECT
«туннелирование» HTTP, второе — обновление HTTP WebSocketпереадресация запроса с последующим подключением «туннеля» или даже полноценным прокси-сервером WebSocket.
Отказ от ответственности, я реализовал все вышеперечисленное в проекте Jetty. Вы можете использовать Jetty 10 или более позднюю версию для реализации HTTP / 1.1, HTTP / 2 или WebSocket, как клиента, так и сервера (и, следовательно, прокси). WebSocket через HTTP / 2 также поддерживается.
Наконец, чтобы ответить на ваш последний вопрос, вполне возможно, чтобы защищенные прокси поддерживали HTTP / 2 даже при наличии WebSocket.
Например, открытое текстовое соединение WebSocket с сервером начинается с запроса на обновление HTTP; этот запрос будет отправлен в зашифрованном виде прокси-серверу, который расшифрует его и перешлет на сервер (используя любой протокол, поддерживаемый сервером — может быть даже WebSocket по защищенному HTTP / 2);сервер ответит 101 и обновит соединение до WebSocket; прокси-сервер получит 101 от сервера и обновится до «туннельного» или прокси-сервера WebSocket; прокси-сервер шифрует ответ 101 и пересылает его клиенту; клиент расшифровывает его и обновляет соединение до WebSocket. На этом этапе клиент передает веб-сокет с открытым текстом на сервер через защищенное соединение с прокси-сервером (прокси-сервер видит сообщение веб-сокета с открытым текстом).
Наоборот, безопасное подключение WebSocket к серверу начинается с установления HTTP CONNECT
-туннеля через прокси-сервер к серверу; затем клиент установит безопасную связь с сервером; затем он отправит обновление HTTP до WebSocket на сервер (через прокси-туннель). На этом этапе клиент передает защищенный WebSocket на сервер через защищенное соединение с прокси-сервером (прокси-сервер не может видеть сообщение WebSocket).
Варианты HTTP / 2 аналогичны, просто учитывают специфические для HTTP / 2 способы «туннелирования» и транспортировки WebSocket.
Комментарии:
1. При использовании прокси-сервера HTTP / 2 метод CONNECT используется браузерами только тогда, когда целевой сайт использует «https». Но когда целевым сайтом является «http», google Chrome и firefox не используют метод CONNECT, вместо этого они переводят некоторые заголовки HTTP1 в HTTP / 2. Конечно, большинство веб-сайтов в настоящее время используют HTTPS, и при просмотре этих веб-сайтов с использованием прокси HTTP / 2 проблем не возникнет.