Разница между HTTP и HTTPS

В связи с массовым переходом сайтов на HTTPS перед разработчиками и администраторами сайтов встал ряд новых проблем. Одной из них является редирект с HTTP на HTTPS и необходимость правильно обрабатывать переадресацию на канонический адрес сайта, чтобы избежать дублирования контента.

HTTPS и редиректы

Рассмотрим пример. Допустим, что у нас есть сайт dnsimple.com . Его канонический URL-адрес — https://dnsimple.com . Тем не менее, существует четыре различных способа, с помощью которых можно подключиться к сайту, и нужно обеспечить, чтобы при любом из них пользователь перенаправлялся на https://dnsimple.com :

Исходный способ Тип
http://dnsimple.com HTTP + no-www
https://dnsimple.com HTTPS + no-www
http://www.dnsimple.com HTTP + www
https://www.dnsimple.com HTTPS + www

Настройка htaccess редиректов HTTP на HTTPS часто является причиной путаницы. Не всегда понятно, как правильно обрабатывать через HTTPS редиректы с WWW на не-WWW (или наоборот ), и почему для этого нужен сертификат SSL / TLS . Чтобы правильно настроить эти перенаправления, необходимо понять основные принципы обработки запросов HTTPS .

Далее мы рассмотрим, в каком порядке устанавливается соединение по протоколу HTTPS , как происходит обработка HTTP-запросов и настройка редиректов с поддержкой HTTPS .

Поток запроса HTTPS

На приведенном выше изображении показана схема прохождения запросов / ответов HTTPS . Для простоты мы разбили все действия на три фазы:

  1. На первом этапе клиент и сервер договариваются о деталях шифрования, таких как протокол шифрования и набор шифров. Также происходит обмен информацией, необходимой для переключения на защищенное соединение: открытые ключи, сведения о сертификате и т.д. Эта фаза называется «SSL / TLS рукопожатие »;
  2. На втором этапе клиент готовит HTTP-запрос , шифрует его и отправляет на сервер для обработки. Сервер принимает зашифрованный HTTP-запрос , расшифровывает его, обрабатывает и выдает HTTP response (ответ );
  3. На третьем этапе, сервер шифрует ответ и отправляет его клиенту для обработки. Клиент получает зашифрованный HTTP response , дешифрует и обрабатывает его (например, браузер начинает загружать и отображать элементы ).

Эта схема потока редиректа с HTTP на HTTPS применима к любому запросу, независимо от содержимого ответа HTTP .

Выше я написал запрос HTTP и ответ HTTP для определенных целей (обратите внимание, что я использовал HTTP , а не HTTPS ). С точки зрения содержимого и структуры важно понимать, что HTTPS-запрос — это HTTP-запрос , но передаваемый через защищенное соединение (TLS / SSL ).

HTTPS-согласования и редиректы

Одна из самых распространенных ошибок при настройке HTTPS-редиректов — это предположение, что вам не нужен сертификат SSL при переадресации клиента с одного домена на другой.

Если посмотреть на поток запросов, то видно, что обмен сертификатами SSL и согласование шифрования выполняются на первом этапе. Обратите внимание, что на этом этапе сервер ничего не знает, какая страница нужна клиенту: клиент и сервер решают, как взаимодействовать друг с другом.

После завершения первого этапа, когда клиент и сервер нашли общий язык (протокол шифрования ), они могут начать взаимодействовать друг с другом, используя зашифрованное соединение. В этот момент клиент отправляет HTTP-запрос на сервер, а сервер отправляет HTTP-ответ , содержащий редирект.

Не забывайте, что редирект — это HTTP-ответ с кодом 301 (иногда 302 или 307 ):

HTTP/1.1 301 Moved Permanently Server: nginx Date: Mon, 01 Aug 2016 14:41:25 GMT Location: https://dnsimple.com/

Перед тем, как сделать редирект с HTTPS на HTTP , помните, что, если нужно создать редирект для всего домена, то необходим валидный сертификат SSL для перенаправляемого домена. Для согласования шифрования требуется сертификат SSL , и происходит оно до того, как запрос был обработан, а ответ о редиректе возвращен клиенту.

Если бы все происходило иначе, то редирект бы обрабатывался перед проверкой сертификата SSL . Тогда клиент и сервер были бы вынуждены общаться с помощью обычного HTTP-соединения , которое не шифруется.

Если нужно перенаправить клиента с любой страницы домена https://www.example.com на другую, необходим установленный на сервере валидный сертификат SSL , который распространяется на весь домен www.example.com .

