Что такое SNI или как ваш провайдер узнает, на какие сайты вы ходите?
В практиках по установке соединения TLS и по HTTPS мы использовали поле заголовка TLS Server Name Indication, сокращенно SNI. Давайте подробно рассмотрим, что это такое, зачем нужно и почему это поле важно.
При установке соединения TLS сервер должен выслать клиенту TLS-сертификат сервера в сообщении Server Hello. Но современные серверы на одном IP-адресе обслуживают несколько Web-сайтов. Например, сайт для практических занятий курса по сетям размещается на сервере GitHub Pages, где есть много других сайтов. Как серверу GitHub Pages узнать, что мы хотим подключиться именно к сайту networkscourse.ru?
В HTTP для решения этой задачи использовался заголовок Host, который вставлялся в первый запрос. Но при переходе на HTTPS мы сначала должны установить соединение TLS, и только после этого отправлять запрос HTTP с заголовком Host. А при установке соединения TLS сервер должен отправить клиенту сертификат сайта с нужным доменным именем, иначе клиент разорвет соединение.
Именно для решения этой проблемы и было создано расширение TLS Server Name Indication(SNI). Его определили в RFC 3546 Transport Layer Security (TLS) Extensions. Поле SNI содержит доменное имя Web-сайта, к которому мы хотим подключиться. Клиент включает его в сообщение Client Hello при установке соединения. По значению SNI сервер выбирает нужный TLS-сертификат и отправляет клиенту.
Важная особенность в том, что доменное имя сайта передается в поле SNI в открытом виде. Соединение TLS в это время еще не установлено, поэтому зашифровать SNI нет возможности. В результате ваш провайдер знает, на какие сайты вы ходите по HTTPS 🙂 (хотя сами передаваемые данные зашифрованы).
Поле SNI удобно использовать для фильтрации трафика HTTPS в Wireshark. Ранее в видео с практиками для подключения к https://networkscourse.ru мы просто перебирали четыре IP-адреса, на которых работает GitHub Pages. При использовании SNI это делать не обязательно: достаточно указать в фильтре имя, которое должно быть в поле SNI и Wireshark отберет нужные пакеты независимо от IP-адреса сервера. Пример фильтра: tls.handshake.extensions_server_name == "networkscourse.ru"
протокол tls
sni tls