Если политика PrivateNetworkAccessRespectPreflightResultsEnabled включена, то сервер не показывает локальный адрес, что позволяет скрыть конфигурацию сети от возможных злоумышленников.
О запросах
Доступ к частной сети (Private Network Access, PNA) ограничивает способность сайтов отправлять запросы на серверы в частных сетях. Он разрешает такие запросы только из безопасных контекстов.
Спецификация также расширяет протокол совместного использования ресурсов из разных источников (CORS). Сайтам надо явно запрашивать разрешение у серверов в частных сетях, прежде чем им разрешат отправлять произвольные запросы.
Как PNA классифицирует IP-адреса и идентифицирует частную сеть
IP-адреса классифицируются по трем пространствам IP-адресов:
local
Локальное пространство IP-адресов содержит IP-адреса:
127.0.0.0/8— обратные адреса IPv4, определенные в разделе 3.2.1.3 RFC1122;
::1/128 — обратные адреса IPv6, определенные в разделе 2.5.3 RFC4291.
private
Пространство частных IP-адресов содержит IP-адреса:
10.0.0.0/8, определенные только в пределах текущей сети;
172.16.0.0/12 и 192.168.0.0/16, определенные в RFC1918;
169.254.0.0/16 — локальные адреса, определенные в RFC3927;
fc00::/7 — локальные адреса, определенные в RFC4193;
fe80::/10 — локальные адреса, определенные в разделе 2.5.6 RFC4291;
адреса IPv6 с привязкой к IPv4, где привязанный IPv4-адрес сам по себе является частным.
public
Пространство публичных IP-адресов содержит все другие адреса, которые не упомянуты ранее.
Локальный IP-адрес считается более приватным, чем частный IP-адрес, который считается более приватным, чем публичный IP-адрес.
Например, при загрузке сайта может быть выполнен размещенный на нем код. Этот код может сканировать частную сеть в поиске стандартных серверов или портов, либо выполнить запрос на какие-то обычные адреса или порты внутри локальной сети.
Возможно, это вредоносный сайт, который пытается получить данные о конфигурации сети организации или иную конфиденциальную информацию.
Типы запросов
Внешний сайт получает информацию из частной сети через запросы, которые бывают:
Простые
Прочие
Простой запрос — это запрос, который удовлетворяет условиям:
Использует простые методы:
GET;
POST;
HEAD.
Использует только простые заголовки:
Accept;
Accept-Language;
Content-Language;
Content-Type со значениями:
application/x-www-form-urlencoded;
multipart/form-data;
text/plain.
Любой иной запрос не считается простым. Например, запрос с методом DELETE или с HTTP-заголовком API-Key не соответствует условиям.
Запросы, которые по своим параметрам не соответствуют простым, относятся к «прочим». Прочие запросы могут использовать другие заголовки и любые HTTP-методы: не только GET/POST, но и PUT, TRACE, CONNECT и другие.
Обработка запросов
Обработка CORS простых запросов
При запросе на другой источник Браузер всегда устанавливает заголовок Origin.
Например, если страница https://javascript.info/page запрашивает https://example.com/request, то заголовки будут такими:
GET /request
Host: example.com
Origin: https://javascript.info
Заголовок Origin содержит именно источник (домен, протокол или порт), без пути.
Сервер может проверить Origin и добавить к ответу заголовок Access-Control-Allow-Origin, если сервер считает такой запрос безопасным и готов на него ответить. В успешном ответе такой заголовок должен содержать разрешенный источник или подстановочный знак *, иначе возникнет ошибка.
Пример успешного ответа на такой запрос:
200 OK
Content-Type: text/html; charset=UTF-8
Access-Control-Allow-Origin: https://javascript.info
Обработка CORS прочих запросов
Запрос, который относится к прочим, Браузер выполняет не сразу. Перед этим он посылает предварительный запрос, спрашивая у сервера разрешения на выполнение «прочего» запроса.
Предварительный запрос использует метод OPTIONS, у него нет тела, но есть три заголовка:
Origin содержит именно источник (домен, протокол или порт), без пути.
Access-Control-Request-Method содержит HTTP-метод «прочего» запроса.
Access-Control-Request-Headers предоставляет список его «непростых» HTTP-заголовков.
Если сервер согласен принять такой запрос, то он должен ответить без тела, со статусом 200 и с заголовками, которые должны содержать:
Access-Control-Allow-Headers — список разрешенных заголовков.
Кроме того, заголовок Access-Control-Max-Age может указывать количество секунд, на которое нужно кешировать разрешения. Это позволит браузеру не посылать предварительный запрос для последующих «прочих» запросов, которые удовлетворяют данным разрешениям.
Пример обработки «прочего» запроса
Допустим, браузеру нужно послать на сервер PATCH-запрос (далее будем называть его основным запросом):
Такой ответ разрешит будущую коммуникацию, иначе возникает ошибка. Если сервер ожидает в будущем другие методы и заголовки, то он может в ответе перечислить их все сразу, чтобы разрешить заранее, например:
200 OK
Access-Control-Allow-Methods: PUT,PATCH,DELETE
Access-Control-Allow-Headers: API-Key,Content-Type,If-Modified-Since,Cache-Control
Access-Control-Max-Age: 86400
Теперь, когда браузер видит, что PATCH есть в Access-Control-Allow-Methods, а Content-Type, API-Key – в списке Access-Control-Allow-Headers, он посылает наш основной запрос.
Кроме того, сервер кеширует разрешения, которые указаны в предварительном запросе, на время, которое указанно в заголовке Access-Control-Max-Age (86400 секунд, один день). Это позволит браузеру не посылать предварительный запрос для последующих «прочих» запросов, которые удовлетворяют данным разрешениям.
Шаг 3 (основной запрос)
Если предварительный запрос успешен, браузер делает основной запрос. Алгоритм здесь такой же, что и для простых запросов.
Основной запрос имеет заголовок Origin (потому что он идет на другой источник):
После этого JavaScript может прочитать ответ сервера.
Примечание
Предварительный запрос отправляется прозрачно для JavaScript, который получает только ответ на основной запрос или ошибку, если со стороны сервера нет разрешения.
Предварительный запрос
Предварительный запрос (Preflight-запрос) — это запрос, который браузер отправляет автоматически перед основным Cross-Origin Resource Sharing (CORS) запросом для проверки безопасности междоменных запросов. Предварительный запрос предотвращает отправку небезопасных или несанкционированных запросов к другим доменам.
Основная цель предварительного запроса — установить доверие между клиентом (браузером) и сервером путем обмена набором HTTP-заголовков, когда одна страница делает запрос к другому домену. Это предотвращает межсайтовое выполнение скриптов (XSS) и другие атаки, связанные с запросами браузера к разным доменам.
Заголовки предварительного запроса
Предварительный запрос выполняется методом OPTIONS и содержит в себе следующие заголовки:
Origin: указывает домен, с которого отправлен основной запрос.
Access-Control-Request-Method: указывает метод основного запроса, например, GET, POST, PUT, DELETE и т. д.
Access-Control-Request-Headers: перечисляет пользовательские заголовки основного запроса.
Заголовки ответа на предварительный запрос
Сервер должен вернуть специальные заголовки, которые подтверждают возможность междоменного запроса:
Access-Control-Allow-Origin: перечисляет домены, которым разрешены междоменные запросы. Может принимать значение *. Это означает, что разрешены запросы с любого домена, или конкретный домен, который имеет право на доступ.
Внимание
В Access-Control-Allow-Origin запрещено использовать подстановочный знак * для запросов с авторизационными данными. В этих случаях необходимо указывать источник. Это дополнительная мера безопасности, которая гарантирует, что серверу известен отправитель запроса.
Access-Control-Expose-Headers: перечисляет заголовки, которые не являются простыми, но доступ к которым разрешен для JavaScript.
Примечание
По умолчанию JavaScript может получить доступ только к простым заголовкам ответа. При доступе к любому другому заголовку ответа будет ошибка.
Access-Control-Allow-Credentials: [true] сообщает браузеру, что сервер разрешает авторизационные данные для запроса между источниками.
Access-Control-Allow-Methods: перечисляет методы, которые можно использовать для основного запроса.
Access-Control-Allow-Headers: перечисляет заголовки, которые можно использовать для основного запроса.
Access-Control-Max-Age: указывает время, в течение которого предварительный запрос считается действительным.
Если сервер выполнил предварительный запрос, то основной запрос будет совершен автоматически до истечения времени, указанного в Access-Control-Max-Age.