Например, чтобы перенаправить клиента с https://www.example.com на https://example.com , необходимо иметь сертификат, который распространяется на оба или два отдельных сертификата (для каждого хоста соответственно ).

Стратегии HTTPS-редиректов

Мы рассмотрели, как обрабатывается редирект с HTTP на HTTPS через htaccess после SSL / TLS согласования. А также выяснили, что для перенаправления клиентов с сайта или страницы на HTTPS нужен валидный сертификат SSL , который охватывает оба домена. Далее я расскажу об общих стратегиях настройки HTTPS-редиректов .

Существует два типа настройки редиректов с HTTPS :

  1. Редирект на уровне сервера;
  2. Редирект на уровне приложений.

Термин сервер обозначает любой сервер, который находится перед веб-приложением и обрабатывает входящий HTTP-запрос . Например, front-end сервер, сервер балансировки нагрузки или единичного приложения.

Термин приложение обозначает веб-приложение, которое может быть либо столь же простым, как PHP-скрипт , либо более сложным, таким как серверное Unicorn-приложение интерпретации Ruby on Rails .

Выполнение HTTPS-редиректов на уровне сервера

Выполнение HTTPS-редиректов на уровне сервера является более предпочтительным. В этом случае сервер, на котором установлен сертификат SSL , принимает зашифрованный HTTP-запрос и возвращает зашифрованный HTTP-ответ о редиректе в соответствии с параметрами конфигурации без соединения с сервером приложения или выполнения кода приложения.


Такой подход является более быстрым, так как сервер может обрабатывать редирект без взаимодействия с приложением. В то же время конфигурация серверов менее гибкая по сравнению с тем, что можно сделать с помощью полноценного языка программирования.
htaccess редирект HTTP на HTTPS на уровне сервера используется для массового перенаправления. Например, редиректа с WWW на не-WWW версию домена с HTTPS (или наоборот ).

Следующий фрагмент кода является примером конфигурации Nginx , в котором задается редирект с http://example.com , http://www.example.com и https://www.example.com на https://example.com :

server { listen 80; server_name example.com www.example.com; return 301 https://example.com$request_uri; } server { listen 443 ssl; server_name example.com www.example.com; # ssl configuration ssl on; ssl_certificate /path/to/certificate.crt; ssl_certificate_key /path/to/private.key; if ($http_host = www.example.com) { return 301 https://example.com$request_uri; } }

Реализация редиректа на уровне сервера более предпочтительна, но она не всегда осуществима, поскольку вы можете не иметь доступа к конфигурации сервера. Это касается виртуального хостинга или таких платформ, как Heroku , Azure или Google Platform .

Выполнение HTTPS-редиректа на уровне приложений

Когда у вас нет доступа к конфигурации сервера, или логика редиректа является более сложной, необходимо обрабатывать редирект с HTTP на HTTPS на уровне приложений.


Такой подход немного медленнее, потому что сервер должен принять запрос, обработать код приложения (или взаимодействовать с сервером приложений ) и вернуть ответ.

То, как выполняется редирект на уровне приложений, зависит от используемого языка программирования и стека. Вот несколько примеров.

Пакет Goland и net/http

Можно использовать http.Redirect .

Ruby on Rails

Можно настроить редирект на уровне маршрутизатора, использовать промежуточное программное обеспечение Rack или метод redirect_to внутри контроллера:

constraints(host: /www.example.com/) do get "*", to: redirect("https://example.com") end

PHP

Используйте функцию header , чтобы отправить HTTP-заголовок перенаправления:

В некоторых случаях это единственно возможный подход. Например, если нужно перенаправить клиентов с WWW на не-WWW версию домена, с HTTPS на Heroku или Azure (или наоборот ), то придется указать оба домена в одном приложении, установить сертификат и через условия обрабатывать редирект на уровне приложений.

Альтернативные способы выполнения HTTPS-редиректа

Существует несколько альтернативных способов редиректа с HTTP на HTTPS .

В некоторых ситуациях отсутствует доступ к конфигурации сервера, а платформа, на которой размещен сайт, не позволяет использовать язык программирования. В качестве типичного примера можно привести Amazon S3 для размещения статических сайтов. В этом случае нужно выяснить, предоставляет ли платформа параметры HTTPS-редиректов , которые можно настроить.

Другой вариант заключается в использовании автономного, независимого приложения для редиректов. Например, если нужно перенаправить клиентов с https://alpha.com на https://beta.com . Тогда для домена alpha.com в качестве DNS можно указать другой сервис или сервер, на котором размещен beta.com . А также настроить редирект на уровне сервера или установить приложение, которое будет выступать в качестве редиректора. При этом также необходим валидный сертификат для alpha.com , который будет установлен там, где необходимо осуществить редирект.

Иногда возникают ситуации, когда при запросе сайта веб-браузером выдается ошибка. Такие ошибки имеют цифровой код и определенное описание.

(101-199) Информационные ответы

Такие ответы указывают на то, что запрос того или иного клиента принят и происходит его непосредственная обработка.

  • 100 - Continue - принята первая часть запрос, клиент может продолжить его передачу.
  • 101 - Switching Protocols - сервисом выполняются определенные требования клиента, а также переключаются протоколы, что соответствует данным в поле заголовка Upgrade.

(200-299) Успешные запросы клиента

В данном диапазоне все запросы клиента выполнены успешно.

  • 200 - OK - успешная обработка запроса клиента, а в ответе сервера имеются все запрашиваемые данные.
  • 201 - Created - такой код состояния может быть использован при смене URL. Помимо кода, сервером также выдается заголовок Location, в котором содержится вся информация о месте перемещения всех новых данных.
  • 202 - Accepted - запрос принимается, но его обработка происходит не сразу. Тело содержимого ответа также может содержать определенную информацию о данной транзакции. Не предоставляются никакие гарантии того, что запрос будет удовлетворен, даже если во время приемы он был допустимым.
  • 203 - Non-Authoritative Information - в заголовке содержимого имеется информация, которая была получена из локальной копии или от третьей стороны.
  • 204 - No Content - в ответе имеется только заголовок и код состояния, само тело ответа не дается. При получении такого ответа документ браузера не должен обновляться. Код может возвращаться обратно после того, как пользователь по пустым участкам изображения.
  • 205 - Reset Content - происходит очистка формы, которая используется для дополнительных вводных данных, браузером.
  • 206 - Partial Content - сервером возвращается только некоторая часть данных. Используется в ответе на запрос при указании заголовка Range. В заголовке Content-Range сервером должен указываться определенный диапазон, который входит в ответ.

(300-399) Переадресация

Код ответа в таком диапазоне означает, что для удовлетворения запроса клиенту необходимо выполнить определенные действия.

  • 300 - Multiple Choices (несколько вариантов на выбор) - затребованный URL может включать несколько ресурсов. В возвращенном сервером теле содержимого должны находиться определенные данные о правильном выборе ресурса.
  • 301 - Moved Permanently (ресурс перемещен на постоянной основе) - требуемый URL сервер уже не использует, поэтому и не выполняется операция, которая указана в запросе. В заголовке Location предоставляются данные о новом местонахождении запрашиваемого документа. При последующих запросах необходимо уже указывать новый URL.
  • 302 - Moved Temporarily (ресурс временно перемещен) - временное перемещение затребованного URL. В заголовке Location указывается новое месторасположение. После получения кода состояния клиент должен разрешить запрос при помощи нового URL, но в дальнейшем пользоваться только старым.
  • 303 - See Other (смотрите другой ресурс) - поиск затребованного URL осуществляется посредством указания другого URL, который находится в заголовке Location.
  • 304 - Not Modified (не изменился) - является кодом ответа на заголовок lf-Modified-Since, если не произошло изменение URL. Тело содержимого не присутствует, поэтому клиентом должна использоваться его локальная копия.
  • 305 - Use Proxy (используйте прокси-сервер) - обращаться к запрашиваемому ресурсу необходимо посредством прокси-сервера, который указывается в поле Location. Также в этом поле имеется URL необходимого прокси-сервера. Запрос необходимо повторить получателю.

(400-499) Неполные запросы клиента

В данном диапазоне коды ответов означают, что запрос клиента неполный. Также это может означать, что клиенту необходимо ввести дополнительную информацию.

  • 400 - Bad Request (некорректный запрос) - сервер не понимает запрос из-за синтаксиса malformed. Запрос можно повторить, но только после проведения определенных модификаций.
  • 401 - Unauthorized (нет разрешения) - пользователь должен подтвердить свою подлинность. В ответе должно присутствовать поле заголовка WWW-Authenticate с вызовом, который применяется к запрошенному ресурсу. Запрос может повториться, но уже с подходящим полем заголовка Authorization. Если в данном поле уже имеются рекомендации по установлению подлинности, то код состояния 401 показывает, что такие рекомендации не подходят для установления подлинности.
  • 402 - Payment Required (требуется оплата) - код зарезервирован и будет использоваться в будущем, но он еще не реализован в HTTP.
  • 403 - Forbidden (доступ запрещен) - отклонение запроса, так у сервера нет возможности ответить клиенту.
  • 404 - Not Found (ресурс не найден) - по указанному URL уже не существует необходимого документа, то есть сервер не нашел ничего, что могло бы соответствовать данному запросу.
  • 405 - Method Not Allowed (недопустимый метод) - в заголовке Allow отмечается, что применяемый клиентом метод не поддерживается.
  • 406 - Not Acceptable (неприемлемый запрос) - идентифицируемый ресурс может генерировать только объекты с характеристикой содержимого, которые не согласуются с заголовками приема.
  • 407 - Proxy Authentication Required (необходима регистрация на сервере-представителе) - указывает на необходимость установления подлинности клиента прокси-серверу. Прокси-сервером возвращается поле заголовка Proxy-Authenticate, где содержится определенный вызов. Запрос может быть повторен, но уже при указании подходящего поля заголовка.
  • 408 - Request Timeout (время обработки запроса истекло) - запрос не осуществился клиентом за время ожидания сервером. Запрос можно повторить позже.
  • 409 - Conflict (конфликт) - запрос не выполняется, так как существует конфликт с состоянием ресурса. Предполагается, что пользователь устранит конфликт и передаст запрос повторно.
  • 410 - Gone (ресурса больше нет) - затребованный URL больше не т на сервере.
  • 411 - Length Required (необходимо указать длину) - запрос не принимается сервером, так как не определен Content-Length. Запрос можно повторить, указав в поле заголовка Content-Length длину тела сообщения.
  • 412 - Precondition Failed (не выполнено предварительное условие) - запрос не обрабатывается сервером, так как объект запроса намного больше, чем он может обработать. При таком раскладе возможно закрытие соединения. Если такое состояние временно, то сервер указывает время в заголовке Retry-After, через которое клиент может повторить попытку.
  • 413 - Request Entity Too Large (запрашиваемый элемент слишком велик) - запрос не обрабатывается сервером из-за его огромной величины.
  • 414 - Request-URI Too Long (идентификатор ресурса в запросе слишком длинный) - запрос не обрабатывается сервером, так как его URL довольно длинный.
  • 415 - Unsupported Media Type (неподдерживаемый тип устройства) - отказ сервера в обслуживании запроса, так как запрошенным ресурсом не поддерживается формат объекта запроса.

(500-599) Ошибки сервера

В данном диапазоне указывается, что запрос, скорее всего, не будет выполнен, так как сервер столкнулся с определенной ошибкой.

  • 500 - Internal Server Error (внутренняя ошибка сервера) - во время обработки запроса один из компонентов сервера столкнулся с определенной ошибкой конфигурации.
  • 501 - Not Implemented (функция не реализована) - запрос клиента не может быть выполнен, так как для выполнения запроса необходима поддержка некоторых функциональных возможностей. Может выдаваться в случае, когда сервер не может распознать метод запроса.
  • 502 - Bad Gateway (дефект шлюза) - сервер при работе в качестве прокси-сервера получил недопустимый ответ в цепочке запросов от следующего сервера.
  • 503 - Service Unavailable (служба недоступна) - служба временно недоступна, но через некоторое время доступ может возобновиться. При наличии у сервера определенных данных, он может выдать ответ с заголовком Retry-After.
  • 504 - Gateway Timeout (время прохождения через шлюз истекло) - шлюзом или сервером превышен лимит времени.
  • 505 - HTTP Version Not Supported (неподдерживаемая версия HTTP) - сервером не поддерживается версия протокола HTTP, которая использовалась в запросе.

HTTP (HyperText Transfer Protocol - протокол передачи гипертекста) был разработан как основа World Wide Web.

Работа по протоколу HTTP происходит следующим образом: программа-клиент устанавливает TCP-соединение с сервером (стандартный номер порта-80) и выдает ему HTTP-запрос. Сервер обрабатывает этот запрос и выдает HTTP-ответ клиенту.

Структура HTTP-запроса

HTTP-запрос состоит из заголовка запроса и тела запроса, разделенных пустой строкой. Тело запроса может отсутствовать.

Заголовок запроса состоит из главной (первой) строки запроса и последующих строк, уточняющих запрос в главной строке. Последующие строки также могут отсутствовать.

Запрос в главной строке состоит из трех частей, разделенных пробелами:

Метод (иначе говоря, команда HTTP):

GET - запрос документа. Наиболее часто употребляемый метод; в HTTP/0.9, говорят, он был единственным.

HEAD - запрос заголовка документа. Отличается от GET тем, что выдается только заголовок запроса с информацией о документе. Сам документ не выдается.

POST - этот метод применяется для передачи данных CGI-скриптам. Сами данные следуют в последующих строках запроса в виде параметров.

PUT - разместить документ на сервере. Насколько я знаю, используется редко. Запрос с этим методом имеет тело, в котором передается сам документ.

Ресурс - это путь к определенному файлу на сервере, который клиент хочет получить (или разместить - для метода PUT). Если ресурс - просто какой-либо файл для считывания, сервер должен по этому запросу выдать его в теле ответа. Если же это путь к какому-либо CGI-скрипту, то сервер запускает скрипт и возвращает результат его выполнения. Кстати, благодаря такой унификации ресурсов для клиента практически безразлично, что он представляет собой на сервере.

Версия протокола -версия протокола HTTP, с которой работает клиентская программа.

Таким образом, простейший HTTP-запрос может выглядеть следующим образом:

Здесь запрашивается корневой файл из корневой директории web-сервера.

Строки после главной строки запроса имеют следующий формат:

Параметр: значениe .

Таким образом задаются параметры запроса. Это является необязательным, все строки после главной строки запроса могут отсутствовать; в этом случае сервер принимает их значение по умолчанию или по результатам предыдущего запроса (при работе в режиме Keep-Alive).

Перечислю некоторые наиболее употребительные параметры HTTP-запроса:

Connection (соединение)- может принимать значения Keep-Alive и close. Keep-Alive ("оставить в живых") означает, что после выдачи данного документа соединение с сервером не разрывается, и можно выдавать еще запросы. Большинство браузеров работают именно в режиме Keep-Alive, так как он позволяет за одно соединение с сервером "скачать" html-страницу и рисунки к ней. Будучи однажды установленным, режим Keep-Alive сохраняется до первой ошибки или до явного указания в очередном запросе Connection: close.
close ("закрыть") - соединение закрывается после ответа на данный запрос.

User-Agent - значением является "кодовое обозначение" браузера, например:

Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt)

Accept - список поддерживаемых браузером типов содержимого в порядке их предпочтения данным браузером, например для моего IE5:

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/vnd.ms-powerpoint, */*

Это, очевидно, нужно для случая, когда сервер может выдавать один и тот же документ в разных форматах.

Значение этого параметра используется в основном CGI-скриптами для формирования ответа, адаптированного для данного браузера.

Referer - URL, с которого перешли на этот ресурс.

Host - имя хоста, с которого запрашивается ресурс. Полезно, если на сервере имеется несколько виртуальных серверов под одним IP-адресом. В этом случае имя виртуального сервера определяется по этому полю.

Accept-Language - поддерживаемый язык. Имеет значение для сервера, который может выдавать один и тот же документ в разных языковых версиях.

Формат HTTP-ответа

Формат ответа очень похож на формат запроса: он также имеет заголовок и тело, разделенное пустой строкой.

Заголовок также состоит из основной строки и строк параметров, но формат основной строки отличается от таковой в заголовке запроса.

Основная строка запроса состоит из 3-х полей, разделенных пробелами:

Версия протокола - аналогичен соответствующему параметру запроса.

Код ошибки - кодовое обозначение "успешности" выполнения запроса. Код 200 означает "все нормально" (OK).

Словесное описание ошибки - "расшифровка" предыдущего кода. Например для 200 это OK, для 500 - Internal Server Error.

Наиболее употребительные параметры http-ответа:

Connection - аналогичен соответствующему параметру запроса.
Если сервер не поддерживает Keep-Alive (есть и такие), то значение Connection в ответе всегда close.

Поэтому, на мой взгляд, правильной тактикой браузера является следующая:
1. выдать в запросе Connection: Keep-Alive;
2. о состоянии соединения судить по полю Connection в ответе.

Content-Type ("тип содержимого") - содержит обозначение типа содержимого ответа.

В зависимости от значения Content-Type браузер воспринимает ответ как HTML-страницу, картинку gif или jpeg, как файл, который надо сохранить на диске, или как что-либо еще и предпринимает соответствующие действия. Значение Content-Type для браузера аналогично значению расширения файла для Windows.

Некоторые типы содержимого:

text/html - текст в формате HTML (веб-страница);
text/plain - простой текст (аналогичен "блокнотовскому");
image/jpeg - картинка в формате JPEG;
image/gif - то же, в формате GIF;
application/octet-stream - поток "октетов" (т.е. просто байт) для записи на диск.

На самом деле типов содержимого гораздо больше.

Content-Length ("длина содержимого") - длина содержимого ответа в байтах.

Last-Modified ("Модифицирован в последний раз") - дата последнего изменения документа.