RFC 9249 A YANG Data Model for NTP

Internet Engineering Task Force (IETF)                             N. Wu
Request for Comments: 9249                                 D. Dhody, Ed.
Category: Standards Track                                         Huawei
ISSN: 2070-1721                                            A. Sinha, Ed.
                                                            A. Kumar S N
                                                            RtBrick Inc.
                                                                 Y. Zhao
                                                                Ericsson
                                                               July 2022

A YANG Data Model for NTP

Модель данных YANG для NTP

PDF

Аннотация

Этот документ задаёт модель данных YANG, которая может служить для настройки и управления протоколом сетевого времени (Network Time Protocol или NTP) версии 4, а также версии 3. Модель включает данные конфигурации и состояния.

Статус документа

Документ относится к категории Internet Standards Track.

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG2. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информация о текущем статусе документа, найденных ошибках и способах обратной связи доступна по ссылке https://www.rfc-editor.org/info/rfc9249.

Авторские права

Copyright (c) 2022. Авторские права принадлежат IETF Trust и лицам, указанным в качестве авторов документа. Все права защищены.

К документу применимы права и ограничения, указанные в BCP 78 и IETF Trust Legal Provisions и относящиеся к документам IETF (http://trustee.ietf.org/license-info), на момент публикации данного документа. Прочтите упомянутые документы внимательно. Фрагменты программного кода, включённые в этот документ, распространяются в соответствии с упрощённой лицензией BSD, как указано в параграфе 4.e документа IETF Trust Legal Provisions, без каких-либо гарантий (как указано в Simplified BSD License).

1. Введение

Этот документ задаёт модель данных YANG [RFC7950], которая может служить для настройки и управления протоколом NTP версии 4 [RFC5905]. Отметим, что модель также подходит для протокола NTPv3 [RFC1305] (см. 7. Версия NTP).

Модель данных охватывает настройку системных параметров NTP, таких как правила доступа, проверка подлинности, привязка маршрутизации и пересылки VPN (VPN Routing and Forwarding или VRF), различные режимы NTP и параметры на уровне интерфейсов. Обеспечивается также доступ к рабочему состоянию реализации NTP.

1.1. Рабочее состояние

Рабочее состояние NTP включено в одно дерево с конфигурацией NTP в соответствии с архитектрой хранилищ данных управления сетью (Network Management Datastore Architecture или NMDA) [RFC8342]. Текущее состояние и статистика NTP, а также статус ассоциации NTP также поддерживаются в рабочем состоянии.

1.2. Терминология

Используемые в документе термины соответствуют [RFC5905] и [RFC1305].

1.3. Диаграммы деревьев

В этом документе применяется графическое представление данных, определённое в [RFC8340].

1.4. Префиксы в именах узлов данных

В этом документе имена узлов данных, действий и других объектов модели данных используются без префиксов, если из контекста очевидно, в каком модуле YANG они определены. В остальных случаях имена указываются со стандартным префиксом соответствующего модуля YANG (Таблица 1).

Таблица 1. Префиксы и соответствующие модули YANG.

 

Префикс

Модуль YANG

Документ

yang

ietf-yang-types

[RFC6991]

inet

ietf-inet-types

[RFC6991]

if

ietf-interfaces

[RFC8343]

sys

ietf-system

[RFC7317]

acl

ietf-access-control-list

[RFC8519]

rt-types

ietf-routing-types

[RFC8294]

nacm

ietf-netconf-acm

[RFC8341]

 

1.5. Ссылки в модели

В таблице 2 указаны документы, на которые ссылается определяемая в документе модель.

Таблица 2. Ссылки в модуле YANG.

 

Название

Документ

Network Time Protocol Version 4: Protocol and Algorithms Specification

[RFC5905]

Common YANG Data Types

[RFC6991]

A YANG Data Model for System Management

[RFC7317]

Common YANG Data Types for the Routing Area

[RFC8294]

Network Configuration Access Control Model

[RFC8341]

A YANG Data Model for Interface Management

[RFC8343]

YANG Data Model for Network Access Control Lists (ACLs)

[RFC8519]

Message Authentication Code for the Network Time Protocol

[RFC8573]

The AES-CMAC Algorithm

[RFC4493]

The MD5 Message-Digest Algorithm

[RFC1321]

US Secure Hash Algorithm 1 (SHA1)

[RFC3174]

FIPS 180-4: Secure Hash Standard (SHS)

[SHS]

 

1.6. Уровни требований

Ключевые слова должно (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

2. Модель данных NTP

Этот документ определяет модуль YANG ietf-ntp, сжатая структура которого показана ниже.

   module: ietf-ntp
     +--rw ntp!
        +--rw port?                    inet:port-number {ntp-port}?
        +--rw refclock-master!
        |  +--rw master-stratum?   ntp-stratum
        +--rw authentication {authentication}?
        |  +--rw auth-enabled?          boolean
        |  +--rw authentication-keys* [keyid]
        |     +--rw keyid       uint32
        |     +--...
        +--rw access-rules {access-rules}?
        |  +--rw access-rule* [access-mode]
        |     +--rw access-mode    identityref
        |     +--rw acl?           -> /acl:acls/acl/name
        +--ro clock-state
        |  +--ro system-status
        |     +--ro clock-state                  identityref
        |     +--ro clock-stratum                ntp-stratum
        |     +--ro clock-refid                  refid
        |     +--...
        +--rw unicast-configuration* [address type]
        |       {unicast-configuration}?
        |  +--rw address           inet:ip-address
        |  +--rw type              identityref
        |  +--...
        +--rw associations
        |  +--ro association* [address local-mode isconfigured]
        |     +--ro address           inet:ip-address
        |     +--ro local-mode        identityref
        |     +--ro isconfigured      boolean
        |     +--...
        |     +--ro ntp-statistics
        |        +--...
        +--rw interfaces
        |  +--rw interface* [name]
        |     +--rw name                if:interface-ref
        |     +--rw broadcast-server! {broadcast-server}?
        |     |  +--...
        |     +--rw broadcast-client! {broadcast-client}?
        |     +--rw multicast-server* [address] {multicast-server}?
        |     |  +--rw address
        |     |  |       rt-types:ip-multicast-group-address
        |     |  +--...
        |     +--rw multicast-client* [address] {multicast-client}?
        |     |  +--rw address    rt-types:ip-multicast-group-address
        |     +--rw manycast-server* [address] {manycast-server}?
        |     |  +--rw address    rt-types:ip-multicast-group-address
        |     +--rw manycast-client* [address] {manycast-client}?
        |        +--rw address
        |        |       rt-types:ip-multicast-group-address
        |        +--...
        +--ro ntp-statistics
           +--...

     rpcs:
       +---x statistics-reset
          +---w input
             +---w (association-or-all)?
                +--:(association)
                |  +---w associations-address?
                |  |       -> /ntp/associations/association/address
                |  +---w associations-local-mode?
                |  |       -> /ntp/associations/association/local-mode
                |  +---w associations-isconfigured?
                |          -> /ntp/associations/association/isconfigured
                +--:(all)

Полное дерево модели данных для модуля YANG ietf-ntp приведено в Приложении A.

Эта модель определяет один контейнер верхнего уровня, включающий конфигурацию и рабочее состояние NTP вместе с правилами доступа, проверкой подлинности, ассоциациями, индивидуалльными (unicast) конфигурациями, интерфейсами, статусом и ассоциациями системы.

3. Связи с NTPv4-MIB

Если устройство поддерживает NTPv4-MIB [RFC5907], узлы данных модуля YANG можно сопоставить с объектами NTPv4-MIB, как показано в таблицах 3 и 4.

Таблица 3. Узлы данных YANG NTP в /ntp/clock-state/system-status и объекты NTPv4-MIB.

Узлы данных YANG в /ntp/ clock-state/system-status

Объекты NTPv4-MIB

clock-state

ntpEntStatusCurrentMode

clock-stratum

ntpEntStatusStratum

clock-refid

NtpEntStatusActiveRefSourceId ntpEntStatusActiveRefSourceName

clock-precision

ntpEntTimePrecision

clock-offset

ntpEntStatusActiveOffset

root-dispersion

ntpEntStatusDispersion

Таблица 4. Узлы данных YANG NTP в /ntp/associations/ и объекты NTPv4-MIB.

 

Узлы данных YANG в /ntp/associations/

Объекты NTPv4-MIB

address

ntpAssocAddressType ntpAssocAddress

stratum

ntpAssocStratum

refid

ntpAssocRefId

offset

ntpAssocOffset

delay

ntpAssocStatusDelay

dispersion

ntpAssocStatusDispersion

ntp-statistics/packet-sent

ntpAssocStatOutPkts

ntp-statistics/packet-received

ntpAssocStatInPkts

ntp-statistics/packet-dropped

ntpAssocStatProtocolError

 

4. Связи с RFC 7317

В этом разделе описаны связи с определениями NTP в параграфе 3.2 (Управление системным временем) [RFC7317]. Узлы данных YANG в /ntp/ поддерживают настройку на уровне интерфейса, которой нет в /system/ntp. При реализации описанной здесь модели данных YANG ветвь /system/ntp не следует использовать и она должна игнорироваться.

Таблица 5. Узлы данных в модели YANG NTP и соответствующие узлы из RFC 7317.

Узлы данных YANG в /ntp/

Узлы данныхYANG в /system/ntp

ntp!

enabled

unicast-configuration

server server/name

unicast-configuration/address

server/transport/udp/address

unicast-configuration/port

server/transport/udp/port

unicast-configuration/type

server/association-type

unicast-configuration/iburst

server/iburst

unicast-configuration/prefer

server/prefer

5. Правила доступа

Правила доступа в этом разделе относятся к управлению доступом к серверу NTP в линии (on-the-wire) и никак не связаны с какими-либо API управления доступом, например, NETCONF Access Control Model (NACM) [RFC8341].

Списки управления доступом (Access Control List или ACL) являются одним из основных элементов настройки поведения устройств пересылки. ACL — это упорядоченный пользователем список правил, применяемых для фильтрации трафика на сетевом устройстве.

В соответствии с [RFC1305] (для NTPv3) и [RFC5905] (для NTPv4) протокол NTP может включать функцию контроля доступа, предотвращающую несанкионированный доступ и управляющую партнёрами, которым разрешено обновлять локальные часы. Кроме того, полезно различать виды доступа и связывать с каждым своё правило acl-rule. Для этого модуль YANG поддерживает конфигурацию через ветвь /ntp/access-rules. Сами правила access-rule настраиваются в соответствии с [RFC8519]. Поддерживаемые режимы доступа перечислены ниже.

Peer — партнёр

Разрешает другим синхронизировать их часы с сущностью NTP и наоборот. Запросы управления NTP воспринимаются.

Server — сервер

Разрешает другим синхронизировать их часы с сущностью NTP, но не наоборот. Запросы управления NTP воспринимаются.

Server-only — только сервер

Разрешает другим синхронизировать их часы с сущностью NTP, но не наоборот. Запросы управления NTP не воспринимаются.

Query-only — только запросы

Воспринимаются только запросы управления.

Режим Query-only задаёт наибольшие ограничения, а Peer даёт полный доступ. Возможность задавать разные правила ACL для разных режимов доступа обеспечивает контроль со стороны оператора.

6. Управление ключами

В соответствии с [RFC1305] (для NTPv3) и [RFC5905] (для NTPv4) протокол NTP при включённой аутентификации использует криптографические контрольные суммы, рассчитываемые отправителем и проверяемые получателем, вместе с набором заранее распространённых алгоритмов и криптографических ключей, индексируемых идентификаторами, включаемыми в сообщение NTP. Идентификатором keyid служит 32-битовое целое число без знака, которое должно быть настроено на партнёрах NTP до начала применения аутентификации. Поэтому данный модуль YANG поддерживает такую настройку в ветви /ntp/authentication/authentication-keys/. Значение keyid указывается при настройке ассоциации NTP (например, unicast-сервер).

Правило nacm:default-deny-all служит для предотвращения доступа к фактическому ключу после его установки.

7. Версия NTP

Эта модель YANG позволяет задать версию NTP для ассоциации, т. е. оператор может выбрать использование NTPv3 [RFC1305] или NTPv4 [RFC5905] для каждой создаваемой ассоциации. Это обеспечивает совместимость с унаследованными системами. Отметим, что протокол NTPv3 [RFC1305] отменён версией NTPv4 [RFC5905].

8. Модуль NTP YANG

   <CODE BEGINS> file "ietf-ntp@2022-07-05.yang"
   module ietf-ntp {
     yang-version 1.1;
     namespace "urn:ietf:params:xml:ns:yang:ietf-ntp";
     prefix ntp;

     import ietf-yang-types {
       prefix yang;
       reference
         "RFC 6991: Common YANG Data Types";
     }
     import ietf-inet-types {
       prefix inet;
       reference
         "RFC 6991: Common YANG Data Types";
     }
     import ietf-interfaces {
       prefix if;
       reference
         "RFC 8343: A YANG Data Model for Interface Management";
     }
     import ietf-system {
       prefix sys;
       reference
         "RFC 7317: A YANG Data Model for System Management";
     }
     import ietf-access-control-list {
       prefix acl;
       reference
         "RFC 8519: YANG Data Model for Network Access Control
          Lists (ACLs)";
     }
     import ietf-routing-types {
       prefix rt-types;
       reference
         "RFC 8294: Common YANG Data Types for the Routing Area";
     }
     import ietf-netconf-acm {
       prefix nacm;
       reference
         "RFC 8341: Network Configuration Access Control Model";
     }

     organization
       "IETF NTP (Network Time Protocol) Working Group";
     contact
       "WG Web:  <https://datatracker.ietf.org/wg/ntp/> 
        WG List:  <mailto: ntp@ietf.org 
        Editor:   Dhruv Dhody
                 <mailto:dhruv.ietf@gmail.com> 
        Editor:   Ankit Kumar Sinha
                 <mailto:ankit.ietf@gmail.com>"; 
     description
       "Этот документ задаёт модель данных YANG, которая может служить
        для настройки и управления NTP версии 4, а также позволяет
        настраивать и поддерживать версию 3. Модель включает данные 
        конфигурации и состояния.

        Ключевые слова ДОЛЖНО, НЕДОПУСТИМО, ТРЕБУЕТСЯ, НУЖНО, НЕ НУЖНО, 
        СЛЕДУЕТ, НЕ СЛЕДУЕТ, РЕКОМЕНДУЕТСЯ, НЕ РЕКОМЕНДУЕТСЯ, МОЖНО,
        НЕОБЯЗАТЕЛЬНО в этом документе трактуются в соответствии с 
        BCP 14 (RFC 2119) (RFC 8174) тогда и только тогда, когда они
        указаны заглавными буквами, как показано здесь.

        Авторские права (Copyright (c) 2021) принадлежат IETF Trust и
        лицам, указанным как авторы. Все права защищены.

        Распространение и применение модуля в исходной или двоичной 
        форме с изменениями или без таковых разрешено в соответствии с
        лицензией Simplified BSD License, изложенной в параграфе 4.c
        IETF Trust's Legal Provisions Relating to IETF Documents
        (https://trustee.ietf.org/license-info). 

        Эта версия модуля YANG является частью RFC 9249, где правовые
        аспекты приведены более полно.";

     revision 2022-07-05 {
       description
         "Исходный выпуск";
       reference
         "RFC 9249: A YANG Data Model for NTP";
     }

     /* Определения типов */

     typedef ntp-stratum {
       type uint8 {
         range "1..16";
       }
       description
         "Уровень каждого сервера в иерархии определяется «слоем» 
          (stratum). Первичные серверы образуют stratum 1, вторичным
          серверам на каждом уровне назначается stratum на 1 больше,
          чем у предшествующего уровня.";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 3";
     }

     typedef ntp-version {
       type uint8 {
         range "3..max";
       }
       default "4";
       description
         "Текущая версия NTP, поддерживаемая соответствующей 
          ассоциацией";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 1";
     }

     typedef refid {
       type union {
         type inet:ipv4-address;
         type uint32;
         type string {
           length "4";
         }
       }
       description
         "Код, указывающий определённый сервер или эталонные часы. 
          Интерпретация зависит от stratum. Это может быть адрес IPv4,
          первые 32 бита хэш-значения MD5, адрес IPv6 или строка для
          Reference Identifier и kiss-кодов. Например,
          - идентификатор эталонных часов 127.127.1.0 для локальной
            синхронизации  
          - индивидуальная, групповая или широковещательная ассоциация 
            вида 203.0.113.1 для IPv4 и 0x4321FEDC для IPv6
          - синхронизация с первичным источником вида DCN, NIST, ATOM
          - kis-коды имеют вид AUTH, DROP, RATE

          Хэш MD5 для адресов IPv6 не служит для криптографии.";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 7.3";
     }

     typedef ntp-date-and-time {
       type union {
         type yang:date-and-time;
         type uint8;
       }
       description
         "Соответствует формату даты и времени при наличии пригодных
          значений. В иных случаях позволяет задавать особые значения,
          такие как 0.";
       reference
         "RFC 6991: Common YANG Data Types";
     }

     typedef log2seconds {
       type int8;
       description
         "8-битовое целое число со знаком для log2 от числа секунд.";
     }

     /* Свойства (функции) */

     feature ntp-port {
       description
         "Поддержка настройки порта NTP.";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 7.2";
     }

     feature authentication {
       description
         "Поддержка аутентификации NTP с симметричным ключом.";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 7.3";
     }

     feature deprecated {
       description
         "Поддержка аутентификации MD5 (RFC 8573), SHA-1 или иного
          устаревшего механизма. Это разрешено для совместимости с
          унаследованными системами, не поддерживающими криптографии,
          а также для строк ключей в формате ASCII.";
       reference
         "RFC 1321: The MD5 Message-Digest Algorithm,
          RFC 3174: US Secure Hash Algorithm 1 (SHA1),
          SHS: Secure Hash Standard (SHS) (FIPS PUB 180-4)";
     }

     feature hex-key-string {
       description
         "Поддержка шестнадцатеричных строк для ключей.";
     }

     feature access-rules {
       description
         "Поддержка управления доступом для NTP.";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 9.2";
     }

     feature unicast-configuration {
       description
         "Поддержка режима NTP клиент-сервер или активный-пассивный
          в индивидуальных сессиях";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 3";
     }

     feature broadcast-server {
       description
         "Поддержка широковещательного сервера.";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 3";
     }

     feature broadcast-client {
       description
         "Поддержка широковещательных клиентов.";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 3";
     }

     feature multicast-server {
       description
         "Поддержка multicast-сервера.";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 3.1";
     }
     feature multicast-client {
       description
         "Поддержка multicast-клиентов.";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 3.1";
     }

     feature manycast-server {
       description
         "Поддержка manycast-сервера.";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 3.1";
     }

     feature manycast-client {
       description
         "Поддержка manycast-клиентов.";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 3.1";
     }

     /* Идентификаторы (отождествления) */
     /* Типы unicast-конфигураций */

     identity unicast-configuration-type {
       if-feature "unicast-configuration";
       description
         "Задаёт режим NTP unicast для индивидуальных сессий.";
     }

     identity uc-server {
       if-feature "unicast-configuration";
       base unicast-configuration-type;
       description
         "Использовать режим клиентской ассоциации, когда задан 
          unicast-адрес сервера.";
     }

     identity uc-peer {
       if-feature "unicast-configuration";
       base unicast-configuration-type;
       description
         "Использовать рехим симметричной активной ассоциации, когда
          настроен адрес партнёра.";
     }

     /* Режимы ассоциаций */

     identity association-mode {
       description
         "Режимы ассоциаций NTP.";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 3";
     }

     identity active {
       base association-mode;
       description
         "Использовать симметричную активную ассоциацию (режим 1).
          Устройство может синхронизироваться от партнёра NTP или
          синхронизировать заданного партнёра NTP.";
     }

     identity passive {
       base association-mode;
       description
         "Использовать симметричную пассивную ассоциацию (режим 2).
          Устройство получило эту ассоциацию динамически и может
          синхронизироваться от партнёра NTP.";
     }

     identity client {
       base association-mode;
       description
         "Использовать клиентскую ассоциацию (режим 3).
          Устройство не синхронизирует заданный сервер NTP.";
     }

     identity server {
       base association-mode;
       description
         "Использовать серверную ассоциацию (режим 4).
          Устройство обеспечивает синхронизацию для клиентов NTP.";
     }

     identity broadcast-server {
       base association-mode;
       description
         "Использовать режим широковещательного сервера (режим 5).
          Сервер работает как широковещательный или групповой.";
     }

     identity broadcast-client {
       base association-mode;
       description
         "Режим широковещательного (6) или группового клиента.";
     }

     /* Режимы доступа */

     identity access-mode {
       if-feature "access-rules";
       description
         "Задаёт режимы доступа NTP (применение ACL для NTP).";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Section 9.2";
     }

     identity peer-access-mode {
       if-feature "access-rules";
       base access-mode;
       description
         "Позволяет другим синхронизировать себя от NTP и наоборот.
          Запросы управления NTP воспринимаются.";
     }

     identity server-access-mode {
       if-feature "access-rules";
       base access-mode;
       description
         "Позволяет другим синхронизировать себя от NTP, но не наоборот.
          Запросы управления NTP воспринимаются.";
     }

     identity server-only-access-mode {
       if-feature "access-rules";
       base access-mode;
       description
         "Позволяет другим синхронизировать себя от NTP, но не наоборот.
          Запросы управления NTP не воспринимаются.";
     }

     identity query-only-access-mode {
       if-feature "access-rules";
       base access-mode;
       description
         "Воспринимаются только запросы управления.";
     }

     /* Состояния часов */

     identity clock-state {
       description
         "Задаёт состояние часов NTP на высоком уровне.";
     }

     identity synchronized {
       base clock-state;
       description
         "Локальные часы синхронизированы с сервером NTP
          или эталонными часами.";
     }

     identity unsynchronized {
       base clock-state;
       description
         "Локальные часы не синхронизированы с каким-либо сервером NTP";
     }

     /* ntp-sync-state */

     identity ntp-sync-state {
       description
         "Состояние синхронизации часов NTP на более детальном уровне.
          Это называется «определением состояния часов» в RFC 5905.";
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Appendix A.1.1";
     }

     identity clock-never-set {
       base ntp-sync-state;
       description
         "Часы никогда не устанавливались.";
     }

     identity freq-set-by-cfg {
       base ntp-sync-state;
       description
         "Частота часов задана настройкой NTP или файлом.";
     }

     identity spike {
       base ntp-sync-state;
       description
         "Обнаружен «всплеск» spike.";
     }

     identity freq {
       base ntp-sync-state;
       description
         "Указывает режим частоты (frequency mode).";
     }

     identity clock-synchronized {
       base ntp-sync-state;
       description
         "Часы синхронизированы.";
     }

     /* Криптоалгоритм */

     identity crypto-algorithm {
       description
         "Базовый идентификатор для криптографических алгоритмов.";
     }

     identity md5 {
       if-feature "deprecated";
       base crypto-algorithm;
       description
         "Алгоритм MD5. В RFC 8573 отменено использование
          аутентификации на основе MD5.";
       reference
         "RFC 1321: The MD5 Message-Digest Algorithm";
     }

     identity sha-1 {
       if-feature "deprecated";
       base crypto-algorithm;
       description
         "Алгоритм SHA-1.";
       reference
         "RFC 3174: US Secure Hash Algorithm 1 (SHA1)";
     }

     identity hmac-sha-1 {
       if-feature "deprecated";
       base crypto-algorithm;
       description
         "Алгоритм аутентификации HMAC-SHA-1.";
       reference
         "SHS: Secure Hash Standard (SHS) (FIPS PUB 180-4)";
     }

     identity hmac-sha1-12 {
       if-feature "deprecated";
       base crypto-algorithm;
       description
         " Алгоритм HMAC-SHA1-12.";
     }

     identity hmac-sha-256 {
       description
         "Алгоритм аутентификации HMAC-SHA-256.";
       reference
         "SHS: Secure Hash Standard (SHS) (FIPS PUB 180-4)";
     }

     identity hmac-sha-384 {
       description
         "Алгоритм аутентификации HMAC-SHA-384.";
       reference
         "SHS: Secure Hash Standard (SHS) (FIPS PUB 180-4)";
     }

     identity hmac-sha-512 {
       description
         "Алгоритм аутентификации HMAC-SHA-512.";
       reference
         "SHS: Secure Hash Standard (SHS) (FIPS PUB 180-4)";
     }

     identity aes-cmac {
       base crypto-algorithm;
       description
         "Алгоритм AES-CMAC, требуемый RFC 8573 для MAC в NTP.";
       reference
         "RFC 4493: The AES-CMAC Algorithm,
          RFC 8573: Message Authentication Code for the Network
          Time Protocol";
     }

     /* Группировки */

     grouping key {
       description
         "The key";
       nacm:default-deny-all;
       choice key-string-style {
         description
           "Стиль строк ключей";
         case keystring {
           leaf keystring {
             if-feature "deprecated";
             type string;
             description
               "Строки ключей в формате ASCII.";
           }
         }
         case hexadecimal {
           if-feature "hex-key-string";
           leaf hexadecimal-string {
             type yang:hex-string;
             description
               "Ключ в форме шестнадцатеричной строки. По сравнению с
                ASCII такие строки повышают уровень энтропии при том же
                числе символов в строке ключа. Кроме того, это 
                препятствует использованию общеизвестных слов и чисел.";
           }
         }
       }
     }

     grouping authentication-key {
       description
         "Задание ключа аутентификации для источника времени NTP.";
       leaf keyid {
         type uint32 {
           range "1..max";
         }
         description
           "Идентификатор ключа аутентификации.";
       }
       leaf algorithm {
         type identityref {
           base crypto-algorithm;
         }
         description
           "Алгоритм аутентификации. RFC 8573 отменяет использование
            аутентификации MD5 и рекомедует применять AES-CMAC.";
       }
       container key {
         uses key;
         description
           "Ключ. RFC 8573 отменяет использование использование
            аутентификации на основе MD5.";
       }
       leaf istrusted {
         type boolean;
         description
           "Доверие к Keyid.";
       }
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification, Sections 7.3 and 7.4";
     }

     grouping authentication {
       description
         "Аутентификация.";
       choice authentication-type {
         description
           "Тип аутентификации.";
         case symmetric-key {
           leaf keyid {
             type leafref {
               path "/ntp:ntp/ntp:authentication/"
                  + "ntp:authentication-keys/ntp:keyid";
             }
             description
               "Идентификатор ключа, указанного в этой ассоциации.";
           }
         }
       }
     }

     grouping statistics {
       description
         "NTP packet statistic";
       leaf discontinuity-time {
         type ntp-date-and-time;
         description
           "Время последнего разрыва одного или нескольких счетчиков
            NTP. Если разрывов не было, указывается время 
            (ре) инициализации ассоциации NTP.";
       }
       leaf packet-sent {
         type yang:counter32;
         description
           "Общее число пакетов NTP, переданных транспортному сервису
            этим объектом NTP в данной ассоциации. Разрывы этого
            счётчика могут возникать при «холодном» перезапуске, 
            реинициализации объекта NTP или системы управления, а также
            в иных случаях.";
       }
       leaf packet-sent-fail {
         type yang:counter32;
         description
           "Число отказов при передаче пакетов NTP.";
       }
       leaf packet-received {
         type yang:counter32;
         description
           "Общее число пакетов NTP, доставленных этому объекту NTP в 
            данной ассоциации. Разрывы этого счётчика могут возникать
            при «холодном» перезапуске, реинициализации объекта NTP или
            системы управления, а также в иных случаях.";
       }
       leaf packet-dropped {
         type yang:counter32;
         description
           "Общее число пакетов NTP, доставленных этому объекту NTP в 
            данной ассоциации, которые не были обработаны в результате
            ошибки NTP. Разрывы этого счётчика могут возникать
            при «холодном» перезапуске, реинициализации объекта NTP или
            системы управления, а также в иных случаях.";
       }
     }

     grouping common-attributes {
       description
         "Базовые атрибуты NTP для конфигурации";
       leaf minpoll {
         type log2seconds;
         default "6";
         description
           "Минимальный интервал опроса в этой ассоциации.";
         reference
           "RFC 5905: Network Time Protocol Version 4: Protocol and
            Algorithms Specification, Section 7.2";
       }
       leaf maxpoll {
         type log2seconds;
         default "10";
         description
           "Максимальный интервал опроса в этой ассоциации.";
         reference
           "RFC 5905: Network Time Protocol Version 4: Protocol and
            Algorithms Specification, Section 7.2";
       }
       leaf port {
         if-feature "ntp-port";
         type inet:port-number {
           range "123 | 1024..max";
         }
         default "123";
         description
           "Порт, используемый для отправки пакетов NTP.";
         reference
           "RFC 5905: Network Time Protocol Version 4: Protocol and
            Algorithms Specification, Section 7.2";
       }
       leaf version {
         type ntp-version;
         description
           "Версия NTP.";
       }
       reference
         "RFC 5905: Network Time Protocol Version 4: Protocol and
          Algorithms Specification";
     }

     grouping association-ref {
       description
         "Указывает режим ассоциации NTP.";
       leaf associations-address {
         type leafref {
           path "/ntp:ntp/ntp:associations/ntp:association"
              + "/ntp:address";
         }
         description
           "Указывает адрес ассоциации, задавший синхронизацию часов.";
       }
       leaf associations-local-mode {
         type leafref {
           path "/ntp:ntp/ntp:associations/ntp:association"
              + "/ntp:local-mode";
         }
         description
           "Указывает локальный режим ассоциации, задавший
            синхронизацию часов.";
       }
       leaf associations-isconfigured {
         type leafref {
           path "/ntp:ntp/ntp:associations/ntp:association/"
              + "ntp:isconfigured";
         }
         description
           "Указывает, была ли ассоциация настроена явно
            (что привело к синхронизации часов).";
       }
     }

     container ntp {
       when 'false() = boolean(/sys:system/sys:ntp)' {
         description
           "Применимо, если не используется /sys/ntp/.";
       }
       presence "NTP включён и системе следует пытаться синхронизировать
                 свои часы с сервером NTP из списка ntp/associations.";
       description
         "Параметры конфигурации для NTP.";
       leaf port {
         if-feature "ntp-port";
         type inet:port-number {
           range "123 | 1024..max";
         }
         default "123";
         description
           "Порт для передачи и приёма пакетов NTP.";
         reference
           "RFC 5905: Network Time Protocol Version 4: Protocol and
            Algorithms Specification, Section 7.2";
       }
       container refclock-master {
         presence "Первичные часы NTP разрешены.";
         description
           "Задаёт локальные часы этого устройства как сервер NTP.";
         leaf master-stratum {
           type ntp-stratum;
           default "16";
           description
             "Уровень stratum, с которым клиенты NTP синхронизируют
              свои часы.";
         }
       }
       container authentication {
         if-feature "authentication";
         description
           "Настройка аутентификации.";
         leaf auth-enabled {
           type boolean;
           default "false";
           description
             "Управляет применением аутентификации NTP на устройстве.";
         }
         list authentication-keys {
           key "keyid";
           uses authentication-key;
           description
             "Список ключей аутентификации.";
         }
       }
       container access-rules {
         if-feature "access-rules";
         description
           "Настройка управления доступом к сервису NTP с помощью
            функции NTP access-group. Значение access-mode указывает
            способ применения ACL для NTP.";
         list access-rule {
           key "access-mode";
           description
             "Список правил доступа.";
           leaf access-mode {
             type identityref {
               base access-mode;
             }
             description
               "Режим доступа NTP (peer, server, synchronization, query
                и т. п.).";
           }
           leaf acl {
             type leafref {
               path "/acl:acls/acl:acl/acl:name";
             }
             description
               "Применяемая конфигурация контроля доступа.";
           }
           reference
             "RFC 5905: Network Time Protocol Version 4: Protocol and
              Algorithms Specification, Section 9.2";
         }
       }
       container clock-state {
         config false;
         description
           "Рабочее состояние часов NTP.";
         container system-status {
           description
             "Cjcnjzybt cbcntvs NTP.";
           leaf clock-state {
             type identityref {
               base clock-state;
             }
             mandatory true;
             description
               "Состояние системых часов (синхронизированы, 
                не синхронизированы).";
           }
           leaf clock-stratum {
             type ntp-stratum;
             mandatory true;
             description
               "Значение stratum объекта NTP. Следует устанаваливать на 
                1 больше, чем на предыдущем уровне. 16 говорит об 
                отсутствии синхронизации.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Section 3";
           }
           leaf clock-refid {
             type refid;
             mandatory true;
             description
               "Код, указывающий определённый сервер или эталонные часы. 
                Интерпретация зависит от stratum. Это может быть адрес
                IPv4,первые 32 бита хэш-значения MD5, адрес IPv6 или 
                строка для Reference Identifier и kiss-кодов. Например,
                - идентификатор эталонных часов 127.127.1.0 для 
                  локальной синхронизации  
                - индивидуальная, групповая или широковещательная 
                  ассоциация вида 203.0.113.1 в IPv4 и 0x4321FEDC в IPv6
                - синхронизация с первичным источником вида DCN, NIST,
                  ATOM
                - kis-коды имеют вид AUTH, DROP, RATE

                Хэш MD5 для адресов IPv6 не служит для криптографии.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Section 7.3";
           }
           uses association-ref {
             description
               "Ссылка на ассоциацию";
           }
           leaf nominal-freq {
             type decimal64 {
               fraction-digits 4;
             }
             units "Hz";
             mandatory true;
             description
               "Номинальная частота локальных часов. Идеальная частота с
                нулевой неопределенностью (погрешностью).";
           }
           leaf actual-freq {
             type decimal64 {
               fraction-digits 4;
             }
             units "Hz";
             mandatory true;
             description
               "Фактическая частота локальных часов.";
           }
           leaf clock-precision {
             type log2seconds;
             mandatory true;
             description
               "Точность часов этой системы в виде целого числа со 
                знаком log2 секунд - (prec=2^(-n)). Значение 5 
                указывает 2^-5 = 0,03125 секунд = 31.25 мсек.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Section 7.3";
           }
           leaf clock-offset {
             type decimal64 {
               fraction-digits 3;
             }
             units "milliseconds";
             description
               "Смещение от текущего источника точного времени, 
                например, 0,032 мсек млм 1,232мсек. Отрицательное 
                значение указывает отставание локальных часов.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Section 9.1";
           }
           leaf root-delay {
             type decimal64 {
               fraction-digits 3;
             }
             units "milliseconds";
             description
               "Общая задержка на пути к эталонным часам.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Sections 4 and 7.3";
           }
           leaf root-dispersion {
             type decimal64 {
               fraction-digits 3;
             }
             units "milliseconds";
             description
               "Дисперсия локальных и корневых часов, например,
                6,927 мсек.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Sections 4, 7.3, and 10";
           }
           leaf reference-time {
             type ntp-date-and-time;
             description
               "Опорная метка времени - момент последней установки или
                корректировки системных часов.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Section 7.3";
           }
           leaf sync-state {
             type identityref {
               base ntp-sync-state;
             }
             mandatory true;
             description
               "Состояние синхронизации локальных часов, называемое 
                «определением состояния часов» в RFC 5905.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Appendix A.1.1";
           }
         }
       }
       list unicast-configuration {
         if-feature "unicast-configuration";
         key "address type";
         description
           "Список unicast-конфигураций NTP.";
         leaf address {
           type inet:ip-address;
           description
             "Адрес для этой ассоциации.";
         }
         leaf type {
           type identityref {
             base unicast-configuration-type;
           }
           description
             "Тип unicast-конфигурации, например, unicast-server";
         }
         container authentication {
           if-feature "authentication";
           description
             "Аутентификация для данной ассоциации.";
           uses authentication;
         }
         leaf prefer {
           type boolean;
           default "false";
           description
             "Является ли ассоциация предпочтительной.";
         }
         leaf burst {
           type boolean;
           default "false";
           description
             "Задаёт отправку серии пакетов вместо одного в каждом
              интервале синхронизации для ускорения синхронизации.";
           reference
             "RFC 5905: Network Time Protocol Version 4: Protocol
              and Algorithms Specification, Section 13.1";
         }
         leaf iburst {
           type boolean;
           default "false";
           description
             "Задаёт отправку серии пакетов вместо одного в каждом
              интервале начальной синхронизации для ускорения 
              начальной синхронизации.";
           reference
             "RFC 5905: Network Time Protocol Version 4: Protocol
              and Algorithms Specification, Section 13.1";
         }
         leaf source {
           type if:interface-ref;
           description
             "Интерфейс, чей адрес IP в этой ассоциации указывает 
              источник.";
         }
         uses common-attributes {
           description
             "Базовые атрибуты, такие как порт, версия, минимальный
              и максимальный интервал опроса.";
         }
       }
       container associations {
         description
           "Параметры ассоциации.";
         list association {
           key "address local-mode isconfigured";
           config false;
           description
             "Список ассоциаций NTP. Требуются поля address, local-mode,
              isconfigured для однозначного указания ассоциации. 

              1) Если RT1 является широковещательным сервером, а RT2 -
                 широковещательным клиентом, RT2 будет создавать 
                 динамическую ассоциацию с address RT1, 
                 local-mode client и isconfigured false.

              2) Если RT2 настроен с unicast-сервером RT1, RT2 будет
                 создавать ассоциацию с address RT1,
                 local-mode client, isconfigured true.

              Все листья служат ключами для указания ассоциации.";
           leaf address {
             type inet:ip-address;
             description
               "Удалённый адрес в этой ассоциации - индивидуальный,
                групповой или широковещательный адрес IP.";
           }
           leaf local-mode {
             type identityref {
               base association-mode;
             }
             description
               "Локальный режим для этой ассоциации NTP.";
           }
           leaf isconfigured {
             type boolean;
             description
               "Указывает, что ассоциация настроена (true) или
                определена динамически (false).";
           }
           leaf stratum {
             type ntp-stratum;
             description
               "Значение stratum для ассоциации.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Section 3";
           }
           leaf refid {
             type refid;
             description
               "Код, указывающий определённый сервер или эталонные часы. 
                Интерпретация зависит от stratum. Это может быть адрес
                IPv4,первые 32 бита хэш-значения MD5, адрес IPv6 или 
                строка для Reference Identifier и kiss-кодов. Например,
                - идентификатор эталонных часов 127.127.1.0 для 
                  локальной синхронизации  
                - индивидуальная, групповая или широковещательная 
                  ассоциация вида 203.0.113.1 в IPv4 и 0x4321FEDC в IPv6
                - синхронизация с первичным источником вида DCN, NIST,
                  ATOM
                - kis-коды имеют вид AUTH, DROP, RATE

                Хэш MD5 для адресов IPv6 не служит для криптографии.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Section 7.3";
           }
           leaf authentication {
             if-feature "authentication";
             type leafref {
               path "/ntp:ntp/ntp:authentication/"
                  + "ntp:authentication-keys/ntp:keyid";
             }
             description
               "Ключ аутентификации, применяемый в этой ассоциации.";
           }
           leaf prefer {
             type boolean;
             default "false";
             description
               "Является ли ассоциация предпочтительной.";
           }
           leaf peer-interface {
             type if:interface-ref;
             description
               "Интерфейс, применяемый для обмена данными.";
           }
           uses common-attributes {
             description
               "Базовые атрибуты, такие как порт, версия, минимальный
                и максимальный интервал опроса.";
           }
           leaf reach {
             type uint8;
             description
               "8-битовый регистр сдвига, отслеживающий генерацию и
                приём пакетов. Служит для определения доступности
                сервера и свежести данных.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Sections 9.2 and 13";
           }
           leaf unreach {
             type uint8;
             units "seconds";
             description
               "Счётчик секунд недоступности сервера, т. е. reach 0.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Sections 9.2 and 13";
           }
           leaf poll {
             type log2seconds;
             description
               "Интервал опроса для ассоциации в форме log2 секунд.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Section 7.3";
           }
           leaf now {
             type uint32;
             units "seconds";
             description
               "Время последнего приёма пакет NTP или синхронизации.";
           }
           leaf offset {
             type decimal64 {
               fraction-digits 3;
             }
             units "milliseconds";
             description
               "Смещение локальный часов от часов партнёра, например, 
                0,032 мсек или 1,232 мсек. Отрицательное значение
                указывает отставание локальных часов.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Section 8";
           }
           leaf delay {
             type decimal64 {
               fraction-digits 3;
             }
             units "milliseconds";
             description
               "Сетевая задержка между локальными часами и часами 
                партнёра.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Section 8";
           }
           leaf dispersion {
             type decimal64 {
               fraction-digits 3;
             }
             units "milliseconds";
             description
               "Корневая дисперсия между локальными часами и часами
                партнёра.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Section 10";
           }
           leaf originate-time {
             type ntp-date-and-time;
             description
               "Локальное время в формате временной метки для момента
                передачи партнёру последнего пакета NTP (T1).";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol and
                Algorithms Specification, Section 8";
           }
           leaf receive-time {
             type ntp-date-and-time;
             description
               "Локальное время в формате временной метки для момента
                доставки партнёру последнего пакета NTP (T2). При 
                недоступности партнёра устанавливается значение 0.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol
                and Algorithms Specification, Section 8";
           }
           leaf transmit-time {
             type ntp-date-and-time;
             description
               "Локальное время в формате временной метки для момента
                отправки партнёром последнего пакета NTP (T3). При 
                недоступности партнёра устанавливается значение 0.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol
                and Algorithms Specification, Section 8";
           }
           leaf input-time {
             type ntp-date-and-time;
             description
               "Локальное время в формате временной метки для момента
                прибытия от пратнера последнего пакета NTP (T4). При 
                недоступности партнёра устанавливается значение 0.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol
                and Algorithms Specification, Section 8";
           }
           container ntp-statistics {
             description
               "Статистика приёма и передачи пакетов для партнёра.";
             uses statistics {
               description
                 "Статистика приёма и передачи пакетов NTP.";
             }
           }
         }
       }
       container interfaces {
         description
           "Параметры конфигурации для интерфейсов NTP.";
         list interface {
           key "name";
           description
             "Список интерфейсов.";
           leaf name {
             type if:interface-ref;
             description
               "Имя интерфейса.";
           }
           container broadcast-server {
             if-feature "broadcast-server";
             presence "Для этого интерфейса настроен широковещательный 
                       сервер NTP.";
             description
               "Конфигурация широковещательного сервера.";
             leaf ttl {
               type uint8;
               description
                 "Срок действия (TTL) для широковещательного пакета.";
               reference
                 "RFC 5905: Network Time Protocol Version 4: Protocol
                  and Algorithms Specification, Section 3.1";
             }
             container authentication {
               if-feature "authentication";
               description
                 "Аутентификация для интерфейса.";
               uses authentication;
             }
             uses common-attributes {
               description
                 "Базовые атрибуты, такие как порт, версия, минимальный
                  и максимальный интервал опроса.";
             }
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol
                and Algorithms Specification, Section 3.1";
           }
           container broadcast-client {
             if-feature "broadcast-client";
             presence "Для этого интерфейса настроен широковещательный 
                       клиент NTP.";
             description
               "Конфигурация широковещательного клиента.";
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol
                and Algorithms Specification, Section 3.1";
           }
           list multicast-server {
             if-feature "multicast-server";
             key "address";
             description
               "Конфигурация группового сервера";
             leaf address {
               type rt-types:ip-multicast-group-address;
               description
                 "IP-адрес для передачи групповых пакетов NTP.";
             }
             leaf ttl {
               type uint8;
               description
                 "TTL для групповых пакетов.";
               reference
                 "RFC 5905: Network Time Protocol Version 4: Protocol
                  and Algorithms Specification, Section 3.1";
             }
             container authentication {
               if-feature "authentication";
               description
                 "Аутентификация для интерфейса.";
               uses authentication;
             }
             uses common-attributes {
               description
                 "Базовые атрибуты, такие как порт, версия, минимальный
                  и максимальный интервал опроса.";
             }
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol
                and Algorithms Specification, Section 3.1";
           }
           list multicast-client {
             if-feature "multicast-client";
             key "address";
             description
               "Конфигурация группового клиента.";
             leaf address {
               type rt-types:ip-multicast-group-address;
               description
                 "IP-адрес группы для присоединения.";
             }
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol
                and Algorithms Specification, Section 3.1";
           }
           list manycast-server {
             if-feature "manycast-server";
             key "address";
             description
               "Конфигурация manycast-сервера.";
             leaf address {
               type rt-types:ip-multicast-group-address;
               description
                 "Групповой адрес IP для приёма клиентских сообщений
                  manycast.";
             }
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol
                and Algorithms Specification, Section 3.1";
           }
           list manycast-client {
             if-feature "manycast-client";
             key "address";
             description
               "Конфигурация manycast-клиента.";
             leaf address {
               type rt-types:ip-multicast-group-address;
               description
                 "Групповой адрес IP, по которому manycast-клиент
                  передаёт запросные сообщения.";
             }
             container authentication {
               if-feature "authentication";
               description
                 "Аутентификация для интерфейса.";
               uses authentication;
             }
             leaf ttl {
               type uint8;
               description
                 "Максимальное значение TTL для расширения
                  циклического поиска.";
               reference
                 "RFC 5905: Network Time Protocol Version 4: Protocol
                  and Algorithms Specification, Section 3.1";
             }
             leaf minclock {
               type uint8;
               description
                 "Минимальное число manycast-оставшихся в ассоциации.";
               reference
                 "RFC 5905: Network Time Protocol Version 4: Protocol
                  and Algorithms Specification, Section 13.2";
             }
             leaf maxclock {
               type uint8;
               description
                 "Максимальное число manycast-кандидатов в ассоциации.";
               reference
                 "RFC 5905: Network Time Protocol Version 4: Protocol
                  and Algorithms Specification, Section 13.2";
             }
             leaf beacon {
               type log2seconds;
               description
                 "Верхний предел интервала опроса. Когда TTL достигает
                  своего предела без обнаружения минимального числа
                  manycast-серверов, интервал опроса увеличивается, пока
                  не достигнет значения beacon, после чего процесс
                  возвращается к началу.";
               reference
                 "RFC 5905: Network Time Protocol Version 4: Protocol
                  and Algorithms Specification, Section 13.2";
             }
             uses common-attributes {
               description
                 "Базовые атрибуты, такие как порт, версия, минимальный
                  и максимальный интервал опроса.";
             }
             reference
               "RFC 5905: Network Time Protocol Version 4: Protocol
                and Algorithms Specification, Section 3.1";
           }
         }
       }
       container ntp-statistics {
         config false;
         description
           "Общая статистика пакетов NTP.";
         uses statistics {
           description
             "Статистика переданных и принятых пакетов NTP.";
         }
       }
     }

     rpc statistics-reset {
       description
         "Сброс собранной статистики.";
       input {
         choice association-or-all {
           description
             "Сброс статистики одной или всех ассоциаций.";
           case association {
             uses association-ref;
             description
               "Сброс всех статистики для ассоциации.";
           }
           case all {
             description
               "Сброс всей собранной статистики.";
           }
         }
       }
     }
   }
   <CODE ENDS>

9. Пример использования

В этом разделе приведены примеры, служащие для иллюстрации. Символ \ в конце строки служит для разделения длинных строк на части [RFC8792].

9.1. Индивидуальная ассоциация

Этот пример описывает настройку предпочтительного unicast-сервера с адресом 192.0.2.1 на порту 1025, ключом аутентификации 10 и версией 4 (принята по умолчанию).

     <edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
       <target>
         <running/>
       </target>
       <config>
         <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
           <unicast-configuration>
             <address>192.0.2.1</address>
             <type>uc-server</type>
             <prefer>true</prefer>
             <port>1025</port>
             <authentication>
               <symmetric-key>
                 <keyid>10</keyid>
               </symmetric-key>
             </authentication>
           </unicast-configuration>
         </ntp>
       </config>
     </edit-config>

В примере для IPv6 в листе address указывается адрес IPv6 (например, 2001:db8::1), а остальное не меняется.

     <edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
       <target>
         <running/>
       </target>
       <config>
         <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
           <unicast-configuration>
             <address>2001:db8::1</address>
             <type>uc-server</type>
             <prefer>true</prefer>
             <port>1025</port>
             <authentication>
               <symmetric-key>
                 <keyid>10</keyid>
               </symmetric-key>
             </authentication>
           </unicast-configuration>
         </ntp>
       </config>
     </edit-config>

Ниже приведён пример извлечения unicast-конфигураций.

   <get>
     <filter type="subtree">
     <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <unicast-configuration>
         </unicast-configuration>
     </ntp>
     </filter>
   </get>

   <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
       <unicast-configuration>
         <address>192.0.2.1</address>
         <type>uc-server</type>
           <authentication>
             <symmetric-key>
               <keyid>10</keyid>
             </symmetric-key>
           </authentication>
         <prefer>true</prefer>
         <burst>false</burst>
         <iburst>true</iburst>
         <source/>
         <minpoll>6</minpoll>
         <maxpoll>10</maxpoll>
         <port>1025</port>
         <stratum>9</stratum>
         <refid>203.0.113.1</refid>
         <reach>255</reach>
         <unreach>0</unreach>
         <poll>128</poll>
         <now>10</now>
         <offset>0.025</offset>
         <delay>0.5</delay>
         <dispersion>0.6</dispersion>
         <originate-time>10-10-2017 07:33:55.253 Z+05:30\
         </originate-time>
         <receive-time>10-10-2017 07:33:55.258 Z+05:30\
         </receive-time>
         <transmit-time>10-10-2017 07:33:55.300 Z+05:30\
         </transmit-time>
         <input-time>10-10-2017 07:33:55.305 Z+05:30\
         </input-time>
         <ntp-statistics>
           <packet-sent>20</packet-sent>
           <packet-sent-fail>0</packet-sent-fail>
           <packet-received>20</packet-received>
           <packet-dropped>0</packet-dropped>
         </ntp-statistics>
       </unicast-configuration>
     </ntp>
   </data>

9.2. Первичные эталонные часы

В этом примере показано, как настроить эталонные часы со stratum 8.

   <edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <target>
       <running/>
     </target>
     <config>
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <refclock-master>
           <master-stratum>8</master-stratum>
         </refclock-master>
       </ntp>
     </config>
   </edit-config>

Следующий пример показывает, как получить конфигурацию эталонных часов.

   <get>
     <filter type="subtree">
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <refclock-master>
         </refclock-master>
       </ntp>
     </filter>
   </get>

   <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
       <refclock-master>
         <master-stratum>8</master-stratum>
       </refclock-master>
     </ntp>
   </data>

9.3. Настройка аутентификации

Этот пример показывает включение проверки подлинности и настройку ддоверенного ключа аутентификации key 10 в режиме AES-CMAC с шестнадчатеричной строкой ключа.

   <edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <target>
       <running/>
     </target>
     <config>
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <authentication>
           <auth-enabled>true</auth-enabled>
           <authentication-keys>
             <keyid>10</keyid>
             <algorithm>aes-cmac</algorithm>
             <key>
               <hexadecimal-string>
                 bb1d6929e95937287fa37d129b756746
               </hexadecimal-string>
             </key>
             <istrusted>true</istrusted>
           </authentication-keys>
         </authentication>
       </ntp>
     </config>
   </edit-config>

9.4. Настройка доступа

Этот пример показывает, как настроить режим peer-access-mode со списком доступа ACL 2000.

   <edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <target>
       <running/>
     </target>
     <config>
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <access-rules>
           <access-rule>
             <access-mode>peer-access-mode</access-mode>
             <acl>2000</acl>
           </access-rule>
         </access-rules>
       </ntp>
     </config>
   </edit-config>

Следующие пример показывает получения конфигурации, связанной с доступом.

   <get>
     <filter type="subtree">
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <access-rules>
         </access-rules>
       </ntp>
     </filter>
   </get>

   <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
       <access-rules>
         <access-rule>
           <access-mode>peer-access-mode</access-mode>
           <acl>2000</acl>
         </access-rule>
       </access-rules>
     </ntp>
   </data>

9.5. Групповая конфигурация

Этот пример описывает настройку группового сервера с адресом 224.0.1.1, портом 1025, версией 3 и ключом аутентификации 10.

   <edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <target>
       <running/>
     </target>
     <config>
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <interfaces>
           <interface>
             <name>Ethernet3/0/0</name>
             <multicast-server>
               <address>224.0.1.1</address>
               <authentication>
                 <symmetric-key>
                   <keyid>10</keyid>
                 </symmetric-key>
               </authentication>
               <port>1025</port>
               <version>3</version>
             </multicast-server>
           </interface>
         </interfaces>
       </ntp>
     </config>
   </edit-config>

Следующий пример иллюстрирует получение конфигурации, связанной с групповым сервером.

   <get>
     <filter type="subtree">
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <interfaces>
           <interface>
             <multicast-server>
             </multicast-server>
           </interface>
         </interfaces>
       </ntp>
     </filter>
   </get>

   <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
       <interfaces>
         <interface>
           <name>Ethernet3/0/0</name>
           <multicast-server>
             <address>224.0.1.1</address>
             <ttl>8</ttl>
             <authentication>
               <symmetric-key>
                 <keyid>10</keyid>
               </symmetric-key>
             </authentication>
             <minpoll>6</minpoll>
             <maxpoll>10</maxpoll>
             <port>1025</port>
             <version>3</version>
           </multicast-server>
         </interface>
       </interfaces>
     </ntp>
   </data>

Ниже приведён пример настройки группового клиента с адресом 224.0.1.1.

   <edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <target>
       <running/>
     </target>
     <config>
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <interfaces>
           <interface>
             <name>Ethernet3/0/0</name>
             <multicast-client>
               <address>224.0.1.1</address>
             </multicast-client>
           </interface>
         </interfaces>
       </ntp>
     </config>
   </edit-config>

Далее показано, как получить связанную с групповым клиентом конфигурацию.

   <get>
     <filter type="subtree">
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <interfaces>
           <interface>
             <multicast-client>
             </multicast-client>
           </interface>
         </interfaces>
       </ntp>
     </filter>
   </get>

   <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
       <interfaces>
         <interface>
           <name>Ethernet3/0/0</name>
           <multicast-client>
             <address>224.0.1.1</address>
           </multicast-client>
         </interface>
       </interfaces>
     </ntp>
   </data>

9.6. Конфигурация manycast

Ниже показана конфигурация manycast-клиента с адресом 224.0.1.1, портом 1025 и ключом аутентификации 10.

   <edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <target>
       <running/>
     </target>
     <config>
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <interfaces>
           <interface>
             <name>Ethernet3/0/0</name>
             <manycast-client>
               <address>224.0.1.1</address>
               <authentication>
                 <symmetric-key>
                   <keyid>10</keyid>
                 </symmetric-key>
               </authentication>
               <port>1025</port>
             </manycast-client>
           </interface>
         </interfaces>
       </ntp>
     </config>
   </edit-config>

Следующий пример иллюстрирует получение конфигурации, связанной с manycast-коиентом.

   <get>
     <filter type="subtree">
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <interfaces>
           <interface>
             <manycast-client>
             </manycast-client>
           </interface>
         </interfaces>
       </ntp>
     </filter>
   </get>

   <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
       <interfaces>
         <interface>
           <name>Ethernet3/0/0</name>
           <manycast-client>
             <address>224.0.1.1</address>
             <authentication>
               <symmetric-key>
                 <keyid>10</keyid>
               </symmetric-key>
             </authentication>
             <ttl>8</ttl>
             <minclock>3</minclock>
             <maxclock>10</maxclock>
             <beacon>6</beacon>
             <minpoll>6</minpoll>
             <maxpoll>10</maxpoll>
             <port>1025</port>
           </manycast-client>
         </interface>
       </interfaces>
     </ntp>
   </data>

Далее показано, как настроить manycast-сервер с адресом 224.0.1.1.

   <edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <target>
       <running/>
     </target>
     <config>
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <interfaces>
           <interface>
             <name>Ethernet3/0/0</name>
             <manycast-server>
               <address>224.0.1.1</address>
             </manycast-server>
           </interface>
         </interfaces>
       </ntp>
     </config>
   </edit-config>

Ниже приведён пример извлечения конфигурации, связанной с manycast-сервером.

   <get>
     <filter type="subtree">
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <interfaces>
           <interface>
             <manycast-server>
             </manycast-server>
           </interface>
         </interfaces>
       </ntp>
     </filter>
   </get>

   <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
       <interfaces>
         <interface>
           <name>Ethernet3/0/0</name>
           <manycast-server>
             <address>224.0.1.1</address>
           </manycast-server>
         </interface>
       </interfaces>
     </ntp>
   </data>

9.7. Состояние часов

Ниже приведён пример получения текущего состояния часов.

   <get>
     <filter type="subtree">
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <clock-state>
         </clock-state>
       </ntp>
     </filter>
   </get>

   <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
       <clock-state>
         <system-status>
           <clock-state>synchronized</clock-state>
           <clock-stratum>7</clock-stratum>
           <clock-refid>192.0.2.1</clock-refid>
           <associations-address>192.0.2.1\
           </associations-address>
           <associations-local-mode>client\
           </associations-local-mode>
           <associations-isconfigured>yes\
           </associations-isconfigured>
           <nominal-freq>100.0</nominal-freq>
           <actual-freq>100.0</actual-freq>
           <clock-precision>18</clock-precision>
           <clock-offset>0.025</clock-offset>
           <root-delay>0.5</root-delay>
           <root-dispersion>0.8</root-dispersion>
           <reference-time>10-10-2017 07:33:55.258 Z+05:30\
           </reference-time>
           <sync-state>clock-synchronized</sync-state>
         </system-status>
       </clock-state>
     </ntp>
   </data>

9.8. Получение всех ассоциаций

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

   <get>
     <filter type="subtree">
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <associations>
         </associations>
       </ntp>
     </filter>
   </get>

   <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
       <associations>
         <association>
           <address>192.0.2.1</address>
           <stratum>9</stratum>
           <refid>203.0.113.1</refid>
           <local-mode>client</local-mode>
           <isconfigured>true</isconfigured>
           <authentication-key>10</authentication-key>
           <prefer>true</prefer>
           <peer-interface>Ethernet3/0/0</peer-interface>
           <minpoll>6</minpoll>
           <maxpoll>10</maxpoll>
           <port>1025</port>
           <version>4</version>
           <reach>255</reach>
           <unreach>0</unreach>
           <poll>128</poll>
           <now>10</now>
           <offset>0.025</offset>
           <delay>0.5</delay>
           <dispersion>0.6</dispersion>
           <originate-time>10-10-2017 07:33:55.253 Z+05:30\
           </originate-time>
           <receive-time>10-10-2017 07:33:55.258 Z+05:30\
           </receive-time>
           <transmit-time>10-10-2017 07:33:55.300 Z+05:30\
           </transmit-time>
           <input-time>10-10-2017 07:33:55.305 Z+05:30\
           </input-time>
           <ntp-statistics>
             <packet-sent>20</packet-sent>
             <packet-sent-fail>0</packet-sent-fail>
             <packet-received>20</packet-received>
             <packet-dropped>0</packet-dropped>
           </ntp-statistics>
         </association>
       </associations>
     </ntp>
   </data>

9.9. Глобальная статистика

Ниже приведён пример извлечения глобальной статистики.

   <get>
     <filter type="subtree">
       <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
         <ntp-statistics>
         </ntp-statistics>
       </ntp>
     </filter>
   </get>

   <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <ntp xmlns="urn:ietf:params:xml:ns:yang:ietf-ntp">
       <ntp-statistics>
         <packet-sent>30</packet-sent>
         <packet-sent-fail>5</packet-sent-fail>
         <packet-received>20</packet-received>
         <packet-dropped>2</packet-dropped>
       </ntp-statistics>
     </ntp>
   </data>

10. Взаимодействие с IANA

10.1. IETF XML Registry

Этот документ регистрирует URI в реестре IETF XML Registry [RFC3688] в формате RFC 3688.

   URI:  urn:ietf:params:xml:ns:yang:ietf-ntp
   Registrant Contact:  The IESG.
   XML:  N/A; запрошенный URI является пространством имён XML.

10.2. YANG Module Names

Этот документ регистрирует модуль YANG в реестре YANG Module Names [RFC6020].

   Name:  ietf-ntp
   Namespace:  urn:ietf:params:xml:ns:yang:ietf-ntp
   Prefix:  ntp
   Reference:  RFC 9249

11. Вопросы безопасности

Заданный этим документом модуль YANG определяет схему для данных, предназначенную для доступа через сеть с использованием протоколов управления, таких как NETCONF [RFC6241] или RESTCONF [RFC8040]. Нижним уровнем NETCONF служит защищённый транспорт с обязательной поддержкой SSH (Secure Shell) [RFC6242]. Нижним уровнем RESTCONF служит протокол HTTPS с обязательной поддержкой защиты на транспортном уровне (TLS) [RFC8446].

Модель доступа к конфигурации сети (NACM – Network Configuration Access Control Model) [RFC8341] обеспечивает возможность разрешить доступ лишь определённых пользователей NETCONF или RESTCONF к заранее заданному подмножеству операций NETCONF или RESTCONF и содержимого.

В этом модуле данных YANG определено множество узлов данных, которые разрешают запись, создание и удаление (т. е. config true, как принято по умолчанию). Эти узлы могут быть конфиденциальными или уязвимыми в некоторых сетевых средах. Запись в такие узлы (например, edit-config) без должной защиты может негативно влиять на работу сети. Ниже перечислены ветви и узлы, которые могут быть конфиденциальны или уязвимы.

/ntp/port

Задаёт номер порта для передачи пакетов NTP. Неожиданная смена может нарушать работу сети.

/ntp/authentication и /ntp/access-rules

Запись конфигураций аутентификации и контроля доступа. Эти параметры следует устанавливать осторожно.

/ntp/unicast-configuration

Записи для всех unicast-конфигураций (режим server или peer), опосредованно создающие или меняющие ассоциации NTP. Неожиданные изменения могут нарушать работу сети.

/ntp/interfaces/interface

Записи для всех конфигураций на уровне интерфейса, относящихся к широковещательному, групповому или индивидуальному режиму, опосредованно создающие или меняющие ассоциации NTP. Неожиданные изменения могут нарушать работу сети. Возможна также синхронизация от недоверенных источников.

Некоторые из доступных для чтения узлов в этом модуле YANG могут быть конфиденциальны или уязвимы в той или иной сетевой среде. Важно контролировать доступ к таким объектам (например, get, get-config, notification). Ниже перечислены ветви и узлы, которые могут быть конфиденциальны или уязвимы.

/ntp/authentication/authentication-keys

Записи списка содержат ключи аутентификации NTP. Несанционированный доступ к ключам может обеспечить доступ к сервису NTP. Ключи конфиденциальны и несанкционированный доступ к ним требуется предотвращать.

/ntp/associations/association/

Этот список содержит все ассоциации NTP во всех режимах. Доступ к этим узлам может раскрывать топологию сети и отношения доверия. Несанкционированный доступ к записям требуется предотвращать.

/ntp/authentication and /ntp/access-rules

Записи этого списка содержат настройки аутентификации и контроля доступа. Доступ к этим узлам может раскрывать топологию сети и отношения доверия.

Некоторые из операций RPC в этом модуле YANG могут быть чувствительны или уязвимы в той или иной сетевой среде. Важно контролировать доступ к таким операциям.

statistics-reset

Этот вызов RPC служит для сброса статистики. Несанкционированный доступ может влиять на мониторинг.

Лист /ntp/authentication/authentication-keys/algorithm может указывать криптографические алгоритмы, которые больше не считаются надёжными. В соответствии с [RFC8573] рекомендуется применять алгоритм AES-CMAC .

12. Литература

12.1. Нормативные документы

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC3688] Mealling, M., «The IETF XML Registry», BCP 81, RFC 3688, DOI 10.17487/RFC3688, January 2004, <https://www.rfc-editor.org/info/rfc3688>.

[RFC5905] Mills, D., Martin, J., Ed., Burbank, J., and W. Kasch, «Network Time Protocol Version 4: Protocol and Algorithms Specification», RFC 5905, DOI 10.17487/RFC5905, June 2010, <https://www.rfc-editor.org/info/rfc5905>.

[RFC6020] Bjorklund, M., Ed., «YANG — A Data Modeling Language for the Network Configuration Protocol (NETCONF)», RFC 6020, DOI 10.17487/RFC6020, October 2010, <https://www.rfc-editor.org/info/rfc6020>.

[RFC6241] Enns, R., Ed., Bjorklund, M., Ed., Schoenwaelder, J., Ed., and A. Bierman, Ed., «Network Configuration Protocol (NETCONF)», RFC 6241, DOI 10.17487/RFC6241, June 2011, <https://www.rfc-editor.org/info/rfc6241>.

[RFC6242] Wasserman, M., «Using the NETCONF Protocol over Secure Shell (SSH)», RFC 6242, DOI 10.17487/RFC6242, June 2011, <https://www.rfc-editor.org/info/rfc6242>.

[RFC6991] Schoenwaelder, J., Ed., «Common YANG Data Types», RFC 6991, DOI 10.17487/RFC6991, July 2013, <https://www.rfc-editor.org/info/rfc6991>.

[RFC7317] Bierman, A. and M. Bjorklund, «A YANG Data Model for System Management», RFC 7317, DOI 10.17487/RFC7317, August 2014, <https://www.rfc-editor.org/info/rfc7317>.

[RFC7950] Bjorklund, M., Ed., «The YANG 1.1 Data Modeling Language», RFC 7950, DOI 10.17487/RFC7950, August 2016, <https://www.rfc-editor.org/info/rfc7950>.

[RFC8040] Bierman, A., Bjorklund, M., and K. Watsen, «RESTCONF Protocol», RFC 8040, DOI 10.17487/RFC8040, January 2017, <https://www.rfc-editor.org/info/rfc8040>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8294] Liu, X., Qu, Y., Lindem, A., Hopps, C., and L. Berger, «Common YANG Data Types for the Routing Area», RFC 8294, DOI 10.17487/RFC8294, December 2017, <https://www.rfc-editor.org/info/rfc8294>.

[RFC8340] Bjorklund, M. and L. Berger, Ed., «YANG Tree Diagrams», BCP 215, RFC 8340, DOI 10.17487/RFC8340, March 2018, <https://www.rfc-editor.org/info/rfc8340>.

[RFC8341] Bierman, A. and M. Bjorklund, «Network Configuration Access Control Model», STD 91, RFC 8341, DOI 10.17487/RFC8341, March 2018, <https://www.rfc-editor.org/info/rfc8341>.

[RFC8343] Bjorklund, M., «A YANG Data Model for Interface Management», RFC 8343, DOI 10.17487/RFC8343, March 2018, <https://www.rfc-editor.org/info/rfc8343>.

[RFC8446] Rescorla, E., «The Transport Layer Security (TLS) Protocol Version 1.3», RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.

[RFC8519] Jethanandani, M., Agarwal, S., Huang, L., and D. Blair, «YANG Data Model for Network Access Control Lists (ACLs)», RFC 8519, DOI 10.17487/RFC8519, March 2019, <https://www.rfc-editor.org/info/rfc8519>.

[RFC8573] Malhotra, A. and S. Goldberg, «Message Authentication Code for the Network Time Protocol», RFC 8573, DOI 10.17487/RFC8573, June 2019, <https://www.rfc-editor.org/info/rfc8573>.

12.2. Дополнительная литература

[RFC1305] Mills, D., «Network Time Protocol (Version 3) Specification, Implementation and Analysis», RFC 1305, DOI 10.17487/RFC1305, March 1992, <https://www.rfc-editor.org/info/rfc1305>.

[RFC1321] Rivest, R., «The MD5 Message-Digest Algorithm», RFC 1321, DOI 10.17487/RFC1321, April 1992, <https://www.rfc-editor.org/info/rfc1321>.

[RFC3174] Eastlake 3rd, D. and P. Jones, «US Secure Hash Algorithm 1 (SHA1)», RFC 3174, DOI 10.17487/RFC3174, September 2001, <https://www.rfc-editor.org/info/rfc3174>.

[RFC4493] Song, JH., Poovendran, R., Lee, J., and T. Iwata, «The AES-CMAC Algorithm», RFC 4493, DOI 10.17487/RFC4493, June 2006, <https://www.rfc-editor.org/info/rfc4493>.

[RFC5907] Gerstung, H., Elliott, C., and B. Haberman, Ed., «Definitions of Managed Objects for Network Time Protocol Version 4 (NTPv4)», RFC 5907, DOI 10.17487/RFC5907, June 2010, <https://www.rfc-editor.org/info/rfc5907>.

[RFC8342] Bjorklund, M., Schoenwaelder, J., Shafer, P., Watsen, K., and R. Wilton, «Network Management Datastore Architecture (NMDA)», RFC 8342, DOI 10.17487/RFC8342, March 2018, <https://www.rfc-editor.org/info/rfc8342>.

[RFC8792] Watsen, K., Auerswald, E., Farrel, A., and Q. Wu, «Handling Long Lines in Content of Internet-Drafts and RFCs», RFC 8792, DOI 10.17487/RFC8792, June 2020, <https://www.rfc-editor.org/info/rfc8792>.

[SHS] National Institute of Standards and Technology (NIST), «Secure Hash Standard (SHS)», DOI 10.6028/NIST.FIPS.180-4, FIPS PUB 180-4, August 2015, <https://doi.org/10.6028/NIST.FIPS.180-4>.

Приложение A. Полное дерево YANG

Полное дерево модели данных YANG ietf-ntp приведено ниже.

   module: ietf-ntp
     +--rw ntp!
        +--rw port?                    inet:port-number {ntp-port}?
        +--rw refclock-master!
        |  +--rw master-stratum?   ntp-stratum
        +--rw authentication {authentication}?
        |  +--rw auth-enabled?          boolean
        |  +--rw authentication-keys* [keyid]
        |     +--rw keyid       uint32
        |     +--rw algorithm?   identityref
        |     +--rw key
        |     |  +--rw (key-string-style)?
        |     |     +--:(keystring)
        |     |     |  +--rw keystring?            string {deprecated}?
        |     |     +--:(hexadecimal) {hex-key-string}?
        |     |        +--rw hexadecimal-string?   yang:hex-string
        |     +--rw istrusted?   boolean
        +--rw access-rules {access-rules}?
        |  +--rw access-rule* [access-mode]
        |     +--rw access-mode    identityref
        |     +--rw acl?           -> /acl:acls/acl/name
        +--ro clock-state
        |  +--ro system-status
        |     +--ro clock-state                  identityref
        |     +--ro clock-stratum                ntp-stratum
        |     +--ro clock-refid                  refid
        |     +--ro associations-address?
        |     |       -> /ntp/associations/association/address
        |     +--ro associations-local-mode?
        |     |       -> /ntp/associations/association/local-mode
        |     +--ro associations-isconfigured?
        |     |       -> /ntp/associations/association/isconfigured
        |     +--ro nominal-freq                 decimal64
        |     +--ro actual-freq                  decimal64
        |     +--ro clock-precision              log2seconds
        |     +--ro clock-offset?                decimal64
        |     +--ro root-delay?                  decimal64
        |     +--ro root-dispersion?             decimal64
        |     +--ro reference-time?              ntp-date-and-time
        |     +--ro sync-state                   identityref
        +--rw unicast-configuration* [address type]
        |       {unicast-configuration}?
        |  +--rw address           inet:ip-address
        |  +--rw type              identityref
        |  +--rw authentication {authentication}?
        |  |  +--rw (authentication-type)?
        |  |     +--:(symmetric-key)
        |  |        +--rw keyid?   leafref
        |  +--rw prefer?           boolean
        |  +--rw burst?            boolean
        |  +--rw iburst?           boolean
        |  +--rw source?           if:interface-ref
        |  +--rw minpoll?          log2seconds
        |  +--rw maxpoll?          log2seconds
        |  +--rw port?             inet:port-number {ntp-port}?
        |  +--rw version?          ntp-version
        +--rw associations
        |  +--ro association* [address local-mode isconfigured]
        |     +--ro address           inet:ip-address
        |     +--ro local-mode        identityref
        |     +--ro isconfigured      boolean
        |     +--ro stratum?          ntp-stratum
        |     +--ro refid?            refid
        |     +--ro authentication?
        |     |       -> /ntp/authentication/authentication-keys/keyid
        |     |       {authentication}?
        |     +--ro prefer?           boolean
        |     +--ro peer-interface?   if:interface-ref
        |     +--ro minpoll?          log2seconds
        |     +--ro maxpoll?          log2seconds
        |     +--ro port?             inet:port-number {ntp-port}?
        |     +--ro version?          ntp-version
        |     +--ro reach?            uint8
        |     +--ro unreach?          uint8
        |     +--ro poll?             log2seconds
        |     +--ro now?              uint32
        |     +--ro offset?           decimal64
        |     +--ro delay?            decimal64
        |     +--ro dispersion?       decimal64
        |     +--ro originate-time?   ntp-date-and-time
        |     +--ro receive-time?     ntp-date-and-time
        |     +--ro transmit-time?    ntp-date-and-time
        |     +--ro input-time?       ntp-date-and-time
        |     +--ro ntp-statistics
        |        +--ro discontinuity-time?   ntp-date-and-time
        |        +--ro packet-sent?          yang:counter32
        |        +--ro packet-sent-fail?     yang:counter32
        |        +--ro packet-received?      yang:counter32
        |        +--ro packet-dropped?       yang:counter32
        +--rw interfaces
        |  +--rw interface* [name]
        |     +--rw name                if:interface-ref
        |     +--rw broadcast-server! {broadcast-server}?
        |     |  +--rw ttl?              uint8
        |     |  +--rw authentication {authentication}?
        |     |  |  +--rw (authentication-type)?
        |     |  |     +--:(symmetric-key)
        |     |  |        +--rw keyid?   leafref
        |     |  +--rw minpoll?          log2seconds
        |     |  +--rw maxpoll?          log2seconds
        |     |  +--rw port?             inet:port-number {ntp-port}?
        |     |  +--rw version?          ntp-version
        |     +--rw broadcast-client! {broadcast-client}?
        |     +--rw multicast-server* [address] {multicast-server}?
        |     |  +--rw address
        |     |  |       rt-types:ip-multicast-group-address
        |     |  +--rw ttl?              uint8
        |     |  +--rw authentication {authentication}?
        |     |  |  +--rw (authentication-type)?
        |     |  |     +--:(symmetric-key)
        |     |  |        +--rw keyid?   leafref
        |     |  +--rw minpoll?          log2seconds
        |     |  +--rw maxpoll?          log2seconds
        |     |  +--rw port?             inet:port-number {ntp-port}?
        |     |  +--rw version?          ntp-version
        |     +--rw multicast-client* [address] {multicast-client}?
        |     |  +--rw address    rt-types:ip-multicast-group-address
        |     +--rw manycast-server* [address] {manycast-server}?
        |     |  +--rw address    rt-types:ip-multicast-group-address
        |     +--rw manycast-client* [address] {manycast-client}?
        |        +--rw address
        |        |       rt-types:ip-multicast-group-address
        |        +--rw authentication {authentication}?
        |        |  +--rw (authentication-type)?
        |        |     +--:(symmetric-key)
        |        |        +--rw keyid?   leafref
        |        +--rw ttl?              uint8
        |        +--rw minclock?         uint8
        |        +--rw maxclock?         uint8
        |        +--rw beacon?           log2seconds
        |        +--rw minpoll?          log2seconds
        |        +--rw maxpoll?          log2seconds
        |        +--rw port?             inet:port-number {ntp-port}?
        |        +--rw version?          ntp-version
        +--ro ntp-statistics
           +--ro discontinuity-time?   ntp-date-and-time
           +--ro packet-sent?          yang:counter32
           +--ro packet-sent-fail?     yang:counter32
           +--ro packet-received?      yang:counter32
           +--ro packet-dropped?       yang:counter32

     rpcs:
       +---x statistics-reset
          +---w input
             +---w (association-or-all)?
                +--:(association)
                |  +---w associations-address?
                |  |       -> /ntp/associations/association/address
                |  +---w associations-local-mode?
                |  |       -> /ntp/associations/association/local-mode
                |  +---w associations-isconfigured?
                |          -> /ntp/associations/association/isconfigured
                +--:(all)

Благодарности

Авторы признательны Sladjana Zoric, Danny Mayer, Harlan Stenn, Ulrich Windl, Miroslav Lichvar, Maurice Angermann, Watson Ladd, Rich Salz за их рецензии и предложения.

Спасибо Andy Bierman за рецензию YANG doctor.

Спасибо Dieter Sibold за выполнение функций Document Shepherd и Erik Kline — за Responsible AD.

Спасибо Takeshi Takahashi за рецензию SECDIR, Tim Evens — за рецензию GENART.

Особая благодарность Tom Petch за очень подробную рецензию YANG и множество предложений и улучшений.

Спасибо за рецензию IESG от Benjamin Kaduk, Francesca Palombini, Eric Vyncke, Murray Kucherawy, Robert Wilton, Roman Danyliw, Zaheduzzaman Sarker.

Адреса авторов

Nan Wu
Huawei
Huawei Bld., No.156 Beiqing Rd.
Beijing
100095
China
Email: eric.wu@huawei.com
 
Dhruv Dhody (editor)
Huawei
Divyashree Techno Park, Whitefield
Bangalore 560066
Kanataka
India
Email: dhruv.ietf@gmail.com
 
Ankit Kumar Sinha (editor)
RtBrick Inc.
Bangalore
Kanataka
India
Email: ankit.ietf@gmail.com
 
Anil Kumar S N
RtBrick Inc.
Bangalore
Kanataka
India
Email: anil.ietf@gmail.com
 
Yi Zhao
Ericsson
China Digital Kingdom Bld., No.1 WangJing North Rd.
Beijing
100102
China
Email: yi.z.zhao@ericsson.com

Перевод на русский язык

Николай Малых

nmalykh@protokols.ru

1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

Рубрика: RFC | Оставить комментарий

RFC 9257 Guidance for External Pre-Shared Key (PSK) Usage in TLS

Internet Engineering Task Force (IETF)                        R. Housley
Request for Comments: 9257                                Vigil Security
Category: Informational                                       J. Hoyland
ISSN: 2070-1721                                          Cloudflare Ltd.
                                                                M. Sethi
                                                        Aalto University
                                                              C. A. Wood
                                                              Cloudflare
                                                               July 2022

Guidance for External Pre-Shared Key (PSK) Usage in TLS

Рекомендации по применению внешних PSK в TLS

PDF

Аннотация

В этом документе приведены рекомендации по использованию внешних, заранее распределенных ключей (Pre-Shared Key или PSK) в защите транспортного уровня (Transport Layer Security или TLS) версии 1.3, определённой в RFC 8446. Указаны свойства защиты TLS, обеспечиваемые PSK с некоторыми допущениями, и показано, как нарушение этих предположений ведёт к атакам. Даны рекомендации для приложений, помогающие соблюсти эти допущенияю В документе также обсуждаются примеры использования PSK и процессы предоставления, а также указаны свойства защиты и приватности, которые не обеспечиваются TLS 1.3 при использовании внешних PSK.

Статус документа

Документ не относится к категории Internet Standards Track и публикуется лишь для информации.

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG2. Не все одобренные IESG документы являются кандидатами в Internet Standard, см раздел 2 RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке https://www.rfc-editor.org/info/rfc9257.

Авторские права

Авторские права (Copyright (c) 2022) принадлежат IETF Trust и лицам, указанным в качестве авторов документа. Все права защищены.

К документу применимы права и ограничения, указанные в BCP 78 и IETF Trust Legal Provisions и относящиеся к документам IETF (http://trustee.ietf.org/license-info), на момент публикации данного документа. Прочтите упомянутые документы внимательно. Фрагменты программного кода, включённые в этот документ, распространяются в соответствии с упрощённой лицензией BSD, как указано в параграфе 4.e документа IETF Trust Legal Provisions, без каких-либо гарантий (как указано в Simplified BSD License).

1. Введение

В этом документе представлены рекомендации по использованию внешних ключей PSK в TLS 1.3 [RFC8446], применимые также к протоколам Datagram TLS (DTLS) 1.3 [RFC9147] и Compact TLS 1.3 [CTLS]. Для удобочитаемости все они обозначаются в документе как TLS.

Внешние PSK являются симметричными секретными ключами, предоставляемыми реализации протокола TLS извне. Внешние PSK обеспечиваются не через сеть (по внешнему каналу — out of band).

Документ перечисляет защитные свойства TLS, обеспечиваемые PSK при некоторых допущениях, и показывает, как нарушение этих предположений ведёт к атакам. В документе рассматриваются примеры использования PSK, процессы представления и поддержка реализации стека TLS в контексте этих допущений. Документ также предлагает варианты применения, способствующие соблюдению этих допущений.

Имеется много ресурсов с рекомендациями по созданию и проверке паролей в целях повышения защищенности. Однако эквивалентных документов для внешних PSK в TLS нет и здесь этот пробел заполняется.

2. Уровни требований

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не нужно (SHALL NOT), следует (SHOULD), не следует (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе должны интерпретироваться в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

3. Обозначения

В этом документе логическим узлом (logical node) считается вычислительная сущность (computing presence), с которой другие стороны могут взаимодействовать по протоколу TLS. Логический узел может быть реализован в форме нескольких физических экземпляров (объектов) с единым административным управлением, например, серверной фермы. Конечной точкой (endpoint) называется клиент или сервер, участвующий в соединении.

4. Свойства безопасности PSK

Использование заранее созданных PSK позволяет узлам TLS проверить подлинность отождествлений конечных точек, а также обеспечивает другие преимущества, такие как устойчивость к атакам в присутствии квантовых компьютеров (см. параграф 4.2). Однако эти ключи не обеспечивают защиту приватности (конфиденциальности) отождествлений конечных точек и неотказуемость (одна из точек соединения может отвергнуть диалог), как отмечено в разделе 7.

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

4.1. Совместное использование PSK

Как обсуждается в параграфе 5.1 для демонстрации атаки, [AASS19] описывает сценарии, где один ключ PSK используется множеством клиентов и множеством серверов. Если по наивности общий ключ предоставлен всем членам группы, TLS проверяет лишь принадлежность к группе и безопасность системы в целом становится достаточно слабой. Здесь имеется ряд указанных ниже недостатков.

  1. Любой член группы может выдать себя за другого члена этой группы.

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

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

Кроме того, не входящий в группу злоумышленник может перенаправить согласование между действительными членами группы для их соединения непредусмотренным способом, как описано ниже. Отметим, что возможно частичное смягчение этого класса атак — каждый член группы включает расширение для индикации имени сервера (Server Name Indication или SNI) [RFC6066] и прерывает соединение при насовпадении представленного SNI с известным идентификатором принимающей стороны. Подробности этого представлены в [Selfie].

Для иллюстрации атак с перенаправлением рассмотрим трёх парнтеров (A, B, C), знающих общий ключ PSK. Атака модет иметь вид, представленный ниже.

  1. A передаёт ClientHello для B.

  2. Атакующий перехватывает сообщение и перенаправляет его C.

  3. C отвечает (ServerHello, …) узлу A.

  4. A передаёт сообщение для B, завершая согласования якабы с B.

  5. Злоумышленник перенаправляет сообщение Finished узлу to C, что завершает его согласование с A.

В этой атаке проверки подлинности партнёра не происходит. Если C поддерживает более слабый набор шифров, чем B, возможны атаки на снижение (ослабление) криптографического алгоритма. Такое перенаправление является атакой с нарушением привязки отождествления [Krawczyk] [Sethi]. Атака Selfie [Selfie] является особым случаем атаки с перенаправлением против члена группы, который может выступать клиентом и сервером TLS. В этой атаке злоумышленник, не входящий в группу, перенаправляет соединение от клиента к серверу на той же конечной точке.

В дополнение к отмеченным недостаткам общий для узлов ключ PSK может негативно влиять на развёртывание. Например, отзыв отдельных элементов группы становится невозможным без создания нового PSK для оставшихся.

4.2. Энтропия PSK

Свойства энтропии внешних PSK также могут влиять на защитные свойства TLS. Например, при использовании PSK с высокой энтропией режимы организации только ключей PSK обеспечивают ожидаемые защитные свойства TLS, включая организацию одного сеансового ключа между партнёрами, секретность сеансовых ключей, проверку подлинности партнёров и защиту от снижения версии. Разъяснение этих свойств дано в приложении E.1 к [RFC8446]. Однако этим режимам не достает полной защиты (forward security), которая может быть достигнута при использовании режима PSK-DH или краткосрочных PSK.

При использовании PSK с малой энтропией режимы организации только ключей PSK подвержены пассивным атакам с исчерпывающим поиском, которые раскрывают ключи трафика. режимы PSK-DH подвержены активным атакам, в которых злоумышленник выдаёт себя за одну сторону. Фаза исчерпывающего поиска в этих атаках может быть организована в автономном режиме (offline) если атакующий перехватывает одно согласование с применением PSK, но такие атаки не ведут к раскрытию ключей трафика для данного соединения, поскольку ключи зависят также от обмена Диффи-Хеллмана (Diffie-Hellman или DH). Ключи с малой энтропией защизены от активных атак, если с TLS применяется обмен ключами с парольной аутентификацией (Password-Authenticated Key Exchange или PAKE). На момент написания этого документа исследовательская группа Crypto Forum (Crypto Forum Research Group илиCFRG) занималась подготовкой спецификации, рекомендуемых PAKE ([CPACE], [OPAQUE]) для симметричных и асимметричных ключей.

5. Внешние PSK на практике

Шифры PSK были впервые заданы для TLS в 2005 г. Сейчас PSK являются частью спецификации TLS 1.3 [RFC8446]. TLS 1.3 также использует PSK для восстановления сессий. Применяемые для восстановления PSK отличаются от внешних PSK, которые представляются по отдельному каналу (out of band0. В этой спецификации описаны известные варианты применения и процессы представляния для внешних PSK в TLS.

5.1. Примеры использования

В этом параграфе даны некоторые варианты применения, где парные внешние ключи PSK (внешние PSK, совместно применяемые одним клиентом и одним сервером) применяются для аутентификации в TLS. Порядок примеров не отражает каких-либо приоритетов.

Взаимодействие между устройствами с синхронизацией ключей по отдельному каналу

PSK предоставляются по отдельному каналу (out of band) для взаимодействия с известными отождествлениями, при этом отождествление раскрывается через другой online-протокол.

Коммуникации внутри ЦОД

Межмашинное взаимодействие в одном центре обработки данных (ЦОД) или точке присутствия (Point of Presence или PoP) может использовать представленные извне PSK. Это применяется в основном для поддержки соединений TLS с упреждающими данными (early data). Соображения об использовании упреждающих данных с внешними PSK представлены в разделе 8.

Межсерверное взаимодействие без сертификатов

При межмашинном взаимодействии могут применяться предоставленные извне PSK. Это служит в основном для организации соединений TLS без издержек на предоставление и поддержку сертификатов PKI.

Интернет вещей (IoT) и устройства с ограниченными вычислительными возможностями

[RFC7925] задаёт профили TLS и DTLS для устройств с ограниченными ресурсами и предлагает применять шифры PSK для совместимых устройств. Спецификация LwM2M (Open Mobile Alliance Lightweight Machine-to-Machine) [LwM2M] указывает, что серверы LwM2M должны поддерживать режим PSK для DTLS.

Защита RADIUS [RFC2865] с помощью TLS

Шифры PSK не обязательны для этого случая, как указано в [RFC6614].

Аутентификация между пользователем и сервером 3GPP

Базовая архитектура аутентификации (Generic Authentication Architecture или GAA), заданная в 3GPP, указывает, что шифры TLS PSK можно применять между сервером и оборудованием пользователя для аутентификации [GAA].

Смарт-карты

Немецкие карты электронной идентификации (German electronic Identity или eID) поддерживают аутентификацию держателя карты в online-службах на основе TLS PSK [SmartCard].

Квантовая устойчивость

В некоторых развёртывания могут применяться PSK (или их комбинация с аутентификацией на основе сертификатов, как описано в [RFC8773]), благодаря предоставляемой защите от квантовых компьютеров.

Имеются также случаи применения PSK, известных более чем двум объектам. Некоторые примеры приведены ниже (отмечены Ахметзяновой и др. В [AASS19]):

Групповые чаты

В этом случае участникам группы могут быть предоставлены внешние PSK по отдельному каналу (out of band) для организации аутентифицированных соединений с другими членами группы.

IoT и устройства с ограниченными вычислительными возможностями

В этом случае возможно много вариантов представления PSK. Например, а данной системе все устройства IoT могут иметь общий ключ PSK и применять его для взаимодействия с центральным сервером (один ключ на n устройств), иметь свои ключи для взаимодействия с центральным сервером (n ключей на n устройств) или иметь парные ключи для вазаимодействия каждого с каждым (n2 ключей на n устройств).

5.2. Примеры представления

Процесс представления зависит от системных требований и модели угроз. По возможности не следует совместно использовать PSK на узлах, однако иногда этого не избежать. В таких случаях следует использовать рекомендации, приведённые в разделе 6. Ниже приведены примеры процессов представления PSK.

  • Многие промышленные протоколы предполагают, что PSK распределяются и назначаются вручную путём (1) прямого ввода PSK в устройство или (2) использования доверенного при первом применении (trust-on-first-use или TOFU) подхода, когда устройство совсем не защищено до первого входа в систему (login). Многие устройства имеют очень ограниченный пользовательский интерфейс (UI). Например, у них может быть лишь цифровая клавиатура или просто несколько кнопок. Когда подход TOFU не подходит, ключ придётся вводить через ограниченный интерфейс UI.

  • Некоторые устройства представляют PSK по особому (out-of-band) протоколу синхронизации на базе облака.

  • Некоторые секреты могут быть встроены в аппаратные или программные компоненты устройства. Если это делается во время производства, секреты могут указываться на этикетке или включаться в спецификацию (Bill of Materials) для упрощения сканирования или импорта.

5.3. Ограничения при представлении

Системы представления PSK часто ограничены в зависимости от применения. Например, хотя одной из целей представления является обеспечение уникальности каждой пары ключей, некоторые системы не хотят распространять парные общие ключи для достижения этого. Другим примером служит требование некоторых систем встраивать в процессе представления зависимую от приложения информацию в PSK или иные отождествления. Для отождествлений иногда может требоваться маршрутизация, что в настоящее время обсуждается [EAP-TLS-PSK].

6. Рекомендации по использованию внешних PSK

  1. При выводе каждого PSK следует обеспечивать хотя бы 128 битов энтропии, ключ должен быть не короче 128 битов и его следует комбинировать с обменом эфемерными ключами, например, с использованием psk_dhe_ke (Pre-Shared Key Exchange Mode) в TLS 1.3 для полной защиты. Как обсуждалось в разделе 4, PSK с низкой энтропией (т. е. выведенные с использованием менее 128 битов энтропии) подвержены атакам и их следует избегать. Если доступны лишь ключи с малой энтропией, следует применять механизмы организации ключей вроде PAKE, которые могут снизить риск offline-атак по словарю. Отметим, что такие механизмы ещё не стандартизованы и не обязательно будут следовать той же архитектуре, что и процесс встраивания внешних ключей PSK, описанный в [RFC9258].

  2. Если не принято иных мер по снижению риска для PSK, известных группе, использование каждого PSK должно ограничиваться не более чем двумя логическими узлами, один из которых играет роль сервера, другой — роль клиента TLS (логические узлы могут совпадать в разных ролях). В [RFC9258] описаны две меры снижения риска: (1) обмен идентификаторами клиента и сервера через соединение TLS после согласования и (2) встраивание идентификаторов клиента и сервера в строку контекста для импортёра внешнего PSK.

  3. Узлам следует импользовать импортёров внешних PSK [RFC9258] при настройке PSK для пары клиент-сервер, когда это возможно. Импортёры упрощают представление внешних PSK и делают их меньше подверженными ошибкам, выводя уникальный импортируемый PSK из внешнего PSK для каждой поддерживаемом узлом функции вывода ключей (см. раздел «Вопросы безопасности» в [RFC9258]).

  4. По возможности основной ключ PSK (передаваемый импортёру) следует удалять после генерации импортируемых ключей. Это не позволит злоумышленнику использовать компрометацию одного узла для атак на соединения между любыми узлами. Иначе атакующий сможет восстановить основной ключ и снова запустить импортёр.

6.1. Интерфейс стека

Большинство основных реализаций TLS поддерживает внешние PSK. Стеки с поддержкой внешних PSK предоставляют интерфейс, который приложения могут использовать при настройке PSK для отдельных соединений. Детали некоторых имеющихся на момент написания документа стеков приведены ниже.

OpenSSL и BoringSSL

Приложения могут указать поддержку внешних PSK через отдельные шифры в TLS 1.2 и ниже. Они также могут настроить обратные вызовы (callback) для выбора PSK при согласовании. Эти вызовы должны обеспечивать ключ и отождествление PSK. Точный формат обратного вызова зависит от согласованной версии протокола TLS, новые функции обратного вызова специально добавлены в OpenSSL для TLS 1.3 [RFC8446] с поддержкой PSK. Размер PSK проверяется на диапазон 1-256 байтов (включительно), отождествление может иметь размер до 128 байтов.

mbedTLS

Клиентские приложения настраивают PSK до создания соединения путём предоставления встроенного отождествления и значения PSK. Серверы должны реализовать обратные вызовы как в OpenSSL. Отождествление и ключ PSK могут иметь размер от 1 до 16 байтов (включительно).

gnuTLS

Приложения настраивают PSK как необработанные (raw) строки байтов или шестнадцатеричные строки. Отождествление и ключ PSK не проверяются.

wolfSSL

Приложения настраивают PSK с обратными вызовами, подобно OpenSSL.

6.1.1. Кодирование и сравнение отождествлений PSK

Параграф 5.1 в [RFC4279] указывает, чтобы отождествление PSK сначала следует преобразовать в строку символов, а затем кодировать в октеты с применением UTF-8. Это делается для предотвращения проблем совместимости (особено при понятных человеку отождествлениях). С другой стороны, [RFC7925] рекомендует реализациям не применять структурированные форматы для отождествлений PSK и выполнять побайтовое сравнение при любых операциях. При ручной настройке отождествлений PSK важно помнить, что визуально идентичные строки могут отличаться кодировкой.

TLS 1.3 [RFC8446] следует той же практике задания отождествлений PSK последовательностью не обрабатываемых байтов (opaque identity<1..216-1> в спецификации), которые сравниваются побайтово. [RFC8446] требует отождествлений PSK не короче 1 1 и не длиннее 65535 байтов. Хотя [RFC8446] не задаёт строгих требований к формату отождествлений, этот формат может быть разным в зависимости от развёртывания, как указано ниже.

  • Отождествление PSK может быть задаваемой пользователем строкой при использовании с такими протоколами как EAP (Extensible Authentication Protocol) [RFC3748]. Например, gnuTLS считает отождествления PSK именами пользователей.

  • Отождествления PSK могут включать суффикс доменного имени для роуминга и объединения. В приложениях и установках, где суффикс домена считается конфиденциальным, такая практика не рекомендуется.

  • При развёртывании следует озаботиться, чтобы размер отождествления позволял предотвратить конфликты.

6.1.2. Конфликты отождествлений PSK

Возможны, хоть и маловероятны, конфликты отождествлений внеших PSK с отождествлениями PSK возобновления. Реализация стека TLS и последовательность обратных вызовов влияют на поведение приложений в случае конфликта. При получении сервером отождествления PSK в TLS 1.3 ClientHello, некоторые стеки TLS выполняют зарегистрированный приложением обратный вызов до проверки кэша возобновления сессий в стеке. Это значит, что при конфликте отождествлений использование внешнего PSK обычно становится предпочтительней восстановления. Поскольку отождествления PSK для восстановления задаёт реализация стека TLS, рекомендуется выделять эти значения так, чтобы можно было отличить PSK возобновления от внешних PSK во избежание конфликтов.

7. Вопросы приватности

Свойства конфиденциальности PSK ортогональны свойствам безопасности, описанным в разделе 4. TLS мало заботится о приватности отождествлений PSK. Например, получает сведения о внешнем PSK или его отождествлении за счёт того, что отождествление открыто передаётся в ClientHello. В результате пассивный противник может связать несколько соединений, использующих один внешний PSK в линии. В зависимости от отождествления PSK пассивный атакующий может также идентифицировать устройство, персону или предприятие, использующее клиент или сервер TLS. Активный злоумышленник может также применить отождествление PSK для помех согласованию или данным приложения от конкретного устройства путём блокировки, задержки или ограничения скорости трафика. Методы снижения таких рисков требуют дополнительного анализа и выходят за рамки документа. Кроме сопоставления устройств в сети внешние PSK по своей природе связаны получателями PSK. В частности, сервер может связывать друг с другом последовательные соединения с одним внешним PSK. Предотвращение этого выходит за рамки документа.

8. Вопросы безопасности

Этот документ посвящён вопросам безопасности. Следует повторить, что имеются опасения, связанные с применением внешних PSK в части подобающей идентификации конечных точек TLS 1.3 и дополнительных рисков при известности внешних PSK группе узлов.

Не рекомендуется применять один ключ PSK более чем на одном клиенте и одном сервере. Однако, как отмечено в параграфе 5.1, имеются приложения, опирающиеся на использование одного PSK множеством узлов. [RFC9258] помогает смягчить перенаправление и отражение в стиле Selfie при использовании одного PSK на множестве узлов. Это достигается корректным применением идентификаторов узлов в конструкции ImportedIdentity.context [RFC9258]. Одним из решений служит выбор каждой конечной точкой одного глобально уникального идентификатора для всех согласования PSK. Таким идентификатором может служить, например, один из MAC-адресов (Media Access Control) точки, 32-битовое случайное значение или UUID (Universally Unique IDentifier) [RFC4122]. Отметим, что такие почтоянные идентификаторы влияют на приватность (см. раздел 7). Каждой конечной точке следует знать идентификатор точки, с которой нужно соединиться и следует сравнивать его с идентификатором из ImportedIdentity.context. Важно помнить, что конечные точки с одним групповым PSK могут представляться друг другом.

Соображения по использованию внешних PSK не ограничиваются верной идентификацией. При использовании упреждающих данных с внешним PSK случайное значение в ClientHello является единственным источником энтропии, способствующим смене ключей между сессиями. В результате при неоднократном применении внешнего PSK источник случайных значений у клиента играет важную роль в защите упреждающих данных.

9. Взаимодействие с IANA

Этот документ не требует действий IANA.

10. Литература

10.1. Нормативные документы

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8446] Rescorla, E., «The Transport Layer Security (TLS) Protocol Version 1.3», RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.

[RFC9258] Benjamin, D. and C. A. Wood, «Importing External Pre-Shared Keys (PSKs) for TLS 1.3», RFC 9258, DOI 10.17487/RFC9258, July 2022, <https://www.rfc-editor.org/info/rfc9258>.

10.2. Дополнительная литература

[AASS19] Akhmetzyanova, L., Alekseev, E., Smyshlyaeva, E., and A. Sokolov, «Continuing to reflect on TLS 1.3 with external PSK», April 2019, <https://eprint.iacr.org/2019/421.pdf>.

[CPACE] Abdalla, M., Haase, B., and J. Hesse, «CPace, a balanced composable PAKE», Work in Progress, Internet-Draft, draft-irtf-cfrg-cpace-06, 24 July 2022, <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-cpace-06>.

[CTLS] Rescorla, E., Barnes, R., Tschofenig, H., and B. M. Schwartz, «Compact TLS 1.3», Work in Progress, Internet-Draft, draft-ietf-tls-ctls-06, 9 July 2022, <https://datatracker.ietf.org/doc/html/draft-ietf-tls-ctls-06>.

[EAP-TLS-PSK] Mattsson, J. P., Sethi, M., Aura, T., and O. Friel, «EAP-TLS with PSK Authentication (EAP-TLS-PSK)», Work in Progress, Internet-Draft, draft-mattsson-emu-eap-tls-psk-00, 9 March 2020, <https://datatracker.ietf.org/doc/html/draft-mattsson-emu-eap-tls-psk-00>.

[GAA] ETSI, «Digital cellular telecommunications system (Phase 2+); Universal Mobile Telecommunications System (UMTS); LTE; 3G Security; Generic Authentication Architecture (GAA); System description», version 12.0.0, ETSI TR 133 919, October 2014, <https://www.etsi.org/deliver/etsi_tr/133900_133999/133919/12.00.00_60/tr_133919v120000p.pdf>.

[Krawczyk] Krawczyk, H., «SIGMA: The ‘SIGn-and-MAc’ Approach to Authenticated Diffie-Hellman and Its Use in the IKE Protocols», DOI 10.1007/978-3-540-45146-4_24, 2003, <https://link.springer.com/content/pdf/10.1007/978-3-540-45146-4_24.pdf>.

[LwM2M] Open Mobile Alliance, «Lightweight Machine to Machine Technical Specification», version 1.0, February 2017, <http://www.openmobilealliance.org/release/LightweightM2M/V1_0-20170208-A/OMA-TS-LightweightM2M-V1_0-20170208-A.pdf>.

[OPAQUE] Bourdrez, D., Krawczyk, H., Lewi, K., and C. A. Wood, «The OPAQUE Asymmetric PAKE Protocol», Work in Progress, Internet-Draft, draft-irtf-cfrg-opaque-09, 6 July 2022, <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-opaque-09>.

[RFC2865] Rigney, C., Willens, S., Rubens, A., and W. Simpson, «Remote Authentication Dial In User Service (RADIUS)», RFC 2865, DOI 10.17487/RFC2865, June 2000, <https://www.rfc-editor.org/info/rfc2865>.

[RFC3748] Aboba, B., Blunk, L., Vollbrecht, J., Carlson, J., and H. Levkowetz, Ed., «Extensible Authentication Protocol (EAP)», RFC 3748, DOI 10.17487/RFC3748, June 2004, <https://www.rfc-editor.org/info/rfc3748>.

[RFC4122] Leach, P., Mealling, M., and R. Salz, «A Universally Unique IDentifier (UUID) URN Namespace», RFC 4122, DOI 10.17487/RFC4122, July 2005, <https://www.rfc-editor.org/info/rfc4122>.

[RFC4279] Eronen, P., Ed. and H. Tschofenig, Ed., «Pre-Shared Key Ciphersuites for Transport Layer Security (TLS)», RFC 4279, DOI 10.17487/RFC4279, December 2005, <https://www.rfc-editor.org/info/rfc4279>.

[RFC6066] Eastlake 3rd, D., «Transport Layer Security (TLS) Extensions: Extension Definitions», RFC 6066, DOI 10.17487/RFC6066, January 2011, <https://www.rfc-editor.org/info/rfc6066>.

[RFC6614] Winter, S., McCauley, M., Venaas, S., and K. Wierenga, «Transport Layer Security (TLS) Encryption for RADIUS», RFC 6614, DOI 10.17487/RFC6614, May 2012, <https://www.rfc-editor.org/info/rfc6614>.

[RFC7925] Tschofenig, H., Ed. and T. Fossati, «Transport Layer Security (TLS) / Datagram Transport Layer Security (DTLS) Profiles for the Internet of Things», RFC 7925, DOI 10.17487/RFC7925, July 2016, <https://www.rfc-editor.org/info/rfc7925>.

[RFC8773] Housley, R., «TLS 1.3 Extension for Certificate-Based Authentication with an External Pre-Shared Key», RFC 8773, DOI 10.17487/RFC8773, March 2020, <https://www.rfc-editor.org/info/rfc8773>.

[RFC9147] Rescorla, E., Tschofenig, H., and N. Modadugu, «The Datagram Transport Layer Security (DTLS) Protocol Version 1.3», RFC 9147, DOI 10.17487/RFC9147, April 2022, <https://www.rfc-editor.org/info/rfc9147>.

[Selfie] Drucker, N. and S. Gueron, «Selfie: reflections on TLS 1.3 with PSK», DOI 10.1007/s00145-021-09387-y, May 2021, <https://eprint.iacr.org/2019/347.pdf>.

[Sethi] Sethi, M., Peltonen, A., and T. Aura, «Misbinding Attacks on Secure Device Pairing and Bootstrapping», DOI 10.1145/3321705.3329813, May 2019, <https://arxiv.org/pdf/1902.07550>.

[SmartCard] Bundesamt für Sicherheit in der Informationstechnik, «Technical Guideline TR-03112-7 eCard-API-Framework — Protocols», version 1.1.5, April 2015, <https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/TechnischeRichtlinien/TR03112/TR-03112-api_teil7.pdf?__blob=publicationFile&v=1>.

Благодарности

Этот документ является результатом работы TLS External PSK Design Team, включающей Benjamin Beurdouche, Björn Haase, Christopher Wood, Colm MacCarthaigh, Eric Rescorla, Jonathan Hoyland, Martin Thomson, Mohamad Badra, Mohit Sethi, Oleg Pekar, Owen Friel, Russ Housley.

Документ был улучшен, благодаря высококачественным рецензиям Ben Kaduk и John Preuß Mattsson.

Адреса авторов

Russ Housley
Vigil Security, LLC
Email: housley@vigilsec.com
 
Jonathan Hoyland
Cloudflare Ltd.
Email: jonathan.hoyland@gmail.com
 
Mohit Sethi
Aalto University
Email: mohit@iki.fi
 
Christopher A. Wood
Cloudflare
Email: caw@heapingbits.net

Перевод на русский язык

Николай Малых

nmalykh@protokols.ru


1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

Рубрика: RFC | Оставить комментарий

RFC 9258 Importing External Pre-Shared Keys (PSKs) for TLS 1.3

Internet Engineering Task Force (IETF)                       D. Benjamin
Request for Comments: 9258                                  Google, LLC.
Category: Standards Track                                     C. A. Wood
ISSN: 2070-1721                                               Cloudflare
                                                               July 2022

Importing External Pre-Shared Keys (PSKs) for TLS 1.3

Импорт внешних ключей PSK для TLS 1.3

PDF

Аннотация

Этот документ описывает интерфейс для импорта внешних заранее распространённых ключей (Pre-Shared Key или PSK) в TLS 1.3.

Статус документа

Документ относится к категории Internet Standards Track.

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG2. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информация о текущем статусе документа, найденных ошибках и способах обратной связи доступна по ссылке https://www.rfc-editor.org/info/rfc9258.

Авторские права

Copyright (c) 2022. Авторские права принадлежат IETF Trust и лицам, указанным в качестве авторов документа. Все права защищены.

К документу применимы права и ограничения, указанные в BCP 78 и IETF Trust Legal Provisions и относящиеся к документам IETF (http://trustee.ietf.org/license-info), на момент публикации данного документа. Прочтите упомянутые документы внимательно. Фрагменты программного кода, включённые в этот документ, распространяются в соответствии с упрощённой лицензией BSD, как указано в параграфе 4.e документа IETF Trust Legal Provisions, без каких-либо гарантий (как указано в Simplified BSD License).

1. Введение

TLS 1.3 [RFC8446] поддерживает аутентификацию с заранее распределенным ключом (PSK), при этом ключи PSK могут устанавливаться с помощью сеансовых квитанций (ticket) из предшествующих соединений или с помощью специального (out-of-band) механизма. Протокол требует, чтобы каждый ключ PSK использовался лишь с одной хэш-функцией. Это сделано для упрощения анализа протокола. В TLS 1.2 [RFC5246] такого требования нет и PSK может применяться с любым алгоритмом хэширования и псевдослучайной функцией (pseudorandom function или PRF) TLS 1.2. Хотя не известно способа, каким один и тот же внешний PSK может давать связанный вывод в TLS 1.3 и предшествующих версиях, был проведён лишь ограниченный анализ. Приложениям следует предоставлять раздельные PSK для (О)TLS 1.3 и прежних версий. Если это невозможно (например, внешние PSK уже развёрнуты или имеются иные ограничения), повторное использование PSK в разных версиях TLS может давать связанный вывод, который, в свою очередь, ведёт к проблемам безопасности (см. Приложение E.7 к [RFC8446]).

Для смягчения проблем этот документ задаёт интерфейс импортёра PSK. С помощью которого можно импортировать внешние PSK и потом привязать их к конкретной функции вывода ключей (key derivation function или KDF) и хэш-функции для использования в TLS 1.3 [RFC8446] и DTLS 1.3 [RFC9147]. В частности, описывается механизм для импорта PSK, выведенных из внешних PSK путём включения целевой KDF, версии протокола (D)TLS и необязательной строки контекста для обеспечения уникальности. Этот процесс даёт набор PSK-кандидатов, каждый из которых привязан к целевой KDF и протоколу, которые отличаются от применяемых в (D)TLS 1.2 и прежних версий. Это преобразует отдельный PSK и отождествление в набор PSK и отождествлений.

2. Принятые соглашения

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не нужно (SHALL NOT), следует (SHOULD), не следует (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе должны интерпретироваться в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

3. Терминология

Ниже приведены определения используемых в документе терминов.

External PSK (EPSK) — внешний PSK

Ключ PSK организованный или предоставленный внешними средствами (out of band), т. е не в соединении TLS, который представляет собой кортеж (Base Key, External Identity, Hash).

Base Key — базовый ключ

Секретное значение EPSK.

External Identity — внешнее отождествление (свидетельство)

Последовательность байтов, служащая для идентификации EPSK.

Target protocol — целевой протокол

Протокол, для которого импортируется PSK.

Target KDF — целевая KDF

Функция KDF, для которой импортируется PSK.

Imported PSK (IPSK) — импортированный PSK

Ключ TLS PSK выведенный из EPSK, необязательной строки контекста, целевого протокола и целевой KDF.

Non-imported PSK — неимпортированный PSK

Ключ EPSK, испольуемый в качестве TLS PSK напрямую (без импорта).

Imported Identity — импортированное отождествление

Последовательность байтов, служащая для идентификации IPSK.

В документе применяется язык представления из раздела 3 в [RFC8446].

4. Обзор

Интерфейс импортёра PSK отражает интерфейс экспортёра TLS (см. [RFC8446]) в том смысле, что он меняет ключ на основе некоторой контекстной информации. В отличие от интерфейса экспортёра, где уникальность вывода достигается за счёт явной метки и строки контекста, определённый здесь интерфейс импортёра принимает внешний ключ PSK и отождествление, «импортируя» их в TLS путём создания набора «производных» PSK и отождествлений, которые уникальны. Каждый из этих выведенных PSK привязывается к целевому протоколу, идентификатору KDF и необязательной строке контекста. Кроме того, полученные ключи изменяются с использованием новой метки вывода для предотвращения конфликтов с неимпортированными PSK. Через этот интерфейс импорт внешних PSK с разными отждествлениями даёт разные ключи привязки PSK (binder).

Использование импортированных ключей не требуется согласовывать, поскольку клиент и сервер не согласуют отождествления, если импорт был некорректен. Конечные точки могут постепенно развёртывать поддержку импортёров PSK, предлагая неимпортированные PSK для TLS версий до TLS 1.3. Неимпортированные и импортированные PSK не эквивалентны, поскольку из отождествления различаются (см. раздел 7).

Конечным точкам, импортирующим внешние ключи, недопустимо применять служащие вводом в процесс импорта ключи для каких-либо иных целей и недопустимо применять выведенные ключи для целей, отличных от TLS PSK. Кроме того, каждый внешний PSK, введенный в процесс импортёра, должен быть связан не более чем с одной хэш-функцией. Это аналогично правилам параграфа 4.2.11 [RFC8446]. Дополнительное обсуждение приведено в разделе 8.

5. Импортёр PSK

В этом разделе описан интерфейс импортёра PSK и лежащий в его основе механизм диверсификации, а также изменение расчёта связующего ключа (binder key).

5.1. Диверсификация внешнего PSK

На входе интерфейс импортёра PSK принимает EPSK с внешним отождествлением (External Identity) external_identity и базовым ключом epsk (определены в разделе 3) вместе с необязательным контекстом. Затем ввод преобразуется в набор PSK и импортированных отождествлений для использования в соединении с целевым протоколом и KDF. В частности, для каждого поддерживаемого целевого протокола target_protocol и KDF target_kdf импортёр создаёт структуру ImportedIdentity, показанную ниже.

   struct {
      opaque external_identity<1...2^16-1>;
      opaque context<0..2^16-1>;
      uint16 target_protocol;
      uint16 target_kdf;
   } ImportedIdentity;

Список значений ImportedIdentity.target_kdf поддерживается IANA, как указано в разделе 10. Внешние PSK недопустимо импортировать для (D)TLS 1.2 и более ранних версий. В разделе 7 обсыждается сосуществование импортированных PSK для TLS 1.3 с неимпортированными PSK более ранних версий при поэтапном развертывании.

Значение ImportedIdentity.context должно включать контекст, используемый для определения EPSK, если тот имеется. Например, ImportedIdentity.context может включать сведения о ролях партнёров или отождествления для смягчения атак с отражением в стиле Selfie (Selfie-style reflection attack) [Selfie] (см. Приложение A). Поскольку EPSK является ключом, выведенным из внешнего протокола или последовательности протоколов, значение ImportedIdentity.context должно включать привязку каналов для производных протоколов [RFC5056]. Детали этой привязки зависят от протокола и выходят за рамки этой спецификации.

Значение ImportedIdentity.target_protocol должно указывать версию протокола (D)TLS, для которой импортируется PSK. Например, TLS 1.3 [RFC8446] использует значение 0x0304, которое применяется также в QUICv1 [QUIC]. Отметим, что это означает зависимость числа PSK, выводимых из EPSK, от числа целевых протоколов.

На основе ImportedIdentity и соответствующего EPSK с базовым ключом epsk, импортированный PSK IPSK с базовым ключом ipskx вычисляется, как показано ниже.

epskx = HKDF-Extract(0, epsk)
ipskx = HKDF-Expand-Label(epskx, "derived psk", Hash(ImportedIdentity), L)

L соответствует размеру вывода KDF ImportedIdentity.target_kdf, как указано в разделе 10. Для основанных на хэшировании KDF, таких как HKDF_SHA256 (0x0001), это будет размер результата хэш-функции, например, 32 октета для SHA256. Ключ IPSK должен иметь размер, подхожящий для поддерживаемых шифров. Внутри HKDF-Expand-Label применяет метку, соответствующую ImportedIdentity.target_protocol (например, «tls13» для TLS 1.3 в соответствии с параграфом 7.1 [RFC8446] или «dtls13» для DTLS 1.3 в соответствии с параграфом Section 5.10 [RFC9147]).

Отождествлением ipskx при передаче в линию служит ImportedIdentity, т. е. преобразованное в последовательную форму содержимое ImportedIdentity выступает как содержимое PskIdentity.identity в расширении PSK. Соответствующим вводом PSK для планирования ключей TLS 1.3 является «ipskx».

Поскольку максимальный размер расширения PSK составляет 216 — 1 октетов, импортированное отождествление (Imported Identity), превышающее этот размер, может вызывать ошибку декодирования. Поэтому интерфейсу импортёра PSK следует отвергать ImportedIdentity с размером, превышающим это значение.

Хэш-функция, используемая для функции вывода ключей на основе HMAC (HMAC-based Key Derivation Function или HKDF) [RFC5869], связана с EPSK. Это не хэш-функция, связанная с ImportedIdentity.target_kdf. Если EPSK не имеет связанной хэш-функции, следует применять SHA-256 [SHA2]. Диверсификация EPSK с помощью ImportedIdentity.target_kdf гарантирует, что IPSK применяется в качестве входного ключевого материала KDF не более 1 раза, что соответствует требованиям [RFC8446] (см. раздел 8).

Конечным точкам следует генерировать совместимые отождествления ipskx для каждого целевого шифра, который точка поддерживает. Например, импорт ключей для TLS_AES_128_GCM_SHA256 и TLS_AES_256_GCM_SHA384 будет давать два PSK, один для HKDF-SHA256, другой для HKDF-SHA384. При поддержке TLS_AES_128_GCM_SHA256 и TLS_CHACHA20_POLY1305_SHA256, напротив, нужен лишь 1 производный ключ. Каждый шифр однозначно указывает целевую функцию KDF. Будущие спецификации, меняющие способ согласования KDF, должны будут обновить эту спецификацию для разъяснения выбора целевых KDF в процессе импорта.

EPSK можно импортировать до начала соединения, если целевые KDF, протоколы и строки контекста известны заранее. Можно также импортировать EPSK для упреждающего использования данных, если они привязаны к настройкам протокола и конфигурации, которые требуются для упреждающей передачи данных. По минимуму это означает, что вместе с EPSK должны быть предоставлены значение согласования протокола прикладного уровня (Application-Layer Protocol Negotiation или ALPN) [RFC7301], транспортные параметры QUIC (при использовании с QUIC) и другие связанные параметры, согласуемые для упреждающих данных.

5.2. Вывод связующего ключа

Для предотвращения путаницы между импортированными и неимпортированными PSK в импортированных PSK меняется метка вывода связующего ключа PSK. В частности, вычисление стандартного связующего ключа TLS 1.3 PSK выполняется, как показано ниже.

              0
              |
              v
    PSK ->  HKDF-Extract = Early Secret
              |
              +-----> Derive-Secret(., "ext binder" | "res binder", "")
              |                     = binder_key
              V

Импортированные PSK при выводе binder_key используют строку «imp binder» вместо «ext binder» или «res binder» и расчёт связующего ключа имеет вид

              0
              |
              v
    PSK ->  HKDF-Extract = Early Secret
              |
              +-----> Derive-Secret(., "ext binder"
              |                      | "res binder"
              |                      | "imp binder", "")
              |                     = binder_key
              V

Эта новая метка гарантирует, что клиент и сервер будут согласовывать применение внешнего PSK тогда и только тогда, когда (a) обе конечные точки импортируют PSK или (b) ни одна из них не делает этого. Поскольку binder_key является ключом листа, изменение расчёта не влияет на другие ключи.

6. Отмена хэш-функций

Клиент или сервер, желающий отменить хэш-функцию и больше не применять её для TLS 1.3, удаляет соответствующую KDF из числа целевых KDF при импорет ключей. Это не влияет на работу KDF, служащих для вывода импортируемых PSK.

7. Постепенное развёртывание

В системах, где PSK уже подготовлены для применения с TLS 1.2, попытка поэтапного развёртывания механизма импорта приведёт к одновременному использованию уже предоставленных PSK напрямую как TLS 1.2 PSK и как EPSK, что, в свою очередь, означает возможность применения одних KDF и ключа а двух разных контекстах протокола. Это не рекомендуется (см. раздел 8). Однако преимущества применения TLS 1.3 и импортёров PSK могут быть достаточно убедительными для выбора в существующем развёртывании такой несовместимой конфигурации на короткий период развёртывания новых программ (использующих TLS 1.3 и импортёры). Операторам рекомендуется делать этот период как можно короче.

8. Вопросы безопасности

Цель безопасности импортёра PSK можно грубо сформулировать как предотвращение повторного применения PSK в KDF при надлежащей аутентификации конечных точек. При моделировании в качестве вычислительных экстракторов KDF предполагают, что входной ключевой материал (input keying material или IKM) отбирается из некого «источника» распределения вероятности и любые два значения IKM выбирабтся независимо одно от другого [Kraw10]. Это требование независимости от источника предполагает, что одно значение IKM не может применяться в разных KDF.

Аутентификация на базе PSK функционально эквивалентна возобновлению сессии, поскольку соединение применяет имеющийся ключевой материал для аутентификации обеих конечных точек. В соответствии с [BAA15] это является формой композитной аутентификации. Такая аутентификация, грубо говоря, является свойством, состоящим в том, что выполнение нескольких протоколов аутентификации, из которых хотя бы 1 не скомпрометирован, совместно аутентифицирует все протоколы. Поэтому аутентификации с предоставленными извне PSK в идеале следует аутентифицировать как соединение TLS, так и внешний процесс представления. Обычно этот процесс создаёт PSK и соответствующий контекст, где PSK был выведен и где его следует применять. При доступности контекст используется как значение ImportedIdentity.context. Внешний PSK без такого контекста называется безконтекстным (context-free).

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

  1. Импорт предоставленных извне PSK в соединение TLS обеспечивает составную аутентификацию соединения и процесса представления.

  2. Безконтекстные PSK обеспечивают аутентификацию лишь в контексте одного соединения.

  3. Импортированные PSK не применяются в качестве IKM для двух разных KDF.

  4. Импортированные PSK не будут конфиликтовать с будущими версиями протокола и функций KDF.

Нет каких-либо известных данных или проблем безопасности, вызываемых процессом расчёта импортируемых PSK из внешниз PSK и обработки имеющихся внешних PSK, применяемых в (D)TLS 1.2 и ниже, как указано в разделе 7. Однако был проведён лишь ограниченный анализ и это является ещё одной причиной, почему приложениям следует предоствалять отдельные PSK для (D)TLS 1.3 и прежних версий даже с интерфейсом импортёра (D)TLS 1.3.

Импортёр PSK не предотвращает создание приложениями отождествлений PSK без импорта, конфликтующих с импортированными отождествлениями PSK.

9. Вопросы приватности

Внешние отождествления PSK обычно имеют статическую структуру, поэтому конечные точки могут применять их для поиска ключевого материала. В некоторых системах и вариантах применения они могут служить для отслеживания.

Отметим, что ImportedIdentity.context является открытым текстом в линии как часть отождествления PSK. Без защиты механизмами вроде TLS Encrypted ClientHello [ECH] приложениям не следует помещать в это поле приватные данные.

10. Взаимодействие с IANA

Агентство IANA создало реестр TLS KDF Identifiers в имеющемся реестре Transport Layer Security (TLS) Parameters. Записи реестра показаны в таблице 1

Таблица 1. Реестр идентификаторов TLS KDF.

 

Значение

Описание KDF

Документ

0x0000

Резерв

RFC 9258

0x0001

HKDF_SHA256

[RFC5869]

0x0002

HKDF_SHA384

[RFC5869]

 

Новые значения для целевых KDF выделяются в соответствии с указанными ниже процедурами:

  • для диапазона 0x0000-0xfeff применяется процедура Specification Required [RFC8126];

  • значения 0xff00-0xffff зарезервированы для приватного использования (Private Use) [RFC8126].

Процедуры регистрации значений в пространстве Specification Required заданы в разделе 17 [RFC8447].

11. Литература

11.1. Нормативные документы

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC5056] Williams, N., «On the Use of Channel Bindings to Secure Channels», RFC 5056, DOI 10.17487/RFC5056, November 2007, <https://www.rfc-editor.org/info/rfc5056>.

[RFC5869] Krawczyk, H. and P. Eronen, «HMAC-based Extract-and-Expand Key Derivation Function (HKDF)», RFC 5869, DOI 10.17487/RFC5869, May 2010, <https://www.rfc-editor.org/info/rfc5869>.

[RFC8126] Cotton, M., Leiba, B., and T. Narten, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8446] Rescorla, E., «The Transport Layer Security (TLS) Protocol Version 1.3», RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.

[RFC8447] Salowey, J. and S. Turner, «IANA Registry Updates for TLS and DTLS», RFC 8447, DOI 10.17487/RFC8447, August 2018, <https://www.rfc-editor.org/info/rfc8447>.

[RFC9147] Rescorla, E., Tschofenig, H., and N. Modadugu, «The Datagram Transport Layer Security (DTLS) Protocol Version 1.3», RFC 9147, DOI 10.17487/RFC9147, April 2022, <https://www.rfc-editor.org/info/rfc9147>.

11.2. Дополнительная литература

[BAA15] Bhargavan, K., Delignat-Lavaud, A., and A. Pironti, «Verified Contributive Channel Bindings for Compound Authentication», Proceedings 2015 Network and Distributed System Security, DOI 10.14722/ndss.2015.23277, February 2015, <https://doi.org/10.14722/ndss.2015.23277>.

[ECH] Rescorla, E., Oku, K., Sullivan, N., and C. A. Wood, «TLS Encrypted Client Hello», Work in Progress, Internet-Draft, draft-ietf-tls-esni-14, 13 February 2022, <https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-14>.

[Kraw10] Krawczyk, H., «Cryptographic Extraction and Key Derivation: The HKDF Scheme», Proceedings of Crypto 2010, May 2010, <https://eprint.iacr.org/2010/264>.

[QUIC] Iyengar, J., Ed. and M. Thomson, Ed., «QUIC: A UDP-Based Multiplexed and Secure Transport», RFC 9000, DOI 10.17487/RFC9000, May 2021, <https://www.rfc-editor.org/info/rfc9000>.

[RFC5246] Dierks, T. and E. Rescorla, «The Transport Layer Security (TLS) Protocol Version 1.2», RFC 5246, DOI 10.17487/RFC5246, August 2008, <https://www.rfc-editor.org/info/rfc5246>.

[RFC7301] Friedl, S., Popov, A., Langley, A., and E. Stephan, «Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension», RFC 7301, DOI 10.17487/RFC7301, July 2014, <https://www.rfc-editor.org/info/rfc7301>.

[Selfie] Drucker, N. and S. Gueron, «Selfie: reflections on TLS 1.3 with PSK», DOI 10.1007/s00145-021-09387-y, May 2021, <https://eprint.iacr.org/2019/347.pdf>.

[SHA2] National Institute of Standards and Technology, «Secure Hash Standard (SHS)», FIPS PUB 180-4, DOI 10.6028/NIST.FIPS.180-4, August 2015, <https://doi.org/10.6028/NIST.FIPS.180-4>.

Приложение A. Атаки Selfie

Атаки Selfie [Selfie] основаны на злоупотреблении интерфейсом PSK, неявно предполагающим, что каждый ключ PSK известен лишь клиенту и серверу. Если несколько клиентов или серверов с разными ролями используют общий ключ PSK, TLS аутентифицирует лишь группу целиком. Узел аутентифицирует своего партнёра из группы независимо от подлинности того. Отметим, что такое возможно и в случае совместного применения PSK двумя узлами без ролей.

Приложения, требующие аутентификации по ролям при использовании общего PSK для всех узлов, могут решить проблему путём передачи сведений о ролях через соединение TLS после согласования или путём включения роли клиента и сервера в строку контекста IPSK. Например, если приложение идентифицирует каждый узел по MAC-адресу (Media Access Control), оно может использовать приведённую ниже строку контекста.

     struct {
       opaque client_mac<0..2^8-1>;
       opaque server_mac<0..2^8-1>;
     } Context;

Если злоумышленник затем переправит сообщение ClientHello, предназначенное одному узлу, на другой узел, включая создателя ClientHello, получатель определит другую строку контекста и согласование не завершится успехом.

Отметим, что в этом варианте по=прежнему применяется один общий ключ PSK для всех узлов поэтому каждый узел должен быть доверенным, чтобы он не взял на себя чужую роль (прикинулся другим узлом).

Благодарности

Авторы признательны Eric Rescorla и Martin Thomson за дискуссии, которые привели к созданию этого документа, а также Christian Huitema за вклад в соображения по приватности внешних PSK. John Preuß Mattsson предоставил сведения по части развёртывания импортёров PSK. Hugo Krawczyk предоставил рекомендации по безопасности. Martin Thomson, Jonathan Hoyland, Scott Hollenbeck, Benjamin Kaduk и другие предоставили рецензии, отклики и предложения по улучшению документа.

Адреса авторов

David Benjamin
Google, LLC.
Email: davidben@google.com
 
Christopher A. Wood
Cloudflare
Email: caw@heapingbits.net

Перевод на русский язык

Николай Малых

nmalykh@protokols.ru

1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

Рубрика: RFC, Безопасность | Оставить комментарий

RFC 9254 Encoding of Data Modeled with YANG in the Concise Binary Object Representation (CBOR)

Internet Engineering Task Force (IETF)                 M. Veillette, Ed.
Request for Comments: 9254                       Trilliant Networks Inc.
Category: Standards Track                                 I. Petrov, Ed.
ISSN: 2070-1721                                  Google Switzerland GmbH
                                                                A. Pelov
                                                                  Acklio
                                                              C. Bormann
                                                  Universität Bremen TZI
                                                           M. Richardson
                                                Sandelman Software Works
                                                               July 2022

Encoding of Data Modeled with YANG in the Concise Binary Object Representation (CBOR)

Кодирование данных модели YANG в CBOR

PDF

Аннотация

Язык моделирования данных YANG (RFC 7950) служит для моделирования данных конфигурации и состояния, параметров и результатов вызовов удалённых процедур (Remote Procedure Call или RPC) или действий и уведомлений.

Этот документ определяет представление правил YANG в CBOR (Concise Binary Object Representation) (RFC 8949).

Статус документа

Документ относится к категории Internet Standards Track.

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG2. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информация о текущем статусе документа, найденных ошибках и способах обратной связи доступна по ссылке https://www.rfc-editor.org/info/rfc9254.

Авторские права

Copyright (c) 2022. Авторские права принадлежат IETF Trust и лицам, указанным в качестве авторов документа. Все права защищены.

К документу применимы права и ограничения, указанные в BCP 78 и IETF Trust Legal Provisions и относящиеся к документам IETF (http://trustee.ietf.org/license-info), на момент публикации данного документа. Прочтите упомянутые документы внимательно. Фрагменты программного кода, включённые в этот документ, распространяются в соответствии с упрощённой лицензией BSD, как указано в параграфе 4.e документа IETF Trust Legal Provisions, без каких-либо гарантий (как указано в Simplified BSD License).

1. Введение

Спецификация языка моделирования данных YANG 1.1 [RFC7950] определяет представление XML для экземпляров данных, т. е. содержимого хранилищ конфигурации, данных состояния, ввода и вывода RPC и действий, уведомлений о событиях. Дополнительный набор правил кодирования задан в [RFC7951] на основе The JavaScript Object Notation (JSON) Data Interchange Format» [RFC8259].

Целью этого документа является задание набора правил кодирования для краткого представления двоичных объектов (Concise Binary Object Representation или CBOR) [RFC8949], называемого YANG-CBOR. Задаваемое кодирование компактней XML и JSON и более подходит для узлов и/или сетей с ограничениями, описанных в [RFC7228].

2. Терминология и нотация

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не нужно (SHALL NOT), следует (SHOULD), не следует (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе должны интерпретироваться в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

Значения SID (и рассчитанные по ним детали SID) показаны в примерах лишь для иллюстрации.

Ниже перечислены термины, определённые в [RFC7950].

  • action — действие;

  • anydata — любые данные;

  • anyxml — любые данные XML;

  • data node — узел данных;

  • data tree — дерево данных;

  • datastore — хранилище данных;

  • feature — функция, возможность;

  • identity — отождествление

  • module — модуль;

  • notification — уведомление;

  • RPC — удаленный вызов процедуры;

  • schema node — узел схемы;

  • submodule — субмодуль.

В [RFC8040] определён термин

  • yang-data extension — расширение yang-data.

В [RFC8791] определён термин

  • YANG data structure — структура данных YANG.

Эта спецификация использует также определённые ниже термины.

YANG Schema Item iDentifier (YANG SID или SID) — идентификатор элемента схемы YANG

63-битовое целое число без знака, служащее для идентификации элемента YANG.

delta — приращение

Разница между текущим и эталонным значением YANG SID. Эталон YANG SID определён в каждом контексте, где применяется приращение.

absolute SID — абсолютный SID

Значение YANG SID, не представляемое приращением. Обычно идентификатор называется явно только в позиции, где обычно можно найти приращение.

representation tree — дерево представления

Дерево данных YANG, возможно заключённое в узел схемы, такое как структура данных YANG, уведомление, RPC, действие.

representation node — узел представления

Узел в дереве представления, т. е. узел дерева данных, или представление узла схемы, такое как структура данных YANG, уведомление, RPC, действие.

item — элемент

Узел схемы, отождествление, модуль или свойство, определённые с использованием языка моделирования YANG.

list entry — запись списка

данные, связанные с одной записью в списке (см. параграф 7.8 в [RFC7950]).

container-like instance — контейнероподобный экземпляр

Экземпляр контейнера, структура данных YANG, содержимое уведомления, ввод или вывод RPC или действия (параграф 4.2), запись в списке (параграф 4.4), узел anydata (параграф 4.5).

parent (of a representation node) — родитель узла представления

Узел схемы ближайшего охватывающего узла представления, в котором определён данный узел представления.

3. Свойства кодирования CBOR

Этот документ задаёт правила кодирования CBOR для деревьев данных YANG и их субдеревьев.

Дерево данных YANG может помещаться в представление узла схемы, такое как структура данных YANG, уведомление, RPC или действие, это называется деревом представления. Узлы дерева данных и представление узла схемы, включающего дерево, совместно называют узлами представления (representation node).

Узел представления, такой как контейнер, записи списка, структура данных YANG, уведомление, ввод или вывод RPC или действия, узел anydata, сериализуется с использованием отображения CBOR, где каждый определённый узел схемы кодируется ключом и значением. Эта спецификация поддерживает два типа ключей CBOR — идентификаторы YANG SID (YANG Schema Item iDentifier), определённые в параграфе 3.2, и имена, как указано в параграфе 3.3. Каждый из этих типов ключей кодируется с применением конкретного типа CBOR, что позволяет интерпретировать их в процессе десериализации. Протоколы и механизмы, реализующие эту спецификацию, могут предписывать применение определённого типа ключей или разрешать генератору свободный выбор для каждого ключа.

Для минимизации размера закодированных данных отображение избегает всей необязательной метаинформации, сверх представленной напрямую базовой моделью данных CBOR (раздел 2 в [RFC8949]). Например, теги CBOR применяются лишь для абсолютных SID, узлов данных anyxml и типа данных union, чтобы явно различать типы данных YANG, закодированные с использованием одного базового типа CBOR.

Если иное явно не указано в протоколе или механизме, реализующем эту спецификацию, нужно поддерживать в декодерах CBOR, реализующих YANG-CBOR, кодирование неопределённого размера, определённое в параграфе 3.2 [RFC8949]. Это позволяет реализации начинать выдачу массива или отображения до того, как станет известно точное число элементов, а также, возможно, предотвратить неоправданные блокировки и конкуренцию. С другой стороны, это лишает получателя кодированных данных возможности заранее аносировать сведения о размере, когда эти преимущества действительно возникают.

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

При сериализации узлов представления по заданным этой спецификацией правилам как части данных (payload) приложения в эти данные следует включать сведения об узлах, позволяющие идентифицировать узлы без хранения состояний, например, связанный с узлом номер SID, приращение SID от другого SID в данных приложения, имя с указанием пространства имён, идентификатор экземпляра.

Примеры в разделе 4 включают корневое отображение CBOR с одной записью, имеющей в качестве ключа имя с указанием пространства имён или SID. Эти корневые отображения CBOR представлены лишь в качестве примеров использования и не являются частью правил кодирования. Обязательным является лишь значение в этом отображении CBOR.

3.1. Диагностическая нотация CBOR

В этом документе двоичное содержимое CBOR представляется с использованием эквивалентной текстовой формы, называемой диагностической нотацией CBOR, как определено в разделе 8 [RFC8949]. Эта нотация служит лишь для документации и не применяется при сериализации данных. Сводка нотации представлена в таблице 1.

Таблица 1. Сводка диагностической нотации CBOR.

Содержимое CBOR

Тип CBOR

Диагностическая нотация

Пример

Код CBOR

Целое число без знака

0

Десятичные цифры

123

18 7B

Отрицательное целое число

1

Десятичные цифры со знаком минус (-)

-123

38 7A

Строка байтов

2

Шестнадцатеричное значение в одинарных кавычках или с префиксом h

h’F15C’

42 F15C

Строка текста

3

Строка символов Unicode в двойных кавычках

«txt»

63 747874

Массив

4

Список значений через запятую, заключённых в квадратные скобки

[ 1, 2 ]

82 01 02

Отображение

5

Список пар ключ-значение через запятую, заключённых в фигурные скобки

{ 1: 123, 2: 456 }

A2 01187B 021901C8

Логическое значение

7/20
7/21

false
true

false
true

F4
F5

Null

7/22

null

null

F6

Не выделено

7/23

undefined

undefined

F7

Примечание. Двоичное содержимое CBOR в этой спецификации сопровождается комментариями, обозначенными символами /, как указано в Приложении G.6 [RFC8610].

3.2. Идентификатор элемента схемы YANG

Некоторые из элементов YANG [RFC7950] требуют применения уникального идентификатора. В протоколах настройки конфигурации сети (Network Configuration Protocol или NETCONF) [RFC6241] и RESTCONF [RFC8040] такими идентификаторами служат строки текста. Для обеспечения реализации моделей данных, определённых в YANG, устроствами или сетями с ограничениями нужен более компактный метод идентификации элементов YANG. Такой компактный идентификатор называется идентификатором элемента схемы YANG (YANG Schema Item iDentifier) и является 63-битовым целым числом без знака (0..9223372036854775807 или 0..0x7fffffffffffffff). Ниже указаны элементы, идентифицируемые с помощью YANG SID (или просто SID).

  • Отождествления;

  • узлы данных,

  • RPC и связанные с ними ввод и вывод;

  • действия и связанные с ними ввод и вывод;

  • структуры данных YANG;

  • уведомления и связанная с ними информация;

  • модули и функции (feature) YANG.

Отметим, что любое структурирование модулей по субмодулям не заметно для YANG-CBOR, SID не выделяются для имён субмодулей и любые элементы внутри субмодуля фактически получают SID при обработке содержащего их модуля.

Для минимизации размера SID, применяемые как ключи в отображениях CBOR кодируются с использованием приращения целыми числами со знаком, которые складываются с эталонным SID для отображения. Эталонный SID внешнего отображения имеет значение 0, если другой эталонный SID не задан однозначно из среды, где применяется внешнее отображение. Эталонный SID отображения, напрямую встроенного в запись отображения с ключом на основе имени имеет значение 0. Для прочих отображений эталонным SID является значение, рассчитанное для записи отображения, в которую оно встроено напрямую (встраивание может быть опосредованным, если применяется массив, например, в списке YANG). Там, где желательны абсолютные SID (целое число предполагает приращение), они должны указываться абсолютными значениями SID с использованием тега CBOR 47 (как указано в параграфе 4.2.1).

Таким образом, преобразование SID в приращение и обратно не использует состояния и основано исключительно на (де)сериализованных данных, возможно в комбинации с эталонным внешним SID, однозначно заданным средой.

Механизмы и процессы назначения SID элементам YANG и обеспечения их уникальности выходят за рамки этой спецификации. Если нужно применять SID, эта спецификация используется вместе со спецификацией, определяющей управление идентификаторами. Связанный документ [CORE-SID] предназначен для указания способа назначения SID для модулей YANG, поддерживаемых IETF, и рекомендуется для остальных модулей YANG. Данная спецификация разработана для поддержки разных методов назначения в отдельных доменах (областях).

Для предоставления реализациям способа внутренней индикации отсутствия SID значение SID = 0 зарезервировано и не будет выделяться. Оно не применяется при обмене.

3.3. Имя

Эта спецификация поддерживает также представление идентификаторов элементов YANG строками текста, подобно принятому в JSON кодированию данных моделей [RFC7951]. Такой подход может избавить от издержек, связанных с выделением SID. Основным недостатком этого подхода является рост размера закодированих данных.

Идентификаторы элементов YANG по именам должны иметь одну из двух форма:

  • простой (simple) идентификатор элемента YANG (узла схемы или отождествления);

  • заданный с пространством имён (namespace-qualified) идентификатор элемента YANG с префиксом в виде имени модуля, где определён элемент, отделённым двоеточием (:).

Имя модуля задаёт пространство имён для всех элементов YANG, определённых в этом модуле. Если элемент задан в субмодуле, полное имя (с пространством имён) использует имя основного модуля, к которому относится субмодуль.

Синтаксис ABNF [RFC5234] для имени показан на рисунке 1, а создание identifier определено в разделе 14 [RFC7950].

   name = [identifier ":"] identifier

Рисунок 1. Вывод ABNF для простого имени или имени с пространством имён.


Полное (namespace-qualified) имя должно применяться для всех элементов верхнего уровня в отображении CBOR, а также во всех случаях, когда пространства имён узла представления и его родителя различаются. В остальных случаях должны использоваться простые имена.

Пример определения

   module example-foomod {
     container top {
       leaf foo {
         type uint8;
       }
     }
   }

   module example-barmod {
     import example-foomod {
       prefix "foomod";
     }
     augment "/foomod:top" {
       leaf bar {
         type boolean;
       }
     }
   }

Действительное кодирование CBOR для контейнера top показано ниже.

Диагностическая нотация CBOR

   {
     "example-foomod:top": {
       "foo": 54,
       "example-barmod:bar": true
     }
   }

Контейнер top и лист bar, определенные в другом модуле YANG как в родительском контейнере, кодируются с полными именами. Лист foo определён в том же модуле YANG, что и его родительский контейнер, кодируется простым именем.

4. Кодирование узлов представления

Узлы представления, определённые с использованием языка моделирования YANG, кодируются с применением CBOR [RFC8949] по правилам, заданным в этом разделе. Предполагается, что читатель знаком с YANG [RFC7950] и CBOR [RFC8949].

4.1. leaf

Кодирование leaf должно выполняться в соответствии с типом данных листа на основе одного из правил раздела 6.

Приведённые ниже примеры, взятые из [RFC6991] и [RFC7317], демонстрируют кодирование листа hostname с применением SID или имени.

   typedef domain-name {
     type string {
       pattern
         '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
       + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
       + '|\.';
       length "1..253";
     }
   }

   leaf hostname {
     type inet:domain-name;
   }

4.1.1. Использование SID

Как и в последующих примера приращение во внешнем отображении предполагает нулевое значение YANG SID (текущий узел схемы).

Диагностическая нотация CBOR

   {
     1752 : "myhost.example.com"     / hostname (SID 1752) /
   }

Представление CBOR

   A1                                         # map(1)
      19 06D8                                 # unsigned(1752)
      72                                      # text(18)
         6D79686F73742E6578616D706C652E636F6D # "myhost.example.com"

4.1.2. Использование имени

Диагностическая нотация CBOR

   {
     "ietf-system:hostname" : "myhost.example.com"
   }

Представление CBOR

   A1                                         # map(1)
      74                                      # text(20)
         696574662D73797374656D3A686F73746E616D65
      72                                      # text(18)
         6D79686F73742E6578616D706C652E636F6D

4.2. Контейнеры и другие узлы из дерева данных

Экземпляры контейнеров, структур данных YANG, содержимого уведомлений, ввода и вывода RPC и действий должны кодироваться с использованием элемента данных отображения CBOR (базовый тип 5). такое же кодирование применяется для элементов списка (параграф 4.4) и узлов anydata (параграф 4.5). Совместно их называют контейнероподобными экземплярами (container-like instances).

Отображение состоит из пар элементов ключ-значение. Каждому ключу с отображении CBOR назначается идентификатор узла схемы, а значению — значение узла представления в соответствии с типом данных экземпляра.

Эта спецификация поддерживает два типа ключей для отображений CBOR — SID (параграф 3.2) и имя (параграф 3.3).

В приведённых ниже применах, взятых из из [RFC6991] и [RFC7317], показано кодирование представления экземпляра контейнера system-state с использованием SID и имени.

   typedef date-and-time {
     type string {
       pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?'
             + '(Z|[\+\-]\d{2}:\d{2})';
     }
   }

   container system-state {
     container clock {
       leaf current-datetime {
         type date-and-time;
       }

       leaf boot-datetime {
         type date-and-time;
       }
     }
   }

4.2.1. Использование SID

В контексте контейнеров и других узлов дерева данных ключи отображений CBOR во внутренних отображениях можно кодировать с помощью приращений (целое число) или абсоютных SID (с тегом 47). Расчёт приращений показан ниже.

  • Для container приращение равно SID текущего узла представления за вычетом SID родительского контейнера.

  • Для list приращения равно SID текущего узла представления за вычетом SID родительского списка.

  • Для RPC input и RPC output приращения равны SID текущего узла представления за вычетом SID RPC.

  • Для action input и action output приращения равны SID текущего узла представления за вычетом SID action.

  • Для содержимого уведомления приращение равно SID текущего узла представления минус SID notification.

Диагностическая нотация CBOR

   {
     1720 : {                              / system-state (SID 1720) /
       1 : {                               / clock  (SID 1721) /
         2 : "2015-10-02T14:47:24Z-05:00", / current-datetime(SID 1723)/
         1 : "2015-09-15T09:12:58Z-05:00"  / boot-datetime (SID 1722) /
       }
     }
   }

Представление CBOR

   A1                                      # map(1)
      19 06B8                              # unsigned(1720)
      A1                                   # map(1)
         01                                # unsigned(1)
         A2                                # map(2)
            02                             # unsigned(2)
            78 1A                          # text(26)
               323031352D31302D30325431343A34373A32345A2D30353A3030
            01                             # unsigned(1)
            78 1A                          # text(26)
               323031352D30392D31355430393A31323A35385A2D30353A3030

Рисунок 2. Кодирование System State Clock.


4.2.2. Использование имени

Ключи отображений CBOR на основе имён должны кодироваться с использованием тектовых строк CBOR (базовый тип 3). Должны применяться полные (namespace-qualified) имена, если пространства имён узла представления и его родителя различаются. В остальных случаях должны применяться простые имена. Имена и пространства имён определены в разделе 4 [RFC7951].

Ниже приведён пример кодирования экземпляра узла представления контейнера system с использованием имени.

Диагностическая нотация CBOR

   {
     "ietf-system:system-state" : {
       "clock" : {
         "current-datetime" : "2015-10-02T14:47:24Z-05:00",
         "boot-datetime" : "2015-09-15T09:12:58Z-05:00"
       }
     }
   }

Представление CBOR

   A1                                      # map(1)
      78 18                                # text(24)
         696574662D73797374656D3A73797374656D2D7374617465
      A1                                   # map(1)
         65                                # text(5)
            636C6F636B                     # "clock"
         A2                                # map(2)
            70                             # text(16)
               63757272656E742D6461746574696D65
            78 1A                          # text(26)
               323031352D31302D30325431343A34373A32345A2D30353A3030
            6D                             # text(13)
               626F6F742D6461746574696D65
            78 1A                          # text(26)
               323031352D30392D31355430393A31323A35385A2D30353A3030

4.3. leaf-list

Для кодирования leaf-list должен использоваться элемент данных массива CBOR (базовый тип 4). Каждая запись массива должна кодироваться с использованием одного из правил, заданных в разделе 6.

Приведённые ниже примеры из [RFC6991] и [RFC7317] показывают кодирование экземпляра представления листа-списка search с записями ietf.org и ieee.org.

   typedef domain-name {
     type string {
       pattern
         '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
       + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
       + '|\.';
       length "1..253";
     }
   }

   leaf-list search {
     type domain-name;
     ordered-by user;
   }

4.3.1. Использование SID

Диагностическая нотация CBOR

   {
     1746 : [ "ietf.org", "ieee.org" ]     / search (SID 1746) /
   }

Представление CBOR

   A1                        # map(1)
      19 06D2                # unsigned(1746)
      82                     # array(2)
         68                  # text(8)
            696574662E6F7267 # "ietf.org"
         68                  # text(8)
            696565652E6F7267 # "ieee.org"

4.3.2. Использование имени

Диагностическая нотация CBOR

   {
     "ietf-system:search" : [ "ietf.org", "ieee.org" ]
   }

Представление CBOR

   A1                                         # map(1)
      72                                      # text(18)
         696574662D73797374656D3A736561726368 # "ietf-system:search"
      82                                      # array(2)
         68                                   # text(8)
            696574662E6F7267                  # "ietf.org"
         68                                   # text(8)
            696565652E6F7267                  # "ieee.org"

4.4. Списки и записи списков

Список или часть списка должны кодироваться с использованием элемента данных массива CBOR (базовый тип 4). Каждая запись списка в массиве CBOR кодируется с использованием элемента данных отображения CBOR (базовый тип 5) по правилам кодирования контейнероподобных экземляров, приведённым в параграфе 4.2.

Важно отметить, что это правило кодирования применимо и к экземплярам узла представления list с 1 элементом.

Пример определения из [RFC7317] показывает кодирование списка server с использованием SID и имени.

   list server {
     key name;

     leaf name {
       type string;
     }
     choice transport {
       case udp {
         container udp {
           leaf address {
             type host;
             mandatory true;
           }
           leaf port {
             type port-number;
           }
         }
       }
     }
     leaf association-type {
       type enumeration {
         enum server;
         enum peer;
         enum pool;
       }
       default server;
     }
     leaf iburst {
       type boolean;
       default false;
     }
     leaf prefer {
       type boolean;
       default false;
     }
   }

4.4.1. Использование SID

Правила кодирования для каждой записи list приведены в параграфе 4.2.1.

Диагностическая нотация CBOR

   {
     1756 : [                      / server (SID 1756) /
       {
         3 : "NRC TIC server",     / name (SID 1759) /
         5 : {                     / udp (SID 1761) /
           1 : "tic.nrc.ca",       / address (SID 1762) /
           2 : 123                 / port (SID 1763) /
         },
         1 : 0,                    / association-type (SID 1757) /
         2 : false,                / iburst (SID 1758) /
         4 : true                  / prefer (SID 1760) /
       },
       {
         3 : "NRC TAC server",     / name (SID 1759) /
         5 : {                     / udp (SID 1761) /
           1 : "tac.nrc.ca"        / address (SID 1762) /
         }
       }
     ]
   }

Представление CBOR

   A1                                      # map(1)
      19 06DC                              # unsigned(1756)
      82                                   # array(2)
         A5                                # map(5)
            03                             # unsigned(3)
            6E                             # text(14)
               4E52432054494320736572766572 # "NRC TIC server"
            05                             # unsigned(5)
            A2                             # map(2)
               01                          # unsigned(1)
               6A                          # text(10)
                  7469632E6E72632E6361     # "tic.nrc.ca"
               02                          # unsigned(2)
               18 7B                       # unsigned(123)
            01                             # unsigned(1)
            00                             # unsigned(0)
            02                             # unsigned(2)
            F4                             # primitive(20)
            04                             # unsigned(4)
            F5                             # primitive(21)
         A2                                # map(2)
            03                             # unsigned(3)
            6E                             # text(14)
               4E52432054414320736572766572 # "NRC TAC server"
            05                             # unsigned(5)
            A1                             # map(1)
               01                          # unsigned(1)
               6A                          # text(10)
                  7461632E6E72632E6361     # "tac.nrc.ca"

4.4.2. Использование имени

Правила кодирования для каждой записи list приведены в параграфе 4.2.2.

Диагностическая нотация CBOR

   {
     "ietf-system:server" : [
       {
         "name" : "NRC TIC server",
         "udp" : {
           "address" : "tic.nrc.ca",
           "port" : 123
         },
         "association-type" : 0,
         "iburst" : false,
         "prefer" : true
       },
       {
         "name" : "NRC TAC server",
         "udp" : {
           "address" : "tac.nrc.ca"
         }
       }
     ]
   }

Представление CBOR

   A1                                      # map(1)
      72                                   # text(18)
         696574662D73797374656D3A736572766572
      82                                   # array(2)
         A5                                # map(5)
            64                             # text(4)
               6E616D65                    # "name"
            6E                             # text(14)
               4E52432054494320736572766572
            63                             # text(3)
               756470                      # "udp"
            A2                             # map(2)
               67                          # text(7)
                  61646472657373           # "address"
               6A                          # text(10)
                  7469632E6E72632E6361     # "tic.nrc.ca"
               64                          # text(4)
                  706F7274                 # "port"
               18 7B                       # unsigned(123)
            70                             # text(16)
               6173736F63696174696F6E2D74797065
            00                             # unsigned(0)
            66                             # text(6)
               696275727374                # "iburst"
            F4                             # primitive(20)
            66                             # text(6)
               707265666572                # "prefer"
            F5                             # primitive(21)
         A2                                # map(2)
            64                             # text(4)
               6E616D65                    # "name"
            6E                             # text(14)
               4E52432054414320736572766572
            63                             # text(3)
               756470                      # "udp"
            A1                             # map(1)
               67                          # text(7)
                  61646472657373           # "address"
               6A                          # text(10)
                  7461632E6E72632E6361     # "tac.nrc.ca"

4.5. anydata

Узлы anydata служат контейнерами для произвольных наборов узлов представления, которые иначе появлялись бы как обычные данные модели YANG. Экземпляр узла представления anydata кодируется с использованием правил, применяемых для контейнеров, т. е. с применением элементов данных отображения CBOR (базовый тип 5) по правилам кодирования контейнероподобных экземпляров, указанным в параграфе 4.2.

Ниже приведён пример, показывающий возможное использование узла anydata. Здесь узел anydata служит для определения узла представления, содержащего уведомление, этот узел может быть частью списка YANG для записи событий.

   module event-log {
     ...
     anydata last-event;                // SID 60123
   }

В этом примере предполагается участие приведённого ниже уведомления.

   module example-port {
     ...

     notification example-port-fault {  // SID 60200
       leaf port-name {                 // SID 60201
         type string;
       }
       leaf port-fault {                // SID 60202
         type string;
       }
     }
   }

4.5.1. Использование SID

Диагностическая нотация CBOR

   {
     60123 : {                   / last-event (SID 60123) /
       77 : {                    / example-port-fault (SID 60200) /
         1 : "0/4/21",           / port-name (SID 60201) /
         2 : "Open pin 2"        / port-fault (SID 60202) /
       }
     }
   }

Представление CBOR

   A1                               # map(1)
      19 EADB                       # unsigned(60123)
      A1                            # map(1)
         18 4D                      # unsigned(77)
         A2                         # map(2)
            01                      # unsigned(1)
            66                      # text(6)
               302F342F3231         # "0/4/21"
            02                      # unsigned(2)
            6A                      # text(10)
               4F70656E2070696E2032 # "Open pin 2"

В некоторых реализациях может быть проще использовать кодирование абсолютных SID (тег 47) для корневого элемента anydata.

Диагностическая нотация CBOR

   {
     60123 : {                   / last-event (SID 60123) /
       47(60200) : {             / event-port-fault (SID 60200) /
         1 : "0/4/21",           / port-name (SID 60201) /
         2 : "Open pin 2"        / port-fault (SID 60202) /
       }
     }
   }

4.5.2. Использование имени

Диагностическая нотация CBOR

   {
     "event-log:last-event" : {
       "example-port:example-port-fault" : {
         "port-name" : "0/4/21",
         "port-fault" : "Open pin 2"
       }
     }
   }

Представление CBOR

   A1                                      # map(1)
      74                                   # text(20)
         6576656E742D6C6F673A6C6173742D6576656E74
      A1                                   # map(1)
         78 1F                             # text(31)
            6578616D706C652D706F72743A
            6578616D706C652D706F72742D6661756C74
         A2                                # map(2)
            69                             # text(9)
               706F72742D6E616D65          # "port-name"
            66                             # text(6)
               302F342F3231                # "0/4/21"
            6A                             # text(10)
               706F72742D6661756C74        # "port-fault"
            6A                             # text(10)
               4F70656E2070696E2032        # "Open pin 2"

4.6. anyxml

Узлы представления anyxml служат для сериализации произвольного содержимого CBOR, т. е. значением может быть любой двоичный объект CBOR (xml в названии не вполне корректно, поскольку применяется лишь к YANG-XML [RFC7950]). Значение anyxml может содержать элементы данных CBOR, помеченные одним из тегов, указанных в параграфе 9.3. Эти теги нужно поддерживать.

В приведённых ниже примерах из [RFC7951] показан действительный экземпляр узла представления anyxml с кодированием CBOR, содержащий массив CBOR с простыми значениями CBOR true, null, true.

   module bar-module {
     ...
     anyxml bar;      // SID 60000
   }

4.6.1. Использование SID

Диагностическая нотация CBOR

   {
     60000 : [true, null, true]   / bar (SID 60000) /
   }

Представление CBOR

   A1         # map(1)
      19 EA60 # unsigned(60000)
      83      # array(3)
         F5   # primitive(21)
         F6   # primitive(22)
         F5   # primitive(21)

4.6.2. Использование имени

Диагностическая нотация CBOR

   {
     "bar-module:bar" : [true, null, true]   / bar (SID 60000) /
   }

Представление CBOR

   A1                                 # map(1)
      6E                              # text(14)
         6261722D6D6F64756C653A626172 # "bar-module:bar"
      83                              # array(3)
         F5                           # primitive(21)
         F6                           # primitive(22)
         F5                           # primitive(21)

5. Кодирование расширения yang-data

Расширение yang-data [RFC8040] служит для определения в YANG структур данных, не предназначенных для реализации как части хранилища. Расширение yang-data будет задавать контейнер, который должен кодироваться по правилам для узлов дерева данных, указанным в параграфе 4.2. Как и контейнеры YANG, расширение yang-data можно кодировать с использованием SID или имени.

Пример определения из Приложения A к [CORE-COMI]

   module ietf-coreconf {
     ...

     import ietf-restconf {
       prefix rc;
     }

     rc:yang-data yang-errors {
       container error {
         leaf error-tag {
           type identityref {
             base error-tag;
           }
         }
         leaf error-app-tag {
           type identityref {
             base error-app-tag;
           }
         }
         leaf error-data-node {
           type instance-identifier;
         }
         leaf error-message {
           type string;
         }
       }
     }
   }

5.1. Использование SID

Расширения yang-data, закодированные с использованием SID, передаются в отображении CBOR с одной парой элементов. Для ключа устанавливается значение SID, выделенное контейнеру расширения yang-data, а в значение помещается CBOR-кодирование этого контейнера, как задано в параграфе 4.2.

Приведённый ниже пример сериализации экземпляра yang-errors расширения yang-data, как определено в [CORE-COMI], с использованием SID в соответствии с параграфом 3.2.

Диагностическая нотация CBOR

   {
     1024 : {                      / error  (SID 1024) /
       4 : 1011,                   / error-tag (SID 1028) /
                                   / = invalid-value (SID 1011) /
       1 : 1018,                   / error-app-tag (SID 1025) /
                                   / = not-in-range (SID 1018) /
       2 : 1740,                   / error-data-node (SID 1026) /
                                   / = timezone-utc-offset (SID 1740) /
       3 : "Maximum exceeded"      / error-message (SID 1027) /
     }
   }

Представление CBOR

   A1                                      # map(1)
      19 0400                              # unsigned(1024)
      A4                                   # map(4)
         04                                # unsigned(4)
         19 03F3                           # unsigned(1011)
         01                                # unsigned(1)
         19 03FA                           # unsigned(1018)
         02                                # unsigned(2)
         19 06CC                           # unsigned(1740)
         03                                # unsigned(3)
         70                                # text(16)
            4D6178696D756D206578636565646564 # "Maximum exceeded"

5.2. Использование имени

Расширение yang-data закодированное с использованием имени передаётся в отображении CBOR с одной парой элементов. Для ключа устанавливается полное (namespace-qualified) имя контейнера расширения yang-data, а значением служит CBOR-кодирование этого контейнера, как указано в параграфе 4.2.

Ниже приведён пример сериализации экземпляра yang-errors расширения yang-data, определённого в [CORE-COMI], с использованием имени, как указано в параграфе 3.3.

Диагностическая нотация CBOR

   {
     "ietf-coreconf:error" : {
       "error-tag" : "invalid-value",
       "error-app-tag" : "not-in-range",
       "error-data-node" : "timezone-utc-offset",
       "error-message" : "Maximum exceeded"
     }
   }

Представление CBOR

   A1                                           # map(1)
      73                                        # text(19)
         696574662D636F7265636F6E663A6572726F72 # "ietf-coreconf:error"
      A4                                        # map(4)
         69                                     # text(9)
            6572726F722D746167                  # "error-tag"
         6D                                     # text(13)
            696E76616C69642D76616C7565          # "invalid-value"
         6D                                     # text(13)
            6572726F722D6170702D746167          # "error-app-tag"
         6C                                     # text(12)
            6E6F742D696E2D72616E6765            # "not-in-range"
         6F                                     # text(15)
            6572726F722D646174612D6E6F6465      # "error-data-node"
         73                                     # text(19)
            74696D657A6F6E652D7574632D6F6666736574
                                                # "timezone-utc-offset"
         6D                                     # text(13)
            6572726F722D6D657373616765          # "error-message"
         70                                     # text(16)
            4D6178696D756D206578636565646564    # "Maximum exceeded"

6. Представление типов данных YANG в CBOR

Кодирование CBOR для экземпляра узла представления leaf или leaf-list зависит от встроенного типа этого узла представления. Ниже определяется кодирование CBOR для каждого встроенного типа, поддерживаемого в YANG (см. параграф 4.2.4 в [RFC7950]). В каждом параграфе приведён пример значения, выделенного экземпляру узла представления обсуждаемого встроенного типа.

6.1. Целочисленные типы без знака

Листья типов uint8, uint16, uint32, uint64 должны кодироваться с использованием беззнакового целочисленного элемента данных CBOR (базовый тип 0).

Пример из [RFC8344] показывает кодирование экземпляра узла представления mtu со значением 1280 байтов.

   leaf mtu {
     type uint16 {
       range "68..max";
     }
   }

Диагностическая нотация CBOR: 1280

Представление CBOR: 19 0500

6.2. Целочисленные типы

Листья типов int8, int16, int32, int64 должны кодироваться с использованием беззнакового целочисленного элемента данных CBOR (базовый тип 0) или отрицательного целого числа CBOR (базовый тип 1), в зависимости от фактического значения.

Пример из [RFC7317] показывает кодирование экземпляра узла представления timezone-utc-offset со значением -300 минут.

Пример определения из [RFC7317]

   leaf timezone-utc-offset {
     type int16 {
       range "-1500 .. 1500";
     }
   }

Диагностическая нотация CBOR: -300

Представление CBOR: 39 012B

6.3. decimal64

Листья типа decimal64 должны кодироваться с использованием десятичной дроби, как указано в параграфе 3.4.4 [RFC8949].

Пример из [RFC7317] показывает кодирование экземпляра узла представления my-decimal со значением 2,57.

   leaf my-decimal {
     type decimal64 {
       fraction-digits 2;
       range "1 .. 3.14 | 10 | 20..max";
     }
   }

Диагностическая нотация: CBOR 4([-2, 257])

Представление CBOR: C4 82 21 19 0101

6.4. string

Листья типа string должны кодироваться с использованием текстовой строки CBOR (базовый тип 3).

Пример из [RFC8343] показывает кодирование экземпляра узла представления name со значением eth0.

   leaf name {
     type string;
   }

Диагностическая нотация CBOR: «eth0»

Представление CBOR: 64 65746830

6.5. boolean

Листья типа boolean должны кодироваться с использованием простого значения CBOR true (базовый тип 7, дополнительное значение 21) или false (базовый тип 7, дополнительное значение 20).

Пример из [RFC7317] показывает кодирование экземпляра узла представления enabled со значением true.

   leaf enabled {
     type boolean;
   }

Диагностическая нотация CBOR: true

Представление CBOR: F5

6.6. enumeration

Листья типа enumeration должны кодироваться с использованием беззнакового целочисленного элемента данных CBOR (базовый тип 0) или отрицательного целого числа CBOR (базовый тип 1), в зависимости от фактического значения, или, в качестве исключения, как строка текста с тегом (см. ниже). Перечисляемые значения выделяются явно с использованием оператора YANG value или автоматически на основе алгоритма, описанного в параграфе 9.6.4.2 [RFC7950].

Пример из [RFC7317] показывает кодирование экземпляра узла представления oper-status со значением testing.

   leaf oper-status {
     type enumeration {
       enum up { value 1; }
       enum down { value 2; }
       enum testing { value 3; }
       enum unknown { value 4; }
       enum dormant { value 5; }
       enum not-present { value 6; }
       enum lower-layer-down { value 7; }
     }
   }

Диагностическая нотация CBOR: 3

Представление CBOR: 03

Значения типа enumeration, заданные в типе union должны кодироваться с использованием строки текста CBOR (базовый тип 3) и должны содержать одно из имён, назначенных оператором enum в YANG (см. параграф 6.12). Кодирование должно использовать тег перечисления CBOR, как указано в параграфе 9.3.

Пример определения из [RFC7950]

   type union {
     type int32;
     type enumeration {
       enum unbounded;
     }
   }

Диагностическая нотация CBOR: 44(«unbounded»)

Представление CBOR: D8 2C 69 756E626F756E646564

6.7. bits

С учётом того, что биты назначаются явно с помощью оператора YANG position или автоматически на основе алгоритма, заданного в параграфе 9.7.4.2 [RFC7950], каждый элемент типа bits можно рассматривать как набор битовых позиций (или смещений от позиции 0), имеющих значение 1 (бит установлен) или 0 (бит сброшен).

Листья типа bits должны кодироваться с использованием массива CBOR (базовый тип 4) или строки байтов (базовый тип 2), а в исключительных случаях — строки текста с тегом (см. ниже). При использовании массива CBOR каждый элемент является (1) положительным целым числом (базовый тип 0, дополнительное значение 0 не разрешено), которое служит для расчёта смещения следующей за ним строки байтов, или (2) строкой байтов (базовый тип 2) с информацией об установленных и сброшенных битах. Начальное смещение имеет значение 0 и каждое целое число без знака меняет смещение следующей за ним строки байтов на целое число, умноженное на 8. Например, если смещение бита равно 0 и имеется целое число 5, первый байт следующей строки байтов будет представлять битовые позиции от 40 до 47, включительно. Если строка байтов имеет второй байт, он будет содержать сведения о битах 48 — 55 и т. д. Внутри каждого байта биты назначаются от младшего к старшему. После строки байтов смещение меняется на число байтов в строке, умноженное на 8. Байты без установленных битов (0) в конце строки байтов не создаются. Если это происходит в конце массива, такие байты просто опускаются. Если же это возникает в конце строки байтов, предшествующей целому числу, байты с нулями удаляются и это целое число увеличивается на количество удалённых байтов с нулями.

В примере представлено кодирование экземпляра узла представления alarm-state с установленными флагами critical (позиция 2), warning ( позиция 8) и indeterminate (позиция 128).

   typedef alarm-state {
     type bits {
       bit unknown;
       bit under-repair;
       bit critical;
       bit major;
       bit minor;
       bit warning {
         position 8;
       }
       bit indeterminate {
         position 128;
       }
     }
   }

   leaf alarm-state {
     type alarm-state;
   }

Диагностическая нотация CBOR: [h’0401′, 14, h’01’]

Представление CBOR: 83 42 0401 0E 41 01

Во многих случаях массив будет содержать лишь 1 элемент — строку из нескольких байтов. В таком случае требуется опустить элемент массива и включать только строку (массив) байтов. В качестве примера рассмотрим приведённое выше определение YANG с кодированием лишь флагов under-repair и critical. Результат показан ниже.

Диагностическая нотация CBOR: h’06’

Представление CBOR: 41 06

Элементы массива должны быть строками байтов без нулевых байтов в конце или положительными целыми числами, которые должны чередоваться со строками байтов, т. е. два целых числа или две строки байтов подряд являются ошибкой. Массив с одной строкой байтов должен кодироваться просто как строка байтов. Массив с одним положительным целым числом является ошибкой. Отметим, что получатель может обрабатывать нулевые байты в конце по обычным правилам без каких-либо проблем, поэтому реализация может просто воспринимать их.

Значения типа bits, определённые в типе union, должны кодироваться с использованием строки текста CBOR (базовый тип 3) и должны содержать последовательность разделённых пробелами имён bits, которые установлены (см. параграф 6.12). Кодирование должно использовать тег CBOR, как указано в параграфе 9.3.

В примере показано кодирование экземпляра узла представления alarm-state, заданного с использованием типа union, где установлены флаги under-repair и critical.

   leaf alarm-state-2 {
     type union {
       type alarm-state;
       type bits {
         bit extra-flag;
       }
     }
   }

Диагностическая нотация CBOR: 43(«under-repair critical»)

Представление CBOR: D8 2B 75 756E6465722D72657061697220637269746963616C

6.8. binary

Листья типа binary должны кодироваться с использованием строки байтов CBOR (базовый тип 2).

Пример показывает кодирование экземпляра узла представления aes128-key со значением 0x1f1ce6a3f42660d888d92a4d8030476e.

   leaf aes128-key {
     type binary {
       length 16;
     }
   }

Диагностическая нотация CBOR: h’1F1CE6A3F42660D888D92A4D8030476E’

Представление CBOR 50: 1F1CE6A3F42660D888D92A4D8030476E

6.9. leafref

Листья типа leafref должны кодироваться по правилам узла представления, указанного оператором YANG path.

Приведённый пример из [RFC8343] показывает кодирование экземпляра узла представления interface-state-ref со значением eth1.

   typedef interface-state-ref {
     type leafref {
       path "/interfaces-state/interface/name";
     }
   }

   container interfaces-state {
     list interface {
       key "name";
       leaf name {
         type string;
       }
       leaf-list higher-layer-if {
         type interface-state-ref;
       }
     }
   }

Диагностическая нотация CBOR: «eth1»

Представление CBOR: 64 65746831

6.10. identityref

Спецификация поддерживает два подхода к кодированию identityref с применением YANG SID (параграф 3.2) или имени (параграф 6.8 в [RFC7951]). Исключение, требующее применять тег, описано в параграфе 6.12.

6.10.1. SID как identityref

При реализации узла представления типа identityref с применением SID он должен кодироваться целым числом без знака CBOR (базовый тип 0). Отметим, что механизм приращений для SID в качестве identityref не применяется, поскольку они не используются как ключи отображения CBOR.

Пример из [RFC7317] показывает кодирование экземпляра узла представления type со значением iana-if-type:ethernetCsmacd (SID 1880).

   identity interface-type {
   }

   identity iana-interface-type {
     base interface-type;
   }

   identity ethernetCsmacd {
     base iana-interface-type;
   }

   leaf type {
     type identityref {
       base interface-type;
     }
   }

Диагностическая нотация CBOR: 1880

Представление CBOR: 19 0758

6.10.2. Имя как identityref

Можно кодировать identityref с использованием имени, как указано в параграфе 3.3. В этом случае для кодирования identityref должна использоваться строка текста CBOR (базовый тип 3). Если отождествление задано не в том модуле, где содержится узел данных identityref, должно указываться полное (namespace-qualified) имя, в остальных случаях разрешены обе формы имён (см. параграф 3.3).

В примере показано кодирование отождествления iana-if-type:ethernetCsmacd с применением полного имени (см. параграф 6.10.1).

Диагностическая нотация CBOR: «iana-if-type:ethernetCsmacd»

Представление CBOR: 78 1B 69616E612D69662D747970653A65746865726E657443736D616364

6.11. empty

Листья типа empty должны кодироваться с использованием значения CBOR null (базовый тип 7, дополнительное значение 22).

Пример из [RFC8344] показывает кодирование экземпляра узла представления is-router, когда он имеется.

   leaf is-router {
     type empty;
   }

Диагностическая нотация CBOR: null

Представление CBOR: F6

6.12. union

Листья типа union должны кодироваться по правилам, связанным с одним из перечисленных ниже типов. При использовании в union указанные ниже типы данных YANG применяются с тегом CBOR для исключения путацицы между разными типами YANG, кодируемыми с использованием одного базового типа CBOR.

  • bits;

  • enumeration;

  • identityref;

  • instance-identifier.

Значения тегов CBOR указаны в параграфе 9.3.

Как отмечено в параграфах 6.6 и 6.7, типы enumeration и bits кодируются с помощью текстовых строк CBOR (базовый тип 3) при определении внутри типа union. Это повышает сложность, но необходимо из-за особенностей модели данных YANG для union — обходной путь обеспечивает совместимость с кодированием перекрывающихся объединений (union) в XML и JSON (см. параграф 9.12 в [RFC7950].)

Пример из [RFC6991] показывает кодирование экземпляра узла представления ip-address для значения 2001:db8:a0b:12f0::1.

   typedef ipv4-address {
     type string {
       pattern
         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
       + '(%[\p{N}\p{L}]+)?';
     }
   }

   typedef ipv6-address {
     type string {
       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
             + '(%[\p{N}\p{L}]+)?';
       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
             + '(%.+)?';
     }
   }

   typedef ip-address {
     type union {
       type ipv4-address;
       type ipv6-address;
     }
   }

   leaf address {
     type ip-address;
   }

Диагностическая нотация CBOR: «2001:db8:a0b:12f0::1»

Представление CBOR: 74 323030313A6462383A6130623A313266303A3A31

6.13. instance-identifier

Эта спецификация поддерживает два подхода к кодированию instance-identifier на основе YANG SID (параграф 3.2) и имён (параграф 3.3). Исключение, требующее применять тег, описано в параграфе 6.12.

6.13.1. SID как instance-identifier

SID однозначно указывает узел схемы. В случае одного экземпляра узла схемы, т. е. при его определении в корне модуля или субмодуля YANG или определении узлов схемы в контейнере, SID достаточно для идентификации экземпляра (узла представления). Отметим, что механизм приращений для SID не применяется (см. параграф 6.10.1.)

В случае узла представления, являющегося записью списка YANG значение SID комбинируется с ключами списка для идентификации каждого экземпляра в списке YANG.

В случае одного экземпляра кодирование instance-identifier должно использовать целое число без знака CBOR (базовый тип 0) со значением SID целевого узла схемы.

В списке YANG для кодирования instance-identifier должен применяться массив CBOR (базовый тип 4), как указано ниже:

  • первый элемент должен кодироваться как целое число без знака (базовый тип 0) со значением SID целевого узла схемы;

  • следующие элементы должны содержать значение ключа, требуемого для идентификации целевого узла схемы. Эти ключи должны быть упорядочены, как указано в операторе YANG key, начиная со списка верхнего уровня и продолжая подчинёнными списками.

Примеры в этом параграфе предполагают определение узла схемы типа instance-identifier. Пример определения из [RFC7950]

   container system {
     ...
     leaf reporting-entity {
       type instance-identifier;
     }

Первый пример

Пример определения из [RFC7317] показывает кодирование экземпляра узла представления reporting-entity со значением /system/contact (SID 1741).

   container system {

     leaf contact {
       type string;
     }

     leaf hostname {
       type inet:domain-name;
     }
   }

Диагностическая нотация CBOR: 1741

Представление CBOR: 19 06CD

Второй пример

Этот пример предназначен для демонстрации идентификации записи узла представления в списке YANG с использованием изменённой версии модуля YANG из [RFC7317] (добавление страны к листься и уполномоченным ключам). Пример иллюстрирует кодирование значения reporting-entity. Указывающего экземпляр списка /system/authentication/user/authorized-key/key-data (предполагается SID 1734) для имени пользователя bob и уполномоченного ключа с именем admin и страной france.

   list user {
     key name;

     leaf name {
       type string;
     }

     leaf password {
       type ianach:crypt-hash;
     }

     list authorized-key {
       key "name country";

       leaf country {
         type string;
       }

       leaf name {
         type string;
       }

       leaf algorithm {
         type string;
       }

       leaf key-data {
         type binary;
       }
     }
   }

Диагностическая нотация CBOR: [1734, «bob», «admin», «france»]

Представление CBOR

   84                 # array(4)
      19 06C6         # unsigned(1734)
      63              # text(3)
         626F62       # "bob"
      65              # text(5)
         61646D696E   # "admin"
      66              # text(6)
         6672616E6365 # "france"

Третий пример

Приведённый ниже пример показывает кодирование значения reporting-entity, указывающего экземпляр списка /system/authentication/user (SID 1730), соответствующий имени пользователя jack.

Диагностическая нотация CBOR: [1730, «jack»]

Представление CBOR

   82             # array(2)
      19 06C2     # unsigned(1730)
      64          # text(4)
         6A61636B # "jack"

6.13.2. Имена как instance-identifier

Значение instance-identifier кодируется как строка текста, аналогично лексическму представлению в XML (см. параграф 9.13.2 в [RFC7950]). Однако кодирование пространства имён в instance-identifier следует правилам параграфа 3.3:

  • самое левое (верхнего уровня) имя узла данных всегда имеет полную форму (namespace-qualified);

  • последующие имена узлов имеют полную форму, если узел определён не в родительском модуле, иначе применяется простая форма (это справедливо и для имён узлов в предикатах).

Например, /ietf-interfaces:interfaces/interface[name=’eth0′]/ietf-ip:ipv4/ip является действительным значением instance-identifier, поскольку узлы данных interfaces, interface, name определены в модуле ietf-interfaces, а ipv4 и ip — в ietf-ip.

Полученное в результате значение XML Path Language (XPath) должно кодироваться с использованием строки текста CBOR (базовый тип 3).

Ниже приведены примеры, описанные в параграфе 6.13.1.

Первый пример

Диагностическая нотация CBOR: «/ietf-system:system/contact»

Представление CBOR

   78 1B 2F696574662D73797374656D3A73797374656D2F636F6E74616374

Второй пример

Диагностическая нотация CBOR (the line break is inserted for exposition only)

   "/ietf-system:system/authentication/user[name='bob']/
   authorized-key[name='admin'][country='france']/key-data"

Представление CBOR

   78 6B
      2F696574662D73797374656D3A73797374656D2F61757468656E74696361
      74696F6E2F757365725B6E616D653D27626F62275D2F617574686F72697A
      65642D6B65795B6E616D653D2761646D696E275D5B636F756E7472793D27
      6672616E6365275D2F6B65792D64617461

Третий пример

Диагностическая нотация CBOR

   "/ietf-system:system/authentication/user[name='jack']"

Представление CBOR

   78 34                                   # text(52)
      2F696574662D73797374656D3A73797374656D2F61757468656E74696361
      74696F6E2F757365725B6E616D653D276A61636B275D

7. Content-Type

Эта спецификация определяет тип носителя application/yang-data+cbor, который можно использовать без параметров или с параметром id, содержащим имя (name) или SID (sid). Этот тип носителя представляет документ YANG-CBOR, содержащий дерево представления. При наличии параметра id в зависимости от его значения каждый узел представления указывается связанным с ним полным именем (namespace-qualified), как указано в параграфе 3.3 (id=name) или YANG SID (представленным, например, ключом отображения CBOR как приращение SID или с помощью тега 47), как указано в параграфе 3.2 (id=sid). При отсутствии параметра id могут применяться обе формы.

Форматом представления application/yang-data+cbor является отображение CBOR, сопоставляющее имена и/или SID (как указано выше) со значениями экземпляров (по правилам раздела 4).

В настоящее время не пердполагается использование для параметра id значений, отличающихся от имени и SID, или отсуствие параметра. Если такое расширение произойдёт, предполагается, что новые значения будут иметь форму [a-z][a-z0-9]*(-[a-z0-9]+)*.

Таким образом, документ задаёт 3 content-type, предназначенных для разных классов приложений.

  • application/yang-data+cbor, id=sid — для приложений, которым требуется экономить пространство кодирования и обработку строк текста (например, приложения на узлах с ограничениями [RFC7228] или с особыми требованиями к производительности).

  • application/yang-data+cbor, id=name — для приложений, которые не хотят поддерживать SID и располагают достаточными ресурсами для работы со строками текста (например, приложения, желающие напрямую заменить application/yang.data+json более эффективным представлением без внесения других изменений).

  • application/yang-data+cbor — для комплексных приложений, которые могут получить преимущество от повышенной эффективности идентификаторов SID, сохраняя интеграцию с базами модулей YANG, пока для них не заданы отображения SID.

Все три content-type основаны на одних механизмах представления, части которых в первом и втором случае просто не используются.

Использование одного из трёх content-type в транспортном протоколе выходит за рамки спецификации. В последнем абзаце параграфа 5.2 [RFC8040] рассматривается индикация и запрос использования конкретных content-type в RESTCONF. Похожие механизмы доступны в протоколе ограниченных приложений (Constrained Application Protocol или CoAP) [RFC7252] на основе опций Content-Format и Accept. В [CORE-COMI] показано, как можно использовать Content-Format для индикации в случае id=sid.

8. Вопросы безопасности

Применимы соображения безопасности, отмеченные в [RFC8949] и [RFC7950].

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

Для снижения рисков приложениям на приёмной стороне следует отвергать все сообщения, не соответствующие правилам этого документа, возвращая отправителю подходящее сообщение об ошибке. Например, при использовании параметра id для типа носителя важно корректно отклонять идентификаторы иного типа, чтобы избежать ситуаций, когда другие реализации по-иному интерпретируют такое содержимое.

При использовании SID интерпретация кодированных данных зависит не только от наличия корректных модулей YANG, но и от правильного отображения SID. Поэтому поддержка и развитие сведений об отображении требует такой же осторожности, как и управление модулями YANG. Процедуры [CORE-SID] учитывают это обстоятельство.

9. Взаимодействие с IANA

9.1. Реестр Media Types

Агентство IANA добавило указанный в таблице 2 тип носителя в реестр Media Types [IANA.media-types].

Таблица 2. Реестр Media Types.

 

Имя

Шаблон

Документ

yang-data+cbor

application/yang-data+cbor

RFC 9254

 

Type name: application
Subtype name: yang-data+cbor
Required parameters: N/A
Optional parameters: id (раздел 7 в RFC 9254)
Encoding considerations: binary (CBOR)
Security considerations: раздел 8 в RFC 9254
Interoperability considerations: N/A
Published specification: RFC 9254
Applications that use this media type: Приложения, которым нужно компактное и эффективное представление данных моделей YANG
Fragment identifier considerations: Синтаксис и семантика идентификатров фрагментов для application/yang-data+cbor совпадают с заданными для application/cbor (на момент публикации этого документа синтаксис идентификации фрагментов для application/cbor не был определен)
Additional information:
Magic number(s): N/A
File extension(s): N/A
Macintosh file type code(s): N/A
Person & email address to contact for further information: почтовая конференция CORE WG (core@ietf.org) или IETF Applications and Real-Time Area (art@ietf.org)
Intended usage: COMMON
Restrictions on usage: N/A
Author: CoRE WG
Change controller: IETF

9.2. Реестр CoAP Content-Formats

Агентство IANA добавило указанные в таблице 3 значения Content-Formats в субреестр CoAP Content-Formats реестра Constrained RESTful Environments (CoRE) Parameters [IANA.core-parameters]. Применяется процедура Expert Review для диапазона 0 — 255 и IETF Review — для 256 — 9999.

Таблица 3. Реестр CoAP Content-Format.

 

Тип носителя

Кодирование

Идентификатор

Документ

application/yang-data+cbor

340

RFC 9254

application/yang-data+cbor; id=name

341

RFC 9254

application/yang-data+cbor; id=sid

140

RFC 9254

 

9.3. Реестр CBOR Tags

Агентство IANA выделило номера тегов CBOR в реестре CBOR Tags [IANA.cbor-tags] заданнов в параграфе 9.2 [RFC8949].

Таблица 4. Реестр CBOR Tags

Тег

Элемент данных

Семантика

Документ

43

Строка текста

Тип YANG bits, параграф 6.7.

RFC 9254

44

Строка текста

Тип YANG enumeration, параграф 6.6.

RFC 9254

45

Целое число без знака или строка текста

Тип YANG identityref, параграф 6.10.

RFC 9254

46

Целое число без знака, строка текста или массив

Тип YANG instance-identifier, параграф 6.13.

RFC 9254

47

Целое число без знака

Тип YANG Schema Item iDentifier (SID), параграф 3.2.

RFC 9254

10. Литература

10.1. Нормативные документы

[IANA.cbor-tags] IANA, «Concise Binary Object Representation (CBOR) Tags», <https://www.iana.org/assignments/cbor-tags>.

[IANA.core-parameters] IANA, «Constrained RESTful Environments (CoRE) Parameters», <https://www.iana.org/assignments/core-parameters/>.

[IANA.media-types] IANA, «Media Types», <https://www.iana.org/assignments/media-types/>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC5234] Crocker, D., Ed. and P. Overell, «Augmented BNF for Syntax Specifications: ABNF», STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, <https://www.rfc-editor.org/info/rfc5234>.

[RFC7950] Bjorklund, M., Ed., «The YANG 1.1 Data Modeling Language», RFC 7950, DOI 10.17487/RFC7950, August 2016, <https://www.rfc-editor.org/info/rfc7950>.

[RFC7951] Lhotka, L., «JSON Encoding of Data Modeled with YANG», RFC 7951, DOI 10.17487/RFC7951, August 2016, <https://www.rfc-editor.org/info/rfc7951>.

[RFC8040] Bierman, A., Bjorklund, M., and K. Watsen, «RESTCONF Protocol», RFC 8040, DOI 10.17487/RFC8040, January 2017, <https://www.rfc-editor.org/info/rfc8040>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8259] Bray, T., Ed., «The JavaScript Object Notation (JSON) Data Interchange Format», STD 90, RFC 8259, DOI 10.17487/RFC8259, December 2017, <https://www.rfc-editor.org/info/rfc8259>.

[RFC8610] Birkholz, H., Vigano, C., and C. Bormann, «Concise Data Definition Language (CDDL): A Notational Convention to Express Concise Binary Object Representation (CBOR) and JSON Data Structures», RFC 8610, DOI 10.17487/RFC8610, June 2019, <https://www.rfc-editor.org/info/rfc8610>.

[RFC8791] Bierman, A., Björklund, M., and K. Watsen, «YANG Data Structure Extensions», RFC 8791, DOI 10.17487/RFC8791, June 2020, <https://www.rfc-editor.org/info/rfc8791>.

[RFC8949] Bormann, C. and P. Hoffman, «Concise Binary Object Representation (CBOR)», STD 94, RFC 8949, DOI 10.17487/RFC8949, December 2020, <https://www.rfc-editor.org/info/rfc8949>.

10.2. Дополнительная литература

[CORE-COMI] Veillette, M., Ed., van der Stok, P., Ed., Pelov, A., Bierman, A., and I. Petrov, Ed., «CoAP Management Interface (CORECONF)», Work in Progress, Internet-Draft, draft-ietf-core-comi-11, 17 January 2021, <https://datatracker.ietf.org/doc/html/draft-ietf-core-comi-11>.

[CORE-SID] Veillette, M., Ed., Pelov, A., Ed., Petrov, I., Ed., Bormann, C., and M. Richardson, «YANG Schema Item iDentifier (YANG SID)», Work in Progress, Internet-Draft, draft-ietf-core-sid-18, 18 November 2021, <https://datatracker.ietf.org/doc/html/draft-ietf-core-sid-18>.

[RFC6241] Enns, R., Ed., Bjorklund, M., Ed., Schoenwaelder, J., Ed., and A. Bierman, Ed., «Network Configuration Protocol (NETCONF)», RFC 6241, DOI 10.17487/RFC6241, June 2011, <https://www.rfc-editor.org/info/rfc6241>.

[RFC6991] Schoenwaelder, J., Ed., «Common YANG Data Types», RFC 6991, DOI 10.17487/RFC6991, July 2013, <https://www.rfc-editor.org/info/rfc6991>.

[RFC7228] Bormann, C., Ersue, M., and A. Keranen, «Terminology for Constrained-Node Networks», RFC 7228, DOI 10.17487/RFC7228, May 2014, <https://www.rfc-editor.org/info/rfc7228>.

[RFC7252] Shelby, Z., Hartke, K., and C. Bormann, «The Constrained Application Protocol (CoAP)», RFC 7252, DOI 10.17487/RFC7252, June 2014, <https://www.rfc-editor.org/info/rfc7252>.

[RFC7317] Bierman, A. and M. Bjorklund, «A YANG Data Model for System Management», RFC 7317, DOI 10.17487/RFC7317, August 2014, <https://www.rfc-editor.org/info/rfc7317>.

[RFC8343] Bjorklund, M., «A YANG Data Model for Interface Management», RFC 8343, DOI 10.17487/RFC8343, March 2018, <https://www.rfc-editor.org/info/rfc8343>.

[RFC8344] Bjorklund, M., «A YANG Data Model for IP Management», RFC 8344, DOI 10.17487/RFC8344, March 2018, <https://www.rfc-editor.org/info/rfc8344>.

Благодарности

Этот документ в значительной мере вдохновлен обширной работой Andy Bierman и Peter van der Stok над [CORE-COMI]. Докумен [RFC7951] также внёс важный вклад в эту работу. Спасибо авторам и участникам создания этих документов.

Авторы хотели бы также поблагодарить Ladislav Lhotka и Jürgen Schönwälder, а также «куратора» документа Marco Tiloca за обзор, отзывы и комментации. Обширные комментарии в процессе рецензирования IESG помогли улучшить документ и авторы хотели бы особо отметить отзывы и рекомендации от руководителя направления (AD) Francesca Palombini, а также существенные улучшения, предложенные членами IESG Benjamin Kaduk и Rob Wilton.

Адреса авторов

Michel Veillette (editor)
Trilliant Networks Inc.
610 Rue du Luxembourg
Granby Quebec J2J 2V2
Canada
Email: michel.veillette@trilliantinc.com
 
Ivaylo Petrov (editor)
Google Switzerland GmbH
Brandschenkestrasse 110
CH-8002 Zurich
Switzerland
Email: ivaylopetrov@google.com
 
Alexander Pelov
Acklio
1137A avenue des Champs Blancs
35510 Cesson-Sevigne Cedex
France
Email: a@ackl.io
 
Carsten Bormann
Universität Bremen TZI
Postfach 330440
D-28359 Bremen
Germany
Phone: +49-421-218-63921
Email: cabo@tzi.org
 
Michael Richardson
Sandelman Software Works
Canada
Email: mcr+ietf@sandelman.ca

Перевод на русский язык

Николай Малых

nmalykh@protokols.ru

1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

Рубрика: RFC | Оставить комментарий

RFC 9114 HTTP/3

Internet Engineering Task Force (IETF)                    M. Bishop, Ed.
Request for Comments: 9114                                        Akamai
Category: Standards Track                                      June 2022
ISSN: 2070-1721

HTTP/3

PDF

Аннотация

Транспортный протокол QUIC имеет ряд особенностей, таких как мультиплексирования потоков, управление потоком данных на уровне потока, быстрая организация соединений, которые желательно использовать в транспорте для HTTP. В этом документе рассматривается отображение семантики HTTP на QUIC. Документ также указывает свойства HTTP/2, включённые в QUIC, и описывает перенос расширений HTTP/2 в HTTP/3.

Статус документа

Документ относится к категории Internet Standards Track.

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG2. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке https://www.rfc-editor.org/info/rfc9114.

Авторские права

Copyright (c) 2022. Авторские права принадлежат IETF Trust и лицам, указанным в качестве авторов документа. Все права защищены.

К документу применимы права и ограничения, указанные в BCP 78 и IETF Trust Legal Provisions и относящиеся к документам IETF (http://trustee.ietf.org/license-info), на момент публикации данного документа. Прочтите упомянутые документы внимательно. Фрагменты программного кода, включённые в этот документ, распространяются в соответствии с упрощённой лицензией BSD, как указано в параграфе 4.e документа IETF Trust Legal Provisions, без каких-либо гарантий (как указано в Revised BSD License).

1. Введение

Семантика HTTP ([HTTP]) используется для широкого спектра услуг Internet и чаще всего применяется с HTTP/1.1 и HTTP/2. Протокол HTTP/1.1 использовался с разными транспортными и сеансовыми уровнями, HTTP/2 — в основном с TLS по протоколу TCP. HTTP/3 поддерживает ту же семантику с новым транспортным протоколом QUIC.

1.1. Прежние версии HTTP

В HTTP/1.1 [HTTP/1.1] при передаче сообщений HTTP используются поля, ограниченные пробельными символами. Хотя это удобно для человека, использование пробельных символов при форматировании сообщений усложняет разбор и слишком терпимо к вариативному поведению.

Поскольку в HTTP/1.1 нет уровня мультиплексирования, часто используется множество соединений TCP для обслуживания запросов в параллель. Однако это оказывает негативное влияние на контроль перегрузок и эффективность сети, поскольку в TCP нет общего контроля перегрузок для нескольких соединений.

В HTTP/2 ([HTTP/2]) введено двоичное кадрирование и уровень мультиплексирования для сокращения задержек без изменения транспортного уровня. Однако параллельная работа мультиплексирования HTTP/2 не видна механизмам восстановления потерь в TCP, поэтому потеря или нарушение порядка пакетов ведёт к остановке всех активных транзакций, независимо от их связи с потерянными пакетами.

1.2. Передача полномочий в QUIC

Транспортный протокол QUIC включает мультиплексирование потоков и управление потоком данных ка уровне потока (stream), аналогичные предоставляемым уровнем кадрирования HTTP/2. Обеспечивая надёжность на уровне потока и контроль перегрузок во всем соединении, QUIC способен повысить производительность HTTP по сравнению с работой по протоколу TCP. QUIC также включает TLS 1.3 ([TLS]) на транспортном уровне, обеспечивая конфиденциальность и целостность, сравнимые с работой TLS по протоколу TCP, а также сокращение задержки при организации соединений TCP (Fast Open) [TFO].

Этот документ определяет HTTP/3 — отображение семантики HTTP на транспортный протокол QUIC в значительной степени основанное на HTTP/2. HTTP/3 полагается на QUIC для защиты конфиденциальности и целостности данных, проверки подлинности партнёров, а также надёжной, упорядоченной доставки по потокам. Полномочия управления сроком действия потока и управления потоком данных передаются в QUIC, а двоичное кадрирование в каждом потоке похоже на кадрирование HTTP/2. Некоторые свойства HTTP/2 включены в QUIC, а иные реализованы над QUIC.

Протокол QUIC описан [QUIC-TRANSPORT], полное описание HTTP/2, приведено в [HTTP/2].

2. Обзор протокола HTTP/3

HTTP/3 предоставляет транспорт для семантики HTTP, используя транспортный протокол QUIC и внутренний уровень кадрирования, похожий на HTTP/2.

Когда клиент знает о наличии сервера HTTP/3 в некой конечной точке, он организует соединение QUIC. QUIC обеспечивает согласование протокола, мультиплексирование по потокам и управление потоком данных. Обнаружение конечных точек HTTP/3 описано в параграфе 3.1.

В каждом потоке базовым коммуникационным блоком HTTP/3 служит кадр (параграф 7.2). Каждый тип кадра применяется для своих целей, например, кадры HEADERS и DATA являются основой запросов и откликов HTTP (параграф 4.1). Кадры, относящиеся к соединению в целом, передаются в выделенном потоке управления.

Мультиплексирование запросов выполняется с использованием абстракции потока QUIC, описанной в разделе 2 [QUIC-TRANSPORT]. Для каждой пары запрос-отклик применяется один поток QUIC. Потоки не зависят один от другого, поэтому блокировка потока или потеря пакетов не препятствует работе других потоков.

Серверное выталкивание (push) — это введённый в HTTP/2 ([HTTP/2]) механизм взаимодействия, позволяющий серверы выталкивать клиенту обмен запрос-отклик в ожидании того, что клиент сделает указанный запрос. Это является компромиссом между загрузкой сети и возможным сокращением задержки. Некоторые кадры HTTP/3 (такие как PUSH_PROMISE, MAX_PUSH_ID, CANCEL_PUSH) служат для управления выталкиванием с сервера.

Как и в HTTP/2поля запросов и откликов сжимаются для передачи. Поскольку HPACK [HPACK] полагается на упорядоченную передачу разделов сжатых полей, QUIC не гарантирует этого, в HTTP/3 вместо HPACK применяется QPACK [QPACK]. В QPACK используются отдельные односторонние потоки для изменения и отслеживания состояния таблицы полей, а кодированные разделы полей ссылаются на состояние таблицы, не изменяя её.

2.1. Состав документа

Подробный обзор жизненного цикла соединений HTTP/3 включает:

  • раздел 3, посвящённый обнаружению конечных точек HTTP/3 и организации соединений HTTP/3;

  • раздел 4, описывающий выражение семантики HTTP с помощью кадров;

  • раздел 5, описывающий прерывание соединений HTTP/3 (аккуратное и внезапное).

Детали протокола передачи и взаимодействия с транспортом включают:

  • раздел 6, описывающий применение потоков QUIC;

  • раздел 7, описывающий кадры, применяемые в большинстве потоков;

  • раздел 8, описывающий ошибки и их обработку для отдельного потока и соединения в целом.

Финальная часть документа включает дополнительные ресурсы:

  • раздел 9, описывающий добавление новых возможностей в будущих документах;

  • Приложение A, сравнивающее HTTP/2 и HTTP/3.

2.2. Соглашения и термины

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

В этом документе используется кодирование целых чисел переменного размера из [QUIC-TRANSPORT].

Ниже даны определения используемых в документе терминов.

abort — прерывание

Внезапное завершение соединения или потока, возможно из-за ошибки.

client — клиент

Конечная точка, инициирующая соединение HTTP/3. Клиенты передают запросы и получают отклики HTTP.

connection — соединение

Соединение транспортного уровня между парой конечных точек, использующих транспортный протокол QUIC.

connection error — ошибка соединения

Ошибка, влияющая на всё соединение HTTP/3.

endpoint — конечная точка

Клиент или сервер в соединении.

frame — кадр

наименьшая коммуникационная единица в потоке HTTP/3, состоящая из заголовка и последовательности байтов переменного размера, структура которой определяется типом кадра.
Элементы протокола, называемые кадрами, присутствуют в этом документе и [QUIC-TRANSPORT]. При обсуждении кадров [QUIC-TRANSPORT] добавляется QUIC, например QUIC CONNECTION_CLOSE. В иных случаях имеются в виду кадры, определённые в параграфе 7.2.

HTTP/3 connection — соединение HTTP/3

Соединение QUIC с согласованным прикладным протоколом HTTP/3.

peer — партнёр

Конечная точка. При обсуждении конкретной конечной точки термин «партнёр» относится к удалённой течке.

receiver — получатель

Конечная точка, принимающая кадры.

sender — отправитель

Конечная точка, передающая кадры.

server — сервер

Конечная точка, воспринимающая соединение HTTP/3. Сервер получает запросы и передаёт отклики HTTP.

stream — поток

Односторонний или двухсторонний поток байтов, обеспечиваемый транспортом QUIC. Все потока соединения HTTP/3 могут считаться потоками HTTP/3, однако в HTTP/3 имеется несколько типов потоков.

stream error — ошибка потока

Ошибка прикладного уровня в отдельном потоке.

Термин «содержимое» (content) определён в параграфе 6.4 [HTTP], термины «ресурс» (resource), «сообщение» (message), «пользовательский агент» (user agent), «сервер-источник» (origin server), «шлюз» (gateway), «посредник» (intermediary), «прокси» (proxy) и «туннель» (tunnel) — в разделе 3 [HTTP].

Пакеты в этом документе показаны в формате, заданном в параграфе 1.3 [QUIC-TRANSPORT], для иллюстрации порядка и размера полей.

3. Организация и поддержка соединений

3.1. Обнаружение конечных точек HTTP/3

HTTP полагается на понятие полномочного отклика, т. е. отклика, сочтённого наиболее подходящим для запроса с учётом состояния целевого ресурса в момент создания сообщения с откликом сервером-источником (или по его указанию), указанным в URI цели. Определение полномочного сервера для HTTP URI описано в параграфе 4.3 [HTTP].

Схема https связывает полномочия с владением сертификатом, который клиент считает доверенным для хоста, указанного компонентом authority в URI. Получив сертификат сервера при согласовании TLS, клиент должен проверить, что этот сертификат приемлем для сервера источника из URI по процедуре, описанной в параграфе 4.3.4 [HTTP]. Если сертификат не удаётся проверить по отношению к серверу источнику в URI, клиенту недопустимо считать этот сервер полномочным для источника.

Клиент может попытаться обратиться к ресурсы по https URI, путём преобразования идентификатора хоста в адрес IP, организации соединения QUIC с этим адресом на указанном порту (включая проверку сертификата сервера, как указано выше) и передачи запросного сообщения HTTP/3, нацеленного URI на сервер через защищённое соединение. Если для выбора HTTP/3 не применяется иной механизм, используется маркер h3 в расширении согласования протокола прикладного уровня (Application-Layer Protocol Negotiation или ALPN, см. [RFC7301]) при согласовании TLS.

Проблемы связности (например, блокировка UDP) могут приводить к отказу при организации соединения QUIC и клиентам следует в таких случаях пытаться использовать основанные на TCP версии HTTP.

Серверы могут обслуживать HTTP/3 на любом порту UDP и анонсы дополнительных служб всегда явно включают порт, а URI содержат явный порт или используют принятый по умолчанию для схемы.

3.1.1. Дополнительные службы HTTP

Источник HTTP может анонсировать доступность эквивалентной конечной точки HTTP/3 в поле заголовка отклика HTTP Alt-Svc или в кадре HTTP/2 ALTSVC ([ALTSVC]), используя маркер ALPN h3. Например, источник может инициировать отклик HTTP о доступности HTTP/3 на порту UDP 50781 хоста с тем же именем, включая в заголовок поле

   Alt-Svc: h3=":50781"

При получении записи Alt-Svc, указывающей поддержку HTTP/3, клиент может попытаться организовать соединение QUIC с указанным хостом и портом и при успехе — передавать запросы HTTP с использованием описанного в этом документе отображения.

3.1.2. Другие схемы

Хотя HTTP не зависит от транспортного протокола, схема http связывает полномочия (authority) с возможностью принимать соединения TCP на указанном порту любого хоста, идентифицированного компонентом authority. Поскольку HTTP/3 не использует TCP, HTTP/3 не может служить для прямого доступа к полномочному серверу ресурса, указанного http URI. Однако расширения протокола, такие как [ALTSVC], позволяют полномочному серверу указать другие службы, которые тоже имеют полномочия и могут быть доступны по протоколу HTTP/3.

Перед запросом к источнику, чья схема отличается от https, клиент должен убедиться в готовности сервера обслуживать эту схему. Для источников со схемой http экспериментальный метод решения этой задачи описан в [RFC8164]. В будущем могут быть определены другие механизмы для различных схем.

3.2. Организация соединения

HTTP/3 работает на основе базового транспорта QUIC версии 1. Будущие спецификации могут задавать другие версии транспорта QUIC для HTTP/3.

QUIC версии 1 использует TLS версии 1.3 или выше в качестве протокола согласования. Клиент HTTP/3 должен поддерживать механизм указания серверу целевого хоста при согласовании TLS. При указании сервера доменным именем [DNS-TERMS], клиенты должны передавать расширение TLS для индикации имени сервера (Server Name Indication или SNI) [RFC6066], если не применяется дополнительный механизм указания целевого хоста.

Соединения QUIC организуются в соответствии с [QUIC-TRANSPORT]. В процессе организации поддержка HTTP/3 указывается выбором маркера ALPN h3 в согласовании TLS. В том же согласовании может быть предложена поддержка других прикладных протоколов.

Опции на уровне соединения, относящиеся к ядру протокола QUIC, устанавливаются при начальном криптографическом согласовании, а опции HTTP/3 передаются в кадре SETTINGS. После организации соединения QUIC каждая из конечных точек должна передать кадр SETTINGS в качестве первого кадра в соответствующего потока управления HTTP.

3.3. Повторное использование соединения

Соединения HTTP/3 сохраняются для множества запросов. Предполагается, что для повышения производительности клиенты не будут закрывать соединения, пока не поймут, что продолжение взаимодействия с сервером больше не нужно (например, при уходе пользователя с web-страницы) или пока сервер не закроет соединения.

После организации соединения с конечной точкой сервера это соединение можно использовать неоднократно для запросов с разными компонентами authority в URI. Для использования имеющегося соединения с новым источником, клиент должен проверить предоставленный сервером сертификат нового источника с использованием процесса, описанного в параграф 4.3.4 [HTTP]. Это означает, что клиенту нужно сохранять сертификат сервера и любые дополнительные сведения, требуемые для его проверки. Не сделав этого, клиент не сможет повторно использовать соединение для дополнительных источников.

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

Клиентам не следует создавать более одного соединения HTTP/3 для данного адреса IP и порта UDP, когда адрес и порт могут быть получены из URI, выбранной дополнительной службы ([ALTSVC]), настроенного прокси или распознавания имён для любого из них. Клиент может создать несколько соединений HTTP/3 с одним адресом IP и портом UDP, используя различные конфигурации транспорта или TLS, но следует избегать создания нескольких соединений с одной конфигурацией.

Серверам рекомендуется поддерживать открытые соединения HTTP/3 как можно дольше, но при необходимости можно разрывать бездействующие (idle) соединения. Когда любая из конечных точек решает закрыть соединение HTTP/3, ей следует сначала передать кадр GOAWAY (параграф 5.2), чтобы обе конечные точки могли надёжно определить, были ли обработаны ранее переданные кадры и прервать все оставшиеся задачи.

Сервер, не желающий, чтобы клиенты повторно использовали соединения HTTP/3 для определённого источника, может указать, что он не является полномочным для запроса, передав код статуса 421 (Misdirected Request) в отклике на запрос (см. параграф 7.4 в [HTTP]).

4. Семантика HTTP в HTTP/3

4.1. Кадрирование сообщений HTTP

Клиент передаёт запрос HTTP в потоке запросов, который является инициированым клиентом двухстороннем потоке QUIC (см. параграф 6.1). Клиент должен передавать в данном потоке лишь один запрос. Сервер может передавать промежуточные отклики HTTP в том же потоке, затем передаёт один финальный отклик HTTP, как описано ниже. Описание промежуточных и финальных откликов дано в разделе 15 [HTTP].

Выталкиваемые (push) отклики передаются в инициированном сервером одностороннем потоке QUIC (см. параграф 6.2.2). Сервер может передать промежуточные отклики HTTP, за которыми следует один финальный отклик HTTP, как при стандартном отклике. Выталкивание более подробно описано в параграфе (4.6).

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

Сообщение HTTP (запрос или отклик) состоит из:

  1. раздела заголовков, включающего данные управления и переданного в одном кадре HEADERS;

  2. необязательного содержимого в виде последовательности кадров DATA;

  3. необязательного раздела трейлеров в кадре HEADERS.

Разделы заголовков и трейлеров описаны в параграфах 6.3 и 6.5 [HTTP], содержимое в параграфе 6.4 [HTTP].

Получение недействительной последовательности кадров должно считаться ошибкой соединения типа H3_FRAME_UNEXPECTED. В частности, это может быть кадр DATA перед кадром HEADERS, кадры HEADERS или DATA после трейлерного кадра HEADERS. Иные типы кадров (особенно, неизвестные) могут разрешаться в соответствии с правилами для них (см. раздел 9).

Сервер может передать один или несколько кадров PUSH_PROMISE перед, в промежутке или после кадров сообщения с откликом. Эти кадры PUSH_PROMISE не относятся к отклику (см. параграф 4.6). Кадры PUSH_PROMISE не разрешается передавать в push-потоках и вытолкнутый отклик с кадрами PUSH_PROMISE должен считаться ошибкой соединения типа H3_FRAME_UNEXPECTED.

Кадры неизвестных типов (раздел 9), включая резервные (параграф 7.2.8) можно передавать в поток запроса или выталкивания до, после или между другими кадрами, описанными в этом разделе.

Кадры HEADERS и PUSH_PROMISE могут указывать обновления динамической таблицы QPACK. Хотя эти обновления и не являются напрямую частью обмена сообщениями, они должны приниматься и передаваться для использования сообщения (см. параграф 4.2).

Транспортное кодирование (раздел 7 в [HTTP/1.1]) не определено для HTTP/3 и заголовок Transfer-Encoding применять недопустимо.

Отклик может состоять из множества сообщений тогда и только тогда, одно или несколько промежуточных сообщений (1xx, см. параграф 15.2 в [HTTP]) предшествует финальному отклику на тот же запрос. Промежуточные отклики не имеют содержимого и разделе трейлеров.

Обмен HTTP запрос-отклик полностью занимает инициированный клиентом двухсторонний поток QUIC. После отправки запроса клиент должен закрыть поток для передачи. Если не применяется метод CONNECT (параграф 4.4), клиенту недопустимо ставить закрытие потока в зависимость от получения отклика на свой запрос. После приёма финального отклика сервер закрыть поток для передачи. С этого момента поток QUIC полностью закрыт.

Закрытие потока означает конец финального сообщения HTTP. Поскольку некоторые сообщения велики и не ограничены, конечной точке следует начинать обработку частичных сообщений HTTP, как получено достаточное для обработки число сообщений. Если инициированный клиентом поток прерывается без достаточного для предоставления полного отклика числа сообщений HTTP, серверу следует прервать поток отклика с кодом ошибки H3_REQUEST_INCOMPLETE.

Сервер может отправить полный отклик до того, как клиент полностью передаст запрос, если отклик не зависит от ещё не полученных частей запроса. Если серверу не нужна остальная часть запроса, он может прервать считывание потока запроса, передать полный отклик и полностью закрыть передающую часть потока. При запросе к клиенту прекратить передачу в поток запроса следует применять код ошибки H3_NO_ERROR. Клиентам недопустимо отбрасывать полные отклики в результате внезапного прерывания их запроса, хотя они всегда могут отбрасывать отклики по своему усмотрению в силу иных причин. Если сервер передал частичный или полный отклик, но не прервал чтение запроса, клиенту следует продолжать передачу содержимого запроса и завершить поток как обычно.

4.1.1. Отмена и отклонение запросов

После открытия потока запроса этот запрос может отклонить любая из конечных точек. Клиенты отклоняют запрос, если он больше не нужен, серверы — при неспособности или нежелании выполнять запрос. Серверам рекомендуется по возможности передавать отклик HTTP с подходящим кодом статуса вместо отмены запроса, обработка которого уже начата. Реализациям следует отклонять запросы прерыванием всех направлений потока, которые ещё открыты. Для этого реализация сбрасывает (reset) передающие стороны потоков и прерывает считывание в приёмных частых (см. параграф 2.4 в [QUIC-TRANSPORT]).

Отмена запроса сервером без какой-либо обработки приложением считается отклонением (reject) запроса. Серверу следует прервать свой поток отклика с кодом ошибки H3_REQUEST_REJECTED. В этом контексте обработка означает, что некоторые данные из потока были переданы программам вышележащего уровня, которые в результате могут выполнить те или иные действия. Клиент может считать запрос, отклонённый (отвергнутый) сервером, непереданным совсем, что позволяет позднее повторить запрос. Серверам недопустимо использовать код ошибки H3_REQUEST_REJECTED для запросов, которые были частично или полностью обработаны. При прерывании сервером отклика после частичной обработки ему следует прерывать свой поток откликов с кодом ошибки H3_REQUEST_CANCELLED.

Клиенту следует применять для отмены запроса код ошибки H3_REQUEST_CANCELLED. При получении этого кода сервер может резко прервать отклик, используя код ошибки H3_REQUEST_REJECTED, если обработка не выполнялась. Клиенту недопустимо применять код ошибки H3_REQUEST_REJECTED, за исключением случаев, когда сервер запросил закрытие потока запроса с тем же кодом.

Если поток отменен после приёма полного отклика, клиент может игнорировать отмену и использовать отклик. Однако при отмене потока после получения лишь частичного отклика применять такой отклик не следует. Безопасно можно повторять лишь идемпотентные методы, такие как GET, PUT, DELETE, и клиенту не следует автоматически повторять запросы с неидемпотентным методом, если у него нет возможности узнать, что семантика запроса идемпотентна независимо от метода, или определить, что исходный запрос так и не был применён (см. параграф 9.2.2 в [HTTP]).

4.1.2. Запросы и отклики некорректной формы

Запросы и отклики считаются сформированными некорректно, если в них применяется верная последовательность кадров, но встречается какая-либо из указанных ниже ошибок.

  • Наличие запрещённых полей или полей псевдозаголовка.

  • Отсутствие обязательных полей псевдозаголовка.

  • Недействительные значения полей псевдозаголовка.

  • Поля псевдозаголовка после других полей (заголовок или трейлер).

  • Недействительная последовательность сообщений HTTP.

  • Заглавные буквы в именах полей.

  • Недопустимые символы в именах или значениях полей.

Запрос или отклик, для которого определено содержимое, включающий поле Content-Length (параграф 8.6 в [HTTP]), считается некорректно сформированным, если значение поля заголовка Content-Length не совпадает с суммой размеров полученных кадров DATA. Отклик, для которого задано отсутствие содержимого, может иметь ненулевое значения поля Content-Length даже при отсутствии содержимого в кадрах DATA.

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

Для некорректно сформированного запроса сервер может передать указывающий ошибку отклик HTTP до закрытия или сброса потока. Клиентам недопустимо воспринимать некорректно сформированные отклики. Отметим, что эти требования предназначены для защиты от некоторых распространённых атак на HTTP и намеренно сделаны строгими, поскольку попустительство может приводить к уязвимостям реализации.

4.2. Поля HTTP

Сообщения HTTP переносят метаданные как последовательность пар ключ-значение, называемых полями HTTP (см. параграфы 6.3 и 6.5 в [HTTP]). Список зарегистрированных полей HTTP содержится в реестре Hypertext Transfer Protocol (HTTP) Field Name Registry (https://www.iana.org/assignments/http-fields/). Как и в HTTP/2, для HTTP/3 имеются дополнительные соображения, связанные с использованием символов в именах полей, поле заголовка Connection и полях псевдозаголовка. Имена полей являются строки, содержащими подмножество символов ASCII. Свойства имён и значений полей HTTP рассмотрены в параграфе 5.1 [HTTP]. Символы в именах полей должны приводиться к нижнему регистру до их кодирования. Запрос или отклик с символами верхнего регистра в именах полей должен считаться некорректно сформированным.

В HTTP/3 поле заголовка Connection не применяется для указания относящихся к соединению полей и связанные с соединением метаданные передаются иначе. Конечной точке недопустимо создавать раздел полей HTTP/3 с относящимися к соединению полями, а сообщения с таким разделом должны считаться ошибочными. Единственным исключением является поле TE, которое может присутствовать в заголовке запроса HTTP/3 и в этом случае в него недопустимо включать что-либо, кроме trailers.

Посредники, преобразующие сообщение HTTP/1.x в HTTP/3, должны удалять связанные с соединением поля заголовка, как указано в параграфе 7.6.1 [HTTP], иначе конечные точки HTTP/3 сочтут их сообщения ошибочными.

4.2.1. Сжатие полей

В [QPACK] описана разновидность HPACK, обеспечивающая кодировщику некоторый контроль над блокировкой head-of-line, которая может вызываться сжатием. Это позволяет кодеру выбрать баланс между эффективностью сжатия и задержкой. QPACK применяется в HTTP/3 для сжатия разделов заголовков и трейлеров, включая данные управления в заголовке.

Для более эффективного сжатия поле заголовка Cookie ([COOKIES]) может быть разделено перед сжатием на несколько строк поля, каждая из которых содержит одну или несколько cookie-пар. Если после декомпрессии поле содержит несколько строк cookie, они должны объединяться (конкатенация) в одну строку с использованием двухбайтового разделителя «; « (ASCII 0x3b, 0x20) до передачи в контекст, отличный от HTTP/2 и HTTP/3, например, в соединение HTTP/1.1 или базовой серверное приложение HTTP.

4.2.2. Ограничение размера заголовков

Реализация HTTP/3 может ограничивать размер заголовка сообщения, который она будет воспринимать в отдельном сообщении HTTP. Сервер, получивший заголовок с размером больше, чем он готов обработать, может передать код статуса HTTP 431 (Request Header Fields Too Large) [RFC6585]. Клиент может отбрасывать отклики, которые он не может обработать. Размер списка полей рассчитывается без учёта сжатия и включает размер имён и значений в байтах, а также издержки в 32 байта на каждое поле.

Если реализация хочет указать партнёру своё ограничение, она может передать его как число байтов в параметре SETTINGS_MAX_FIELD_SECTION_SIZE. Получившей такой параметр реализации не следует передавать сообщения HTTP с заголовком больше указанного размера, поскольку партнёр, скорей всего, откажется их обрабатывать. Однако сообщение HTTP может проходить через одного или несколько посредников на пути к серверу-источнику (см. параграф 3.7 в [HTTP], поэтому ограничение применяется раздельно каждой реализацией, обрабатывающей сообщение и размер заголовка выше3 указанного предела не гарантирует восприятие этого сообщения.

4.3. Данные управления HTTP

Как и в HTTP/2, в HTTP/3 применяется ряд полей псевдозаголовка, имена которых начинаются с символа двоеточия (:, ASCII 0x3a). Эти поля переносят данные управления для сообщения (см. параграф 6.2 в [HTTP]). Поля Поля псевдозаголовков не являются полями заголовка HTTP. Конечным точкам недопустимо генерировать поля псевдозаголовка, кроме заданных в этом документе, однако расширения могут менять эти ограничения (см. раздел 9).

Поля псевдозаголовка действительны лишь в контексте, где они были определены, поля псевдозаголовка откликов недопустимо включать в запросы и наоборот, а также недопустимо включать поля псевдозаголовка в трейлеры. Конечные точки должны считать запрос или отклик с неопределённым или недействительным полем псевдозаголовка некорректно сформированными.

Все поля псевдозаголовка должны включаться в блок полей до строй обычных полей. Любой запрос или отклик с полями псевдозаголовка в блоке полей после обычных полей заголовка должен считаться ошибочным.

4.3.1. Поля псевдозаголовка запроса

:method

Указывает метод HTTP (раздел 9 of [HTTP])

:scheme

Указывающая схему часть URI цели (параграф 3.1 в [URI]).
В поле :scheme можно указывать не только http и https. Прокси и шлюзы могут транслировать запросы в другие (не HTTP) схемы, обеспечивая взаимодействие HTTP с другими типами служб. Рекомендации по использованию отличных от https схем даны в параграфе 3.1.2.

:authority

Компонент полномочий из URI цели (параграф 3.2 в [URI]). Недопустимо включать в это поле устаревший субкомпонент userinfo для схем URI http и https.
Для обеспечения точного воспроизведения строки запроса HTTP/1.1 это поле псевдозаголовка должно опускаться при трансляции запроса HTTP/1.1 с целью в зависимой от метода форме (см. параграф 7.1 в [HTTP]). Клиентам, генерирующим запросы HTTP/3 напрямую, следует использовать поле псевдозаголовка :authority вместо поля заголовка Host. Посредник ACK, преобразующий запрос HTTP/3 в HTTP/1.1, должен создавать поле Host, если его нет в запросе, копируя значение из поля псевдозаголовка :authority.

:path

Компоненты пути и запроса из URI цели (path-absolute и необязательный символ ? (ASCII 0x3f) с последующим запросом, см. параграф 4.1 в [HTTP] и 3.4 в [URI]4). Этому полю псевдозаголовка недопустимо быть пустым для URI http и https, которые при отсутствии компонента пути должны включать значение /. Запрос OPTIONS без компонента пути включает значение * (ASCII 0x2a) в поле заголовка :path (см. параграф 7.1 в [HTTP]).

Все запросы HTTP/3, кроме CONNECT (параграф 4.4), должны включать в точности одно значение для полей псевдозаголовка :method, :scheme, :path.

Если поле псевдозаголовка :scheme указывает схему, где компонент authority обязателен (включая схемы http и https), запрос должен содержать поле псевдозаголовка :authority или поле заголовка Host. При наличии этих полей им недопустимо быть пустыми. Если присутствуют оба поля, из значения должны совпадать. Если схема не требует обязательного компонента authority и он не указан в цели запроса, недопустимо включать в запрос :authority или Host.

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

HTTP/3 не задаёт способа передачи идентификатора версии, который включается в строку запроса HTTP/1.1. Запросы HTTP/3 неявно имеют версию протокола 3.0.

4.3.2. Поля псевдозаголовка отклика

Для откликов определено одно поле псевдозаголовка :status, передающее код статуса HTTP (см. раздел 15 в [HTTP]). Это поле должно включаться во все отклики, которые иначе станут некорректно сформированными (параграф 4.1.2).

HTTP/3 не задаёт способа передачи версии или фразы с причиной, включаемых в строку состояния HTTP/1.1. В откликах HTTP/3 неявно используется протокол версии 3.0.

4.4. Метод CONNECT

Метод CONNECT запрашивает у получателя организацию туннеля к серверу-источнику, указанному в request-target (см. параграф 9.3.6 в [HTTP]) и применяется в основном HTTP-прокси при организации сессии TLS с сервером-источником для взаимодействия с ресурсами https.

В HTTP/1.x метод CONNECT служит для преобразования всего соединения HTTP в туннель к удалённому хосту, в HTTP/2 и HTTP/3 метод CONNECT служит для организации туннеля через один поток.

Запрос CONNECT должен создаваться в соответствии с приведёнными ниже требованиями.

  • В поле псевдозаголовка :method указывается CONNECT.

  • Поля псевдозаголовка :scheme и :path не используются.

  • Поле псевдозаголовка :authority содержит хост и порт для организации соединения (эквивалент authority-form для the request-target в запросах CONNECT, см. параграф 7.1 в [HTTP]).

Поток запроса по его завершении остаётся открытым для передачи данных. Запросы CONNECT, не соответствующие этим требованиям, считаются некорректно сформированными.

Прокси, поддерживающий CONNECT, организует соединение TCP [TCP] с хостом и портом, указанными в поле псевдозаголовка :authority. После организации соединения прокси передаёт клиенту кадр HEADERS с кодом 2xx, как указано в параграфе 15.3 [HTTP]. Все кадры DATA в потоке соответствуют данным, переданным через соединение TCP. Содержимое (payload) всех кадров DATA от клиента прокси передаёт серверу TCP, а данные от этого сервера прокси собирает в кадры DATA. Отметим, что размер и число сегментов TCP не обязательно совпадает с размером и числом кадров HTTP DATA или QUIC STREAM.

По завершении метода CONNECT в поток можно передавать лишь кадры DATA. Могут использоваться кадры расширения, если это явно разрешено в их определении. Приём иного типа кадра должен считаться ошибкой соединения типа H3_FRAME_UNEXPECTED.

Соединение TCP может закрыть любой из партнёров. Когда клиент завершает поток запроса (приёмный поток на прокси переходит в состояние Data Recvd), прокси устанавливает бит FIN в своём соединении с сервером TCP. При получении прокси пакета с установленным битом FIN он закрывает поток передачи, отправляемый клиенту. Соединения TCP, остающиеся полузакрытыми в одном направлении, не являются недействительными, но серверы зачастую плохо обрабатывают их, поэтому клиентам не следует закрывать поток для передачи, пока они ещё ожидают получения данных от цели CONNECT.

Ошибки соединения TCP указываются резким прерыванием потока. Прокси считает любую ошибку соединения TCP, включающую получение сегмента TCP с установленным битом RST, ошибкой потока типа H3_CONNECT_ERROR. Если прокси обнаруживает ошибку в потоке или соединении QUIC, от должен закрыть соединение TCP. Если прокси обнаруживает, что клиент сбросил (reset) поток или прервал чтение из него, прокси следует выполнить такую же операцию в другом направлении, чтобы гарантированно отменить оба направления потока. Во всех таких случаях прокси следует передавать сегмент TCP с установленным битом RST, если реализация TCP позволяет это.

Поскольку CONNECT создаёт туннель к произвольному серверу, прокси, поддерживающим CONNECT, следует разрешать применение этого метода лишь для известных портов или списка безопасных целей запроса (см. параграф 9.3.6 в [HTTP]).

4.5. Обновление HTTP

HTTP/3 не поддерживает механизм HTTP Upgrade (параграф 7.8 в [HTTP]) и код статуса 101 (Switching Protocols) (параграф 15.2.2 в [HTTP]).

4.6. Выталкивание с сервера

Выталкивание с сервера — это интерактивный режим, позволяющий серверу вытолкнуть (push) обмен запрос-отклик клиенту в расчёте на то, что клиент внесёт такой запрос. С этим связан компромисс между загрузкой сети и возможной задержкой. Выталкивание с сервера HTTP/3 похоже на описанное в параграфе 8.2 [HTTP/2], но использует другие механизмы.

Каждому выталкиванию присваивается уникальный идентификатор (push ID), служащий для указания выталкивания в разных контекстах в течение срока действия соединения HTTP/3. Пространство push ID начинается с 0 и завершается максимальным значением, заданным кадром MAX_PUSH_ID. Сервер не может выталкивать отклики до момента передачи клиентом кадра MAX_PUSH_ID, который служит для управления числом выталкиваний, которые может обещать сервер. Серверу следует использовать идентификаторы по порядку, начиная с 0. Клиент должен считать получение вытолкнутого потока ошибкой соединения типа H3_ID_ERROR, если не был передан кадр MAX_PUSH_ID или значение push ID превышает заданный максимум.

Идентификатор выталкивания используется в одном или нескольких кадрах PUSH_PROMISE, передающих данные управления и поля заголовка запросного сообщения. Эти кадры передаются в потоке запросов, вызвавшем выталкивание, что позволяет серверу связать выталкивание с запросом клиента. Когда один идентификатор выталкивания обещан в нескольких потоках запросов, распакованные разделы полей запросов должны содержать одни и те же поля в одинаковом порядке, а имя и значение каждого поля должны быть идентичны.

Идентификатор выталкивания включается в поток выталкивания, который в конечном итоге выполняет обещания. Идентификатор потока выталкивания указывает push ID выполняемого обещания и включает отклик на предсказанный (promised) запрос, как указано в параграфе 4.1. Идентификатор выталкивания может использоваться в кадрах CANCEL_PUSH (см. параграф 7.2.3), используемых клиентами. Чтобы указать нежелание получать обещанный ресурс. Сервер использует эти кадры, чтобы указать отмену исполнения предыдущего обещания.

Не все отклики пригодны для выталкивания. Сервер может выталкивать запросы, которые:

  • являются кэшируемыми (см. параграф 9.2.3 в [HTTP]);

  • безопасны (см. параграф 9.2.1 в [HTTP]);

  • не включают содержимого и раздела трейлеров.

Сервер должен включать поле псевдозаголовка :authority, для которого сервер является полномочным. Если клиент ещё не проверил соединение на предмет источника, указанного вытолкнутым запросом, он должен выполнить такой же процесс проверки, который он применил бы перед отправкой запроса этому источнику (см. параграф 3.3). если проверка завершается отказом, клиенту недопустимо считать сервер полномочным для этого источника.

Клиентам следует передавать кадр CANCEL_PUSH при получении кадра PUSH_PROMISE с запросом, который не может кэшироваться, не содержит сведений о своей безопасности, указывает наличие содержимого или для которого сервер не является полномочным. Соответствующие отклики недопустимо использовать и кэшировать.

Каждый выталкиваемый отклик связан с одним или несколькими клиентскими запросами. Выталкивание связывается с потоком запросов, в котором был получен кадр PUSH_PROMISE. Выталкивание с сервера может быть с дополнительными клиентскими запросами с помощью кадров PUSH_PROMISE с тем же push ID в нескольких потоках запросов. Эти связи не влияют на работу протокола, но могут учитываться пользовательским агентом при решении вопроса об использовании вытолкнутых ресурсов.

Важен порядок PUSH_PROMISE относительно некоторых частей отклика. Серверу следует передавать кадры PUSH_PROMISE до отправки HEADERS или DATA, ссылающихся на обещанные отклики. Это снижает вероятность запроса клиентом ресурса, который был вытолкнут сервером. При изменении порядка данные вытолкнутого потока могут прибывать раньше соответствующего кадра PUSH_PROMISE. При получении клиентом нового push-потока с неизвестным идентификатором выталкивания связанный с ним запрос клиента и поля заголовка вытолкнутого запроса неизвестны. Клиент может буферизовать данные потока в ожидании соответствующего кадра PUSH_PROMISE. Клиент может использовать управление потоком данных в потоке (stream) (параграф 4.1 в [QUIC-TRANSPORT]) для ограничения объёма данных, которые сервер может представить в выталкиваемый поток. Клиентам следует прерывать чтение и отбрасывать уже прочтённые данные из push-потоков, если соответствующий кадр PUSH_PROMISE не был получен в разумное время.

Данные вытолкнутого потока могут прибывать после того, как клиент отменит выталкивание. В этом случае клиент может прервать чтение потока с кодом ошибки H3_REQUEST_CANCELLED. Это будет просить у сервера прекратить передачу дополнительных данных и указывать, что они будут отброшены при получении.

Вытолкнутые отклики, которые являются кэшируемыми (см. раздел 3 в [HTTP-CACHING]), могут сохраняться клиентом, если он реализует кэширование HTTP. Вытолкнутые отклики считаются подтверждёнными сервером-источником (например, наличием в отклике директивы no-cache, см. параграф 5.2.2.4 в [HTTP-CACHING) в момент их получения. Вытолкнутые отклики, которые не являются кэшируемыми, недопустимо сохранять в кэшах HTTP. Они могут быть сделаны доступными приложению отдельно.

5. Закрытие соединения

Организованное соединение HTTP/3 можно применять для множества запросов и откликов, пока оно не будет закрыто. Закрытие соединения может выполняться разными способами, описанными ниже.

5.1. Бездействующие соединения

Каждая конечная точка QUIC при согласовании объявляет тайм-аут простоя. Если соединение QUIC бездействует (пакеты не передаются) дольше этого времени, партнёр будет считать соединение закрытым. Реализациям HTTP/3 потребуется создать новое соединение HTTP/3 для новых запросов, если имеющееся соединение простаивало (idle) дольше тайм-аута, заданного при согласовании QUIC и это следует делать при приближении тайм-аута (см. параграф 10.1 в [QUIC-TRANSPORT]).

Предполагается, что клиенты HTTP будут просить у транспорта сохранять соединения открытыми, пока остаются отклики на запросы или сервер использует выталкивание, как описано в параграфе 10.1.2 [QUIC-TRANSPORT]. Если клиент не ожидает отклика от сервера, лучше позволить завершить простаивающее соединение, чем прилагать усилия по его сохранению, которые могут оказаться пустыми. Шлюз может поддерживать соединения в ожидании потребности в них, чтобы не возникало задержки на организацию нового соединения. Серверам не следует активно поддерживать соединения открытыми.

5.2. Отключение соединения

Конечная точка может остановить использование соединения и инициировать его аккуратное закрытие, даже если соединение не простаивает. Конечная точка инициирует аккуратное отключение (shutdown) соединения HTTP/3 передачей кадра GOAWAY. Такой кадр содержит идентификатор, указывающий получателю диапазон запросов или выталкиваний, которые были или могут быть обработаны в этом соединении. Сервер передаёт идентификатор инициированного клиентом двухстороннего потока. клиент передаёт идентификатор выталкивания. Запросы или выталкивания с указанным или большим идентификатором отклоняются (параграф 4.1.1) отправителем кадра GOAWAY. Идентификатор может иметь значение 0, если запросы или выталкивания не обрабатывались.

Сведения из кадра GOAWAY позволяют клиенту и серверу договориться о том, какие запросы или выталкивания были восприняты до отключения соединения HTTP/3. После отправки GOAWAY конечной точке следует явно отменять (см. параграфы 4.1.1 и 7.2.3) любые запросы или выталкивания, имеющие идентификатор не меньше указанного, чтобы очистить транспортное соединение от затронутых потоков. Конечной точке следует продолжать это делать по мере прибытия новых запросов или выталкиваний.

Конечным точкам недопустимо инициировать новые запросы в соединении после приёма от партнёра кадра GOAWAY. Для передачи дополнительных запросов клиенты могут создавать новое соединение.

Некоторые запросы или выталкивания могут оказаться уже переданными (но ещё не полученными).

  • После получения кадра GOAWAY запросы клиента, переданные с идентификатором потока не меньше указанного в кадре GOAWAY, не будут обработаны. Клиенты могут безопасно повторить такие запросы в другом соединении HTTP. Клиент, не способный повторить запрос, теряет все запросы, находившиеся в пути, когда сервер закрыл соединение. Запросы с идентификатором потока меньше указанного в GOAWAY от сервера могут быть обработаны, но их статус нельзя узнать, пока не будет получен отклик, поток не будет сброшен индивидуально или не будет получен другой кадр GOAWAY с меньшим идентификатором потока, чем у рассматриваемого запроса, или соединение не будет прервано. Сервер может отклонять отдельные запросы в потоках с идентификатором меньше указанного, если эти запросы не были обработаны.

  • Если сервер получает кадр GOAWAY после отправки обещанных выталкиваний и push ID не меньше указанного в кадре GOAWAY, эти выталкивания не будут восприняты.

Серверам следует передавать кадр GOAWAY, когда о закрытии соединения известно заранее, даже если это упреждение невелико, чтобы удалённый партнёр мог знать, был ли его запрос частично обработан. Например, при передаче клиентом HTTP запроса POST в то время, когда сервер закрывает соединение QUIC, клиент не может знать, началась ли обработка POST, если сервер не передал кадр GOAWAY с указанием потоков, на которые он мог влиять.

Конечная точка может передать несколько кадров GOAWAY с разными идентификаторами, но каждый следующий идентификатор должен быть не больше предшествующего, поскольку клиенты уже могли повторить необработанные запросы в другом соединении HTTP. Получение GOAWAY с большим, чем раньше значением идентификатора, должно считаться ошибкой соединения типа H3_ID_ERROR.

Конечная точка, пытающаяся аккуратно завершить соединение, может передать кадр GOAWAY с максимально возможным значением идентификатора (262-4 для сервера, 262-1 для клиента). Это гарантирует, что партнёр остановит создание новых запросов или выталкиваний. По истечении времени на прибытие находящихся в пути запросов или выталкиваний конечная точка может передать другой кадр GOAWAY, указывающий, какие запросы или выталкивания она может воспринять до завершения соединения. Это гарантирует завершение соединения без потери запросов.

Клиент имеет больше возможностей для выбора значения Push ID в передаваемом кадре GOAWAY. Значение 262-1 указывает, что сервер может продолжать выталкивания, которые он уже обещал. Меньшее значение указывает, что клиент будет отклонять выталкивания с Push ID не меньше указанного им значения. Как и сервер, клиент может передать следующие кадры GOAWAY, в которых Push ID не превышает переданное ранее значение.

Даже когда кадр GOAWAY указывает, что данный запрос или выталкивание не будет обработан или воспринят после получения, ресурсы базового транспорта ещё сохраняются. Инициировавшая такие запросы конечная точка может отменить их для очистки своего транспортного состояния.

После обработки всех воспринятых запросов и выталкиваний конечная точка может сохранять простаивающее соединение или может инициировать его незамедлительное закрытие. Конечное точке, завершающей аккуратное отключение, следует использовать при закрытии код H3_NO_ERROR.

Если клиент уже использовал все доступные идентификаторы двухсторонних потоков в запросах, серверу не требуется передавать кадр GOAWAY, поскольку клиент больше не сможет подавать запросы.

5.3. Немедленное закрытие приложения

Реализация HTTP/3 может в любой момент без промедления закрыть соединение QUIC. Это ведёт к отправке партнёру кадра QUIC CONNECTION_CLOSE, указывающего, что прикладной уровень прервал соединение. Код ошибки прикладного уровня в этом кадре говорит партнёру о причине разрыва соединения. В разделе 8 указаны коды ошибок, которые можно использовать при закрытии соединения HTTP/3.

Перед закрытием соединения может быть передан кадр GOAWAY, чтобы клиент мог повторить некоторые запросы. Включение GOAWAY в один пакет с кадром QUIC CONNECTION_CLOSE повышает вероятность получения кадра клиентом.

При наличии открытых потоков, которые не были закрыты явно, они неявно закрываются при закрытии соединения (см. параграф 10.2 в [QUIC-TRANSPORT]).

5.4. Закрытие транспорта

По разным причинам транспорт QUIC может сообщать прикладному уровню о разрыве соединения. Это может быть результатом явного закрытия партнёром, ошибки на транспортном уровне или изменения топологии сети, прерывающего связность. Если соединение прерывается без передачи кадра GOAWAY, клиенты должны полагать, что любые переданные запросы обработаны полностью или частично.

6. Сопоставление и использование потоков

Поток QUIC обеспечивает надёжную, упорядоченную доставку байтов, но не даёт гарантий порядка доставки байтов относительно других потоков. В QUIC версии 1 поток данных с кадрами HTTP передаётся в кадрах QUIC STREAM, но это кадрирование невидимо для уровня кадрирования HTTP. Транспортный уровень буферизует и упорядочивает полученные данные потока, предоставляя приложению надёжный поток байтов. Хотя QUIC допускает доставку с нарушением порядка в потоке, HTTP/3 эту возможность не использует.

Потоки QUIC могут быть односторонними, передающими лишь данные от инициатора к получателю, или двухсторонними с передачей данных в обоих направлениях. Инициатором потока может быть клиент или сервер. Дополнительные сведения о потоках QUIC приведены в разделе 2 [QUIC-TRANSPORT].

Когда поля и данные HTTP передаются через QUIC, уровень QUIC обеспечивает большую часть управления потоком (stream). HTTP не требуется какое-либо мультиплексирование при использовании QUIC, данные, переданные в поток QUIC, всегда сопоставляются с конкретной транзакцией HTTP или контекстом всего соединения HTTP/3.

6.1. Двухсторонние потоки

Все инициируемые клиентом двухсторонние потоки применяются для запросов и откликов HTTP. Двухсторонний поток гарантирует надёжное сопоставление откликов с запросами. Такие потоки называются потоками запросов. Это означает, что первый запрос клиента выполняется в потоке QUIC 0, в последующие в потоках 4, 8 и т. д. Чтобы разрешить создание этих потоков серверу HTTP/3 следует задать отличные от 0 значения для числа разрешённых потоков и исходного размера окна управления потоком данных в потоке (stream). Чтобы не вносить избыточных ограничений для параллельной работы следует разрешать не менее 100 потоков запросов.

В HTTP/3 не применяются инициируемые сервером двухсторонние потоки, хотя могут задаваться расширения с такими потоками. Клиенты должны считать инициированный сервером двухсторонний поток ошибкой соединения типа H3_STREAM_CREATION_ERROR, если не было согласовано применяющее такие потоки расширение.

6.2. Односторонние потоки

Односторонние потоки обоих направлений применяются для разных целей. Назначение потока определяет тип, указываемый целым числом переменного размера в начале потока. Формат и структура данных в потоке определяются типом потока.

   Unidirectional Stream Header {
     Stream Type (i),
   }

Рисунок . Заголовок одностороннего потока.


Этот документ определяет два типа — потоки управления (control stream, параграф 6.2.1) и потоки выталкивания (push stream, параграф 6.2.2). В [QPACK] определены два дополнительных типа, а расширения HTTP/3 могут задавать свои типы (см. раздел 9). Некоторые типы потоков зарезервированы (параграф 6.2.3).

Производительность соединения HTTP/3 в его ранней фазе зависит от создания и обмена данными через односторонние потоки. Конечные точки, чрезмерно ограничивающие число потоков или размер окна управления потоком данных для этих потоков, повышают вероятность того, что удалённый партнёр быстрее достигнет предела и будет заблокирован. В частности, реализациям следует учитывать, что удалённые партнёры могут захотеть использовать поведение зарезервированного потока (параграф 6.2.3) с некоторыми из односторонних потоков, которые им разрешены.

Каждая конечная точка должна по меньшей мере создать один односторонний поток для управления HTTP. Для QPACK нужны два дополнительных односторонних потока, а другим расширениям могут требоваться свои потоки. Поэтому параметры транспорта, переданные клиентом и сервером, должны разрешать партнёру создание не менее трёх односторонних потоков. Этим параметрам следует предоставлять кредит управления потоком данных не менее 1024 байтов для каждого одностороннего потока. Отметим, что конечная точка не обязана предоставлять дополнительный кредит для создания большего числа односторонних потоков, когда партнёр уже использовал весь выделенный кредит до создания критически важных односторонних потоков. Конечным точкам следует сначала создавать поток управления HTTP, а также односторонние потоки, требуемые для обязательных расширений (таких как потоки кодера и декодера QPACK), а затем — дополнительные потоки, разрешённые партнером.

Если заголовок потока указывает не поддерживаемый получателем тип, остальная часть потока не может быть воспринята, так как её семантика неизвестна. Получатель потока неизвестного типа должен прервать чтение из потока или отбросить входные данные без дальнешей обработки. При прерывании чтения получателю следует использовать код ошибки H3_STREAM_CREATION_ERROR или резервный код (параграф 8.1). Получателю недопустимо считать неизвестный тип потока ошибкой соединения.

Поскольку некоторые типы потоков могут влиять на состояние соединения, получателю не следует отбрасывать данные из входящего одностороннего потока до прочтения типа потока. Реализации могут передавать потоки, не зная, поддерживается ли тип потока партнёром. Однако типы потока, которые могут менять статус и семантику имеющихся компонентов протокола, включая QPACK и другие расширения, недопустимо передавать, пока неизвестно об их поддержке партнёром.

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

6.2.1. Поток управления

Поток управления имеет тип 0x00, а данными этого потока являются кадры HTTP/3, определённые в параграфе 7.2.

Каждая сторона должна инициировать один поток управления в начале соединения и первым передать в него кадр SETTINGS. Приём первым кадра иного типа должно считаться ошибкой соединения типа H3_MISSING_SETTINGS. Для партнёра создаётся лишь один поток управления и получение другого потока этого типа должно считаться ошибкой соединения типа H3_STREAM_CREATION_ERROR. Отправителю недопустимо закрывать поток управления, а получателю недопустимо запрашивать у отправителя закрытие такого потока. Закрытие любого из потоков управления любой точкой должно считаться ошибкой соединения типа H3_CLOSED_CRITICAL_STREAM. Ошибки соединений описаны в разделе 8.

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

Для управления используется пара односторонних потоков и не один двухсторонний. Это позволяет любому из партнёров передавать данные, как только он сможет. В зависимости от доступности 0-RTT в соединении QUIC клиент или сервер сможет первым начать передачу данных в поток.

6.2.2. Push-потоки

Выталкивание (push) с сервера, введённое в HTTP/2, позволяет серверу инициировать отклик до получения запроса (см. параграф 4.6). Выталкиваемый поток указывается типом 0x01, за которым следует идентификатор выталкивания (push ID) для выполняемого обещания (promise) в виде целого числа с переменным размером. Данными в этом потоке являются кадры HTTP/3 (см. параграф 7.2), выполняющие обещанное сервером выталкивание с помощью необязательных промежуточных откликов HTTP, за которыми следует финальный отклик HTTP, как указано в параграфе 4.1. Выталкивание с сервера и его идентификатор описаны в параграфе 4.6.

Выталкивание разрешено только серверу и получение сервером инициированного клиентом push-потока должно считаться ошибкой соединения типа H3_STREAM_CREATION_ERROR.

   Push Stream Header {
     Stream Type (i) = 0x01,
     Push ID (i),
   }

Рисунок . Заголовок потока Push.


Клиенту не следует прерывать чтение push-потока, пока не прочитан его заголовок, поскольку это может приводить к разному воспринятию клиентом и сервером уже использованных push ID. Каждый идентификатор потока должен использоваться только один раз в заголовке push-потока. Если клиент обнаруживает в заголовке push-потока значение push ID, которое уже использовалось в заголовке другого push-потока, он должен считать это ошибкой соединения типа H3_ID_ERROR.

6.2.3. Зарезервированные типы потоков

Потоки типов 0x1f * N + 0x21 с неотрицательными значениями N зарезервированы для выполнения требования игнорировать неизвестные типы. Эти потоки не имеют семантики и могут передаваться при необходимости заполнения на прикладном уровне. Они могут также передаваться в соединениях, где в настоящее время не передаются данные. Конечным точкам недопустимо придавать таким потокам какое-либо значение.

Содержимое и размер потока выбираются произвольным способом по выбору передающей реализации. Передав поток зарезервированного типа, реализация может полностью прервать или сбросить его. При сбросе следует использовать код H3_NO_ERROR или зарезервированный код ошибки (параграф 8.1).

7. Уровень кадрирования HTTP

Кадры HTTP передаются в потоках QUIC, как описано в разделе 6. В HTTP/3 определено 3 типа потоков — управление (control stream), запрос (request stream) и выталкивание (push stream). В этом разделе описаны форматы кадров HTTP/3 и разрешённые для них типы потоков (см. таблицу 1). Сравнение кадров HTTP/2 и HTTP/3 приведено в Приложении A.2.

Таблица . Типы кадров и потоков HTTP/3.

 

Кадр

Поток управления

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

Поток выталкивания

Параграф

DATA

нет

да

да

7.2.1

HEADERS

нет

да

да

7.2.2

CANCEL_PUSH

да

нет

нет

7.2.3

SETTINGS

да (1)

нет

нет

7.2.4

PUSH_PROMISE

нет

да

нет

7.2.5

GOAWAY

да

нет

нет

7.2.6

MAX_PUSH_ID

да

нет

нет

7.2.7

Reserved

да

да

да

7.2.8

 

Кадр SETTINGS может передаваться лишь в качестве первого кадра в потоке управления, это отмечено в таблице 1 как (1). Конкретные рекомендации приведены в соответствующем параграфе.

Отметим, что в отличие от кадров QUIC, кадры HTTP/3 могут разделяться между несколькими пакетами.

7.1. Схема кадра

Формат кадров показан на рисунке 3.

   HTTP/3 Frame Format {
     Type (i),
     Length (i),
     Frame Payload (..),
   }

Рисунок . Формат кадра HTTP/3.


Ниже описаны поля кадра.

Type

Целое число переменного размера, указывающее тип кадра.

Length

Целое число переменного размера, указывающее число байтов в Frame Payload.

Frame Payload

Содержимое, семантика которого определяется полем Type.

В содержимом (payload) каждого кадра должны присутствовать именно те поля, которые указаны в описании кадра. Кадр, содержимое ккоторого включает байты после указанных полей или завершается до конца указанных полей, должен считаться ошибкой соединения типа H3_FRAME_ERROR. Избыточное значение размера в поле Length должно проверяться на самосогласованность (см. параграф 10.8).

При полном (чистом) завершении потока отсечка должна считаться ошибкой соединения типа H3_FRAME_ERROR. При внезапном завершении поток может прерываться в любом месте кадра.

7.2. Определения кадров

7.2.1. DATA

Кадры DATA (type=0x00) передают последовательности байтов переменного размера, связанных с содержимым запроса или отклика HTTP.

   DATA Frame {
     Type (i) = 0x00,
     Length (i),
     Data (..),
   }

Рисунок . Кадр DATA.


Кадры DATA должны быть связаны с запросом или откликом HTTP. На приём кадра DATA в потоке управления получатель должен отвечать ошибкой соединения типа H3_FRAME_UNEXPECTED.

7.2.2. HEADERS

Кадр HEADERS (type=0x01) служит для передачи раздела заголовков HTTP, кодируемого с использованием QPACK. Дополнительные сведения представлены в [QPACK].

   HEADERS Frame {
     Type (i) = 0x01,
     Length (i),
     Encoded Field Section (..),
   }

Рисунок . Кадр HEADERS.


Кадры HEADERS могут передаваться только в потоке запроса или выталкивания. Получение HEADERS в потоке управления должно считаться ошибкой соединения типа H3_FRAME_UNEXPECTED.

7.2.3. CANCEL_PUSH

Кадр CANCEL_PUSH (type=0x03) служит для запроса отмены выталкивания с сервера до получения push-потока и указывает идентификатор выталкиваемого потока (параграф 4.6), указанный целым числом с переменным размером.

Передача клиентом кадра CANCEL_PUSH указывает его нежелание принимать обещанный (promise) отклик. Серверу следует прервать передачу ресурса, но механизм прерывания зависит от состояния соответствующего push-потока. Если сервер ещё не создал поток выталкивания, он просто не создаётся. Если такой поток создан, серверу следует резко прервать его. Если поток уже завершён, сервер может резко прервать его или не делать ничего.

Сервер передаёт кадр CANCEL_PUSH, чтобы указать отказ от выполнения переданного ранее обещания. Клиент не может ожидать соответствующего обещания, если он уже не получил и не обработал обещанный отклик. Независимо от того, был ли создан push-поток, серверу следует передавать кадр CANCEL_PUSH, когда он понимает, что обещание не будет исполнено. Если поток создан, сервер может прервать его передачу с кодом ошибки H3_REQUEST_CANCELLED.

Передача CANCEL_PUSH не оказывает прямого воздействия на имеющиеся потоки выталкивания. Клиенту не следует передавать кадр CANCEL_PUSH, если он уже получил соответствующий push-поток. Вытолкнутый поток может прибыть после отправки кадра CANCEL_PUSH, поскольку сервер мог не обработать этот кадр. Клиенту в таком случае следует прервать считывание потока с кодом ошибки H3_REQUEST_CANCELLED.

Кадр CANCEL_PUSH передаётся в потоке управления и его получение в другом потоке должно считаться ошибкой соединения типа H3_FRAME_UNEXPECTED.

   CANCEL_PUSH Frame {
     Type (i) = 0x03,
     Length (i),
     Push ID (i),
   }

Рисунок . Кадр CANCEL_PUSH.


Кадр CANCEL_PUSH содержит идентификатор выталкивания в форме целого числа с переменным размером. Поле Push ID указывает отменяемое выталкивание с сервера (см. параграф 4.6). Получение CANCEL_PUSH с идентификатором выталкивания больше текущего значения в соединении должно считаться ошибкой соединения типа H3_ID_ERROR.

Полученный клиентом кадр CANCEL_PUSH может указывать идентификатор выталкивания, ещё не принятый в кадре PUSH_PROMISE по причине нарушения порядка. Если сервер получает CANCEL_PUSH для идентификатора выталкивания, ещё не указанного в кадре PUSH_PROMISE, он должен считать это ошибкой соединения типа H3_ID_ERROR.

7.2.4. SETTINGS

Кадр SETTINGS (type=0x04) передаёт параметры концигурации, влияющие на взаимодействие конечных точек, например, предпочтения и ограничения в поведении партнёра. Параметры SETTINGS по-отдельности называют также установками (setting), а идентификатор и значение «идентификатором» и «значением» установки.

Кадры SETTINGS всегда применяются к соединению HTTP/3 в целом, а не к отдельным потокам. Кадр SETTINGS должен быть первым кадром в каждом потоке управления (см. параграф 6.2.1) каждого партнёра, а последующая передача таких кадров недопустима. Получив второй кадр SETTINGS в потоке управления, конечная точка должна ответить ошибкой соединения типа H3_FRAME_UNEXPECTED.

Кадры SETTINGS недопустимо передавать в каких-либо потоках, кроме потока управления. Получив такой кадр в ином потоке, конечная точка должна возвращать ошибку соединения типа H3_FRAME_UNEXPECTED.

Параметры SETTINGS не согласуются, они описывают характеристики передающего партнёра, которые могут использоваться принимающим партнёром. Однако применение кадров SETTINGS может предполагать согласование — каждый партнёр применяет SETTINGS для анонсирования набора поддерживаемых им значений. Определение установки описывает, как каждый из партнёров комбинирует свои и партнерские параметры для выбора используемого значения. Кадр SETTINGS не предоставляет механизма оповещения о вступлении настроек в силу.

Каждый партнёр может анонсировать своё значение конкретного параметра. Например, клиент может быть готов использовать большой раздел заголовков, а сервер может более осторожно подойти к выбору размера запросов. Один идентификатор установки (параметра) недопустимо включать в кадр SETTINGS более одного раза. Получатель может считать наличие дубликатов идентификаторов ошибкой соединения типа H3_SETTINGS_ERROR.

Содержимое (payload) кадра SETTINGS может включать параметры, каждый из которых состоит из идентификатора и значения, представляемых в формате QUIC для целых чисел с переменным размером.

   Setting {
     Identifier (i),
     Value (i),
   }

   SETTINGS Frame {
     Type (i) = 0x04,
     Length (i),
     Setting (..) ...,
   }

Рисунок . Кадр SETTINGS.


Реализации должны игнорировать параметры с неизвестными (непонятными) идентификаторами.

7.2.4.1. Параметр SETTINGS

В HTTP/3 определена одна настройка (параметр).

SETTINGS_MAX_FIELD_SECTION_SIZE (0x06)

По умолчанию значение не ограничено. Применение описано в параграфе 4.2.2.

Идентификаторы настроек в формате 0x1f * N + 0x21 с неотрицательными значениями N зарезервированы для выполнения требования игнорировать неизвестные идентификаторы. Такие настройки не имеют значения. Конечной точке следует включать хотя бы одну такую настройку в кадр SETTINGS. Конечным точкам недопустимо придавать смысл зарезервированным настройкам. Поскольку эти настройки не имеют смысла, реализация может выбирать для них произвольные значения.

Идентификаторы настроек из [HTTP/2], для которых нет соответствующей настройки HTTP/3, также являются зарезервированными (параграф 11.2.2). Эти настройки недопустимо передавать, а их получение должно считаться ошибкой соединения типа H3_SETTINGS_ERROR.

В расширениях HTTP/3 могут определяться дополнительные настройки (см. раздел 9).

7.2.4.2. Инициализация

Реализации HTTP недопустимо передавать кадры или запросы, непригодные в соответствии с текущим пониманием настроек партнёра.

Все установки начинаются с исходного значения. Каждой конечной точке следует применять исходные значения при отправке сообщений до получения кадра SETTINGS, поскольку пакеты с настройками могут быть потеряны или задержаны. При поступлении кадра SETTINGS для всех настроек устанавливаются новые значения. Это избавляет от необходимости ждать приёма кадра SETTINGS перед отправкой сообщений. Конечным точкам недопустимо требовать получения от партнёра каких-либо данных до отправки кадра SETTINGS, установки должны передаваться, как только транспорт будет готов к передаче данных. Для сервера начальным значением каждой установки клиента является принятое по умолчанию значение. Для клиентов, использующих соединение QUIC 1-RTT, начальным значением каждой установки сервера является принятое по умолчанию значение. Ключи 1-RTT всегда становятся доступными до того, как пакет с кадром SETTINGS будет обработан QUIC, даже если сервер передаст SETTINGS незамедлительно. Клиентам не следует дожидаться получения SETTINGS перед отправкой запросов, но следует обрабатывать полученные дейтаграммы, чтобы повысить вероятность обработки SETTINGS до отправки первого запроса. При использовании соединения QUIC 0-RTT начальным значением каждой установки сервера является значение из предыдущей сессии. Клиентам следует сохранять установки, представленные сервером в соединении HTTP/3, где были предоставлены сведения о восстановлении, но в некоторых случаях (например, при получении сеансовой квитанции до кадра SETTINGS) установки можно не сохранять. Клиент должен соблюдать сохранённые установки (или принятые по умолчанию значения, если установки не сохранены) при попытке 0-RTT. Если сервер предоставил новые установки, клиент должен соблюдать их.

Сервер может запоминать анонсированные установки или сохранять копию значений с защитой целостности в квитанции и восстанавливать сведения при получении данных 0-RTT. Сервер использует значения установок HTTP/3 при решении вопроса о восприятии данных 0-RTT. Если сервер не может определить, что запомненные клиентом установки совместимы с его текущими установками, серверу недопустимо воспринимать данные 0-RTT. Запомненные установки считаются совместимыми, если соблюдающий их клиент не нарушает текущих установок сервера.

Сервер может воспринять 0-RTT и впоследствии предоставить другие установки в своём кадре SETTINGS. Если данные 0-RTT восприняты сервером, в его кадре SETTINGS недопустимо снижать какие-либо пределы или менять значения, которые могут быть нарушены клиентом в соответствии с его данными 0-RTT. Сервер должен включить все установки, которые отличаются от принятых по умолчанию значений. Если сервер воспринимает 0-RTT, а затем передаёт установки, не совместимые с заданными ранее, это должно считаться ошибкой соединения типа H3_SETTINGS_ERROR. Если сервер воспринимает 0-RTT, а затем передаёт кадр SETTINGS, где отсутствует понятное клиенту значение (помимо зарезервированных идентификаторов установок), для которого было установлено отличное от принятого по умолчанию значение, это должно считаться ошибкой соединения типа H3_SETTINGS_ERROR.

7.2.5. PUSH_PROMISE

Кадр PUSH_PROMISE (type=0x05) служит для передачи раздела заголовков предсказанного (promise) запроса от сервера клиенту в потоке запросов.

   PUSH_PROMISE Frame {
     Type (i) = 0x05,
     Length (i),
     Push ID (i),
     Encoded Field Section (..),
   }

Рисунок . Кадр PUSH_PROMISE.


Поля содержимого (payload) кадра описаны ниже.

Push ID

Целое число с переменным размером, указывающее операцию выталкивания с сервера. Идентификатор применяется в заголовках push-потоков (параграф 4.6) и кадрах CANCEL_PUSH.

Encoded Field Section

Поля заголовка с кодированием QPACK [QPACK] для предсказанного (promised) запроса.

Серверу недопустимо использовать Push ID больше значения, указанного клиентом в кадре MAX_PUSH_ID (параграф 7.2.7). Клиент должен считать получение кадра PUSH_PROMISE с таким значением Push ID ошибкой соединения типа H3_ID_ERROR.

Сервер может использовать одно значение Push ID в нескольких кадрах PUSH_PROMISE. В этом случае распакованные наборы заголовков запросов должны содержать те же поля в том же порядке и все значения полей должны совпадать. Клиентам следует сравнивать разделы заголовков для ресурсов, обещанных неоднократно. Если клиент получает уже обещанный Push ID и обнаруживает несоответствие, он должен отвечать ошибкой соединения типа H3_GENERAL_PROTOCOL_ERROR. Если распакованные разделы полей совпадают, клиенту следует связывать вытолкнутое содержимое с каждым потоком, где был получен кадр PUSH_PROMISE.

Разрешение дублирования ссылок на один Push ID предназначено в первую очередь для сокращения дублирования, вызываемого одновременными запросами. Серверу следует избегать долгосрочного использования Push ID. Клиенты, скорей всего, будут потреблять вытолкнутые сервером отклики, не сохраняя их для повторного использования в течение долгого времени. Клиенты, встречающиеся с кадром PUSH_PROMISE, содержащим уже использованный и отброшенный Push ID, вынуждены будут игнорировать это обещание.

При получении кадра PUSH_PROMISE в потоке управления клиент должен возвращать ошибку соединения типа H3_FRAME_UNEXPECTED.

Клиенту недопустимо передавать кадр PUSH_PROMISE, а сервер должен считать получение PUSH_PROMISE ошибкой соединения типа H3_FRAME_UNEXPECTED.

Общее описание механизма выталкивания с сервера приведено в параграфе 4.6.

7.2.6. GOAWAY

   GOAWAY Frame {
     Type (i) = 0x07,
     Length (i),
     Stream ID/Push ID (i),
   }

Рисунок . Кадр GOAWAY.


Кадр GOAWAY (type=0x07) служит для инициирования аккуратного завершения соединения HTTP/3 любой из конечных точек. GOAWAY позволяет конечной точке прекратить восприятие новых запросов или выталкиваний, сохраняя обработку полученных ранее. Это позволяет выполнять административные операции, такие как обслуживание сервера. Кадр GOAWAY сам по себе не закрывает соединение.

Кадр GOAWAY всегда передаётся в пакете управления. В направлении от сервера к клиенту кадр содержит идентификатор потока QUIC, инициированного клиентом двухстороннего потока, в виде целого числа с переменным размером. Клиент должен считать получение GOAWAY с идентификатором потока иного типа ошибкой соединения типа H3_ID_ERROR. В направлении от клиента к серверу кадр GOAWAY содержит идентификатор выталкивания в виде целого числа с переменным размером.

Кадр GOAWAY относится ко всему соединению, а не к отдельному потоку. Клиент должен считать получение GOAWAY в потоке, отличном от потока управления, ошибкой соединения типа H3_FRAME_UNEXPECTED.

Дополнительные сведения о кадрах GOAWAY приведены в параграфе 5.2.

7.2.7. MAX_PUSH_ID

Кадр MAX_PUSH_ID (type=0x0d) используется клиентом для управления числом выталкиваний (push), которые может инициировать сервер, путём задания максимального значения Push ID, разрешённого серверу в кадрах PUSH_PROMISE и CANCEL_PUSH. Это ограничивает число инициируемых сервером потоков выталкивания в дополнением к ограничению, задаваемому транспортном QUIC.

Кадр MAX_PUSH_ID всегда передаётся в потоке управления и его получение в ином потоке должно считаться ошибкой соединения типа H3_FRAME_UNEXPECTED. Серверу недопустимо передавать кадры MAX_PUSH_ID и клиент должен считать получение такого кадра ошибкой соединения типа H3_FRAME_UNEXPECTED.

   MAX_PUSH_ID Frame {
     Type (i) = 0x0d,
     Length (i),
     Push ID (i),
   }

Рисунок . Кадр MAX_PUSH_ID.


Максимальный идентификатор выталкивания ещё не задан в момент организации соединения HTTP/3 и сервер не может применять выталкивание до получения кадра MAX_PUSH_ID. Клиент, желающий управлять числом предсказанных сервером выталкиваний, может увеличивать максимальный идентификатор, передавая кадры MAX_PUSH_ID по мере получения выталкиваний от сервера или их отмены сервером.

Кадр MAX_PUSH_ID содержит одно целое число с переменным размером, указывающее максимальное значение Push ID, разрешённое для сервера (см. параграф 4.6). Кадр MAX_PUSH_ID не может снижать значение максимального идентификатора, установленное ранее для соединения, и получение такого кадра MAX_PUSH_ID должно считаться ошибкой соединения типа H3_ID_ERROR.

7.2.8. Зарезервированные типы кадров

Кадры типов 0x1f * N + 0x21 с неотрицательными значениями N зарезервированы для выполнения требования игнорировать неизвестные типы (раздел 9). Эти кадры не имеют семантики и могут передаваться в любом потоке, где передача кадров разрешена. Конечным точкам недопустимо придавать таким кадрам какое-либо значение. Содержимое (payload) и размер кадров определяется реализацией.

Кадры типов, использованных в HTTP/2, для которых нет соответствующего кадра HTTP/3, также являются зарезервированными (параграф 11.2.1). Кадры этих типов недопустимо передавать, а их получение должно считаться ошибкой соединения типа H3_FRAME_UNEXPECTED.

8. Обработка ошибок

Когда поток не удаётся закрыть успешно, QUIC разрешает приложению резко прервать (сбросить — reset) поток и сообщить причину этого (см. параграф 2.4 в [QUIC-TRANSPORT]). Это называется ошибкой потока (stream error). Реализация HTTP/3 может принять решение о закрытии соединения QUIC и указать тип ошибки. Формат передачи кодов ошибок описан в параграфе 8.1. Ошибки потока отличаются от кодов статуса HTTP, которые указывают условия ошибки. Ошибка потока говорит, что её отправитель не передал или не воспринял запрос или отклик, а код статуса HTTP указывает результат успешно полученного запроса.

Для прерывания соединения целиком QUIC предоставляет похожие механизмы указания причины (см. параграф 5.3 в [QUIC-TRANSPORT]). Это называется ошибкой соединения (connection error). Как и при ошибках потока, реализация HTTP/3 может разорвать соединение QUIC и сообщить причину в коде ошибки (параграф 8.1).

Хотя причины закрытия потоков и соединений называются ошибками, они не всегда говорят о проблеме с соединением или реализацией. Например, поток может быть сброшен, если запрошенный ресурс больше не нужен.

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

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

8.1. Коды ошибок HTTP/3

Перечисленные ниже коды ошибок определены для использования при резком прерывании потоков, прерывании чтения из потока и незамедлительного закрытия соединений HTTP/3.

H3_NO_ERROR (0x0100)

Нет ошибок. Этот код применяется, когда нужно закрыть поток или соединение, но нет ошибки для её указания.

H3_GENERAL_PROTOCOL_ERROR (0x0101)

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

H3_INTERNAL_ERROR (0x0102)

Внутренняя ошибка в стеке HTTP.

H3_STREAM_CREATION_ERROR (0x0103)

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

H3_CLOSED_CRITICAL_STREAM (0x0104)

Поток, требуемый соединением HTTP/3, был закрыт или сброшен.

H3_FRAME_UNEXPECTED (0x0105)

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

H3_FRAME_ERROR (0x0106)

Получен кадр, нарушающий требования к компоновке или размеру.

H3_EXCESSIVE_LOAD (0x0107)

Конечная точка обнаружила, что поведение партнёра может вызывать чрезмерную нагрузку.

H3_ID_ERROR (0x0108)

Некорректное использование идентификатора потока или выталкивания, например, превышение предела, снижение предела или повторное использование.

H3_SETTINGS_ERROR (0x0109)

Конечная точка обнаружила ошибку в содержимом кадра SETTINGS.

H3_MISSING_SETTINGS (0x010a)

В начале потока управления не был получен кадр SETTINGS.

H3_REQUEST_REJECTED (0x010b)

Сервер отклонил запрос без обработки в приложении.

H3_REQUEST_CANCELLED (0x010c)

Запрос или отклик на него (включая выталкиваемый) был отменен.

H3_REQUEST_INCOMPLETE (0x010d)

Поток клиента прервался без получения полного запроса.

H3_MESSAGE_ERROR (0x010e)

Сообщение HTTP имеет некорректную форму и не может быть обработано.

H3_CONNECT_ERROR (0x010f)

Соединение TCP, созданное в ответ на запрос CONNECT, сброшено или аварийно закрыто.

H3_VERSION_FALLBACK (0x0110)

Запрошенную операцию невозможно выполнить по протоколу HTTP/3. Партнёру следует повторить её по протоколу HTTP/1.1.

Коды ошибок 0x1f * N + 0x21 с неотрицательными значениями N зарезервированы для выполнения требования считать неизвестные коды эквивалентом H3_NO_ERROR (раздел 9). Реализации следует с некоторой вероятностью выбирать коды из этого пространства, когда можно было передать H3_NO_ERROR.

9. Расширения HTTP/3

Протокол HTTP/3 допускает расширения. В рамках заданных этим разделом ограничений расширения протокола могут применяться для предоставления дополнительных услуг или изменения любых аспектов протокола. Расширение действует лишь в рамках конкретного соединения HTTP/3. Это относится к элементам протокола, заданным в этом документе и не влияет на имеющиеся возможности расширения HTTP, такие как задание новых методов, кодов статуса и полей.

Расширениям разрешается применять новые типы кадров (параграф 7.2), установки (параграф 7.2.4.1), коды ошибок (раздел 8), типы односторонних потоков (параграф 6.2). Для точек расширения созданы реестры типов кадров (параграф 11.2.1), установок (параграф 11.2.2), кодов ошибок (параграф 11.2.3) и типов потоков (параграф 11.2.4).

Реализации должны игнорировать неизвестные и неподдерживаемые значения во всех расширяемых элементах протокола, а также должны отбрасывать данные или прерывать чтение односторонних потоков неизвестных и неподдерживаемых типов. Это означает, что любая точка расширения может безопасно использоваться расширениями без предварительной договорённости или согласования. Однако если известный тип кадр должен размещаться в определённом месте (как кадр SETTINGS, являющийся первым в потоке управления, см. параграф 6.2.1), неизвестный тип кадра, нарушающий это требование, следует считать ошибкой.

Расширения, способные менять семантику имеющихся компонентов протокола, должны согласовываться перед использованием. Например, расширение, меняющее структуру кадра HEADERS, не может применяться без согласования с партнёром. Координация вступления в силу такого изменения структуры может оказаться сложной, поэтому выделение новых идентификаторов для новых определений будет, вероятно, более эффективной мерой.

Этот документ не задаёт конкретного метода согласования применения расширений, но указывает, что для этого можно использовать настройки (параграф 7.2.4.1). Если оба партнёра устанавливают значение, указывающее желание применять расширения, это расширение может использоваться. Если для согласования расширения применяется настройка, принятое по умолчанию значение должно быть задано так, чтобы расширение было отключено при отсутствии этой установки.

10. Вопросы безопасности

Соображения безопасности для HTTP/3 сопоставимы с принятыми для HTTP/2 с TLS. Многие из вопросов, рассмотренных в разделе 10 [HTTP/2], применимы к [QUIC-TRANSPORT] и рассматриваются в этом документе.

10.1. Полномочия сервера

HTTP/3 полагается на определение полномочности HTTP. Вопросы безопасности, связанные с полномочиями, рассмотрены в параграфе 17.1 [HTTP].

10.2. Кросс-протокольные атаки

Применение ALPN в согласовании TLS и QUIC устанавливает целевой транспортный протокол до начала обработки байтов прикладного уровня. Это обеспечивает конечным точкам уверенность в том, что они используют один протокол. Однако это не обеспечивает защиты от кросс-протокольных атак. В параграфе 21.5 [QUIC-TRANSPORT] описаны некоторые способы использования открытого текста (plaintext) из пакетов QUIC для подделки запросов к конечным точкам, не использующим транспорт с проверкой подлинности.

10.3. Атаки на инкапсуляцию в посредниках

Кодирование полей HTTP/3 позволяет выражать имена, не соответствующие синтаксису имён полей HTTP (параграф 5.1 в [HTTP]). Запросы и отклики с недействительными именами полей должны считаться ошибочными. Поэтому посредники не могут преобразовать запрос или отклик HTTP/3 с недействительными именами полей в сообщение HTTP/1.1.

HTTP/3 может передавать значения полей, которые не являются действительными. Хотя большинство значений, которые могут быть закодированы, не повлияют на разбор поля, символы возврата каретки (ASCII 0x0d), перевода строки (ASCII 0x0a) и null-символ (ASCII 0x00) могут использоваться атакующим, если они будут транслироваться буквально. Любой запрос или отклик с недействительным символом в значении поля должен считаться ошибочным. Действительные символы определяет правило ABNF field-content из параграфа 5.5 и [HTTP].

10.4. Кэшируемость вытолкнутых откликов

Вытолкнутые отклики не имеют явного запроса от клиента, запрос предоставляется сервером в кадре PUSH_PROMISE.

Кэширование вытолкнутых откликов возможно на основе рекомендаций от сервера-источника в поле заголовка Cache-Control. Однако это может вызывать проблемы при размещении на сервере более одного арендатора (например, сервер может предоставлять нескольким пользователям по небольшой части своего пространства URI). При использовании серверного пространства несколькими арендаторами этот сервер должен гарантировать, что арендаторы не могут выталкивать представления ресурсов, для которых у них нет полномочий. Отказ от выполнения этого правила позволит арендатору выдавать представление, которое будет обслуживаться в кэше, переопределяя фактическое представление от полномочного арендатора.

Клиенты должны отклонять вытолкнутые отклики, для которых сервер-источник не имеет полномочий (параграф 4.6).

10.5. DoS-атаки

Для работы соединения HTTP/3 может запрашиваться больше ресурсов, чем для HTTP/1.1 или HTTP/2. Использование сжатия полей и управления потоком данных зависит от выделения ресурсов для хранения большого объёма состояний. Настройки для этих функций обеспечивают строгое ограничение используемого объёма памяти.

Число кадров PUSH_PROMISE ограничивается похожим способом. Клиенту, воспринимающему выталкивание с сервера, следует ограничивать число идентификаторов (Push ID), выталкиваемых за один раз.

Пропускную способность при обработке невозможно защитить также эффективно, как объем хранимых состояний.

Возможностью отправлять неопределённые элементы протокола, которые партнёр не обязан игнорировать, может быть использована для того, чтобы вынудить партнёра затрачивать дополнительное время на обработку. Это можно сделать путём передачи множества неопределённых параметром SETTINGS, неизвестных типов кадров или потоков. Следует отметить, что некоторые из таких случаев вполне корректны, например, необязательные для понимания расширения или заполнение для повышения устойчивости к анализу трафика.

Сжатие раздела полей также предоставляет некоторые возможности дополнительного расхода ресурсов при обработке, более подробно описанные в разделе 7 [QPACK].

Все эти возможности — выталкивание с сервера, неизвестные элементы протокола, сжатие полей — могут применяться корректно и становятся вредными лишь при ненужном или избыточном применении. Конечные точки, не отслеживающие такое поведение, подвергают себя риску DoS-атак. Реализациям следует отслеживать и ограничивать использование таких возможностей. Конечная точка может считать подозрительную активность ошибкой соединения типа H3_EXCESSIVE_LOAD, но ложные срабатывания будут нарушать действительные соединения и запросы.

10.5.1. Ограничения размера раздела заголовков

Большой раздел полей (параграф 4.1) может вынудить реализацию зафиксировать большой объем состояния. Важные для маршрутизации строки полей могут размещаться в конце блока, что будет мешать передаче потока полей конечному адресату. Такое упорядочивание и другие причины, например, обеспечение корректности кэша, означают, что конечной точке может потребоваться целиком буферизовать блок полей. Поскольку размер блока полей жёстко не ограничен, некоторым конечным точкам может потребоваться большой объём памяти для блока полей.

Конечная точка может использовать установку SETTINGS_MAX_FIELD_SECTION_SIZE (параграф 4.2.2) для информирования своих партнёров о возможных ограничениях размера несжатого раздела полей. Эта настройка является лишь рекомендацией, поэтому конечные точки могут передавать блок полей, размер которого превышает этот предел, рискуя тем, что запрос или отклик будет сочтён ошибочным. Этот параметр относится к соединению HTTP/3 и любой запрос или отклик может столкнуться в пути с более низким и неизвестным ограничением. Посредник может попытаться избежать этой проблемы, передавая значения, представленные разными партнёрами, но не обязан делать этого.

Сервер, получивший блок полей, размер которого превышает тот, который сервер готов обработать, может передать код статуса HTTP 431 (Request Header Fields Too Large) [RFC6585]. Клиент может отбрасывать отклики, которые он не может обработать.

10.5.2. Проблемы CONNECT

Метод CONNECT можно использовать для создания непропорциональной нагрузки на прокси, поскольку создание потока относительно недорого по сравнению с созданием и поддержкой соединения TCP. Поэтому прокси с поддержкой CONNECT может быть более консервативным в части числа воспринимаемых одновременно запросов. Прокси может также поддерживать некоторые ресурсы для соединения TCP после закрытия потока, в котором передан запрос CONNECT, поскольку исходящее соединение TCP остаётся в состоянии TIME_WAIT. С учётом этого прокси может задерживать повышение пределов для соединения QUIC в течение некоторого времени послезакрытия соединения TCP.

10.6. Использование сжатия

Сжатие может позволить атакующему восстановить секретные данные, если они сжаты в одном контексте с данными, контролируемыми им. HTTP/3 разрешает сжатие строк полей (параграф 4.2), а приведённые ниже соображения относятся также к использованию в HTTP кодирования содержимого со сжатием (параграф 8.4.1 в [HTTP]).

Существуют наглядные атаки на сжатие, использующие свойства Web (например, [BREACH]). Атакующий создаёт множество запросов с различными открытыми данными (plaintext), наблюдая для каждого размер полученного шифротекста (ciphertext), который будет более коротким при угаданном секрете.

Реализациям, обменивающимся данными по защищённому каналу, недопустимо сжимать содержимое, включающее как конфиденциальные, так и контролируемые злоумышленником данные, если только для каждого источника данных не применяются свои словари. Недопустимо сжимать данные, если их источник невозможно определить достоверно.

Дополнительные соображения безопасности применительно к сжатию полей представлены в [QPACK].

10.7. Заполнение и анализ трафика

Заполнение может служить для сокрытия точного размера содержимого кадра и предназначено для смягчения определённых атак в HTTP, например, атак, где сжатое содержимое включает контролируемый злоумышленником открытый текст и секретные данные (например, [BREACH]).

Если HTTP/2 использует поля Padding5 в некоторых кадрах для повышения устойчивости соединения к анализу трафика, то HTTP/3 может полагаться на заполнение транспортного уровня или использовать зарезервированные типы кадров и потоков, описанные в параграфах 7.2.8 и 6.2.3. Эти методы заполнения дают разные результаты с точки зрения детализации заполнения, его размещения относительно защищаемой информации, применения заполнения в случае потери пакетов и способа управления заполнением в реализации.

Зарезервированные типы кадров и потоков можно применять для создания видимости передачи трафика при простое соединения. Поскольку трафик HTTP зачастую имеет характер всплесков (burst), видимый трафик может служить для маскировки времени и продолжительности таких всплесков, вплоть до создания иллюзии постоянного потока данных. Однако для такого трафика все равно применяется управление потоком данных со стороны получателя и неспособность своевременно «осушить» фиктивный трафик и предоставить дополнительный кредит на передачу может помешать отправке реального трафика.

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

Использование заполнения может предоставлять более слабую защиту, чем кажется на первый взгляд, а избыточное заполнение даже может быть вредным. В лучшем случае заполнение лишь усложняет для атакующего получение сведений о размере за счёт увеличения числа кадров, которые тому приходится наблюдать. Некорректно реализованные схемы заполнения легко преодолеваются. В частности, случайное заполнение с предсказуемым распределением обеспечивает лишь очень слабую защиту, а заполнение до определённого размера раскрывает сведения о размере, когда кадр превосходит заданный предел, что может быть полезно для злоумышленника, контролирующего открытый текст.

10.8. Разбор кадров

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

10.9. Ранние данные

Использование 0-RTT с HTTP/3 открывает возможность для атак с воспроизведением (replay). Должны применяться средства смягчения, описанные в [HTTP-REPLAY], при использовании HTTP/3 с 0-RTT. При использовании [HTTP-REPLAY] для HTTP/3 ссылки на уровень TLS относятся к согласованию, выполняемому в QUIC, а ссылки на данные приложения — к содержимому потоков.

10.10. Смена адреса

Некоторые реализации HTTP используют адрес клиента для протоколирования (log) или контроля доступа. Поскольку адрес клиента в QUIC может меняться в процессе действия соединения (а в будущих версиях может поддерживаться использование нескольких адресов), таким реализациям потребуется активно извлекать текущий адрес (или адреса) клиента, когда это актуально, или явно разрешать возможность смены исходного адреса.

10.11. Вопросы приватности

Некоторые особенности HTTP/3 дают наблюдателю возможность составить временную картину действий клиента или сервера. Это включает значения настроек, время реакции на воздействия и работу функций, управляемых настройками. По мере возникновения наблюдаемых различий в поведении эти свойства могут стать основой для «отпечатка» конкретного клиента

Предпочтение HTTP/3 использовать одно соединение QUIC позволяет отслеживать активность пользователя на сайте. Повторное использование соединений для других источников позволяет отслеживать эти источники.

Некоторые функции QUIC требуют немедленного отклика и могут использоваться конечной точкой для измерения задержки до своего партнёра, что может в некоторых случаях влиять на приватность.

11. Взаимодействие с IANA

Этот документ регистрирует новый идентификатор протокола ALPN (параграф 11.1) и создаёт новые реестры для кодов HTTP/3.

11.1. Регистрация строки идентификации HTTP/3

Этот документ задаёт новую регистрацию для идентификации HTTP/3 в реестре TLS Application-Layer Protocol Negotiation (ALPN) Protocol IDs, созданном в [RFC7301].

   Протокол:  HTTP/3
   Строка идентификации:  0x68 0x33 ("h3")
   Спецификация:  Этот документ

11.2. Новые реестры

В новых реестрах, созданных этим документом, применяется политика регистрации QUIC, заданная в параграфе 22.1 [QUIC-TRANSPORT]. Все эти реестры включают общий набор полей, указанный в параграфе 22.1.1 [QUIC-TRANSPORT] и собраны по общим заголовком Hypertext Transfer Protocol version 3 (HTTP/3).

Все исходные значения в этих реестрах имеют статус постоянных (permanent) и включают IETF в качестве контролёра изменений, а также контактный адрес рабочей группы HTTP (ietf-http-wg@w3.org).

11.2.1. Типы кадров

Этот документ создаёт реестр кодов типа кадров HTTP/3 Frame Types с 62-битовым пространством с политикой регистрации QUIC (см. параграф 11.2). Постоянные регистрации в этом реестре выполняются по процедуре Specification Required ([RFC8126]), за исключением диапазона 0x00 0x3f (включительно), где применяется процедура Standards Action или IESG Approval в соответствии с параграфами 4.9 и 4.10 в [RFC8126].

Хотя этот реестр отделен от реестра HTTP/2 Frame Type, заданного в [HTTP/2], предпочтительно выполнять назначения параллельно при перекрытии пространств кодов. Если запись присутствует лишь в одном реестре, следует приложить все усилия, чтобы избежать соответствующего значения для несвязанной операции. Эксперты могут отклонять несвязанные регистрации, конфликтующие с таким же значением в соответствующем реестре.

В дополнение к общим полям, указанным в параграфе 11.2, постоянные записи в этом реестре должны включать указанное ниже поле.

Frame Type

Имя или метка для типа кадра.

Спецификация типа кадра должна содержать описание структуры кадра и его семантики, включая любые части кадра с условным присутствием.

Этот документ регистрирует записи, приведённые в таблице 2.

Таблица . Исходные типы кадров HTTP/3.

 

Тип кадра

Значение

Спецификация

DATA

0x00

параграф 7.2.1

HEADERS

0x01

параграф 7.2.2

Reserved

0x02

этот документ

CANCEL_PUSH

0x03

параграф 7.2.3

SETTINGS

0x04

параграф 7.2.4

PUSH_PROMISE

0x05

параграф 7.2.5

Reserved

0x06

этот документ

GOAWAY

0x07

параграф 7.2.6

Reserved

0x08

этот документ

Reserved

0x09

этот документ

MAX_PUSH_ID

0x0d

параграф 7.2.7

 

Коды вида 0x1f * N + 0x21 для неотрицательный целых значений N (0x21, 0x40, …, 0x3ffffffffffffffe) недопустимо выделять агентству IANA и недопустимо включать в список выделенных значений.

11.2.2. Установки

Этот документ создаёт реестр установок (параметров) HTTP/3 Settings с 62-битовым пространством с политикой регистрации QUIC (см. параграф 11.2). Постоянные регистрации в этом реестре выполняются по процедуре Specification Required ([RFC8126]), за исключением диапазона 0x00 0x3f (включительно), где применяется процедура Standards Action или IESG Approval в соответствии с параграфами 4.9 и 4.10 в [RFC8126].

Хотя этот реестр отделен от реестра HTTP/2 Settings [HTTP/2], предпочтительно выполнять назначения параллельно при перекрытии пространств кодов. Если запись присутствует лишь в одном реестре, следует приложить все усилия, чтобы избежать соответствующего значения для несвязанной операции. Эксперты могут отклонять несвязанные регистрации, конфликтующие с таким же значением в соответствующем реестре.

В дополнение к общим полям, указанным в параграфе 11.2, постоянные записи в этом реестре должны включать указанные ниже поля.

Setting Name

Символьное имя параметра (необязательно).

Default

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

Этот документ регистрирует записи, приведённые в таблице 3.

Таблица . Исходные установки HTTP/3.

 

Имя параметра

Значение

Спецификация

Значение по умолчанию

Reserved

0x00

этот документ

N/A

Reserved

0x02

этот документ

N/A

Reserved

0x03

этот документ

N/A

Reserved

0x04

этот документ

N/A

Reserved

0x05

этот документ

N/A

MAX_FIELD_SECTION_SIZE

0x06

параграф 7.2.4.1

Unlimited

 

В целях форматирования префикс SETTINGS_ в именах можно не указывать.

Коды вида 0x1f * N + 0x21 для неотрицательный целых значений N (0x21, 0x40, …, 0x3ffffffffffffffe) недопустимо выделять агентству IANA и недопустимо включать в список выделенных значений.

11.2.3. Коды ошибок

Этот документ создаёт реестр кодов ошибок HTTP/3 Error Codes с 62-битовым пространством с политикой регистрации QUIC (см. параграф 11.2). Постоянные регистрации в этом реестре выполняются по процедуре Specification Required ([RFC8126]), за исключением диапазона 0x00 0x3f (включительно), где применяется процедура Standards Action или IESG Approval в соответствии с параграфами 4.9 и 4.10 в [RFC8126].

Регистрация должна включать описание кода ошибки. Экспертам рекомендуется проверять новые регистрации на предмет дублирования имеющихся кодов. Применение имеющихся кодов рекомендуется, но не требуется. Использовать значения из реестра HTTP/2 Error Code не рекомендуется и эксперты могут отклонять такие регистрации.

В дополнение к общим полям, указанным в параграфе 11.2, постоянные записи в этом реестре должны включать указанные ниже поля.

Name

Имя кода ошибки.

Description

Краткое описание семантики кода.

Этот документ регистрирует записи, приведённые в таблице 4. Эти коды были выбраны из диапазона, требующего использовать процедуру Specification Required для исключения конфликтов с кодами ошибок HTTP/2.

Таблица . Исходные коды ошибок HTTP/3.

 

Имя

Значение

Описание

Спецификация

H3_NO_ERROR

0x0100

Нет ошибок

параграф 8.1

H3_GENERAL_PROTOCOL_ERROR

0x0101

Протокольная ошибка общего типа

параграф 8.1

H3_INTERNAL_ERROR

0x0102

Внутренняя ошибка

параграф 8.1

H3_STREAM_CREATION_ERROR

0x0103

Ошибка при создании потока

параграф 8.1

H3_CLOSED_CRITICAL_STREAM

0x0104

Закрыт критически важный поток

параграф 8.1

H3_FRAME_UNEXPECTED

0x0105

Кадр не разрешён в текущем состоянии

параграф 8.1

H3_FRAME_ERROR

0x0106

Кадр нарушает требования к схеме или размеру

параграф 8.1

H3_EXCESSIVE_LOAD

0x0107

Партнёр создаёт чрезмерную нагрузку

параграф 8.1

H3_ID_ERROR

0x0108

Идентификатор применён некорректно

параграф 8.1

H3_SETTINGS_ERROR

0x0109

Непригодное значение в кадре SETTINGS

параграф 8.1

H3_MISSING_SETTINGS

0x010a

Не получен кадр SETTINGS

параграф 8.1

H3_REQUEST_REJECTED

0x010b

Запрос не обработан

параграф 8.1

H3_REQUEST_CANCELLED

0x010c

Данные больше не требуются

параграф 8.1

H3_REQUEST_INCOMPLETE

0x010d

Поток закрыт рано

параграф 8.1

H3_MESSAGE_ERROR

0x010e

Некорректно сформированное сообщение

параграф 8.1

H3_CONNECT_ERROR

0x010f

Сброс TCP или ошибка в запросе CONNECT

параграф 8.1

H3_VERSION_FALLBACK

0x0110

Повтор через HTTP/1.1

параграф 8.1

 

Коды вида 0x1f * N + 0x21 для неотрицательный целых значений N (0x21, 0x40, …, 0x3ffffffffffffffe) недопустимо выделять агентству IANA и недопустимо включать в список выделенных значений.

11.2.4. Типы потоков

Этот документ создаёт реестр типов односторонних потоков HTTP/3 Stream Types с 62-битовым пространством с политикой регистрации QUIC (см. параграф 11.2). Постоянные регистрации в этом реестре выполняются по процедуре Specification Required ([RFC8126]), за исключением диапазона 0x00 0x3f (включительно), где применяется процедура Standards Action или IESG Approval в соответствии с параграфами 4.9 и 4.10 в [RFC8126].

В дополнение к общим полям, указанным в параграфе 11.2, постоянные записи в этом реестре должны включать указанные ниже поля.

Stream Type

Имя или метка типа потока.

Sender

Конечная точка, которая может инициировать поток этого типа (Client, Server, Both).

Спецификация для постоянной регистрации должна содержать описание типа потока, включая структуру и семантику его содержимого.

Этот документ регистрирует записи, приведённые в таблице 5.

Таблица . Исходные типы потоков.

 

Тип потока

Значение

Спецификация

Отправитель

Control Stream

0x00

параграф 6.2.1

Оба

Push Stream

0x01

параграф 4.6

Сервер

 

Коды вида 0x1f * N + 0x21 для неотрицательный целых значений N (0x21, 0x40, …, 0x3ffffffffffffffe) недопустимо выделять агентству IANA и недопустимо включать в список выделенных значений.

12. Литература

12.1. Нормативные документы

[ALTSVC] Nottingham, M., McManus, P., and J. Reschke, «HTTP Alternative Services», RFC 7838, DOI 10.17487/RFC7838, April 2016, <https://www.rfc-editor.org/info/rfc7838>.

[COOKIES] Barth, A., «HTTP State Management Mechanism», RFC 6265, DOI 10.17487/RFC6265, April 2011, <https://www.rfc-editor.org/info/rfc6265>.

[HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «HTTP Semantics», STD 97, RFC 9110, DOI 10.17487/RFC9110, June 2022, <https://www.rfc-editor.org/info/rfc9110>.

[HTTP-CACHING] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «HTTP Caching», STD 98, RFC 9111, DOI 10.17487/RFC9111, June 2022, <https://www.rfc-editor.org/info/rfc9111>.

[HTTP-REPLAY] Thomson, M., Nottingham, M., and W. Tarreau, «Using Early Data in HTTP», RFC 8470, DOI 10.17487/RFC8470, September 2018, <https://www.rfc-editor.org/info/rfc8470>.

[QPACK] Krasic, C., Bishop, M., and A. Frindell, Ed., «QPACK: Field Compression for HTTP/3», RFC 9204, DOI 10.17487/RFC9204, June 2022, <https://www.rfc-editor.org/info/rfc9204>.

[QUIC-TRANSPORT] Iyengar, J., Ed. and M. Thomson, Ed., «QUIC: A UDP-Based Multiplexed and Secure Transport», RFC 9000, DOI 10.17487/RFC9000, May 2021, <https://www.rfc-editor.org/info/rfc9000>.

[RFC0793] Postel, J., «Transmission Control Protocol», STD 7, RFC 793, DOI 10.17487/RFC0793, September 1981, <https://www.rfc-editor.org/info/rfc793>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC6066] Eastlake 3rd, D., «Transport Layer Security (TLS) Extensions: Extension Definitions», RFC 6066, DOI 10.17487/RFC6066, January 2011, <https://www.rfc-editor.org/info/rfc6066>.

[RFC7301] Friedl, S., Popov, A., Langley, A., and E. Stephan, «Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension», RFC 7301, DOI 10.17487/RFC7301, July 2014, <https://www.rfc-editor.org/info/rfc7301>.

[RFC8126] Cotton, M., Leiba, B., and T. Narten, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[URI] Berners-Lee, T., Fielding, R., and L. Masinter, «Uniform Resource Identifier (URI): Generic Syntax», STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, <https://www.rfc-editor.org/info/rfc3986>.

12.2. Дополнительная литература

[BREACH] Gluck, Y., Harris, N., and A. Prado, «BREACH: Reviving the CRIME Attack», July 2013, <http://breachattack.com/resources/BREACH%20-%20SSL,%20gone%20in%2030%20seconds.pdf>.

[DNS-TERMS] Hoffman, P., Sullivan, A., and K. Fujiwara, «DNS Terminology», BCP 219, RFC 8499, DOI 10.17487/RFC8499, January 2019, <https://www.rfc-editor.org/info/rfc8499>.

[HPACK] Peon, R. and H. Ruellan, «HPACK: Header Compression for HTTP/2», RFC 7541, DOI 10.17487/RFC7541, May 2015, <https://www.rfc-editor.org/info/rfc7541>.

[HTTP/1.1] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «HTTP/1.1», STD 99, RFC 9112, DOI 10.17487/RFC9112, June 2022, <https://www.rfc-editor.org/info/rfc9112>.

[HTTP/2] Thomson, M., Ed. and C. Benfield, Ed., «HTTP/2», RFC 9113, DOI 10.17487/RFC9113, June 2022, <https://www.rfc-editor.org/info/rfc9113>.

[RFC6585] Nottingham, M. and R. Fielding, «Additional HTTP Status Codes», RFC 6585, DOI 10.17487/RFC6585, April 2012, <https://www.rfc-editor.org/info/rfc6585>.

[RFC8164] Nottingham, M. and M. Thomson, «Opportunistic Security for HTTP/2», RFC 8164, DOI 10.17487/RFC8164, May 2017, <https://www.rfc-editor.org/info/rfc8164>.

[TFO] Cheng, Y., Chu, J., Radhakrishnan, S., and A. Jain, «TCP Fast Open», RFC 7413, DOI 10.17487/RFC7413, December 2014, <https://www.rfc-editor.org/info/rfc7413>.

[TLS] Rescorla, E., «The Transport Layer Security (TLS) Protocol Version 1.3», RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.

Приложение A. Вопросы перехода с HTTP/2

HTTP/3 в значительной степени опирается на HTTP/2 и протоколы имеют много сходств. В этом приложении описан подход к разработке HTTP/3, указаны важные отличия от HTTP/2 и описано, как сопоставить расширения HTTP/2 с HTTP/3.

HTTP/3 исходит из того, что сходство с HTTP/2 предпочтительно, но не является жёстким требованием. HTTP/3 отличается от HTTP/2 там, где QUIC отличается от TCP, нужно воспользоваться преимуществами QUIC (например, потоками) или нужно учесть важные недостатки (например, отсутствие полного упорядочивания). Хотя HTTP/3 похож на HTTP/2 в основных аспектах, таких как связь запросов и откликов с потоками, детали устройства HTTP/3 существенно отличаются от HTTP/2.

Некоторые важные отличия рассматриваются в следующих параграфах.

A.1. Потоки

HTTP/3 позволяет использовать большее число потоков (262-1), чем HTTP/2. Применяются такие же соображения в части исчерпания пространства идентификаторов потоков, хотя пространство значительно больше и, скорей всего, раньше будут достигнуты ограничения QUIC, такие как ограничения для окна управления потоком данных.

В отличие от HTTP/2 управление одновременными потоками HTTP/3 осуществляется в QUIC. Поток в QUIC считается закрытым, когда все данные были получены, а все передачи подтверждены партнёром. HTTP/2 считает поток закрытым, когда транспорту представлен кадр с флагом END_STREAM, в результате чего поток для эквивалентного обмена может сохранять состояние active достаточно долго. Серверы HTTP/3 могут разрешать большее число инициированных клиентом одновременных двухсторонних потоков по сравнению с HTTP/2, в зависимости от ожидаемой картины использования.

В HTTP/2 управление потоком данных применяется только для тела запросов и откликов (содержимое кадров DATA), а в HTTP/3 — для всех потоков QUIC (следовательно, для всех кадров HTTP/3).

Из-за наличия других типов односторонних потоков, HTTP/3 не полагается исключительно на число одновременных односторонних потоков при контроле числа одновременных выталкиваний, находящихся в пути. Вместо этого клиенты HTTP/3 используют кадр MAX_PUSH_ID для управления числом выталкиваний с сервера HTTP/3.

A.2. Типы кадров HTTP

Многие концепции кадрирования HTTP/2 могут быть исключены, поскольку в QUIC этим занимается транспорт. Кадры уже находятся в потоке и номер потока можно не указывать. Поскольку кадры не блокируют мультиплексирование (в QUIC это происходит на нижележащем уровне), поддержка пакетов с переменным максимальным размером не нужна. Прерывание потоков обрабатывается в QUIC и флаг END_STREAM не требуется, что позволило исключить поле Flags из базового формата кадров.

Содержимое (payload) кадров в значительной мере взято из [HTTP/2]. Протокол QUIC включает многие функции (например, управление потоком данный), присутствующие в HTTP/2 и в таких случаях отображение HTTP не реализует их заново. В результате некоторые типы кадров HTTP/2 не нужны в HTTP/3. Идентификаторы таких кадров были зарезервированы для обеспечения максимальной переносимости между реализациями HTTP/2 и HTTP/3. Однако все кадры, присутствующие в обоих отображениях, имеют идентичную семантику.

Многие различия связаны с тем, что в HTTP/2 применяется абсолютное упорядочивание кадров между всеми потоками, а QUIC обеспечивает такую гарантию лишь в рамках потока. В результате, если тип кадра предполагает, что кадр из другого потока будет получен в порядке передачи, HTTP/3 нарушает это.

Ниже приведены некоторые примеры адаптации, а также общие рекомендации для реализации кадров расширения, преобразующих расширения HTTP/2 в HTTP/3.

A.2.1. Различия в приоритизации

HTTP/2 задаёт приоритет в кадрах PRIORITY и (опционально) HEADERS, а в HTTP/3 нет сигналов приоритета. Однако отсутствие явного указания приоритета не означает, что приоритизация не важна для достижения высокой производительности.

A.2.2. Различия в сжатии полей

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

Поскольку в QUIC не поддерживается полного упорядочивания, HTTP/3 использует модифицированную версию HPACK, называемую QPACK. В QPACK используется один односторонний поток для внесения всех изменений в динамическую таблицу, что гарантирует общий порядок обновлений. Все кадры с закодированными полями просто ссылаются на состояние таблицы в данный момент, не изменяя его. Дополнительные сведения приведены в [QPACK].

A.2.3. Различия в управлении потоком данных

HTTP/2 задаёт механизм управления потоком данных в потоках (stream). Хотя все кадры HTTP/2 доставляются в потоках, управление потоком данных применяется лишь для содержимого кадров DATA. QUIC обеспечивает управление потоком данных для потоков и все кадры HTTP/3, заданные в этом документе, передаются через потоки, поэтому подвержены управлению потоком данных.

A.2.4. Рекомендации для определения новых типов кадров

В кадрах HTTP/3 часто применяется кодирование QUIC для целых чисел с переменным размером. В частности, такое кодирование применяется для идентификаторов потока, что позволяет использовать больше значений, чем в HTTP/2. В некоторых кадрах HTTP/3 используются идентификаторы, отличные от идентификатора потока (например Push ID). Переопределение кодирования типов кадров расширения может потребоваться, если оно включает идентификатор потока.

Поскольку поле Flags не применяется в базовом формате кадров HTTP/3, кадры, зависящие от наличия флагов, должны предусматривать место для них как часть своего содержимого (payload).

За исключением отмеченного выше, расширения HTTP/2 для типов кадров обычно переносятся в QUIC простой заменой потока 0 в HTTP/2 потоком управления HTTP/3. Расширения HTTP/3 не предполагают упорядочивания, но оно не повредит, и предполагается, что они будут переносимы в HTTP/2.

A.2.5. Сравнение кадров HTTP/2 и HTTP/3

DATA (0x00)

Заполнение не определено для HTTP/3 (параграф 7.2.1).

HEADERS (0x01)

Область PRIORITY и заполнение не определены в HTTP/3 (параграф 7.2.2).

PRIORITY (0x02)

Как указано в Приложении A.2.1, в HTTP/3 не поддерживается сигнализация приоритета.

RST_STREAM (0x03)

Кадров RST_STREAM нет в HTTP/3, поскольку потоками управляет QUIC. Тот же код применяется для кадров CANCEL_PUSH (параграф 7.2.3).

SETTINGS (0x04)

Кадры SETTINGS передаются лишь в начале соединения (параграф 7.2.4 и Приложение A.3).

PUSH_PROMISE (0x05)

Кадр PUSH_PROMISE не указывает поток, а вытолкнутый поток ссылается на кадр PUSH_PROMISE в Push ID (параграф 7.2.5).

PING (0x06)

Кадров PING нет в HTTP/3, поскольку QUIC обеспечивает эквивалентную функциональность.

GOAWAY (0x07)

GOAWAY не включает код ошибки. В направлении от клиента к серверу он передаёт Push ID вместо идентификатора созданного сервером потока (параграф 7.2.6).

WINDOW_UPDATE (0x08)

Кадров WINDOW_UPDATE нет в HTTP/3, поскольку управление потоком данных обеспечивает QUIC.

CONTINUATION (0x09)

Кадров CONTINUATION нет в HTTP/3 и вместо этого разрешены более крупные кадры HEADERS и PUSH_PROMISE.

Типы кадров, определённые расширениями HTTP/2, не требуется отдельно регистрировать для HTTP/3, если они применимы. Идентификаторы кадров из [HTTP/2] для простоты зарезервированы. Отметим, что пространство типов кадров в HTTP/3 значительно шире (62 бита вместо 8), поэтому многие типы кадров HTTP/3 не имеют эквивалентных кодов HTTP/2 (параграф 11.2.1).

A.3. Параметры HTTP/2 SETTINGS

Важным отличием от HTTP/2 является то, что настройки передаются один раз как первый кадр потока управления и в дальнейшем не могут меняться. Это исключает множество случаев, связанных с синхронизацией изменений.

Некоторые опции транспортного уровня, задаваемые в HTTP/2 через кадры SETTINGS, заменены транспортными параметрами QUIC в HTTP/3. Параметры уровня HTTP, сохраняющиеся в HTTP/3, имеют такое же значение, как в HTTP/2. Переопределенные параметры зарезервированы и их получение считается ошибкой (см. параграф 7.2.4.1).

Ниже приведено сопоставление параметров HTTP/2 SETTINGS.

SETTINGS_HEADER_TABLE_SIZE (0x01)

См. [QPACK].

SETTINGS_ENABLE_PUSH (0x02)

Удалено с заменой кадром MAX_PUSH_ID, обеспечивающим более детальное управление выталкиванием с сервера. Указание параметра с идентификатором 0x02 (SETTINGS_ENABLE_PUSH) в кадре HTTP/3 SETTINGS является ошибкой.

SETTINGS_MAX_CONCURRENT_STREAMS (0x03)

QUIC контролирует наибольший идентификатор потока в логике управления потоком данных. Указание параметра с идентификатором 0x03 (SETTINGS_MAX_CONCURRENT_STREAMS) в кадре HTTP/3 SETTINGS является ошибкой.

SETTINGS_INITIAL_WINDOW_SIZE (0x04)

QUIC требует задания размера окна управления потоком данных на уровне соединения и потока при начальном согласовании транспорта. Указание параметра с идентификатором 0x04 (SETTINGS_INITIAL_WINDOW_SIZE) в кадре HTTP/3 SETTINGS является ошибкой.

SETTINGS_MAX_FRAME_SIZE (0x05)

This setting has no equivalent in HTTP/3. Указание параметра с идентификатором 0x05 (SETTINGS_MAX_FRAME_SIZE) в кадре HTTP/3 SETTINGS является ошибкой.

SETTINGS_MAX_HEADER_LIST_SIZE (0x06)

Переименован в SETTINGS_MAX_FIELD_SECTION_SIZE.

В HTTP/3 значения настроек являются целыми числами переменного размера (6, 14, 30 или 62 бита) в отличие от 32-битовых полей в HTTP/2. Это часто обеспечивает более компактное кодирование, но может удлинять процесс для установок, использующих все 32-битовое пространство. Настройки, перенесённые из HTTP/2, могут переопределять своё значение с ограничением размера 30 битами для более эффективного кодирования или использовать 62 бита, если 30 не достаточно.

Настройки для HTTP/2 и HTTP/3 должны определяться раздельно. Идентификаторы настроек из [HTTP/2] для простоты зарезервированы. Пространство настроек HTTP/3 значительно шире (62 бита вместо 16 bits) и для многих настроек HTTP/3 нет эквивалентного кода HTTP/2 (см. параграф 11.2.2).

Потоки QUIC могут доставляться с нарушением порядка, поэтому конечным точка рекомендуется не ждать получения установок от партнёра перед ответом на другие потоки (см. параграф 7.2.4.2).

A.4. Коды ошибок HTTP/2

В QUIC используется такая же концепция ошибок потока и соединения, как в HTTP/2. Однако различия между HTTP/2 и HTTP/3 не позволяют напрямую переносить коды ошибок между версиями. Ниже приведено логическое сопоставление кодов ошибок HTTP/2 из раздела 7 в [HTTP/2] с кодами ошибок HTTP/3.

NO_ERROR (0x00)

H3_NO_ERROR (параграф 8.1).

PROTOCOL_ERROR (0x01)

H3_GENERAL_PROTOCOL_ERROR за исключением случаев наличия более конкретного кода (H3_FRAME_UNEXPECTED, H3_MESSAGE_ERROR, H3_CLOSED_CRITICAL_STREAM, см. параграф 8.1).

INTERNAL_ERROR (0x02)

H3_INTERNAL_ERROR (параграф 8.1).

FLOW_CONTROL_ERROR (0x03)

Не применим, поскольку потоком данных управляет QUIC.

SETTINGS_TIMEOUT (0x04)

Не применим, поскольку подтверждение SETTINGS не определено.

STREAM_CLOSED (0x05)

Не применим, поскольку потоками управляет QUIC.

FRAME_SIZE_ERROR (0x06)

H3_FRAME_ERROR (параграф 8.1).

REFUSED_STREAM (0x07)

H3_REQUEST_REJECTED (параграф 8.1) применяется для указания того, что запрос не был обработан. В иных случаях код не применим, поскольку потоками управляет QUIC.

CANCEL (0x08)

H3_REQUEST_CANCELLED (параграф 8.1).

COMPRESSION_ERROR (0x09)

Несколько кодов ошибок, заданных в [QPACK].

CONNECT_ERROR (0x0a)

H3_CONNECT_ERROR (параграф 8.1).

ENHANCE_YOUR_CALM (0x0b)

H3_EXCESSIVE_LOAD (параграф 8.1).

INADEQUATE_SECURITY (0x0c)

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

HTTP_1_1_REQUIRED (0x0d)

H3_VERSION_FALLBACK (параграф 8.1).

Коды ошибок для HTTP/2 и HTTP/3 должны определяться раздельно (см. параграф 11.2.3).

A.4.1. Сопоставление ошибок HTTP/2 и HTTP/3

Посредник, преобразующий между HTTP/2 и HTTP/3, может столкнуться с ошибками в любом восходящем потоке. Полезно сообщать об ошибках нисходящему потоку, но коды ошибок в основном отражают локальные проблемы соединения, о которых нет смысла сообщать.

Посредник, обнаруживший ошибку от восходящего источника, может указать её отправкой кода статуса HTTP, такого как 502 (Bad Gateway), который подходит для широкого класса ошибок.

Имеется несколько редких случаев, когда полезно сообщить об ошибке, отображением её на тип, наиболее соответствующий получателю. Например, посредник, получивший ошибку потока HTTP/2 типа REFUSED_STREAM от источника, имеет чёткий сигнал, что запрос не был обработан и его можно безопасно повторить. Передача этих сведений клиенту как ошибки потока HTTP/3 типа H3_REQUEST_REJECTED позволяет клиенту выполнить действия, которые он сочтёт подходящими. В обратном направлении посредник может счесть уместным передавать отмену клиентского запроса, которая указывается прерыванием потока с ошибкой H3_REQUEST_CANCELLED (параграф 4.1.1).

Преобразование ошибок описаны выше (логическое сопоставление). Коды определены в неперекрывающихся пространствах для защиты от случайного преобразования, способного привести к использованию неподходящих или неизвестных кодов. Посреднику разрешено преобразовывать ошибки потока в ошибки соединения, но ему следует учитывать стоимость организации соединения HTTP/3 в случаях, когда ошибка может быть временной или нерегулярной.

Благодарности

Robbie Shade и Mike Warres были авторами draft-shade-quic-http2-mapping, предшественника этого документа.

Рабочая группа IETF QUIC получила огромную поддержку от многих людей. Ниже перечислены некоторые люди, внёсшие существенный вклад в этот документ.

Bence Beky
Daan De Meyer
Martin Duke
Roy Fielding
Alan Frindell
Alessandro Ghedini
Nick Harper
Ryan Hamilton
Christian Huitema
Subodh Iyengar
Robin Marx
Patrick McManus
Luca Niccolini
奥 一穂 (Kazuho Oku)
Lucas Pardue
Roberto Peon
Julian Reschke
Eric Rescorla
Martin Seemann
Ben Schwartz
Ian Swett
Willy Taureau
Martin Thomson
Dmitri Tikhonov
Tatsuhiro Tsujikawa

Работа Mike Bishop частично поддерживалась компанией Microsoft, пока он был её сотрудником.

Адрес автора

Mike Bishop (editor)
Akamai
Email: mbishop@evequefou.be

Перевод на русский язык

nmalykh@protokols.ru


1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

3В оригинале ошибочно сказано «ниже», см. https://www.rfc-editor.org/errata/eid7238. Прим. перев.

4В оригинале ошибочно указаны параграфы 3.3 и 3.4 в [URI], см. https://www.rfc-editor.org/errata/eid7014. Прим. перев.

5В оригинале ошибочно указан ещё кадр PADDING, см. https://www.rfc-editor.org/errata/eid7702. Прим. перев.

Рубрика: RFC | Оставить комментарий

RFC 9113 HTTP/2

Internet Engineering Task Force (IETF)                   M. Thomson, Ed.
Request for Comments: 9113                                       Mozilla
Obsoletes: 7540, 8740                                   C. Benfield, Ed.
Category: Standards Track                                     Apple Inc.
ISSN: 2070-1721                                                June 2022

HTTP/2

PDF

Аннотация

Эта спецификация описывает оптимизированное выражение семантики протокола передачи гипертекста (Hypertext Transfer Protocol или HTTP), называемого HTTP версии 2 (HTTP/2). HTTP/2 обеспечивает более эффективно использование ресурсов сети и сокращение задержек благодаря сжатию полей и возможности множества обменов одновременно через одно соединение.

Этот документ отменяет RFC 7540 и RFC 8740.

Статус документа

Документ относится к категории Internet Standards Track.

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG2. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке https://www.rfc-editor.org/info/rfc9113.

Авторские права

Copyright (c) 2022. Авторские права принадлежат IETF Trust и лицам, указанным в качестве авторов документа. Все права защищены.

К документу применимы права и ограничения, указанные в BCP 78 и IETF Trust Legal Provisions и относящиеся к документам IETF (http://trustee.ietf.org/license-info), на момент публикации данного документа. Прочтите упомянутые документы внимательно. Фрагменты программного кода, включённые в этот документ, распространяются в соответствии с упрощённой лицензией BSD, как указано в параграфе 4.e документа IETF Trust Legal Provisions, без каких-либо гарантий (как указано в Revised BSD License).

1. Введение

Производительность приложений, использующих протокол HTTP [HTTP] зависит от способа использования базового транспорта каждой версией HTTP и условий работы этого транспорта.

Выполнение нескольких запросов одновременно может снизить задержку и повысить производительность приложения. В HTTP/1.0 разрешается лишь один запрос в каждый момент работы данного соединения TCP [TCP]. В HTTP/1.1 [HTTP/1.1] добавлен конвейер запросов, но это лишь частично решило задачу параллельных запросов и по-прежнему сталкивается с проблемой блокировки head-of-line. Поэтому клиенты HTTP/1.0 и HTTP/1.1 используют множество соединений с сервером для одновременного выполнения запросов.

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

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

В результате протокол более дружелюбен к сети, поскольку может применяться меньшее число соединений TCP, нежели для HTTP/1.x. Это означает меньшую конкуренцию с другими потоками и долгосрочными соединениями, что, в свою очередь, ведёт к более эффективному использованию доступной пропускной способности сети. Однако, следует отметить, что протокол не решает проблему блокировки head-of-line в TCP.

HTTP/2 также обеспечивает более эффективную обработку сообщений за счёт применения двоичной структуры сообщений.

Этот документ отменяет RFC 7540 и RFC 8740. Важные отличия приведены в Приложении B.

2. Обзор протокола HTTP/2

HTTP/2 обеспечивает оптимизированный транспорт для семантики HTTP и поддерживает все базовые свойства HTTP, стремясь быть более эффективным по сравнению с HTTP/1.1.

HTTP/2 — это основанный на соединениях протокол прикладного уровня, работающий через соединения TCP ([TCP]), инициируемые клиентом.

Базовым элементом протокола HTTP/2 является кадр (frame, параграф 4.1). Каждый тип кадра служит для своих целей. Например, кадры HEADERS и DATA являются основой для запросов и откликов HTTP (параграф 8.1), другие типы, такие как SETTINGS, WINDOW_UPDATE, PUSH_PROMISE используются для поддержки иных функций HTTP/2.

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

Эффективное применение мультиплексирования зависит от управления потоками данных и приоритизацией. Управление потоком данных (параграф 5.2) обеспечивает возможность эффективного использования мультиплексируемых потоков, ограничивая передачу данных возможностями их обработки получателем. Приоритизация (параграф 5.3) обеспечивает наиболее эффективное использование ограниченных ресурсов. В данной версии HTTP/2 отменена схема сигнализации для приоритетов из [RFC7540].

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

В HTTP/2 добавлен новый (необязательный) режим взаимодействия, где сервер может выталкивать (push) отклики клиенту (параграф 8.4). Это позволяет серверу по своему усмотрению отправлять клиенту данные, которые сервер считает нужными для этого клиента, что ведёт к некой добавочной нагрузке на сеть но может сокращать задержки. Для этого сервер синтезирует запрос, который он отправляет в виде кадра PUSH_PROMISE. После этого сервер может передать ответ на синтезированный запрос в отдельном потоке.

2.1. Организация документа

Спецификация HTTP/2 делится на 4 части:

  • раздел 3 посвящён инициированию соединений HTTP/2;

  • разделы 4 (кадры) и 5 (потоки) описывают структурирование кадров HTTP/2 и формирование мультиплексируемых потоков;

  • разделы 6 (кадры) и 7 (ошибки) определяют детали кадров и типы ошибок, применяемые в HTTP/2;

  • раздел 8 описывает сопоставления, а раздел 9 — дополнительные требования, связанные с выражением семантики HTTP с использованием кадров и потоков.

Хотя некоторые концепции уровней кадров и потоков отделены от HTTP, спецификация на задаёт базовый уровень кадров. Уровни кадров и потоков адаптированы к потребностям HTTP.

2.2. Соглашения и термины

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

Все числовые значения приводятся с сетевым порядком байтов и не включают знак, если явно не указано иное. Литеральные значения указываются в десятичном или шестнадцатеричном формате в зависимости от ситуации. Для шестнадцатеричных литералов используется префикс 0x, отличающий их от десятичных литералов.

Эта спецификация описывает двоичные форматы в соответствии с соглашениями, описанными в формате 1.3 RFC 9000 [QUIC]. Отметим, что в этом формате применяется сетевой порядок байтов и сначала указываются старшие биты.

Ниже приведены используемые в документе термины.

client — клиент

Конечная точка, инициирующая соединение HTTP/2. Клиент передаёт запросы HTTP и получает отклики HTTP.

connection — соединение

Соединение транспортного уровня между парой конечных точек.

connection error — ошибка соединения

Ошибка, влияющая на всё соединение HTTP/2.

endpoint — конечная точка

Клиент или сервер в соединении.

frame — кадр

Наименьшая единица коммуникаций в соединении HTTP/2, состоящая из заголовка и последовательности октетов с переменным размером в соответствии с типом кадра.

peer — партнёр

Конечная точка. При обсуждении конкретной точки партнёром называется удалённая по отношению к ней точка.

receiver — получатель

Конечная точка, принимающая кадры.

sender — отправитель

Конечная точка, передающая кадры.

server — сервер

Конечная точка, воспринимающая соединение HTTP/2. Сервер принимает запросы HTTP и передаёт отклики HTTP.

stream — поток

Двухсторонний поток кадров в соединении HTTP/2connection.

stream error — ошибка потока

Ошибка в отдельном потоке HTTP/2.

Термины шлюз *gateway), посредник (intermediary), прокси (proxy) и туннель (tunnel) определены в параграфе 3.7 [HTTP]. Посредники выступают в разные моменты как клиенты и серверы.

Термин содержимое (content) применительно к телу сообщения определён в параграфе 6.4 [HTTP].

3. Начало работы HTTP/2

Реализации, генерирующей запросы HTTP, нужно выяснить, поддерживает ли сервер HTTP/2.

В HTTP/2 применяются схемы URI http и https, определённые в параграфе 4.2 [HTTP], с теми же принятыми по умолчанию номерами портов, что и HTTP/1.1 [HTTP/1.1]. Эти URI не включают индикации версий HTTP, поддерживаемых сервером восходящего направления (прямой партнёр, с которым клиент хочет организовать соединение). Средства определения поддержки HTTP/2 различаются для схем URI http и https, вариант для https описан в параграфе 3.2. Поддержку HTTP/2 для URI http можно обнаружить только внешними (out-of-band) средствами и знать о ней нужно заранее, как описано в параграфе 3.3.

3.1. Идентификация версии HTTP/2

Заданный этим документом протокол имеет два идентификатора и создание соединения на основе любого их них предполагает использование транспорта, кадрирования и семантики сообщений, определённых в этом документе.

  • Строка h2 указывает протокол, где HTTP/2 использует защиту транспортного уровня (Transport Layer Security или TLS), см. параграф 9.2. Этот идентификатор применяется в поле расширения согласования протокола транспортного уровня TLS (TLS Application-Layer Protocol Negotiation или ALPN) [TLS-ALPN] и в любом месте, где идентифицирован протокол HTTP/2 через TLS. Строка h2 преобразуется в идентификатор протокола ALPN в форме двухоктетной последовательности 0x68, 0x32.

  • Строка h2c ранее применялась как маркер для использования в поле заголовка Upgrade механизма HTTP Upgrade (параграф 7.8 в [HTTP]). Это так и не получило широкого распространения и отменено данным документом. Это же относится к полю заголовка HTTP2-Settings, которое применялось при обновлении до h2c.

3.2. Начало работы HTTP/2 для URI https

Клиент, запрашивающий URI https, использует TLS [TLS13] с расширением ALPN [TLS-ALPN].

HTTP/2 через TLS использует идентификатор протокола h2. Идентификатор протокола h2c недопустимо передавать клиенту или выбирать серверу, поскольку этот идентификатор указывает протокол, не использующий TLS.

По завершении согласования TLS клиент и сервер должны передать предисловие к соединению (параграф 3.4).

3.3. Начало работы HTTP/2 с предварительными сведениями

Клиент может узнать о поддержке сервером HTTP/2 другими способами, например, это может быть указано в его конфигурации. Клиент, знающий о поддержке сервером HTTP/2, может организовать соединение TCP и передать предисловие (параграф 3.4), а затем — кадры HTTP/2. Серверы могут идентифицировать такие соединения по наличию предисловия. Это влияет лишь на организацию соединений HTTP/2 через «чистый» протокол TCP, в соединениях через TLS должно применяться согласование протокола в TLS [TLS-ALPN].

Сервер тоже должен передать предисловие к соединению (параграф 3.4).

Без дополнительных сведений нельзя полагать, что сервер будет поддерживать HTTP/2 в будущих соединениях. Например, может измениться конфигурация сервера, а также могут различаться конфигурации разных серверов или условия в сети.

3.4. Предисловие соединения HTTP/2

В HTTP/2 каждая конечная точка должна передать предисловие к соединению как окончательное подтверждение применяемого протокола и установки начальных настроек для соединения HTTP/2. Клиент и сервер передают разные предисловия к соединению. Клиентское предисловие начинается с последовательности из 24 октетов

     0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a

т. е. предисловие начинается со строки PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n. За ней должен следовать кадр SETTINGS (параграф 6.5), который может быть пустым. Клиент передаёт предисловие к соединению в качестве первых октетов данных приложения в соединении.

Примечание. Клиентское предисловие к соединению выбрано так, что большинство серверов и посредников HTTP/1.1 и HTTP/1.0 не пытаются обрабатывать последующие кадры. Отметим, что это не решает проблемы, указанные в [TALKING].

Серверное предисловие к соединению состоит из (возможно пустого) кадра SETTINGS (параграф 6.5), который должен быть первым кадром, передаваемым сервером в соединение HTTP/2. Кадры SETTINGS, полученные от партнёра как часть предисловия к соединению, должны подтверждаться (параграф 6.5.3) после отправки предисловия.

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

Клиент и сервер должны считать недействительное предисловие к соединению ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR. В этом случае кадр GOAWAY (параграф 6.8) можно опустить, поскольку недействительное предисловие указывает, что партнёр не использует HTTP/2.

4. Кадры HTTP

После организации соединения HTTP/2 конечные точки могут начинать обмен кадрами.

4.1. Формат кадра

Все кадры начинаются с фиксированного 9-октетного заголовка, за которым следуют данные переменного размера.

   HTTP Frame {
     Length (24),
     Type (8),

     Flags (8),

     Reserved (1),
     Stream Identifier (31),

     Frame Payload (..),
   }

Рисунок .Схема кадра.


Length

24-битовое целое число без знака, указывающее размер кадра в октетах без учёта 9 октетов заголовка кадра. Недопустимо передавать значения больше 214 (16384), если получатель не указал большее значение для SETTINGS_MAX_FRAME_SIZE.

Type

8-битовое значение типа, определяющее формат и семантику кадра. Определения типов приведены в разделе 6. Реализация должна игнорировать и отбрасывать кадры неизвестных типов.

Flags

8-битовое резервное поле флагов, связанных с типом кадра. Семантика флагов определяется типом кадра, не имеющие семантики флаги не используются. Они должны игнорироваться при получении и сбрасываться (0x00) при отправке.

Reserved

Резервный бит без определённой семантики. Бит должен оставаться сброшенным (0x00) при передаче и игнорироваться при получении.

Stream Identifier

Идентификатор потока (параграф 5.1.1), указанный 31-битовым целым числом без знака. Значение 0x00 зарезервировано для кадров, связанных с соединением в целом, а не с отдельными потоками.

Структура и содержимое данных (payload) полностью зависят от типа кадра.

4.2. Размер кадра

Размер данных кадра ограничен максимумом, заданным получателем в SETTINGS_MAX_FRAME_SIZE. Этот параметр может принимать значение от 214 (16384) до 224-1 (16777215), включительно.

Все реализации должны уметь принимать и минимально обрабатывать кадры размером до 214 октетов + 9 октетов заголовка кадра (параграф 4.1). Размер заголовка не учитывается при описании размеров кадров.

Примечание. Для некоторых кадров, например, PING (параграф 6.7), имеются дополнительные ограничения размера данных.

Конечная точка должна передавать код ошибки FRAME_SIZE_ERROR, если размер кадра превышает SETTINGS_MAX_FRAME_SIZE, ограничение, заданное для типа кадра, или кадр слишком мал для включения обязательных данных. Ошибка размера в кадре, способном изменить состояние соединения в целом, должна считаться ошибкой соединения (параграф 5.4.1). Это относится к любым кадрам с блоком полей (параграф 4.3) (HEADERS, PUSH_PROMISE, CONTINUATION), кадрам SETTINGS, а также кадрам с идентификатором потока 0.

Конечные точки не обязаны использовать все доступное в кадре пространство. Отзывчивость можно улучшить используя кадры размером меньше разрешённого максимума. Большой размер может приводить к задержкам при отправке чувствительных ко времени кадров (например, RST_STREAM, WINDOW_UPDATE, PRIORITY), блокировка которых передачей большого кадра может влиять на производительность.

4.3. Сжатие и декомпрессия раздела полей

Сжатие раздела полей представляет собой компрессию набора строк полей (параграф 5.2 в [HTTP]) для формирования блока полей. Декомпрессия раздела полей — это декодирование блока полей в набор строк полей. Детали сжатия и декомпрессии раздела полей HTTP/2 приведены в [COMPRESSION], где в силу исторических причин они называются сжатием и декомпрессией заголовков.

Каждый блок полей содержит все сжатые строки полей из одного раздела полей. Разделы полей включают также данные управления,связанные с сообщением в форме полей псевдозаголовка (параграф 8.3) с тем же форматом, что и строка поля.

Примечание. В RFC 7540 [RFC7540] применяется термин блок заголовка (header block), а не блок полей (field block).

Блоки полей содержат данные управления и разделы заголовков для запросов, откликов, обещанных запросов и выталкиваемых откликов (см. параграф 8.4). Все эти сообщения, за исключением промежуточных откликов и запросов, содержащихся в кадрах PUSH_PROMISE (параграф 6.6), могут включать блок полей с разделом трейлеров.

Раздел полей — это набор строк полей и каждая строка в блоке передаёт одно значение. Сериализованный блок полей после этого делится на последовательности октетов, называемыми фрагментами блока полей. Первый фрагмент блока передаётся в данных кадра HEADERS (параграф 6.2) или PUSH_PROMISE (параграф 6.6), за каждым из которых могут следовать кадры CONTINUATION (параграф 6.10) с последующими фрагментами блока.

Поле заголовка Cookie [COOKIE] особо обрабатывается отображением HTTP (см. параграф 8.2.3).

Принимающая конечная точка собирает блок полей путём конкатенации фрагментов и затем применяет декомпрессию для восстановления раздела полей. Полный раздел полей содержит одно из двух:

  • один кадр HEADERS или PUSH_PROMISE с установленным флагом END_HEADERS;

  • кадр HEADERS или PUSH_PROMISE со сброшенным флагом END_HEADERS и один или несколько кадров CONTINUATION, в последнем из которых установлен флаг END_HEADERS.

Каждый блок полей обрабатывается как дискретная единица. Блоки полей должны передаваться как непрерывная последовательность кадров без промежуточных кадров другого типа или из другого потока. В последнем кадре последовательности HEADERS или CONTINUATION, а также последовательности PUSH_PROMISE или CONTINUATION установлен флаг END_HEADERS. Это позволяет блоку полей быть эквивалентным одному кадру.

Фрагменты блока полей могут передаваться лишь как данные (payload) кадров HEADERS, PUSH_PROMISE или CONTINUATION, поскольку эти кадры переносят сведения, которые могут менять контекст сжатия, используемый получателем. Конечная точка, получающая кадры HEADERS, PUSH_PROMISE или CONTINUATION должна собрать блоки полей и выполнить декомпрессию, даже если кадры будут отброшены. Получатель должен прерывать соединение с ошибкой (параграф 5.4.1) типа COMPRESSION_ERROR, если блок полей не распакован (decompress).

Ошибка декодирования блока полей должна считаться ошибкой соединения (параграф 5.4.1) типа COMPRESSION_ERROR.

4.3.1. Состояние сжатия

Сжатие полей выполняется с поддержкой состояния. У каждой конечной точки имеется контекст кодирования и декодирования HPACK, которые используются для кодирования и декодирования всех блоков полей в соединении. В разделе 4 [COMPRESSION] определена динамическая таблица, которая является основным состоянием для каждого контекста. Динамическая таблица имеет максимальный размер, устанавливаемый декодером HPACK. Конечная точка передаёт размер, выбранный её контекстом декодера HPACK, с помощью установки SETTINGS_HEADER_TABLE_SIZE (см. параграф 6.5.2). При организации соединения для динамических таблиц кодера и декодера HPACK на обеих конечных точках устанавливается размер 4096 байтов — исходное значение SETTINGS_HEADER_TABLE_SIZE. Любая смена максимального значения, заданного SETTINGS_HEADER_TABLE_SIZE, вступает в силу, когда конечная точка подтверждает установки (параграф 6.5.3). Кодер HPACK в конечной точке может установить для динамической таблицы любой размер, вплоть до максимума, заданного декодером. Кодер HPACK объявляет размер динамической таблицы инструкцией Dynamic Table Size Update (параграф 6.3 в [COMPRESSION]).

Когда конечная точка подтверждает смену SETTINGS_HEADER_TABLE_SIZE, снижающую максимум до значения меньше текущего размера динамической таблицы, кодер HPACK в конечной точке должен начать следующий блок полей с инструкцией Dynamic Table Size Update, устанавливающей для динамической таблицы размер не больше сниженного максимума (см. параграф 4.2 в [COMPRESSION]). Конечная точка должна считать блок полей, следующий за подтверждением сокращения максимального размера динамической таблицы, ошибкой соединения (параграф 5.4.1) типа COMPRESSION_ERROR, если он не начинается с инструкции Dynamic Table Size Update.

Разработчикам следует учитывать, что снижение SETTINGS_HEADER_TABLE_SIZE не обеспечивает широкой совместимости. Применение предисловия соединения для снижения значения ниже исходных 4096 байтов иногда поддерживается лучше, но может вызывать отказы некоторых реализаций.

5. Потоки и мультиплексирование

Поток (stream) — это независимая двухсторонняя последовательность кадров, передаваемых между клиентом и сервером в соединении HTTP/2. Потоки имеют несколько важных характеристик.

  • В одном соединении HTTP/2 может быть множество одновременных открытых потоков, при этом конечные точки могут чередовать кадры из нескольких потоков.

  • Потоки могут создаваться и использоваться каждой точкой в одностороннем порядке или совместно.

  • Поток может закрыть любая из конечных точек.

  • Порядок передачи кадров является важным. Получатель обрабатывают кадры в порядке их приёма. В частности, порядок кадров HEADERS и DATA значим семантически.

  • Потоки указываются целочисленными идентификаторами, которые назначаются конечной точкой, инициировавшей поток.

5.1. Состояния потока

Жизненный цикл потока показан на рисунке 2.

                         +--------+
                 send PP |        | recv PP
                ,--------+  idle  +--------.
               /         |        |         \
              v          +--------+          v
       +----------+          |           +----------+
       |          |          | send H /  |          |
,------+ reserved |          | recv H    | reserved +------.
|      | (local)  |          |           | (remote) |      |
|      +---+------+          v           +------+---+      |
|          |             +--------+             |          |
|          |     recv ES |        | send ES     |          |
|   send H |     ,-------+  open  +-------.     | recv H   |
|          |    /        |        |        \    |          |
|          v   v         +---+----+         v   v          |
|      +----------+          |           +----------+      |
|      |   half-  |          |           |   half-  |      |
|      |  closed  |          | send R /  |  closed  |      |
|      | (remote) |          | recv R    | (local)  |      |
|      +----+-----+          |           +-----+----+      |
|           |                |                 |           |
|           | send ES /      |       recv ES / |           |
|           |  send R /      v        send R / |           |
|           |  recv R    +--------+   recv R   |           |
| send R /  `----------->|        |<-----------'  send R / |
| recv R                 | closed |               recv R   |
`----------------------->|        |<-----------------------'
                         +--------+

Рисунок .Состояния потока.


send

Конечная точка передаёт этот кадр.

recv

Конечная точка получает этот кадр.

H

Кадр HEADERS (с подразумеваемыми кадрами CONTINUATION).

ES

Флаг END_STREAM.

R

Кадр RST_STREAM.

PP

Кадр PUSH_PROMISE (с подразумеваемыми кадрами CONTINUATION), переходы состояний указаны для обещанного потока.

Отметим, что на рисунке показаны только смены состояния потока, а также кадры и флаги, влияющие на эти переходы. Кадры CONTINUATION не меняют состояния, они фактически являются частью HEADERS или PUSH_PROMISE, за которыми следуют. Применительно к смене состояний флаг END_STREAM обрабатывается как отдельное событие для кадра, где он установлен — кадр HEADERS с флагом END_STREAM может вызвать две смены состояния.

Обе конечные точки имеют субъективное представление о состоянии потока, которое может отличаться, когда кадры находятся в пути (in transit). Конечные точки не координируют создание потоков, они создаются любой из них в одностороннем порядке. Негативные последствия такого рассогласования ограничиваются состоянием closed после отправки RST_STREAM, когда кадры могут приниматься в течение некоторого времени после закрытия.

Возможные состояния потока показаны ниже

idle

Начальное состояние каждого потока, из которого возможны указанные ниже переходы.
  • Передача кадра HEADERS в качестве клиента или приём HEADERS в качестве сервера вызывает переход потока в состояние open. Идентификатор потока выбирается в соответствии с параграфом 5.1.1. Тот же кадр HEADERS может вызвать немедленный переход потока в состояние half-closed.
  • Отправка кадра PUSH_PROMISE в другой поток резервирует бездействующий (idle) поток для последующего использования, меняя его состояние на reserved (local). Кадры PUSH_PROMISE может передавать только сервер.
  • Приём кадра PUSH_PROMISE в другом потоке резервирует бездействующий поток для последующего использования, переводя его в состояние reserved (remote). Кадры PUSH_PROMISE может получать только клиент.
  • Отметим, что кадр PUSH_PROMISE не передаётся в бездействующий поток, а ссылается на новый зарезервированный поток в поле Promised Stream ID.
  • Открытие потока с большим идентификатором вызывает незамедлительный переход потока в состояние closed (это не показано на рисунке).
Приём любого кадра, отличного от HEADERS и PRIORITY, в бездействующем потоке должен считаться ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR. Если поток инициирован сервером, как описано в параграфе 5.1.1, получение кадра HEADERS должно считаться ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

reserved (local)

Поток в состоянии reserved (local) — это поток, обещанный передачей кадра PUSH_PROMISE, который резервирует бездействующий поток, связывая его с открытым потоком, инициированным удаленным партнёром (параграф 8.4). Из этого состояния возможны лишь указанные ниже переходы.
  • Конечная точка может передать кадр HEADERS, переводящий поток в состояние half-closed (remote).
  • Любая из конечных точек может передать кадр RST_STREAM для перехода потока в состояние closed с освобождением выделенных для него резервов.
В этом состоянии конечной точке недопустимо передавать кадры кроме HEADERS, RST_STREAM, PRIORITY.
В этом состоянии может быть получен кадр PRIORITY или WINDOW_UPDATE. Получение любого кадра, отличного от RST_STREAM, PRIORITY и WINDOW_UPDATE потоком в этом состоянии должно считаться ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

reserved (remote)

Поток в состоянии reserved (remote) зарезервирован удаленным партнёром и возможны лишь указанные ниже переходы.
  • Получение кадра HEADERS переводит поток в состояние half-closed (local).
  • Любая из конечных точек может передать кадр RST_STREAM для перехода потока в состояние closed с освобождением выделенных для него резервов.
Конечной точке в этом состоянии недопустимо передавать кадры кроме RST_STREAM, WINDOW_UPDATE, PRIORITY. Получение любого кадра, отличного от HEADERS, RST_STREAM и PRIORITY потоком в этом состоянии должно считаться ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

open

Поток в состоянии open оба партнёра могут использовать для передачи кадров любого типа. В этом состоянии передающие партнёры соблюдают анонсированные ограничения управления потоком данных, анонсированные на уровне потока (параграф 5.2).
В этом состоянии любая из конечных точек может передать кадр с установленным флагом END_STREAM, вызывающий переход потока в состояние half-closed. Конечная точка, передавшая флаг END_STREAM, переводит поток в состояние half-closed (local), а получившая его — в состояние half-closed (remote).
Любая из конечных точек может передать кадр RST_STREAM для перевода потока в состояние closed.

half-closed (local)

Поток в состоянии half-closed (local) не может использоваться для передачи кадров кроме WINDOW_UPDATE, PRIORITY и RST_STREAM.
Поток переходит из этого состояния в closed при получении кадра с флагом END_STREAM или отправке любым из партнёров кадра RST_STREAM.
Конечная точка в этом состоянии может получить кадр любого типа. Необходимо получение кредита управления потоком данных с использованием кадров WINDOW_UPDATE для продолжения получения кадров с управлением потоком данных. В этом состоянии получатель может игнорировать кадры WINDOW_UPDATE, которые могут приходить в течение короткого интервала после отправки кадра с флагом END_STREAM.
В этом состоянии могут приниматься кадры PRIORITY.

half-closed (remote)

Поток в состоянии half-closed (remote) не может больше использоваться партнёрами для передачи кадров. В этом состоянии конечная точка больше не обязана поддерживать приёмное окно управления потоком данных.
Если конечная точка получает для потока в этом состоянии дополнительные кадры кроме WINDOW_UPDATE, PRIORITY, RST_STREAM, она должна отвечать ошибкой потока (параграф 5.4.2) типа STREAM_CLOSED.
Поток в состоянии half-closed (remote) может использоваться конечной точкой для передачи кадров любого типа. Конечная точка продолжает соблюдать анонсированные ограничения управления потоком данных (параграф 5.2).
Поток может перейти из этого состояния в closed, передав кадр с флагом END_STREAM или получив от партнёра кадр RST_STREAM.

closed

Состояние closed является терминальным. Поток переходит в это состояние после передачи и приёма кадра с установленным флагом END_STREAM. Поток переходит также в состояние closed после отправки или приёма конечной точкой кадра RST_STREAM.
Конечной точке недопустимо передавать в закрытый поток кадры, отличные от PRIORITY. Конечная точка может считать получение кадров любого другого типа в закрытом соединении ошибкой соединения (параграф 5.4.1) типа STREAM_CLOSED, за исключением описанных ниже случаев.
Конечная точка, передавшая кадр с флагом END_STREAM или кадр RST_STREAM, может получить от своего партнёра кадр WINDOW_UPDATE или RST_STREAM до того, как партнёр получит и обработает кадр, закрывающий поток. Конечная точка, передавшая кадр RST_STREAM в поток с состоянием open или half-closed (local), может получить кадр любого типа. Партнёр может передать или поместить эти кадры в очередь передачи до получения кадра RST_STREAM.
Конечная точка должна по минимуму обрабатывать и отбрасывать любые кадры, полученные в этом состоянии. Это означает обновление состояния сжатия заголовков в кадрах HEADERS и nd PUSH_PROMISE. Получение кадра PUSH_PROMISE также вызывает переход обещанного потока в состояние reserved (remote), даже при получении кадра PUSH_PROMISE в закрытом потоке. Содержимое кадров DATA учитывается в окне управления потоком данных соединения. Конечная точка может выполнять эту минимальную обработку для всех потоков, находящихся в состоянии closed. Конечные точки могут использовать другие сигналы для обнаружения приёма партнёром кадров, переводящих поток в состояние closed, и считать получения любого кадра кроме PRIORITY ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR. Конечные точки могут использовать для этого кадры, указывающие получение партнёром сигнала закрытия. Конечным точкам не следует применять для этого таймеры. Например, конечная точка, передавшая кадр SETTINGS после закрытия потока, может безопасно считать ошибкой приём в потоке кадра DATA после получения подтверждения установок. Могут также применяться кадры PING, получение данных или отклики на запросы в потоках, открытых после закрытия потока.

В отсутствие более конкретных правил реализациям следует считать получение кадра, не разрешённого явно в описании состояния, ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR. Кадры PRIORITY могут передаваться и приниматься в любом состоянии потока.

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

5.1.1. Идентификаторы потоков

Потоки указываются 31-битовым целым числом без знака. Инициированные клиентом потоки должны иметь нечётные идентификаторы потока, инициированные сервером — чётные. Поток с идентификатором 0x00 служит для сообщений управления соединением и этот идентификатор не может применяться для создания нового потока.

Идентификатор вновь созданного потока должен быть численно больше идентификаторов всех потоков, созданных или зарезервированных инициирующей конечной точкой. Это относится к потокам, создаваемым с помощью кадра HEADERS и резервируемым с помощью PUSH_PROMISE. Конечная точка, получившая неожиданный идентификатор потока, должна отвечать ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Кадр HEADERS переводит инициированный клиентом поток, указанный идентификатором в заголовке кадра, из состояния idle в состояние open. Кадр PUSH_PROMISE переводит инициированный сервером поток, указанный полем Promised Stream ID в данных (payload) кадра из состояния idle в состояние reserved (local) или reserved (remote). Когда поток выходит из состояния idle, все бездействующие потоки, которые могли быть созданы партнёром с меньшим значением идентификатора потока, незамедлительно переходят в состояние closed, т. е. конечная точка может пропускать идентификаторы потоков и пропущенные потоки будут сразу же закрываться.

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

5.1.2. Одновременные потоки

Партнёр может ограничить число одновременно активных потоков с помощью параметра SETTINGS_MAX_CONCURRENT_STREAMS (параграф 6.5.2) в кадре SETTINGS. Этот параметр связан с конкретной конечной точкой и применяется лишь партнёром, получившим его. Т. е. клиент задаёт максимальное число одновременных потоков, которые может инициировать сервер, а сервер — число одновременных потоков, которые может инициировать клиент. Применительно в SETTINGS_MAX_CONCURRENT_STREAMS учитываются потоки в состоянии open и любом из состояний half-closed, а потоки в состояниях reserved не считаются.

Конечной точке недопустимо превышать заданный партнёром предел. Получив кадр HEADERS, ведущий к превышению установленного конечной точкой предельного числа одновременных потоков, эта точка должна считать кадр ошибкой потока (параграф 5.4.2) типа PROTOCOL_ERROR или REFUSED_STREAM. Выбор типа ошибки определяет возможность автоматического повторения (см. параграф 8.7).

Конечная точка, решившая снизить значение SETTINGS_MAX_CONCURRENT_STREAMS ниже текущего числа открытых потоков, может закрыть лишние потоки или дождаться их завершения.

5.2. Управление потоком данных

Мультиплексирование с помощью потоков вызывает борьбу за использование ресурсов соединения TCP, ведущую к блокировке потоков. Схема управления потоком данных позволяет предотвратить разрушительное влияние потоков одного соединения друг на друга. Управление потоком данных применяется для отдельных потоков и соединения в целом. В HTTP/2 управление потоками данных выполняется с помощью кадров WINDOW_UPDATE (параграф 6.9).

5.2.1. Принципы управления потоком данных

Управление потоком данных в потоке HTTP/2 нацелено на использование различных алгоритмов управления потоком данных без необходимости внесения изменений в протокол. Характеристики управления потоком данных HTTP/2 приведены ниже.

  1. Управление потоком данных HTTP/2 связано с соединением и осуществляется между конечными точками одного интервала пересылки, а не на сквозном пути.

  2. Управление осуществляется с помощью кадров WINDOW_UPDATE. Получатель анонсирует число октетов, которые он готов принять в потоке и соединении в целом. Эта схема основана на кредитах.

  3. Управление потоком данных является направленным, а общий контроль выполняет получатель. Получатель может установить любой желаемый размер окна для каждого потока и соединения в целом. Отправитель должен соблюдать заданные получателем ограничения. Клиенты, серверы и посредники независимо анонсируют размер своего окна управления потоком данных в качестве получателя и соблюдают ограничения, заданные партнёром.

  4. Начальный размер окна управления потоком данных для нового потока и всего соединения — 65535 октетов.

  5. Тип кадра определяет применение к нему управления потоком данных. Из заданных в этом документе типов кадров управление потоком данных применяется только к кадрам DATA, а прочие не занимают места в анонсированном окне управления потоком данных. Это гарантирует, что важные кадры управления не будут блокироваться алгоритмом управления потоком данных.

  6. Конечная точка может отключить своё управление потоком данных, но не может игнорировать сигналы управления потоком данных от партнёра.

  7. HTTP/2 задаёт только формат и семантику кадров WINDOW_UPDATE (параграф 6.9). Этот документ не указывает, как получатель решает, когда отправить кадр, или какое значение передать, а также не задаёт способ отправки пакетов. Реализации могут выбрать любой алгоритм, соответствующий их потребностям.

Реализации отвечают за приоритизацию отправки запросов и откликов, выбирая способ предотвращения блокировки head-of-line для запросов и управляя созданием новых потоков. Алгоритмы решения этих задач могут взаимодействовать с любым алгоритмом управления потоком данных.

5.2.2. Приемлемое использование управления потоком данных

Управление потоком данных определяется для защиты конечных точек, работающих в условиях нехватки ресурсов. Например, прокси нужна общая память для многочисленных соединений и у него может быть медленное восходящее соединение и быстрое нисходящее. Управление потоком данных решает проблему, когда получатель не способен обработать данные в одном потоке, но хочет продолжать обработку других потоков в том же соединении.

Там, где не требуются такие возможности, можно анонсировать окно управления потоком данных максимального размера (231-1) и поддерживать его, передавая кадр WINDOW_UPDATE при получении любых данных. Это фактически отключает управление потоком данных для данного получателя. Отправитель всегда соблюдает заданное получателем окно управления потоком данных.

В системах с ограниченными ресурсами (например, памятью) управление потоком данных может применяться для ограничения расхода дефицитных ресурсов. Однако следует отметить, что это может приводить к неоптимальному использованию доступных сетевых ресурсов, если управление потоком данных включить без знания произведения пропускной способности и задержки (bandwidth*delay, см. [RFC7323]). Даже при полной осведомлённости о текущем значении bandwidth*delay реализация управления потоком данных может оказаться сложной. Конечные точки должны считывать и обрабатывать кадры HTTP/2 из приёмного буфера TCP, как только данные становятся доступными. Несвоевременное считывание может заводить в тупик, когда важные кадры, такие как WINDOW_UPDATE, не будут вовремя прочитаны и обработаны. Оперативное считывание кадров не открывает конечные точки для атак на истощения ресурсов, поскольку управление потоком данных в HTTP/2 ограничивает расход ресурсов.

5.2.3. Производительность управления потоком данных

Если конечная точка не может гарантировать, что у её партнёра всегда имеется место в окне управления потоком данных, превышающее значение bandwidth*delay для этого соединения, её пропускная способность на приёме будет ограничиваться управлением потоком данных HTTP/2, что приведёт к снижению производительности. Своевременная передача кадров WINDOW_UPDATE может повышать производительность.

Конечным точкам нужен баланс между повышением пропускной способности на приёме и предотвращением истощения ресурсов, поэтому следует внимательно изучить замечания в параграфе 10.5 при определении стратегии управления размером окна.

5.3. Приоритизация

В мультиплексируемых протоколах, таких как HTTP/2, приоритизация выделения потокам пропускной способности и вычислительных ресурсов может иметь решающее значение для достижения высокой производительности. Неудачная схема приоритизации может приводить в низкой производительности HTTP/2. При отсутствии распараллеливания на уровне TCP производительность может оказаться ниже, чем у HTTP/1.1.

Хорошая схема приоритизации выигрывает от применения сведений о контексте, таких как содержимое ресурсов, их взаимосвязь и способы использования этих ресурсов партнёром. В частности, клиенты могут иметь сведения о приоритете запросов, которые связаны с приоритизацией сервера. Предоставление клиентам сведений о приоритетах может повышать производительность.

5.3.1. Приоритеты в RFC 7540

В RFC 7540 определён богатый набор средств указания приоритета запросов. Однако система оказалась сложной и не получила широкого распространения.

Гибкая схема позволяла клиентам указывать приоритет самыми разными способами, при этом подходы не отличались согласованностью. Для серверов реализация поддержки этой схемы оказалась сложной. Реализация приоритетов в клиентах и серверах была несогласованной. Многие серверы игнорировали сигналы клиентов при определении приоритета обработки запросов.

Таким образом, сигнализация приоритета RFC 7540 [RFC7540] не достигла успеха.

5.3.2. Указание приоритета в этом документе

Это обновление HTTP/2 отменяет сигнализацию приоритетов, заданную в RFC 7540 [RFC7540]. Большая часть текста, связанного с указанием приоритета не включена в этот документ. Сохранены описания полей кадров и некоторая обязательная обработка для обеспечения совместимости реализаций этой спецификации с реализациями, применяющими сигналы приоритета из RFC 7540.

Подробное описание схемы приоритетов RFC 7540 дано в параграфе 5.3 [RFC7540].

Сведения о приоритете нужны во многих случаях для достижения высокой производительности. Там, где сведения о приоритете важны, конечным точкам рекомендуется использовать альтернативную схему, например, [HTTP-PRIORITY].

Хотя сигнализация приоритета из RFC 7540 не получила широкого распространения, предоставляемые ею сведений могут быть полезны при отсутствии лучших сигналов. Конечные точки, получающие сигналы приоритета в кадрах HEADERS или PRIORITY могут выиграть от использования этих сведений. В частности, реализации, воспринимающие такие сигналы, не выиграют от их запрета при отсутствии альтернативы.

Серверам следует использовать другие данные контекста при определении приоритета запросов в отсутствие каких-либо сигналов. Серверы могут считать полное отсутствие сигналов приоритета указанием на то, что клиент не поддерживает приоритизацию. Принятые по умолчанию значения (параграф 5.3.5 в [RFC7540]) не обеспечивают высокой производительности в большинстве случаев и их использованием вряд ли имеет смысл.

5.4. Обработка ошибок

Кадрирование HTTP/2 допускает два класса ошибок:

  • ошибки, делающие соединение непригодны целиком (ошибки соединения);

  • ошибки в отдельном потоке (ошибки потока).

Список кодов ошибок приведён в разделе 7.

Конечная точка может сталкиваться с кадрами, вызывающими несколько ошибок. Реализации могут обнаруживать несколько ошибок в процессе обработки, но им следует сообщать в результате не более одной ошибки потока и одной ошибки соединения. Первая ошибка потока, указанная для данного потока, предотвращает передачу других ошибок этого потока. Протокол допускает несколько кадров GOAWAY, однако конечной точке следует сообщать лишь об одном типе ошибки соединения, если не происходит ошибки в процессе аккуратного разрыва соединения. Если такая ошибка возникает, конечная точка может передать дополнительный кадр GOAWAY с новым кодом ошибки в дополнение к предшествующему GOAWAY с NO_ERROR.

Если конечная точка обнаруживает несколько разных ошибок, она может сообщить о любой из них. Если кадр вызывает ошибку соединения, эта ошибка должна указываться. Кроме того, конечная точка может использовать любой подходящий код при обнаружении ошибки, а базовые коды (такие как PROTOCOL_ERROR и INTERNAL_ERROR) всегда можно применять вместо более конкретных кодов.

5.4.1. Обработка ошибок соединения

Ошибкой соединения считается любая ошибка, препятствующая дальнейшей обработке уровня кадров или повреждающая состояние соединения.

Конечной точке, столкнувшейся с ошибкой соединения, следует сначала передать кадр GOAWAY (параграф 6.8) с идентификатором последнего потока, успешно принятого от партнёра. Кадр GOAWAY включает код ошибки (раздел 7), указывающий причину разрыва соединения. После отправки GOAWAY, конечная точка должна закрыть соединение TCP.

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

Конечная точка может завершить соединение в любой момент. В частности, она может счесть ошибку потока ошибкой соединения. Конечным точкам следует передавать кадр GOAWAY при завершении соединения, если это возможно.

5.4.2. Обработка ошибок потока

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

Конечная точка, столкнувшаяся с ошибкой потока, передаёт кадр RST_STREAM (параграф 6.4) с идентификатором потока, где произошла ошибка, включающий код, который указывает тип ошибки.

RST_STREAM является последним кадром, передаваемым конечной точкой в этот поток, и эта точка должна быть готова принять любые кадры, которые были переданы или помещены удаленным партнёром в очередь передачи. Эти кадры можно игнорировать, за исключением случаев, когда они меняют состояние соединения, например, статус, поддерживаемый для сжатия полей заголовка (параграф 4.3) или управление потоком данных.

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

Для предотвращения петель конечной точке недопустимо передавать кадр RST_STREAM в ответ на RST_STREAM.

5.4.3. Прерывание соединения

Если соединение TCP закрывается или сбрасывается при наличии в нем потоков в состоянии open или half-closed, затронутые этим потоки не могут быть перезапущены автоматически (см. параграф 8.7).

5.5. Расширение HTTP/2

HTTP/2 допускает расширение протокола. В рамках заданных в этом параграфе ограничений расширения протокола можно применять для предоставления дополнительных услуг и изменения любых аспектов протокола. Расширения действуют только в рамках одного соединения HTTP/2. Это относится к элементам протокола, заданным в этом документе и не влияет на имеющиеся опции расширения HTTP, такие как определение новых методов, кодов статуса и полей (см. раздел 16 в [HTTP]).

Расширениям разрешено применять новые типы кадров (параграф 4.1), установки (параграф 6.5) и коды ошибок (раздел 7). Реестры для управления этими точками расширения определены в разделе 11 [RFC7540].

Реализации должны игнорировать любые неизвестные или неподдерживаемые значения во всех расширяемых элементах протокола, а также отбрасывать кадры неизвестных или неподдерживаемых типов. Это значит, что точки расширения можно безопасно использовать в расширениях без предварительного согласования или переговоров. Однако кадры расширения в середине блока полей (параграф 4.3) не разрешены и должны считаться ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Расширениям следует избегать изменения элементов протокола, заданных в этом документе, и элементов, не имеющих механизма расширения. Это включает изменение схем кадров, добавления или изменения способов компоновки кадров в сообщения HTTP (параграф 8.1), определение полей псевдозаголовков, а также изменения любых элементов протокола, которые соответствующая спецификации конечная точка может счесть ошибкой соединения (параграф 5.4.1).

Расширение, меняющее имеющиеся элементы протокола или состояние, должно быть согласовано до использования. Например, расширение, меняющее схему кадров HEADERS, не может применяться, пока партнёр не укажет его приемлемость. В этом случае может также потребоваться согласование момента вступления новой схемы в силу. Например, трактовка отличных от DATA кадров как подверженных управлению потоком данных требует изменения их семантику, которую должны понимать обе конечные точки, поэтому может быть принята только после согласования.

Этот документ не задаёт конкретного метода согласования использования расширений, но отмечает возможность использования настроек (параграф 6.5.2) для решения этой задачи. Если оба партнёра установили значение, указывающее готовность применять расширение, это расширение можно использовать. Если для согласования расширения применяется настройка, исходное значение должно быть задано так, чтобы расширение было отключено.

6. Определения кадров

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

Передача определённого типа кадров может менять состояние соединения. Если конечные точки не могут синхронизировать состояние соединения, последующие взаимодействия через это соединение будут невозможны. Поэтому важно, чтобы конечные точки имели общее представление о влиянии использования того или иного кадра на состояние соединения.

6.1. DATA

Кадры DATA (type=0x00) переносят произвольные последовательности октетов переменного размера, связанные с потоком. Например, один или несколько кадров DATA могут служить для передачи содержимого запроса или отклика HTTP. Кадры DATA могут включать заполнение, применяемое для сокрытия размера сообщений. Это защитное свойство описано в параграфе 10.7.

   DATA Frame {
     Length (24),
     Type (8) = 0x00,

     Unused Flags (4),
     PADDED Flag (1),
     Unused Flags (2),
     END_STREAM Flag (1),

     Reserved (1),
     Stream Identifier (31),

     [Pad Length (8)],
     Data (..),
     Padding (..2040),
   }

Рисунок .Формат кадра DATA.


Поля Length, Type, Unused Flag(s), Reserved, Stream Identifier описаны в разделе 4. Поля данных кадра DATA приведены ниже.

Pad Length

8-битовое значение размера заполнения кадра в октетах, присутствующее лишь при наличии флага PADDED.

Data

Данные приложения. Объем данных — это часть содержимого кадра (payload) за вычетом размера других полей.

Padding

Октеты заполнения, не имеющие семантического смысла. При передаче в октетах заполнения должно указываться значение 0. Получатель не обязан проверять заполнение, но может считать отличное от 0 заполнение ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Флаги кадров DATA указаны ниже.

PADDED (0x08)

Установленный флаг указывает присутствие поля Pad Length и октетов заполнения.

END_STREAM (0x01)

Установленный флаг указывает, что это последний кадр, который конечная точка передаёт в указанный поток. Наличие флага указывает, что поток переходит в состояние half-closed или closed (параграф 5.1).
Примечание. Конечная точка, узнавшая о закрытии потока после отправки всех данных, может закрыть этот поток отправкой кадра DATA3 с пустым полем Data и установленным флагом END_STREAM. Это возможно лишь в том случае, когда конечная точка не передаёт трейлеров, поскольку в этом случае флаг END_STREAM устанавливается в кадре HEADERS (см. параграф 8.1).

Кадры DATA должны связываться с потоком. При получении кадра DATA с Stream Identifier = 0x00 получатель должен возвращать ошибку соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

К кадрам DATA применяется управление потоком данных и они могут передаваться лишь в потоках со статусом open и half-closed (remote). Управление потоком данных применяется ко всему содержимому (payload) кадра, включая поля Pad Length и Padding (при наличии). При получении кадра DATA в потоке с состоянием, отличным от open и half-closed (local), получатель должен возвращать ошибку потока (параграф 5.4.2) типа STREAM_CLOSED.

Число октетов заполнения определяется значением поля Pad Length. Если размер заполнения не меньше размера содержимого кадра, получатель должен считать это ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Примечание. Размер кадра может увеличиваться на 1 октет включением поля Pad Length со значением 0.

6.2. HEADERS

Кадр HEADERS (type=0x01) служит для открытия потока (параграф 5.1), а также передаёт фрагмент блока полей. Несмотря на имя, кадры HEADERS могут содержать разделы заголовков и трейлеров. Кадры могут передаваться в потоках со статусом idle, reserved (local), open, half-closed (remote).

   HEADERS Frame {
     Length (24),
     Type (8) = 0x01,

     Unused Flags (2),
     PRIORITY Flag (1),
     Unused Flag (1),
     PADDED Flag (1),
     END_HEADERS Flag (1),
     Unused Flag (1),
     END_STREAM Flag (1),

     Reserved (1),
     Stream Identifier (31),

     [Pad Length (8)],
     [Exclusive (1)],
     [Stream Dependency (31)],
     [Weight (8)],
     Field Block Fragment (..),
     Padding (..2040),
   }

Рисунок .Формат кадра HEADERS.


Поля Length, Type, Unused Flag(s), Reserved, Stream Identifier описаны в разделе 4. Поля содержимого кадра HEADERS приведены ниже.

Pad Length

8-битовое значение размера заполнения кадра в октетах, присутствующее лишь при наличии флага PADDED.

Exclusive

Флаг, присутствующий лишь при наличии флага PRIORITY. Сигнализация приоритета в кадрах HEADERS отменена (см. параграф 5.3.2).

Stream Dependency

31-битовый идентификатор потока, используемый лишь при наличии флага PRIORITY.

Weight

8-битовое целое число без знака, присутствующее лишь при наличии флага PRIORITY.

Field Block Fragment

Фрагмент блока полей (параграф 4.3).

Padding

Октеты заполнения, не имеющие семантического смысла. При передаче в октетах заполнения должно указываться значение 0. Получатель не обязан проверять заполнение, но может считать отличное от 0 заполнение ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Флаги кадров HEADERS приведены ниже.

PRIORITY (0x20)

Установленный флаг указывает наличие полей Exclusive, Stream Dependency, Weight.

PADDED (0x08)

Установленный флаг указывает присутствие поля Pad Length и октетов заполнения.

END_HEADERS (0x04)

Установленный флаг указывает наличие в кадре полного блока полей (параграф 4.3) и отсутствие последующих кадров CONTINUATION. За кадром HEADERS без флага END_HEADERS в том же потоке должен следовать кадр CONTINUATION. Получатель должен считать получение кадра иного типа или приём кадра продолжения в другом потоке ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

END_STREAM (0x01)

Установленный флаг указывает, что блок полей (параграф 4.3) является последним, передаваемым конечной точкой для указанного потока. Кадр HEADERS с флагом END_STREAM говорит о завершении потока, однако за ним в том же потоке может следовать кадр CONTINUATION. Логически CONTINUATION служит частью HEADERS.

Содержимым (payload) кадра HEADERS свляется фрагмент блока полей (параграф 4.3). Если блок не помещается в кадр HEADERS, он продолжается в кадре CONTINUATION (параграф 6.10).

Кадры HEADERS должны связываться с потоком. При получении кадра HEADERS с Stream Identifier = 0x00 получатель должен возвращать ошибку соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Кадр HEADERS меняет состояние соединения, как описано в параграфе 4.3.

Число октетов заполнения определяется значением поля Pad Length. Если размер заполнения не меньше размера содержимого кадра, получатель должен считать это ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Примечание. Размер кадра может увеличиваться на 1 октет включением поля Pad Length со значением 0.

6.3. PRIORITY

Кадры PRIORITY (type=0x02) устарели (см. параграф 5.3.2). Такой кадр может передаваться в потоке с любым состоянием, включая idle и closed.

   PRIORITY Frame {
     Length (24) = 0x05,
     Type (8) = 0x02,

     Unused Flags (8),

     Reserved (1),
     Stream Identifier (31),

     Exclusive (1),
     Stream Dependency (31),
     Weight (8),
   }

Рисунок .Формат кадра PRIORITY.


Поля Length, Type, Unused Flag(s), Reserved, Stream Identifier описаны в разделе 4. Поля содержимого кадра PRIORITY приведены ниже.

Exclusive

Однобитовый флаг.

Stream Dependency

31-битовый идентификатор потока.

Weight

8-битовое целое число без знака.

Для кадров PRIORITY не задано флагов.

Кадр PRIORITY всегда идентифицирует поток. При получении кадра PRIORITY с Stream Identifier = 0x00 получатель должен возвращать ошибку соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Приём или передача PRIORITY не влияет на состояния потоков (параграф 5.1). Кадр PRIORITY можно передавать в поток с любым статусом, включая idle и closed. Кадр PRIORITY не может передаваться между парой кадров, переносящих один блок полей (параграф 4.3).

Кадр PRIORITY с размером, отличным от 5 октетов, должен считаться ошибкой потока (параграф 5.4.2) типа FRAME_SIZE_ERROR.

6.4. RST_STREAM

Кадр RST_STREAM (type=0x03) позволяет сразу же прервать поток и передаётся для запроса прерывания потока или указания обнаруженной ошибки.

   RST_STREAM Frame {
     Length (24) = 0x04,
     Type (8) = 0x03,

     Unused Flags (8),

     Reserved (1),
     Stream Identifier (31),

     Error Code (32),
   }

Рисунок .Формат кадра RST_STREAM.


Поля Length, Type, Unused Flag(s), Reserved, Stream Identifier описаны в разделе 4. Кроме того, кадр RST_STREAM содержит одно 32-битовое целочисленное значение без знака, указывающее код ошибки (раздел 7) с причиной прерывания потока.

Для кадров RST_STREAM не задано флагов.

Кадр RST_STREAM полностью прерывает указанный поток и переводит его в состояние closed. После приёма в потоке кадра RST_STREAM получателю недопустимо передавать в этот поток кадры, за исключением PRIORITY. Однако после отправки RST_STREAM конечная точка должна быть готова принять в этом потоке кадры, которые партнёр мог передать до прибытия к нему кадра RST_STREAM.

Кадр RST_STREAM должен быть связан с потоком. При получении кадра RST_STREAM с Stream Identifier = 0x00 получатель должен возвращать ошибку соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Кадры RST_STREAM недопустимо передавать в потоки с состоянием idle. При получении кадра RST_STREAM, указывающего бездействующий поток, получатель должен возвращать ошибку соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Кадр RST_STREAM с размером, отличным от 4 октетов, должен считаться ошибкой соединения (параграф 5.4.1) типа FRAME_SIZE_ERROR.

6.5. SETTINGS

Кадр SETTINGS (type=0x04) передаёт параметры конфигурацииЮ влияющие на взаимодействие конечных точек, такие как предпочтения или ограничения для поведения партнёра, а также для подтверждения приёма таких установок. Параметры из кадра SETTINGS называются установками, настройками или параметрами (setting). Настройки не согласуются, они описывают характеристики передающего партнёра и используются принимающим. Кадлый из партнёров может анонсировать своё значение настройки. Например, клиент может задать большое начальное окно управления потоком данных, а север — меньшее для экономии ресурсов.

Кадры SETTINGS должны передавать обе конечные точки при старте соединения и эти кадры могут передаваться в любой момент в течение срока работы соединения каждой из конечных точек. Реализации должны поддерживать все настройки, заданные в этой спецификации. Каждый параметр из кадра SETTINGS заменяет имеющееся значение. Настройки обрабатываются в порядке их указания и получатель SETTINGS не обязан поддерживать какое-либо состояние сверх текущего значения параметра. Поэтому значение параметра в SETTINGS является последним значением у получателя.

Кадры SETTINGS подтверждаются получившим их партнёром. Для этого в SETTINGS применяется флаг ACK.

ACK (0x01)

Установка флага указывает, что этот кадр подтверждает получение и применение кадра SETTINGS от партнёра. При установленном флаге содержимое (payload) кадра SETTINGS должно быть пустым. Получение кадра SETTINGS с флагом ACK и ненулевым размером должно считаться ошибкой соединения (параграф 5.4.1) типа FRAME_SIZE_ERROR (см. параграф 6.5.3).

Кадр SETTINGS всегда применяется к соединению, а не к отдельному кадру, и идентификатор потока в нем должен иметь значение 0x00. Если конечная точка получает кадр SETTINGS с другим значением fStream Identifier, она должна возвращать ошибку соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Кадр SETTINGS влияет на статус соединения. Некорректный или неполный кадр SETTINGS должен считаться ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Кадр SETTINGS с размером, отличным от 6 октетов, должен считаться ошибкой соединения (параграф 5.4.1) типа FRAME_SIZE_ERROR.

6.5.1. Формат SETTINGS

Данные (payload) кадра SETTINGS могут содержать установки, каждая из которых включает 16-битовый идентификатор параметра и его 32-битовое целочисленное значение без знака.

   SETTINGS Frame {
     Length (24),
     Type (8) = 0x04,

     Unused Flags (7),
     ACK Flag (1),

     Reserved (1),
     Stream Identifier (31) = 0,

     Setting (48) ...,
   }

   Setting {
     Identifier (16),
     Value (32),
   }

Рисунок .Формат кадра SETTINGS.


Поля Length, Type, Unused Flag(s), Reserved, Stream Identifier описаны в разделе 4. Данные кадра SETTINGS могут включать любое число полей Setting, описанных ниже.

Identifier

16-битовый идентификатор параметра (параграф 6.5.2).

Value

32-битовое значение параметра.

6.5.2. Заданные настройки

Ниже приведены определённые этим документом настройки (параметры).

SETTINGS_HEADER_TABLE_SIZE (0x01)

Позволяет отправителю информировать удалённую точку о максимальном размере (в октетах) таблицы сжатия, применяемой для декодирования блоков полей. Кодер может выбрать любой размер, не превышающий это значение, используя сигналы, специфичные для формата сжатия в блоке полей (см. [COMPRESSION]). Начальное значение — 4096 октетов.

SETTINGS_ENABLE_PUSH (0x02)

Этот флаг может применяться для включения и отключения выталкивания с сервера (push). Серверу недопустимо передавать кадр PUSH_PROMISE, если он получил этот параметр со значением 0 (параграф 8.4). Клиент, передавший значение 0 и получивший подтверждение, должен считать получение кадра PUSH_PROMISE ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.
Исходно устанавливается SETTINGS_ENABLE_PUSH = 1. Для клиента это указывает его желание принимать кадры PUSH_PROMISE, а для сервера не имеет значения и эквивалентно 0. Любое значение кроме 0 и 1 должно считаться ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.
Серверу недопустимо явно устанавливать для этого параметра значение 1 и он может опустить эту настройку при отправке кадра SETTINGS, но если сервер включает этот параметр он должен иметь значение 0. Клиент должен считать получение кадра PUSH_PROMISE с SETTINGS_ENABLE_PUSH = 1 ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

SETTINGS_MAX_CONCURRENT_STREAMS (0x03)

Указывает максимальное число одновременных потоков, разрешаемых отправителем. Это ограничение однонаправленное и применяется для числа пакетов, которые отправитель позволяет создать получателю. Исходно ограничение не задано и рекомендуется устанавливать значение не меньше 100, чтобы не ограничивать распараллеливание без необходимости.
Значение SETTINGS_MAX_CONCURRENT_STREAMS =0 не следует считать особым, оно препятствует созданию новых потоков, однако это может происходить и при достижении предела. Серверу следует устанавливать значение 0 лишь на короткое время. Если сервер не хочет воспринимать запросы, лучше закрыть соединение.

SETTINGS_INITIAL_WINDOW_SIZE (0x04)

Указывает исходный размер (в октетах) окна управления потоком данных у отправителя на уровне потока. Исходное значение — 216-1 (65535) октетов.
Этот параметр влияет на размер окна во всех потоках (см. параграф 6.9.2).
Значения выше максимального размера окна управления потоком данных 231-1 должны считаться ошибкой соединения (параграф 5.4.1) типа FLOW_CONTROL_ERROR.

SETTINGS_MAX_FRAME_SIZE (0x05)

Указывает наибольший размер (в октетах) данных кадра (payload) которые отправитель готов получать.
Исходное значение — 214 (16384) октетов. Анонсируемое конечной точной значение должно быть в интервале между исходным значением и максимальным размером кадра 224-1 (16777215), включительно. Иные значения должны считаться ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

SETTINGS_MAX_HEADER_LIST_SIZE (0x06)

Информирует партнёра о максимальном размере (в октетах) раздела полей, который отправитель готов воспринимать. Значение учитывает размеры несжатых полей, включая имя и значение, а также издержки в 32 октета на каждую строку поля.
Для любого данного запроса может устанавливаться предел ниже указанного этим значением. Исходно размер не ограничивается.

Конечная точка, получившая кадр SETTINGS с неизвестным или неподдерживаемым идентификатором, должна игнорировать соответствующий параметр.

6.5.3. Синхронизация установок

Для большинства значений в SETTINGS требуется или полезно понимание того, что партнёр получил и применил изменённые значения параметров. Для обеспечения таких моментов синхронизации получатель кадра SETTINGS со сброшенным флагом ACK должен применить обновлённые установки как можно быстрее. Кадры SETTINGS подтверждаются в порядке их получения.

Значения из кадра SETTINGS должны обрабатываться в порядке их указания, а неподдерживаемые значения должны игнорироваться. По завершении обработки всех значений получатель должен сразу же передать кадр SETTINGS с установленным флагом ACK. При получении такого кадра отправитель изменённых настроек может полагаться на то, что применены значения из самого старого неподтвержденного до этого кадра SETTINGS.

Если отправитель кадра SETTINGS не получил подтверждения в течение разумного интервала времени, он может выдать ошибку соединения (параграф 5.4.1) типа SETTINGS_TIMEOUT. При установке тайм-аута нужно учитывать время обработки партнёром, поскольку тайм-аут, учитывающий лишь время передачи по сети может вызывать ложные ошибки.

6.6. PUSH_PROMISE

   PUSH_PROMISE Frame {
     Length (24),
     Type (8) = 0x05,

     Unused Flags (4),
     PADDED Flag (1),
     END_HEADERS Flag (1),
     Unused Flags (2),

     Reserved (1),
     Stream Identifier (31),

     [Pad Length (8)],
     Reserved (1),
     Promised Stream ID (31),
     Field Block Fragment (..),
     Padding (..2040),
   }

Рисунок .Формат кадра PUSH_PROMISE.


Кадр PUSH_PROMISE (type=0x05) служит для предварительного уведомления партнёра о потоках, которые отправитель намерен инициировать. PUSH_PROMISE включает 31-битовый идентификатор потока, который конечная точка планирует создать, а также раздел полей с дополнительным контекстом для потока. Подробное описание использования кадров PUSH_PROMISE дано в параграфе 8.4.

Поля Length, Type, Unused Flag(s), Reserved, Stream Identifier описаны в разделе 4. Содержимое кадра PUSH_PROMISE показано ниже.

Pad Length

8-битовое значение размера заполнения кадра в октетах, присутствующее лишь при наличии флага PADDED.

Promised Stream ID

31-битовое целое число, указывающее поток, резервируемый кадром PUSH_PROMISE. Идентификатор обещанного потока должен иметь значение, подходящее для следующего потока, передаваемого отправителем (см. параграф 5.1.1).

Field Block Fragment

Фрагмент блока полей (параграф 4.3) с данными управления запросом и разделом заголовков.

Padding

Октеты заполнения, не имеющие семантического смысла. При передаче в октетах заполнения должно указываться значение 0. Получатель не обязан проверять заполнение, но может считать отличное от 0 заполнение ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Ниже указаны флаги кадров PUSH_PROMISE.

PADDED (0x08)

Установленный флаг указывает присутствие поля Pad Length и октетов заполнения.

END_HEADERS (0x04)

Установленный флаг указывает наличие в кадре полного блока полей (параграф 4.3) и отсутствие последующих кадров CONTINUATION. За кадром PUSH_PROMISE без флага END_HEADERS в том же потоке должен следовать кадр CONTINUATION. Получатель должен считать получение кадра иного типа или приём кадра продолжения в другом потоке ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Кадры PUSH_PROMISE должны передаваться только через инициированный партнёром поток, находящийся в состоянии open или half-closed (remote). Идентификатор потока в PUSH_PROMISE указывает связанный с кадром поток. Если Stream Identifier = 0x00, получатель кадра должен отвечать ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Обещанные потоки не требуется применять в порядке их предложения и кадры PUSH_PROMISE лишь резервируют потоки для использования в будущем.

Кадр PUSH_PROMISE недопустимо передавать, если у партнёра установлено SETTINGS_ENABLE_PUSH = 0. Конечная точка с такой установкой, получавшая подтверждение, должна считать приём кадра PUSH_PROMISE ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Получатель PUSH_PROMISE может отвергнуть предложенный поток, возвращая кадр RST_STREAM с указанием идентификатора обещанного потока отправителю PUSH_PROMISE.

Кадр PUSH_PROMISE меняет состояние соединения двумя способами. Во-первых, включение блока полей (параграф 4.3) может менять состояние, поддерживаемое для сжатия полей. Во-вторых, PUSH_PROMISE резервирует поток для последующего использования, заставляя обещанный поток принимать состояние reserved (local) или reserved (remote). Отправителю недопустимо передавать PUSH_PROMISE в поток, не имеющий состояния open или half-closed (remote), он должен убедиться, что обещанный поток имеет подходящий идентификатор (параграф 5.1.1), т. е. обещанный поток должен иметь статус idle.

Поскольку PUSH_PROMISE резервирует поток, игнорирование кадра делает состояние этого потока неопределённым. Получатель PUSH_PROMISE в потоке, не находящемся в состоянии open или half-closed (local), должен считать это ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR. Однако конечная точка, передавшая RST_STREAM в соответствующий поток, должна обрабатывать кадры PUSH_PROMISE, которые могли быть созданы до получения и обработки RST_STREAM.

Получатель должен считать приём PUSH_PROMISE и непригодным идентификатором потока (параграф 5.1.1) ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR. Непригодным считается идентификатор потока, который не имеет в данный момент состояния idle.

Число октетов заполнения определяется значением поля Pad Length. Если размер заполнения не меньше размера содержимого кадра, получатель должен считать это ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Примечание. Размер кадра может увеличиваться на 1 октет включением поля Pad Length со значением 0.

6.7. PING

Кадры PING (type=0x06) служат механизмом измерения минимального времени кругового обхода от отправителя, а также проверки функционирования бездействующих соединений. PING может передавать любая конечная точка.

   PING Frame {
     Length (24) = 0x08,
     Type (8) = 0x06,

     Unused Flags (7),
     ACK Flag (1),

     Reserved (1),
     Stream Identifier (31) = 0,

     Opaque Data (64),
   }

Рисунок .Формат кадра PING.


Поля Length, Type, Unused Flag(s), Reserved, Stream Identifier описаны в разделе 4.

В дополнение к заголовку кадры PING должны включать 8 октетов неинтерпретируемых (opaque) данных в содержимом кадра (payload). Отправитель может указать любое значение и применять его по своему усмотрению.

Получатель кадра PING со сброшенным флагом ACK должен передать в ответ PING с установленным флагом ACK и идентичным содержимым. Откликам PING следует предоставлять приоритет перед кадрами иных типов.

Ниже описан флаг кадров PING.

ACK (0x01)

Установка флага указывает, что этот кадр является откликом на PING. Конечная точка должна устанавливать этот флаг в откликах PING. На кадры PING с этим флагом недопустимо отвечать.

Кадры PING не связаны с каким-либо отдельным потоком. При получении PING с отличным от 0 значением Stream Identifier получатель должен отвечать ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Кадр PING с размером, отличным от 8 октетов, должен считаться ошибкой соединения (параграф 5.4.1) типа FRAME_SIZE_ERROR.

6.8. GOAWAY

Кадры GOAWAY (type=0x07) применяются для инициирования закрытия (shutdown) соединения или сигнализации о серьёзных ошибках. GOAWAY позволяет конечной точке аккуратно прекратить восприятие новых потоков, сохраняя обработку созданных ранее. Это позволяет выполнять административные операции, такие как обслуживание сервера.

Между конечной точкой, запускающей новые потоки, и её партнёром, передающим кадр GOAWAY возникает соперничество. Для решения проблемы в кадр GOAWAY включается идентификатор потока, который был или может быть обработан передающей кадр конечной точкой в этом соединении. Например при передаче кадра GOAWAY сервером указываться будет созданный клиентом поток с наибольшим номером.

После передачи кадра GOAWAY отправитель игнорирует кадры от партнёра, если идентификатор потока в них превышает указанный в кадре. Получателю кадра GOAWAY недопустимо открывать в соединении дополнительные потоки, но можно создавать для таких потоков новое соединение. Если получатель GOAWAY передал данные в потоке с идентификатором больше указанного в кадре GOAWAY, эти кадры не будут обработаны. Получатель кадра GOAWAY может считать такие потоки не созданными, что позволяет повторить их в новом соединении.

Конечным точкам следует всегда передавать кадр GOAWAY перед закрытием соединения, чтобы удалённый партнёр мог знать, был ли поток частично обработан. Например, если клиент HTTP отправил POST в то же время, когда сервер закрывал соединение, клиент не будет знать, обработан ли запрос POST сервером, если тот не передаст кадр GOAWAY для указания потоков, которые он мог обработать.

Конечная точка может закрыть соединение без отправки кадра GOAWAY, если партнёр ведёт себя некорректно.

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

   GOAWAY Frame {
     Length (24),
     Type (8) = 0x07,

     Unused Flags (8),

     Reserved (1),
     Stream Identifier (31) = 0,

     Reserved (1),
     Last-Stream-ID (31),
     Error Code (32),
     Additional Debug Data (..),
   }

Рисунок .Формат кадра GOAWAY.


Поля Length, Type, Unused Flag(s), Reserved, Stream Identifier описаны в разделе 4.

Для кадров GOAWAY не задано флагов.

Кадр GOAWAY применяется к соединению, а не к отдельному потоку. Конечная точка должна считать кадр GOAWAY с ненулевым идентификатором потока ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Идентификатор последнего потока в кадре GOAWAY содержит наибольший номер потока, для которого отправитель GOAWAY выполнил или может выполнить какие-либо действия. Все потоки до указанного, включительно, могли быть как-то обработаны. Значение 0 для последнего идентификатора указывает, что потоки не обрабатывались.

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

Если соединение прерывается без кадра GOAWAY, последним идентификатором потока фактически становится максимальный возможный номер.

В потоках с идентификаторами не больше указанного в кадре значения, которые не были полностью закрыты до завершения соединения, попытки повтора запросов, транзакции или иные операции протокола невозможны, за исключением идемпотентных действий, таких как HTTP GET, PUT, DELETE. Любые действия протокола, использующие потоки с большими идентификаторами, можно безопасно повторить в новом соединении. Действия в потоках с номерами не больше указанного в кадре могут завершиться успехом. Отправитель кадра GOAWAY может аккуратно завершить соединение, сохраняя его в состоянии open до завершения всех обрабатываемых потоков.

При изменении ситуации конечная точка может передать несколько кадров GOAWAY. Например, после отправки GOAWAY с NO_ERROR в процессе аккуратного завершения может возникнуть ситуация, требующая немедленного разрыва соединения. Идентификатор последнего потока из последнего принятого кадра GOAWAY указывает, для каких потоков могли быть выполнены действия. Конечной точке недопустимо увеличивать значение последнего идентификатора потока, поскольку партнёры уже могли передать необработанные запросы в новом соединении.

Клиент, не способный повторять запросы, при закрытии соединения сервером теряет все находящиеся в пути запросы. Это особенно важно для посредников, не способных обслуживать клиентов, использующих HTTP/2. Серверу, пытающемуся аккуратно завершить соединение, следует передать первый кадр GOAWAY с максимальным идентификатором 231-1 и кодом NO_ERROR. Оно укажет клиенту неизбежность разрыва и запрет отправки новых запросов. По истечении времени для создания находящихся в пути потоков (не менее времени кругового обхода) сервер может передать другой кадр GOAWAY с обновлённым последним номером. Это обеспечит завершение соединения без потери запросов.

После передачи GOAWAY отправитель может отбрасывать кадры потоков, созданных получателем с идентификаторами больше указанного в кадре. Однако кадры, меняющие состояние соединения, нельзя игнорировать полностью. Например, кадры HEADERS, PUSH_PROMISE, CONTINUATION должны обрабатываться по минимуму, чтобы обеспечить согласованность состояния сжатия полей (параграф 4.3), кадры DATA должны учитываться в окне управления потоком данных соединения. Отказ от обработки этих кадров вызовет несогласованность управления потоком данных или состояния сжатия раздела полей.

Кадр GOAWAY содержит 32-битовый код ошибки (раздел 7), указывающий причину закрытия соединения.

Конечная точка может добавлять необрабатываемые (opaque) данные в конце содержимого (payload) любого кадра GOAWAY. Дополнительные отладочные данные служат лишь для диагностики и не имеют семантического смысла. Отладочные данные могут быть приватными или конфиденциальными. При их регистрации или ином постоянном хранении должны обеспечиваться адекватные меры защиты от несанкционированного доступа.

6.9. WINDOW_UPDATE

Кадры WINDOW_UPDATE (type=0x08) служат для управления потоком данных (см. параграф 5.2). Управление потоком данных работает на двух уровнях — для потока и для соединения в целом. Оба типа управления работают поэтапно (hop by hop), т. е. лишь между парой конечных точек. Посредники не пересылают кадры WINDOW_UPDATE между связанными соединениями. Однако дросселирование передачи данных любым получателем может косвенно приводить к распространению сведений управления потоком данных в направлении исходного отправителя.

Управление потоком данных применяется лишь к кадрам, которые указаны как подлежащие такому управлению. Из заданных этим документом кадров к таковым относятся лишь кадры DATA. Кадры, для которых не применяется управление потоком данных, должны восприниматься и обрабатываться, пока получатель может выделить ресурсы для их обслуживания. Получатель может отвечать ошибкой потока (параграф 5.4.2) или соединения (параграф 5.4.1) типа FLOW_CONTROL_ERROR, если он не способен воспринять кадр.

   WINDOW_UPDATE Frame {
     Length (24) = 0x04,
     Type (8) = 0x08,

     Unused Flags (8),

     Reserved (1),
     Stream Identifier (31),

     Reserved (1),
     Window Size Increment (31),
   }

Рисунок .Формат кадра WINDOW_UPDATE.


Поля Length, Type, Unused Flag(s), Reserved, Stream Identifier описаны в разделе 4. Содержимым (payload) кадра WINDOW_UPDATE является зарезервированный бит и 31-битовое целое число, указывающее количество октетов, которые отправитель может передать с дополнение к имеющемуся окну управления потоком данных. Диапазон разрешённых размеров увеличения окна управления потоком данных составляет 1 — 231-1 (2147483647) октетов.

Для кадров WINDOW_UPDATE не задано флагов.

Кадр WINDOW_UPDATE может относиться к отдельному потоку или соединению в целом. В первом случае в кадре указывается идентификатор соответствующего потока, в последнем — 0.

Получатель должен считать приём кадра WINDOW_UPDATE с инкрементом окна управления потоком данных 0 ошибкой потока (параграф 5.4.2) типа PROTOCOL_ERROR, ошибки для окна управления потоком данных в соединении должны считаться ошибками соединения (параграф 5.4.1).

Кадр WINDOW_UPDATE может быть передан партнёром, отправившим кадр с флагом END_STREAM. Это означает, что получатель примет кадр WINDOW_UPDATE в потоке со статусом half-closed (remote) или closed. Недопустимо считать это ошибкой (см. параграф 5.1).

Получатель кадра, подлежащего управлению потоком данных, всегда должен учитывать вклад этого кадра в окно управления потоком данных соединения, если он не рассматривает это как ошибку соединения (параграф 5.4.1). Это требуется даже для кадров с ошибками. Отправитель учитывает кадр в окне управления потоком данных, но если этого не делает получатель, размер окна у отправителя и получателя становится разным.

Кадр WINDOW_UPDATE с размером, отличным от 4 октетов, должен считаться ошибкой соединения (параграф 5.4.1) типа FRAME_SIZE_ERROR.

6.9.1. Окно управления потоком данных

Управление потоком данных в HTTP/2 реализовано с применением окна, хранящегося у каждого отправителя в каждом потоке. Размер окна указывается целым числом, которое говорит, сколько октетов данных разрешается передать отправителю, размер окна определяется буферной ёмкостью получателя.

Применяется два окна — на уровне потока и на уровне соединения в целом. Отправителю недопустимо передавать кадры, подверженные управлению потоком данных, размер которых превышает пространство, доступное в любом из анонсированных получателем окон. Кадры нулевого размера с установленным флагом END_STREAM (пустые кадры DATA) можно передавать даже при отсутствии пространства в окнах управления потоком данных. При расчётах для управления потоком данных 9-октетные заголовки кадров не учитываются.

После отправки кадра с управлением потоком данных отправитель уменьшает доступное пространство в обоих окнах на размер переданного кадра. Получатель передаёт кадр WINDOW_UPDATE при прочтении данных и освобождении пространства в окнах управления потоком данных. Для окон потока и соединения передаются отдельные кадры WINDOW_UPDATE. Получателям рекомендуется иметь механизм предотвращения отправки кадров WINDOW_UPDATE с очень малым приращением (см. параграф 4.2.3.3 в [RFC1122]).

Отправитель, получив кадр WINDOW_UPDATE, обновляет соответствующее окно, добавляя значение из кадра.

Отправителю недопустимо разрешать окно управления потоком данных размером больше 231-1 октетов. Если отправитель получает кадр WINDOW_UPDATE, вызывающий такое превышение, он должен прервать поток или соединение (что подходит). Для потоков отправитель передаёт кадр RST_STREAM с кодом ошибки FLOW_CONTROL_ERROR, для соединения — GOAWAY с кодом ошибки FLOW_CONTROL_ERROR.

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

6.9.2. Начальный размер окна управления потоком данных

При организации соединения HTTP/2 новые потоки создаются с начальным размером окна управления потоком данных в 65535 октетов, такой же размер окна устанавливается для соединения. Обе конечные точки могут настроить размер начального окна для новых потоков, включив значение SETTINGS_INITIAL_WINDOW_SIZE в кадр SETTINGS. Размер начального окна для соединения изменяется с помощью кадра WINDOW_UPDATE. Перед отправкой кадра SETTINGS со значением SETTINGS_INITIAL_WINDOW_SIZE конечная точка может использовать лишь принятый по умолчанию начальный размер окна при передаче кадров с управлением потоком данных. Окно для соединения устанавливается на основе принятого по умолчанию размера окна, пока не будет получен кадр WINDOW_UPDATE. Помимо изменения размера окна управления потоком данных для ещё не активных потоков, кадр SETTINGS может менять начальный размер окна для потоков с активным окно управления потоком данных (потоков со статусом open и half-closed (remote)). При смене значения SETTINGS_INITIAL_WINDOW_SIZE получатель должен изменить размер окна управления потоком данных во всех потоках, которые он поддерживает на разность между новым и старым значением. Изменение SETTINGS_INITIAL_WINDOW_SIZE может приводить к отрицательному размеру доступного в окне управления потоком данных пространства. Отправитель должен отслеживать такие случаи и ему недопустимо передавать новые кадры с управлением потоком данных, пока не будет принят кадр WINDOW_UPDATE, делающий размер окна положительным. Например, если клиент передал 60 Кбайт сразу после организации соединения, а сервер установил начальный размер окна в 16 Кбайт, клиент будет иметь размер доступного окна -44 Кбайт после приёма кадра SETTINGS. Клиент будет сохранять отрицательный размер окна, пока кадры WINDOW_UPDATE не восстановят положительное значение, после чего клиент может продолжить отправку.

Кадр SETTINGS не может менять окно управления потоком данных.

Конечная точка должна считать установку SETTINGS_INITIAL_WINDOW_SIZE, вызывающую превышение любым окном управления потоком данных максимального размера, ошибкой соединения (параграф 5.4.1) типа FLOW_CONTROL_ERROR.

6.9.3. Снижение размера окна для потока

Получатель, желающий использовать меньшее окно управления потоком данных, чем сейчас, может передать новый кадр SETTINGS. Однако он должен быть готов к получению большего объёма данных, поскольку отправитель мог передать эти данные до получения кадра SETTINGS.

После отправки кадра SETTINGS, сокращающего окно управления потоком данных, получатель может продолжать обработку потоков, превышающих ограничение. Это не позволяет получателю моментально сократить пространство, используемое для окно управления потоком данных. Продвижение этих потоков может застопориться, поскольку нужны кадры WINDOW_UPDATE, позволяющие отправителю возобновить передачу. Получатель может взамен передать для затронутых потоков RST_STREAM с кодом ошибки FLOW_CONTROL_ERROR.

6.10. CONTINUATION

   CONTINUATION Frame {
     Length (24),
     Type (8) = 0x09,

     Unused Flags (5),
     END_HEADERS Flag (1),
     Unused Flags (2),

     Reserved (1),
     Stream Identifier (31),

     Field Block Fragment (..),
   }

Рисунок .Формат кадра CONTINUATION.


Кадр CONTINUATION (type=0x09) служит для продолжения последовательности фрагментов блока полей (параграф 4.3). Можно передать любое число кадров CONTINUATION, пока предыдущий кадр передаётся в том же потоке и имеет тип HEADERS, PUSH_PROMISE или CONTINUATION без флага END_HEADERS.

Поля Length, Type, Unused Flag(s), Reserved, Stream Identifier описаны в разделе 4. Содержимым (payload) кадра CONTINUATION является фрагмент блока полей (параграф 4.3).

Флаг для кадра CONTINUATION описан ниже.

END_HEADERS (0x04)

Установленный флаг указывает, что этот кадр является последним для блока полей (параграф 4.3), а при сброшенном флаге в том же потоке должен следовать другой кадр CONTINUATION. Получатель должен считать получение кадра иного типа или приём кадра продолжения в другом потоке ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Кадр CONTINUATION меняет статус соединения, как указано в параграфе 4.3.

Кадр CONTINUATION должен быть связан с потоком, а при получении такого кадра с Stream Identifier = 0x00 получатель должен отвечать ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Кадру CONTINUATION должен предшествовать кадр HEADERS, PUSH_PROMISE или CONTINUATION без флага END_HEADERS. При нарушении этого получатель должен отвечать ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

7. Коды ошибок

Коды ошибок передаются 32-битовым полем в кадрах RST_STREAM и GOAWAY для указания причины ошибки.

Для кодов ошибок используется общее пространство. Некоторые коды применимы к потокам или всему соединению и не имеют семантики в ином контексте. Идентификаторы и значения кодов ошибок приведены ниже.

NO_ERROR (0x00)

Связанное с кодом условие не является результатом ошибки. Например, кадр GOAWAY может включать этот код для указания аккуратного завершения соединения.

PROTOCOL_ERROR (0x01)

Конечная точка обнаружила не указанную ошибку протокола. Этот код применяется при отсутствии более конкретного.

INTERNAL_ERROR (0x02)

Конечная точка столкнулась с неожиданной внутренней ошибкой.

FLOW_CONTROL_ERROR (0x03)

Конечная точка обнаруженила нарушение партнёром протокола управления потоком данных.

SETTINGS_TIMEOUT (0x04)

Конечная точка передала кадр SETTINGS и не получила своевременного отклика (см. параграф 6.5.3).

STREAM_CLOSED (0x05)

Конечная точка получила кадр в полузакрытом потоке.

FRAME_SIZE_ERROR (0x06)

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

REFUSED_STREAM (0x07)

Конечная точка отвергла поток до выполнения прикладной обработки (см. параграф 8.7).

CANCEL (0x08)

Конечная точка использует этот код для укащания того, что поток больше не нужен.

COMPRESSION_ERROR (0x09)

Коенчная точка не может поддерживать контекст сжатия полей для соединения.

CONNECT_ERROR (0x0a)

Соединение, организованное по запросу CONNECT (параграф 8.5) сброшено или аварийно закрыто.

ENHANCE_YOUR_CALM (0x0b)

Конечная точка обнаружила, что поведение партнёра может вызывать избыточную нагрузку.

INADEQUATE_SECURITY (0x0c)

Базовый транспорт не соответствует минимальным требованиям безопасности (см. параграф 9.2).

HTTP_1_1_REQUIRED (0x0d)

Конечная точка требует использовать HTTP/1.1 вместо HTTP/2.

Неизвестным или неподдерживаемым кодам ошибок недопустимо вызывать особое поведение. Реализация может считать такие коды эквивалентом INTERNAL_ERROR.

8. Выражение семантики HTTP в HTTP/2

HTTP/2 является реализацией абстракции сообщений HTTP (раздел 6 в [HTTP]).

8.1. Кадрирование сообщений HTTP

Клиент передаёт запрос HTTP в новый поток, используя незанятый идентификатор потока (параграф 5.1.1), а север возвращает отклик HTTP в том же потоке. Сообщение HTTP (запрос или отклик) состоит из::

  1. одного кадра HEADERS (за которым могут следовать кадры CONTINUATION), содержащего раздел заголовков (см. параграф 6.3 в [HTTP]);

  2. необязательных кадров DATA с содержимым сообщения ( см. параграф 6.4 в [HTTP]);

  3. необязательного кадра HEADERS (за которым могут следовать кадры CONTINUATION), содержащего раздел трейлеров, если он имеется ( см. параграф 6.5 в [HTTP]).

При ответе сервер может передать любое число промежуточных (interim) откликов до кадра HEADERS с финальным откликом. Промежуточный отклик ACK состоит из кадра HEADERS (за которым могут следовать кадры CONTINUATION) с данными управления и разделом заголовков промежуточного (1xx) отклика HTTP (см. раздел 15 в [HTTP]). Кадр HEADERS с установленным флагом END_STREAM, содержащий информационный (1xx) код статуса, является некорректно сформированным (параграф 8.1.1). В последнем кадре последовательности устанавливается флаг END_STREAM, но за ним могут следовать кадры CONTINUATION с остальными фрагментами блока полей. Другие кадры (из любого потока) недопустимо включать между кадром HEADERS и следующими за ним кадрами CONTINUATION.

HTTP/2 использует кадры DATA для передачи содержимого сообщения. Блочное (chunked) транспортное кодирование, определённое в параграфе 7.1 [HTTP/1.1], неприменимо в HTTP/2 (см. параграф 8.2.2).

Поля трейлера передаются в блоке полей, который завершает поток. Т. е. поля трейлера образуют последовательность, начинающуюся с кадра HEADERS с установленным флагом END_STREAM, за которым могут следовать кадры CONTINUATION. В трейлер недопустимо включать поля псевдозаголовка (параграф 8.3). Конечная точка, получившая такие поля в трейлере, должна считать запрос или отклик неверно сформированным (параграф 8.1.1). Конечная точка, получившая кадр HEADERS без флага END_STREAM после приёма открывающего запрос кадра HEADERS или после финального (не информационного) кода статуса, должна считать запрос или отклик неверно сформированным (параграф 8.1.1).

Обмен HTTP запрос-отклик полностью расходует один поток. Запрос начинается с кадра HEADERS, переводящего поток в состояние open, и завершается кадром с флагом END_STREAM, который вызывает переход потока в состояние half-closed (local) для клиента и half-closed (remote) для сервера. Поток отклика начинается с необязательный промежуточных откликов в кадрах HEADERS, за которыми следует кадр HEADERS с финальным кодом статуса.

Запрос HTTP завершается после того, как сервер отправит или клиент получит кадр с флагом END_STREAM (включая кадры CONTINUATION для завершения блока полей). Сервер может передать полный отклик до того, как клиент отправит весь запрос, если отклик не зависит от ещё не полученной части запроса. В таком случае сервер может попросить клиента прервать передачу запроса без ошибки, передав RST_STREAM с кодом NO_ERROR после отправки полного отклика (кадр с флагом END_STREAM). Клиенту недопустимо отбрасывать отклик при получении такого RST_STREAM, хотя он всегда может отбросить отклик по своему усмотрению в силу иных причин.

8.1.1. Некорректно сформированные сообщения

Некорректно сформированным считается запрос или отклик, непригодный из-за наличия лишних кадров, запрещённых полей или псевдозаголовков, отсутствия обязательных полей псевдозаголовка, наличия заглавных букв в именах полей, недействительных имён или значений полей (в некоторых случаях, см. параграф 8.2), а в остальном являющийся корректной последовательностью кадров HTTP/2.

Запрос или отклик с содержимым может включать поле заголовка content-length, но будет считаться некорректно сформированным, если значение поля content-length не равно сумме размеров данных (payload) в кадрах DATA, образующих содержимое (если только сообщение не определено как не имеющее содержимого). Например, отклики 204 и 304 не имеют содержимого, как и отклик на запрос HEAD. Отклик, заданный как не имеющий содержимого (см. параграф 6.4.1 в [HTTP]), может включать отличное от 0 поле content-length, даже при отсутствии содержимого в кадрах DATA.

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

Для некорректно сформированных запросов сервер может передавать отклик HTTP до закрытия или сброса потока. Клиенту недопустимо воспринимать некорректно сформированные откликиaccept a malformed response.

Конечные точки, обрабатывающие сообщения постепенно могут выполнить часть обработки до обнаружения непригодной формы запроса или отклика. Например, можно сгенерировать информационный код статуса или код 404 без получения запроса целиком. Посредник может переслать неполное сообщение до обнаружения ошибки. Сервер может сгенерировать окончательный отклик до получения всего запроса, когда отклик не зависит от корректности оставшейся части запроса.

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

8.2. Поля HTTP

Поля HTTP (параграф 5 в [HTTP]) передаются в кадрах HTTP/2 HEADERS, CONTINUATION, PUSH_PROMISE со сжатием HPACK [COMPRESSION].

При создании сообщения HTTP/2 имена полей должны приводиться к нижнему регистру.

8.2.1. Пригодность поля

Определения имён и значений полей HTTP запрещают некоторые символы, которые может передавать HPACK. реализациям HTTP/2 следует проверять соответствие имён и значений полей их определениям в параграфах 5.1 и 5.5 в HTTP] и считать некорректно сформированными (параграф 8.1.1) поля с запретными символами.

Отказы при проверке полей могут использоваться для атак с контрабандой запросов. В частности, непроверенные поля могут применяться для атак при пересылке сообщений, использующих HTTP/1.1 [HTTP/1.1], где символы возврата каретки (CR), перевода строки (LF) и двоеточие (COLON) служат разделителями. Реализации должны выполнять минимальные проверки имён и значений полей, как указано ниже.

  • В имена полей недопустимо включать символы из диапазонов 0x00-0x20, 0x41-0x5a, 0x7f-0xff (включительно). Это запрещает все невидимые символы ASCII, ASCII SP (0x20) и символы верхнего регистра (A-Z, ASCII 0x41 — 0x5a).

  • За исключением полей псевдозаголовка (параграф 8.3), начинающихся с двоеточия (:), в имена полей недопустимо включать символ двоеточния (ASCII COLON, 0x3a).

  • В значения полей недопустимо включать символ NUL (ASCII NUL, 0x00), а также символ перевода строки (ASCII LF, 0x0a) и возвраат каретки (ASCII CR, 0x0d).

  • Значение поля недопустимо начинать или заканчивать пробельным символом ASCII (ASCII SP или HTAB, 0x20 или 0x09).

    Примечание. Реализации, проверяющей поля в соответствии с определениями параграфов 5.1 и 5.5 в [HTTP] нужна лишь проверка отсутствия в именах полей заглавных букв.

Запрос или отклик, включающий поле, которое нарушает приведённые выше требования, должен считаться некорректно сформированным (параграф 8.1.1). В частности, посреднику, не обрабатывающему поля при пересылке, недопустимо пересылать поля, значения которых указаны выше как запрещенные.

При нарушении запросом любого из указанных выше требований реализации следует генерировать код статуса 400 (Bad Request) (см. параграф 15.5.1 в [HTTP]), если нет более подходящего кода или код статуса невозможно передать (например, при ошибке в поле трейлера).

Примечание. Имена полей, недействительные в соответствии с определением, не вызывают признания запроса некорретно сформированным. Приведённые выше требования применяются лишь к базовому синтаксису полей, заданному в разделе 5 [HTTP].

8.2.2. Связанные с соединением поля заголовка

В HTTP/2 не применяется поле заголовка Connection (параграф 7.6.1 в [HTTP]) для указания специфичных для соединения полей. В этом протоколе специфичные для соединения метаданные передаются иначе. Конечной точке недопустимо генерировать сообщения HTTP/2 со специфичными для соединения полями заголовка. Это включает Connection и поля, указанные как специфичные для соединения в параграфе 7.6.1 [HTTP] (Proxy-Connection, Keep-Alive, Transfer-Encoding, Upgrade). Сообщения со специфичными для соединения полями заголовка должны считаться некорректно сформированными (параграф 8.1.1). Едиственным исключением является поле заголовка TE, которое может присутствовать в запросе HTTP/2, этому полю недопустимо иметь значение, отличное от trailers.

Посредник, преобразующий сообщение HTTP/1.x в HTTP/2, должен удалять специфичные для соединения поля, как описано в параграфе 7.6.1 [HTTP], иначе такие сообщения другие конечные точки HTTP/2 будут считать некорректно сформированными (параграф 8.1.1).

Примечание. В HTTP/2 целенаправленно не поддерживается переход на другой протокол (обновление). Методы согласования, описанные в разделе 3, считаются достаточными для согласования дополнительных протоколов.

8.2.3. Сжатие поля заголовка Cookie

В поле заголовка Cookie [COOKIE] применяется точка с запятой (;) для разделения cookie-пар (crumb). В этом поле содержится несколько значений, но запятая (, COMMA) не применяется как разделитель, предотвращая передачу cookie-пар в нескольких строках поля (см. параграф 5.2 в [HTTP]). Это может значительно снизить эффективность сжатия, поскольку при обновлении отдельных cookie-пар все записи в таблице HPACK становятся недействительными.

Для повышения эффективности сжатия поле заголовка Cookie можно разделить на отдельные поля, каждое из которых содержит одну или несколько cookie-пар. Если после декомпресии остаётся несколько полей Cookie, они должны объединяться в одну строку октетов с использованием двухоктетного разделителя 0x3b, 0x20 (строка ASCII string «; «) до передачи в контекст, не относящийся к HTTP/2, например, в соединение HTTP/1.1 или обычное серверное приложение HTTP. С учётом этого два приведённых ниже списка полей заголовка Cookie семантически эквивалентны.

   cookie: a=b; c=d; e=f

   cookie: a=b
   cookie: c=d
   cookie: e=f

8.3. Данные управления HTTP

В HTTP/2 применяются специальные поля псевдозаголовка, начинающиеся с символа двоеточия (:, ASCII 0x3a), для передачи данных управления (см. параграф 6.2 в [HTTP]). Поля псевдозаголовков не являются полями заголовка HTTP. Конечным точкам недопустимо генерировать поля псевдозаголовка, кроме заданных в этом документе, однако расширения могут задавать дополнительные поля (см. параграф 5.5).

Поля псевдозаголовка действительны лишь в контексте, где они были определены, поля псевдозаголовка откликов недопустимо включать в запросы и наоборот, а также недопустимо включать поля псевдозаголовка в трейлеры. Конечные точки должны считать запрос или отклик с неопределённым или недействительным полем псевдозаголовка некорректно сформированными (параграф 8.1.1).

Все поля псевдозаголовка должны включаться в блок полей до строй обычных полей. Любой запрос или отклик с полями псевдозаголовка в блоке полей после обычных полей заголовка должен считаться некорректно сформированным (параграф 8.1.1).

Одно и то же поле заголовка недопустимо включать в блок полей более одного раза. Блок полей для запроса или отклика HTTP с повторяющимся полем заголовка должен считаться некорректно сформированным (параграф 8.1.1).

8.3.1. Поля псевдозаголовка запроса

Ниже указаны поля псевдозаголовка, определённые для запросов HTTP/2.

  • :method указывает метод HTTP method (параграф 9 в [HTTP]).

  • :scheme включает схему из цели запроса. Схема берётся из URI цели (параграф 3.1 в [RFC3986]) при генерации запроса напрямую или из схемы транслированного запроса (см., например, параграф 3.3 в [HTTP/1.1]). В запросах CONNECT (параграф 8.5) схема не указывается.

    В поле :scheme можно указывать не только http и https. Прокси и шлюзы могут транслировать запросы в другие (не HTTP) схемы, обеспечивая взаимодействие HTTP с другими типами служб.

  • :authority содержит компонент полномочий (параграф 3.2 в [RFC3986]) из URI цели (параграф 7.1 of [HTTP]). Получателю запроса HTTP/2 недопустимо использовать поле заголовка Host для указания URI цели при наличии :authority.

    Клиенты, создающие запросы HTTP/2 напрямую, должны использовать поле :authority для передачи сведений о полномочиях, если эти сведения нужно передавать (в ином случае создавать :authority недопустимо).

    Клиентам недопустимо создавать запросы с полем заголовка Host, отличающимчя от поля псевдозаголовка :authority. Серверу следует считать такие запросы некорректно сформированными, если поле Host указывает сущность, отличающуюся от указанной в :authority. Значение полей при сравнении должны нормализоваться (см. параграф 6.2 вf [RFC3986]). Сервер-источник может применять любой метод нормализации, а другие серверы должны использовать нормализацию на основе схемы (см. параграф 6.2.3 в [RFC3986]) из двух полей.

    Посредник, пересылающий запрос по HTTP/2, должен создавать поле псевдозаголовка :authority и использованием сведений о полномочиях из данных управления исходного запроса, если она имеется в URI цели (в ином случае создавать :authority недопустимо). Отметим, что поле заголовка Host не является единственным источником таких сведений (см. параграф 7.2 в [HTTP]). Посредник, которому нужно создавать поле заголовка Host (это может требоваться для создания запроса HTTP/1.1), должен использовать значение :authority в качестве значения поля Host, если только он не меняет цель запроса. Это заменяет имеющееся значение поля Host для предотвращения возможных уязвимостей маршрутизации HTTP. Посредник, пересылающий запрос через HTTP/2, может сохранить поле заголовка Host.

    Отметим, что цель запроса для CONNECT или asterisk-form в OPTIONS не включает сведений о полномочиях (см. параграфы 7.1 и 7.2 в [HTTP].

    В :authority недопустимо включать устаревший субкомпонент userinfo для URI со схемой http или https.

  • :path включает путь и части запроса URI цели (absolute-path и необязательный символ ?, за которым следует запрос (query), см. параграф 4.1 в [HTTP]). Запрос в форме * (для OPTIONS) включает значение * для поля псевдозаголовка :path.

    Этому полю псевдозаголовка недопустимо быть пустым для URI http и https, которые при отсутствии компонента пути должны включать значение /. Исключения из этого правила приведены ниже.

    • Запрос OPTIONS для URI http или https без компонента пути должен включать поле псевдозаголовка :path со значением * (см. параграф 7.1 в [HTTP]).

    • Запросы CONNECT (параграф 8.5), где поле псевдозаголовка :path отсутствует.

Все запросы HTTP/2, кроме CONNECT (параграф 8.5), должны включать в точности одно значение для полей псевдозаголовка :method, :scheme, :path. Запрос HTTP без обязательных полей псевдозаголовка считается некорректно сформированным (параграф 8.1.1).

В отдельных запросах HTTP/2 нет явного индикатора версии протокола. Все запросы HTTP/2 неявно имеют версию протокола 2.0 (см. параграф 6.2 в [HTTP]).

8.3.2. Поля псевдозаголовка отклика

Для откликов HTTP/2 определено единственное поле псевдозаголовка :status, передающее код статуса (см. раздел 15 в [HTTP]). Это поле должно включаться во все отклики, в том числе, промежуточные. В противном случае отклик будет считаться сформированным некорректно (параграф 8.1.1).

Отклик HTTP/2 неявно имеют версию протокола 2.0.

8.4. Выталкивание с сервера

HTTP/2 позволяет серверу заранее передавать (выталкивать — push) отклики, основанные на предшествующем запросе клиента, вместе с соответствующими «предсказанными» (promised) запросами. Выталкивание с сервера было разработано для того, чтобы позволить серверу повысить воспринимаемую клиентом производительность путём предсказания запросов, которые последуют за полученными, что позволяло исключить один интервал кругового обхода. Например, за запросом страницы HTML часто следуют запросы таблиц стилей и сценариев, на которые эта страница ссылается. При выталкивании таких запросов клиенту не ждать получения ссылок на них в HTML и отправлять отдельные запросы.

На практике сложно эффективно использовать выталкивание с сервера, поскольку для этого требуется конкретно предсказать дополнительные запросы, которые клиент может сделать, учитывая такие факторы, как кэширование, согласование содержимого и поведение пользователя. Ошибки при прогнозировании ведут к снижению производительности из-за дополнительных затрат на передачу данных. В частности, выталкивание значительного объёма данных может приводить к проблемам из-за соперничества с откликами, которое более важны. Клиент может запросить запрет выталкивания с сервера, но это нужно независимо согласовывать на каждом интервале (hop). Для отключения выталкивания с сервера можно передать SETTINGS_ENABLE_PUSH = 0.

Предсказанные запросы должны быть безопасными (см. параграф 9.2.1 в [HTTP]) и кэшируемыми (параграф 9.2.3 в [HTTP]), а также не могут включать содержимого и раздела трейлеров. Получение клиентом предсказанного запроса, который не является кэшируемым, для которого неизвестно о безопасности и в котором указано наличие содержимого, должно сбрасывать promised-поток с ошибкой потока (параграф 5.4.2) типа PROTOCOL_ERROR. Отметим, что это может приводить к сбросу promised-потока, если клиент не считает вновь определённый метод безопасным.

Вытолкнутые отклики, которые являются кэшируемыми (см. раздел 3 в [CACHING]), клиент может сохранять, если он реализует кэширование HTTP. Вытолкнутые отклики считаются подтверждёнными сервером-источником, пока поток, указанный идентификатором promised-потока, остаётся открытым (для случая наличия директивы кэширования откликов no-cache см. параграф 5.2.2.4 в [CACHING]). Некэшируемые вытолкнутые отклики недопустимо сохранять в каком-либо кэше HTTP. Они могут быть сделаны доступными приложению отдельно.

Сервер должен включать значение в поле псевдозаголовка :authority, для которого сервер является полномочным (см. параграф 10.1). Клиент должен считать кадр PUSH_PROMISE, для которого сервер не является полномочным, ошибкой потока (параграф 5.4.2) типа PROTOCOL_ERROR.

Посредники могут получать выталкивание (push) от сервера и отказываться от его пересылки клиенту. Иными словами, решение о применении вытолкнутой информации посредник принимает сам. Он также может передавать клиенту дополнительные push-отправки без каких-либо действий со стороны сервера.

Клиент не может применять выталкивание, поэтому получение сервером кадра PUSH_PROMISE должно считаться ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR. Сервер не может передавать SETTINGS_ENABLE_PUSH с отличным от 0 значением (см. параграф 6.5.2).

8.4.1. Выталкивание запроса

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

Предсказанный запрос всегда связывается с явным запросом от клиента. Кадры PUSH_PROMISE передаются сервером в поток явного запроса и включают идентификатор предсказанного (promised) потока, выбранный из доступных серверу идентификаторов потока (см. параграф 5.1.1). Поля заголовка в PUSH_PROMISE и последующих кадрах CONTINUATION должны образовывать действительный и полный набор полей заголовка запроса (параграф 8.3.1). Сервер должен указывать в поле псевдозаголовка :method безопасный и кэшируемый метод. Если клиент получает кадр PUSH_PROMISE без полного и действительного набора заголовков или поле псевдозаголовка :method указывает небезопасный метод, он должен ответить в promised-потоке ошибкой потока (параграф 5.4.2) типа PROTOCOL_ERROR. Серверу следует передавать кадры PUSH_PROMISE (параграф 6.6) до отправки любых кадров, ссылающихся на предсказанные отклики. Это позволяет предотвратить состязание при отправке клиентом запроса до получения PUSH_PROMISE. Например, если сервер получает запрос на документ, содержащий встроенные ссылки на несколько файлов с изображениями, и решает вытолкнуть клиенту эти дополнительные изображения, передавая кадры PUSH_PROMISE до кадров DATA, содержащих ссылки на изображения, чтобы клиент мог видеть, что ресурс вытолкнут до обнаружения встроенных ссылок. Если сервер выталкивает ресурсы, указанные блоком полей (например, поля заголовка Link), отправка PUSH_PROMISE до передачи заголовка гарантирует, что клиенты не запросят эти ресурсы.

Клиенту недопустимо передавать кадры PUSH_PROMISE.

Сервер может передавать кадры PUSH_PROMISE в любой поток, инициированный клиентом, но этот поток должен иметь статус open или half-closed (remote) применительно к серверу. Кадры PUSH_PROMISE перемежаются с кадрами отклика, не не могут перемежаться с кадрами HEADERS и CONTINUATION, образующими один блок полей.

Передача кадра PUSH_PROMISE создаёт новый поток и помещает его в состояние reserved (local) для сервера и reserved (remote) для клиента.

8.4.2. Выталкивание отклика

После отправки кадра PUSH_PROMISE сервер может начать доставку выталкиваемого отклика (параграф 8.3.2) в инициированном сервером потоке, который использует идентификатор предсказанного (promised) потока. Сервер использует этот поток для передачи отклика HTTP, применяя последовательность кадров, описанную в параграфе 8.1. Этот поток принимает для клиента состояние half-closed (параграф 5.1) после отправки начального кадра HEADERS.

Когда клиент получает кадр PUSH_PROMISE и решает принять вытолкнутый отклик, ему не следует отправлять запросов, пока promised-поток не будет закрыт. Если клиент по какой-либо причине отказывается принимать вытолкнутый отклик или сервер слишком долго не начинает передачу предсказанного отклика, клиент может передать кадр RST_STREAM с кодом CANCEL или REFUSED_STREAM и идентификатором выталкиваемого потока.

Клиент может использовать установку SETTINGS_MAX_CONCURRENT_STREAMS для ограничения числа откликов, которые сервер может вытолкнуть одновременно. Анонсирование SETTINGS_MAX_CONCURRENT_STREAMS = 0 не позволяет серверу открыть потоки, требуемые для выталкивания откликов. Однако это не мешает серверу резервировать потоки с помощью кадров PUSH_PROMISE, поскольку такие потоки не учитываются в числе одновременных потоков. Клиенту, не желающему принимать выталкиваемые ресурсы, нужно сбрасывать (reset) любые нежелательные зарезервированные потоки или задать SETTINGS_ENABLE_PUSH = 0.

Клиенты, принимающие вытолкнутые отклики, должны проверять, что сервер полномочен для них (параграф 10.1) или прокси, предоставивший такой отклик, настроен для соответствующего запроса. Например, серверу, предлагающему сертификат лишь для DNS-ID example.com (см. [RFC6125]), не разрешается выталкивать отклики для https://www.example.org/doc.

Отклик для потока PUSH_PROMISE начинается с кадра HEADERS, который сразу переводит поток в состояние half-closed (remote) для сервера и half-closed (local) для клиента, а завершается кадром с флагом END_STREAM, переводящим поток в состояние closed.

Примечание. Клиент никогда не передаёт кадр с флагом END_STREAM для выталкивания с сервера.

8.5. Метод CONNECT

Метод CONNECT (параграф 9.3.6 в [HTTP]) служит для преобразования соединения HTTP в туннель к удалённому хосту и применяется в основном HTTP-прокси при организации сессии TLS с сервером-источником для взаимодействия с ресурсами https.

В HTTP/2 метод CONNECT организует туннель через один поток HTTP/2 к удалённому хосту, а не преобразует в туннель соединение целиком. Раздел заголовков CONNECT создаётся, как указано в параграфе 8.3.1 с некоторыми отличиями:

  • в поле псевдозаголовка :method устанавливается значение CONNECT;

  • поля псевдозаголовка :scheme и :path должны быть опущены;

  • поле псевдозаголовка :authority содержит хост и порт для организации соединения (эквивалент authority-form для the request-target в запросах CONNECT, см. параграф 3.2.3 в [HTTP/1.1]).

Запросы CONNECT, не соответствующие этим требованиям, считаются ошибочными (параграф 8.1.1).

Прокси, поддерживающий CONNECT, организует соединение TCP [TCP] с хостом и портом, указанными в поле псевдозаголовка :authority. После организации соединения прокси передаёт клиенту кадр HEADERS с кодом 2xx, как указано в параграфе 9.3.6 [HTTP]. После отправки каждым партнёром начального кадра HEADERS все последующие кадры DATA соответствуют данным, переданным через соединение TCP. Содержимое (payload) всех кадров DATA от клиента прокси передаёт серверу TCP, а данные от этого сервера прокси собирает в кадры DATA. Кадры иных типов (не DATA) и кадры управления потоком (RST_STREAM, WINDOW_UPDATE, PRIORITY) недопустимо передавать в поток соединения TCP и получение такого кадра должно считаться ошибкой потока (параграф 5.4.2).

Соединение TCP может закрыть любой из партнёров. Флаг END_STREAM в кадре DATA считается эквивалентом бита TCP FIN. Предполагается, что клиент передаст кадр DATA с флагом END_STREAM после получения кадра с установленным флагом END_STREAM. Прокси, получивший кадр DATA с флагом END_STREAM, отправляет присоединённые данные с установленным в последнем сегменте TCP битом FIN. Прокси, получивший сегмент TCP с битом FIN, передаёт кадр DATA с установленным флагом END_STREAM. Отметим, что финальный сегмент TCP или кадр DATA может быть пустым.

Ошибки соединения TCP указываются флагом RST_STREAM. Прокси считает любую ошибку соединения TCP, включающую получение сегмента TCP с установленным битом RST, ошибкой потока (параграф 5.4.2) типа CONNECT_ERROR. Соответственно, прокси должен передать сегмент TCP с установленным битом RST при обнаружении ошибки в потоке или соединении HTTP/2.

8.6. Поле заголовка Upgrade

HTTP/2 не поддерживает информационный код статуса 101 (Switching Protocols) (параграф 15.2.2 в [HTTP]). Семантика кода 101 (Switching Protocols) не применима к мультиплексируемому протоколу, а такая же функциональность может быть обеспечена расширенным методом CONNECT [RFC8441] и другими протоколами, способными использовать такие же механизмы, как применяются для согласования в HTTP/2 (раздел 3).

8.7. Надёжность запросов

В общем случае клиент HTTP не может повторить неидемпотентный запрос при возникновении ошибки, поскольку у него нет возможности определить природу ошибки (см. параграф 9.2.2 в [HTTP]). Сервер мог выполнить какую-то часть обработки запроса до возникновения ошибки и повторное выполнение запроса может иметь нежелательные последствия. В HTTP/2 имеется два механизма для информирования клиента о том, что запрос не обработан.

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

  • В кадр RST_STREAM может включаться код ошибки REFUSED_STREAM для индикации закрытия потока до выполнения обработки. Любой запрос, отправленный в закрытый поток, можно повторять без опасений.

Необработанные запросы не вызывают отказа и клиент может автоматически повторить запрос даже для неидемпотентного метода.

Серверу недопустимо указывать, что поток не был обработан, если сервер не может это гарантировать. Если находящиеся в потоке кадры переданы на уровень приложения из любого потока, использовать REFUSED_STREAM для этого потока недопустимо, а кадр GOAWAY должен включать идентификатор потока, не меньше идентификатора данного потока.

В дополнение к этим механизмам кадры PING позволяют клиенту легко проверить соединение. Соединения, остающиеся бездействующими (idle), можно разорвать, поскольку некоторые промежуточные устройства (например, трансляторы сетевых адресов и балансировщики нагрузки) молча отбрасывают привязки соединений. Кадр PING позволяет клиенту безопасно проверить сохранение активности соединения без отправки запроса.

8.8. Примеры

В этом параграфе показаны запросы и отклики HTTP/1.1, а также их эквиваленты в HTTP/2.

8.8.1. Простой запрос

Запрос HTTP GET включает данные управления и заголовок запроса без содержимого сообщения, поэтому передаётся как один кадр HEADERS, за которым могут следовать кадры CONTINUATION с сериализованным блоком полей заголовка. В приведённом ниже кадре HEADERS установлены флаги END_HEADERS и END_STREAM, а кадров CONTINUATION не передаётся.

     GET /resource HTTP/1.1           HEADERS
     Host: example.org          ==>     + END_STREAM
     Accept: image/jpeg                 + END_HEADERS
                                          :method = GET
                                          :scheme = https
                                          :authority = example.org
                                          :path = /resource
                                          host = example.org
                                          accept = image/jpeg

8.8.2. Простой отклик

Отклик, включающий только данные управления и поля заголовка, передаётся как кадр HEADERS (за которым могут следовать кадры CONTINUATION) с сериализованным блоком полей заголовка отклика.

     HTTP/1.1 304 Not Modified        HEADERS
     ETag: "xyzzy"              ==>     + END_STREAM
     Expires: Thu, 23 Jan ...           + END_HEADERS
                                          :status = 304
                                          etag = "xyzzy"
                                          expires = Thu, 23 Jan ...

8.8.3. Составной запрос

Запрос HTTP POST с данными управления, заголовком и содержимым сообщения передаётся как один кадр HEADERS, за которым могут следовать кадры CONTINUATION с заголовком и кадры DATA с содержимым. Финальный кадр CONTINUATION (или HEADERS) и финальный кадр DATA имеют установленный флаг END_STREAM.

     POST /resource HTTP/1.1          HEADERS
     Host: example.org          ==>     - END_STREAM
     Content-Type: image/jpeg           - END_HEADERS
     Content-Length: 123                  :method = POST
                                          :authority = example.org
                                          :path = /resource
     {двоичные данные}                    :scheme = https

                                      CONTINUATION
                                        + END_HEADERS
                                          content-type = image/jpeg
                                          host = example.org
                                          content-length = 123

                                      DATA
                                        + END_STREAM
                                      {двоичные данные}

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

8.8.4. Отклик с телом

Отклик с данными управления, заголовком и содержимым сообщения передаётся как кадр HEADERS, за которым могут следовать кадры CONTINUATION с заголовком и кадры DATA с содержимым. В последнем кадре DATA устанавливается флаг END_STREAM.

     HTTP/1.1 200 OK                  HEADERS
     Content-Type: image/jpeg   ==>     - END_STREAM
     Content-Length: 123                + END_HEADERS
                                          :status = 200
     {двоичные данные}                    content-type = image/jpeg
                                          content-length = 123

                                      DATA
                                        + END_STREAM
                                      {двоичные данные}

8.8.5. Информационный отклик

Информационный отклик с кодом статуса 1xx, отличным от 101, передаётся в кадре HEADERS, за которым могут следовать кадры CONTINUATION. Раздел трейлера передаётся как блок полей после передачи блока полей запроса или отклика и всех кадров DATA. В кадре HEADERS, начинающем блок полей с разделом трейлера имеет установленный флаг END_STREAM.

Ниже приведён пример отклика с кодом 100 (Continue) на запрос с маркером 100-continue в поле заголовка Expect и раздел трейлера.

     HTTP/1.1 100 Continue            HEADERS
     Extension-Field: bar       ==>     - END_STREAM
                                        + END_HEADERS
                                          :status = 100
                                          extension-field = bar

     HTTP/1.1 200 OK                  HEADERS
     Content-Type: image/jpeg   ==>     - END_STREAM
     Transfer-Encoding: chunked         + END_HEADERS
     Trailer: Foo                         :status = 200
                                          content-type = image/jpeg
     123                                  trailer = Foo
     {двоичные данные}
     0                                DATA
     Foo: bar                           - END_STREAM
                                      {двоичные данные}

                                      HEADERS
                                        + END_STREAM
                                        + END_HEADERS
                                          foo = bar

9. Соединения HTTP/2

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

9.1. Управление соединениями

Соединения HTTP/2 сохраняются (persistent). В целях повышения производительности ожидается, что клиенты не будут закрывать соединение, пока не будет установлено, что взаимодействие с сервером больше не нужно (например, пользователь ушёл с web-страницы) или пока соединение не закроет сервер.

Клиент не следует создавать более одного соединения HTTP/2 с данным хостом и портом, где хост выводится из URI, выбранной альтернативной службы [ALT-SVC] или настроенного прокси.

Клиент может создавать дополнительные соединения на замену, для подготовки замены соединений с заканчивающимся пространством доступных идентификаторов потоков (параграф 5.1.1), для обновления ключевого материала соединения TLS или замены соединений, где возникли ошибки (параграф 5.4.1).

Клиент может создать несколько соединений с одним адресом IP и портом TCP, используя разные значения индикации имени сервера (Server Name Indication или SNI) [TLS-EXT] для обеспечения разных сертификатов TLS, но следует избегать создания нескольких соединений с одной конфигурацией.

Серверам рекомендуется поддерживать соединения открытыми как можно дольше, но при необходимости разрешается прерывать бездействующие соединения. Любой из конечных точек, закрывающей транспортное соединение TCP, следует сначала передать кадр GOAWAY (параграф 6.8), чтобы обе конечных точки могли надёжно определить, были ли обработаны переданные прежде кадры и аккуратно завершить и прервать оставшиеся задачи.

9.1.1. Повторное использование соединения

Соединения, организованные с сервером-источником напрямую или через туннель с использованием метода CONNECT (параграф 8.5), можно повторно использовать для запросов с разными компонентами authority в URI. Соединение можно использовать до тех пор, пока сервер остаётся полномочным (параграф 10.1). Для соединений TCP без TLS это зависит от распознавания имени хоста с одним и тем же адресом IP.

Для ресурсов https повторное использование соединения зависит от пригодности сертификата для хоста в URI. Предоставленный сервером сертификат должен удовлетворять всем проверкам, которые клиент выполняет для организации соединения TLS с хостом из URI. Один сертификат может служить для подтверждения полномочности нескольких источников. В параграфе 4.3 [HTTP] описано, как клиент проверяет полномочия сервера для URI.

В некоторых случаях повторное использование соединения для разных источников может приводить к передаче запросов не тому серверу-источнику. Например, завершение TLS может происходить на промежуточном устройстве, использующем расширение TLS SNI [TLS-EXT] для выбора сервера-источника. Это означает, что клиенты могут отправлять запросы серверам, которые могут не быть целью запроса, оставаясь в остальном полномочными.

Сервер, не желающий, чтобы клиенты повторно использовали соединение, может указать, что он не уполномочен для запроса, передав код статуса 421 (Misdirected Request) в отклике (см. параграф 15.5.20 в [HTTP]).

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

9.2. Использование свойств TLS

Реализации HTTP/2 должны использовать TLS версии 1.2 [TLS12] или выше при работе HTTP/2 через TLS. Следует выполнять общие рекомендации по использованию TLS [TLSBCP] с дополнительными ограничениями, связанными с HTTP/2. Реализация TLS должна поддерживать расширение TLS SNI [TLS-EXT]. Если сервер указан доменным именем [DNS-TERMS], клиенты должны передавать расширение TLS server_name, если не применяется иной механизм указания целевого хоста.

Требования к развёртываниям HTTP/2, согласующим TLS 1.3 [TLS13], включены в параграф 9.2.3, а системы TLS 1.2 подчиняются требованиям параграфов 9.2.1 и 9.2.2. Реализациям рекомендуется представлять принятые по умолчанию значения, соответствующие этим требованиям, но в конечном итоге за соответствие отвечает само развёртывание.

9.2.1. Свойства TLS 1.2

У этом параграфе указаны ограничения для набора функций TLS 1.2, которые можно использовать с HTTP/2. Из-за ограничений развёртывания может оказаться невозможным отказ при согласовании TLS, когда эти ограничения не соблюдаются. Конечная точка может незамедлительно разорвать соединение HTTP/2, где не выполняются указанные здесь ограничения для TLS, передав ошибку соединения (параграф 5.4.1) типа INADEQUATE_SECURITY.

При развёртывании HTTP/2 через TLS 1.2 сжатие должно быть отключено, поскольку оно может приводить к раскрытию сведений, которые без этого остались бы скрытыми [RFC3749]. Базовое сжатие не требуется, поскольку в HTTP/2 имеются средства сжатия, лучше учитывающие контекст и поэтому более подходящие в плане производительности, безопасности и других аспектов.

При развёртывании HTTP/2 через TLS 1.2 должно быть отключено повторное согласование и конечная точка ACK должна считать его ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR. Отметим, что запрет повторного согласования может приводить к непригодности долгосрочных соединений из-за ограничений на число сообщений, которые разрешено обрабатывать базовому шифру.

Конечная точка может использовать повторное согласование для защиты конфиденциальности свидетельств клиента, предоставляемых при согласовании, но любое повторное согласование должно выполняться до отправки предисловия к соединению. Серверу следует запрашивать сертификат клиента, если он видит запрос на повторное согласование сразу после организации соединения. Это препятствует использованию повторного согласования в отклике на запрос к конкретному защищённому ресурсу. Будущие спецификации могут обеспечить поддержку для таких случаев. Кроме того, сервер может передать ошибку (параграф 5.4) типа HTTP_1_1_REQUIRED для запроса, где клиент применяет протокол, поддерживающий повторное согласование.

Реализации должны поддерживать обмен эфемерными ключами размером не менее 2048 битов для шифров, использующих эфемерное конечное поле Diffie-Hellman (DHE) (параграф 8.1.2 и [TLS12]), и 224 битов для шифров, использующих эфемерную эллиптическую кривую Diffie-Hellman (ECDHE) [RFC8422]. Клиенты должны воспринимать DHE размером до 4096 битов. Конечные точки могут считать согласование ключей размером меньше нижнего предела ошибкой соединения (параграф 5.4.1) типа INADEQUATE_SECURITY.

9.2.2. Шифры TLS 1.2

При развёртывании HTTP/2 через TLS 1.2 не следует применять какой-либо из шифров, указанных в Приложении A. Конечная точка может возвращать ошибку соединения (параграф 5.4.1) типа INADEQUATE_SECURITY при согласовании любого из запрещённых шифров. Системы, выбравшие запрещённый шифр, рискуют столкнуться с ошибкой соединения, если нет уверенности, что партнёр поддерживает этот шифр. Реализациям недопустимо возвращать такую ошибку в ответ на согласование незапрещенного шифра. Поэтому клиенты, предлагающие незапретные шифры, должны быть готовы к использованию этих шифров с HTTP/2.

Список запрещённых шифров включает обязательные для TLS 1.2 шифры, что означает возможность наличия в системах TLS 1.2 непересекающихся наборов разрешённых шифров. Для предотвращения вызываемых этим отказов при согласовании TLS в системах HTTP/2, использующих TLS 1.2, должен поддерживаться шифр TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE] с эллиптической кривой P-256 [RFC8422].

Отметим, что клиенты могут анонсировать поддержку запретных шифров для соединения с серверами, не поддерживающими HTTP/2. Это позволяет серверу выбрать HTTP/1.1 с запрещённым для HTTP/2 шифром, но может приводить к согласованию запрещённого шифра для HTTP/2 при независимом выборе прикладного протокола и шифра.

9.2.3. Свойства TLS 1.3

TLS 1.3 включает много свойств, не доступных в прежних версиях. Использование таких свойств рассматривается здесь.

Серверам HTTP/2 недопустимо передавать сообщения TLS 1.3 CertificateRequest после согласования. Клиенты HTTP/2 должны считать такое сообщение ошибкой соединения (параграф 5.4.1) типа PROTOCOL_ERROR.

Запрет аутентификации после согласования может анонсироваться даже после расширения TLS post_handshake_auth, а поддержка такой аутентификации может анонсироваться независимо от ALPN [TLS-ALPN]. Клиенты могут предлагать возможность применения других протоколов, но включение расширения не может означать его поддержку в HTTP/2.

В [TLS13] имеются другие сообщения после согласования — NewSessionTicket и KeyUpdate, которые можно использовать, поскольку они напрямую не взаимодействуют с HTTP/2. Если использование нового типа сообщений TLS не зависит от взаимодействия с протоколом прикладного уровня, такое сообщение TLS можно передавать после согласования.

Можно использовать ранние данные TLS для отправки запроса при соблюдении рекомендаций [RFC8470]. Клиенты передают такие запросы в предположении использования исходных значений для всех настроек сервера.

10. Вопросы безопасности

Применение TLS необходимо для обеспечения многих свойств безопасности этого протокола. Многие утверждения этого раздела утрачивают силу, если не применяется TLS в соответствии с параграфом 9.2.

10.1. Полномочия сервера

HTTP/2 полагается на определение полномочий в HTTP для решения вопроса о полномочиях сервера для предоставления данного отклика (см. параграф 4.3 в [HTTP]). Это опирается на локальное распознавание имён для схемы URI http и аутентифицированную идентификацию сервера для схемы https.

10.2. Кросс-протокольные атаки

При кросс-протокольной атаке злоумышленник заставляет клиента инициировать транзакцию с сервером по протоколу, отличному от понимаемого сервером. Злоумышленник может сделать транзакцию воспринимаемой как действительная для второго протокола. В сочетании с возможностями web-контекста это может служить для взаимодействия со слабо защищёнными серверами в частных сетях.

Завершение согласования TLS идентификатором ALPN для HTTP/2 может считаться достаточной защитой от кросс-протокольных атак. ALPN обеспечивает положительную индикацию готовности сервера работать с HTTP/2, что предотвращает атаки на другие протоколы, основанные на TLS.

Шифрование TLS затрудняет атакующим контроль над данными, который может применяться в кросс-протокольных атаках на протокол с открытым текстом. У открытого (cleartext) варианта HTTP/2 имеется лишь минимальная защита от кросс-протокольных атак. Предисловие к соединению (параграф 3.4) содержит строку, призванную запутать серверы HTTP/1.1, но для других протоколов не предусмотрено какой-либо специальной защиты.

10.3. Атаки на промежуточную инкапсуляцию

HPACK позволяет кодировать имена и значения полей, которые в других версиях HTTP могут считаться разделителями. Посредник, транслирующий запрос или отклик HTTP/2, должен проверять поля в соответствии с правилами параграфа 8.2 до преобразования сообщения в другую версию HTTP. Трансляция поля с непригодными разделителями может использована для ошибочной интерпретации сообщений получателями, которой может воспользоваться атакующий. В параграфе 8.2 не задано специальных правил для проверки полей псевдозаголовков. При использовании значений таких полей нужна дополнительная проверка. Это особенно важно при объединении полей :scheme, :authority и :path в одну строку URI [RFC3986]. Аналогичные проблемы могут возникать при объединении этого URI или просто :path с полем :method для создания строки запроса (раздел 3 в [HTTP/1.1]). Простая конкатенация не будет защищённой, если не проверяются полностью входные значения.

Посредник может по иным причинам отвергать поля с недействительными имена или значениями — в частности, поля, не соответствующие базовой грамматике HTTP ABNF из раздела 5 в [HTTP]. Посредники, не выполняющие проверки полей сверх минимума, требуемого параграфом 8.2, могут пересылать поля с непригодными именами и значениями.

Посредник, получивший какие-либо поля, которые требуют удаления до пересылки (см. параграф 7.6.1 в [HTTP]), должен удалить эти поля заголовка перед пересылкой сообщения. Кроме того, при пересылке сообщений с полыми Content-Length посредникам следует контролировать корректность формы сообщения (параграф 8.1.1). Это гарантирует корректность кадрирования при трансляции сообщений в HTTP/1.1.

10.4. Кэшируемость выталкиваемых откликов

Для вытолкнутых откликов нет явного запроса от клиента, такой запрос представляет сервер в кадре PUSH_PROMISE.

Кэширование выталкиваемых откликов возможно на основе рекомендаций, предоставленных сервером-источником в поле заголовка Cache-Control. Однако это может вызывать проблемы при наличии на сервер более одного арендатора. Например, может предоставлять каждому из пользователей небольшую часть пространства URI. При совместном использовании пространства на сервере несколькими арендаторами этот сервер должен предотвратить возможность арендаторам выталкивать представления ресурсов, для которых у них нет полномочий. Отказ от этого позволит арендатору выдать представление, которое будет обслуживаться из кэша, переопределяя актуальное представление от полномочного арендатора.

Вытолкнутые отклики, для которых сервер-источник не является полномочным (параграф 10.1), недопустимо использовать для кэширования.

10.5. DoS-атаки

Для работы соединения HTTP/2 может потребоваться больше ресурсов, чем для соединения HTTP/1.1. Сжатие раздела полей и управление потоком данных зависят от большого числа состояний. Настройки этих функций обеспечивают строгое ограничение выделяемой для них памяти.

Число кадров PUSH_PROMISE не ограничивается таким же способом. Клиенту, воспринимающему выталкивание с сервера, следует ограничивать число потоков, которые он разрешает держать в состоянии reserved (remote). Подтверждение чрезмерного числа push-потоков от сервера может считаться ошибкой потока (параграф 5.4.2) типа ENHANCE_YOUR_CALM.

В ряде реализаций HTTP/2 обнаружена уязвимость к DoS-атакам [NFLX-2019-002] и ниже приведён список известных способов, которыми реализации могут быть атакованы.

  • Неэффективное отслеживание остающихся исходящих кадров может вызывать перегрузку, если атакующий может вызвать постановку с очередь передачи большого числа кадров. Партнёр может воспользоваться несколькими методами для генерации большого числа кадров:

    • предоставление очень мелких приращений для управления потоком данных в кадрах WINDOW_UPDATE, способное заставить отправителя генерировать большое число кадров DATA;

    • требование наличия конечной точки для ответа на кадры PING;

    • требование подтверждать каждый кадр SETTINGS;

    • недействительный запрос (или выталкивание с сервера), способный вызвать передачу кадров RST_STREAM.

  • Атакующий может предоставить большой объем кредитов управления потоком данных на уровне HTTP/2, не предоставляя их на уровне TCP, что будет препятствовать передаче кадров. Конечная точка, создающая и запоминающая кадры для отправки без учёта ограничений TCP, может столкнуться с нехваткой ресурсов.

  • Можно использовать большое число мелких или пустых кадров, чтобы вынудить партнёра затратить время на обработку их заголовков. Здесь нужна осторожность, поскольку некоторые варианты применения мелких кадров полностью легитимны (например, обработка пустого кадра DATA или CONTINUATION в конце потока).

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

  • Обработка изменения приоритетов с помощью кадров PRIORITY может потребовать значительного времени и приводить к перегрузке, если передаётся много кадров PRIORITY.

  • Сжатие раздела полей предоставляет атакующему возможность расхода ресурсов на обработку. Возможные злоупотребления рассмотрены в разделе 7 [COMPRESSION].

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

Большинство свойств, которые могут быть использованы для DoS-атак (например, изменения SETTINGS, мелкие кадры, сжатие полей) имеют легитимное применение. Эти свойства становятся обременительными лишь при неоправданном или избыточном их применении. Конечная точка, не отслеживающая использование таких свойств, подвергается риску DoS-атак. реализациям следует контролировать использование таких свойств и устанавливать пределы использования. Конечная точка может считать подозрительную активность ошибкой соединения (параграф 5.4.1) типа ENHANCE_YOUR_CALM.

10.5.1. Предельный размер блока полей

Большой блок полей (параграф 4.3) может вынудить реализацию зафиксировать большой объем состояния. Важные для маршрутизации строки полей могут размещаться в конце блока, что будет мешать передаче потока полей конечному адресату. Такое упорядочивание и другие причины, например, обеспечение корректности кэша, означают, что конечной точке может потребоваться целиком буферизовать блок полей. Поскольку размер блока полей жёстко не ограничен, некоторым конечным точкам может потребоваться большой объём памяти для блока полей.

Конечная точка может использовать SETTINGS_MAX_HEADER_LIST_SIZE для информирования своих партнёров о возможных ограничениях размера несжатого блока полей. Эта настройка является лишь рекомендацией, поэтому конечные точки могут передавать блок полей, размер которого превышает этот предел, рискуя тем, что запрос или отклик будет сочтён некорректно сформированным. Этот параметр относится к соединению и любой запрос или отклик может столкнуться в пути с более низким и неизвестным ограничением. Посредник может попытаться избежать этой проблемы, передавая значения, представленные разными партнёрами, но не обязан делать этого.

Сервер, получивший блок полей, размер которого превышает тот, который сервер готов обработать, может передать код статуса HTTP 431 (Request Header Fields Too Large) [RFC6585]. Клиент может отбрасывать отклики, которые он не может обработать. Блок полей должен быть обработан для обеспечения согласованного (consistent) состояния соединения, если только соединение не закрыто.

10.5.2. Проблемы CONNECT

Метод CONNECT можно использовать для создания непропорциональной нагрузки на прокси, поскольку создание потока относительно недорого по сравнению с созданием и поддержкой соединения TCP. Прокси может также поддерживать некоторые ресурсы для соединения TCP после закрытия потока, в котором передан запрос CONNECT, поскольку исходящее соединение TCP остаётся в состоянии TIME_WAIT. Поэтому прокси не может полагаться только на SETTINGS_MAX_CONCURRENT_STREAMS для ограничения ресурсов, потребляемых запросами CONNECT.

10.6. Использование сжатия

Сжатие может позволить атакующему восстановить секретные данные, если они сжаты в одном контексте с данными, контролируемыми злоумышленником. HTTP/2 разрешает сжатие строк полей (параграф 4.3), а приведённые ниже соображения относятся также к использованию в HTTP кодирования содержимого со сжатием(параграф 8.4.1 в [HTTP]).

Существуют наглядные атаки на сжатие, использующие свойства Web (например, [BREACH]). Атакующий создаёт множество запросов с различными открытыми данными (plaintext), наблюдая для каждого размер полученного шифротекста (ciphertext), который будет более коротким при угаданном секрете.

Реализациям, обменивающимся данными по защищённому каналу, недопустимо сжимать содержимое, включающее как конфиденциальные, так и контролируемые злоумышленником данные, если только для каждого источника данных не применяются свои словари. Недопустимо сжимать данные, если их источник невозможно определить достоверно. Базовое сжатие потоков, такое как предоставляемое TLS, недопустимо использовать с HTTP/2 (см. параграф 9.2).

Дополнительные соображения безопасности применительно к сжатию полей представлены в [COMPRESSION].

10.7. Использование заполнения

Заполнение в HTTP/2 не предназначено для замены заполнения общего назначения, вроде предоставляемого TLS [TLS13]. Избыточное заполнение может быть даже вредным (counterproductive). Корректность применения может зависть от наличия конкретных сведений о данных для дополнения.

Для смягчения атак, основанных на сжатии, запрет компрессии может оказаться полезней, чем заполнение.

Заполнение может служить для сокрытия точного размера содержимого кадра и предназначено для смягчения определённых атак в HTTP, например, атак, где сжатое содержимое включает контролируемый злоумышленником открытый текст и секретные данные (например, [BREACH]).

Использование заполнения может предоставлять более слабую защиту, чем кажется на первый взгляд. В лучшем случае заполнение лишь усложняет для атакующего получение сведений о размере за счёт увеличения числа кадров, которые тому приходится наблюдать. Некорректно реализованные схемы заполнения легко преодолеваются. В частности, случайное заполнение с предсказуемым распределением обеспечивает лишь очень слабую защиту, а заполнение до определённого размера раскрывает сведения о размере, когда кадр превосходит заданный предел, что может быть полезно для злоумышленника, контролирующего открытый ьекст.

Посредникам следует сохранять заполнение в кадрах DATA, но они могут исключать его из кадров HEADERS и PUSH_PROMISE. Уважительной причиной изменения размера заполнения посредником является повышение уровня защиты, обеспечиваемой заполнением.

10.8. Вопросы приватности

Некоторые особенности HTTP/2 дают наблюдателю возможность состатвить временную картину действий клиента или сервера. Это включает значения настроек, манеру поддержки окна управления потоком данных, способ распределения приоритетов между потоками, время реации на воздействия и работу функций, управляемых настройками. По мере возникновения наблюдаемых различий в поведении эти свойства могут стать основой для «отпечатка» конкретного клиента, как указано в параграфе 3.2 [PRIVACY].

Предпочтение HTTP/2 использовать одно соединение TCP позволяет отслеживать активность пользователя на сайте. Повторное использование соединений для других источников позволяет отслеживать эти источники.

Поскольку кадры PING и SETTINGS запрашивают незамедлительные отклики, любая конечная точка может применять их для измерения задержки между собой и партнёром, что может в некоторых случаях влиять на приватность.

10.9. Удалённые атаки по времени

Удалённые атаки по времени извлекают секреты серверов путём наблюдения за вариациями времени обработки запросов, включающих использование секретов. HTTP/2 позволяет одновременно создавать и обрабатывать запросы, что может дать злоумышленнику возможность точнее контролировать время начала обработки запроса. Несколько запросов HTTP/2 могут быть включены в один пакет IP или запись TLS, поэтому HTTP/2 может снизить эффективность удалённых атак по времени, устраняя вариативность доставки запросов и оставляя лишь их порядок и доставку откликов в качестве источника сведений об изменчивости.

Независимость времени обработки от значения секрета является лучшей формой защиты от атак по времени.

11. Взаимодействие с IANA

В этой редакции HTTP/2 поле заголовка HTTP2-Settings и маркер обновления h2c из [RFC7540] признаны устаревшими.

Раздел 11 [RFC7540] регистрирует идентификаторы ALPN h2 и h2c вместе с методом HTTP PRI. В RFC 7540 также организован реестр для типов кадров, параметров и кодов ошибок. Эти регистрации и реестры применяются к HTTP/2, но не переопределяются этим документом.

Агентство IANA обновило ссылки на RFC 7540 указанием на этот документ в реестрах TLS Application-Layer Protocol Negotiation (ALPN) Protocol IDs, HTTP/2 Frame Type, HTTP/2 Settings, HTTP/2 Error Code, HTTP Method Registry. Регистрация метода PRI обновлена со ссылкой на параграф 3.4, остальные номера параграфов не изменились.

Агентство IANA изменило правила для тех частей HTTP/2 Frame Type и HTTP/2 Settings, которые были зарезервированы в RFC 7540 для экспериментов (Experimental Use), и сейчас для них применяется та же процедура, что м для остальной части каждого реестра.

11.1. Регистрация поля заголовка HTTP2-Settings

В этом параграфе признано устаревшим поле заголовка HTTP2-Settings, зарегистрированное параграфом 11.5 [RFC7540] в реестре Hypertext Transfer Protocol (HTTP) Field Name Registry. Это свойство может быть удалено (см. параграф 3.1). регистрация обновлена для включения деталей, требуемых параграфом 18.4 в [HTTP]:

   Field Name:  HTTP2-Settings
   Status:  obsoleted
   Reference:  параграф 3.2.1 в [RFC7540]
   Comments:  Устарело, см. параграф 11.1 в этом документе.

11.2. Маркер обновления h2c

В этом параграфе признан устаревшим маркер обновления h2c, включенный параграфом 11.8 [RFC7540] в реестр Hypertext Transfer Protocol (HTTP) Upgrade Token Registry. Это свойство может быть удалено (см. параграф 3.1). Обновление регистрации приведено ниже.

Value:  h2c
Description:  (OBSOLETE) Hypertext Transfer Protocol version 2 (HTTP/2)
Expected Version Tokens:  None
Reference:  Section 3.1 of this document

12. Литература

12.1. Нормативные документы

[CACHING] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «HTTP Caching», STD 98, RFC 9111, DOI 10.17487/RFC9111, June 2022, <https://www.rfc-editor.org/info/rfc9111>.

[COMPRESSION] Peon, R. and H. Ruellan, «HPACK: Header Compression for HTTP/2», RFC 7541, DOI 10.17487/RFC7541, May 2015, <https://www.rfc-editor.org/info/rfc7541>.

[COOKIE] Barth, A., «HTTP State Management Mechanism», RFC 6265, DOI 10.17487/RFC6265, April 2011, <https://www.rfc-editor.org/info/rfc6265>.

[HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «HTTP Semantics», STD 97, RFC 9110, DOI 10.17487/RFC9110, June 2022, <https://www.rfc-editor.org/info/rfc9110>.

[QUIC] Iyengar, J., Ed. and M. Thomson, Ed., «QUIC: A UDP-Based Multiplexed and Secure Transport», RFC 9000, DOI 10.17487/RFC9000, May 2021, <https://www.rfc-editor.org/info/rfc9000>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, «Uniform Resource Identifier (URI): Generic Syntax», STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, <https://www.rfc-editor.org/info/rfc3986>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8422] Nir, Y., Josefsson, S., and M. Pegourie-Gonnard, «Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS) Versions 1.2 and Earlier», RFC 8422, DOI 10.17487/RFC8422, August 2018, <https://www.rfc-editor.org/info/rfc8422>.

[RFC8470] Thomson, M., Nottingham, M., and W. Tarreau, «Using Early Data in HTTP», RFC 8470, DOI 10.17487/RFC8470, September 2018, <https://www.rfc-editor.org/info/rfc8470>.

[TCP] Postel, J., «Transmission Control Protocol», STD 7, RFC 793, DOI 10.17487/RFC0793, September 1981, <https://www.rfc-editor.org/info/rfc793>.

[TLS-ALPN] Friedl, S., Popov, A., Langley, A., and E. Stephan, «Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension», RFC 7301, DOI 10.17487/RFC7301, July 2014, <https://www.rfc-editor.org/info/rfc7301>.

[TLS-ECDHE] Rescorla, E., «TLS Elliptic Curve Cipher Suites with SHA-256/384 and AES Galois Counter Mode (GCM)», RFC 5289, DOI 10.17487/RFC5289, August 2008, <https://www.rfc-editor.org/info/rfc5289>.

[TLS-EXT] Eastlake 3rd, D., «Transport Layer Security (TLS) Extensions: Extension Definitions», RFC 6066, DOI 10.17487/RFC6066, January 2011, <https://www.rfc-editor.org/info/rfc6066>.

[TLS12] Dierks, T. and E. Rescorla, «The Transport Layer Security (TLS) Protocol Version 1.2», RFC 5246, DOI 10.17487/RFC5246, August 2008, <https://www.rfc-editor.org/info/rfc5246>.

[TLS13] Rescorla, E., «The Transport Layer Security (TLS) Protocol Version 1.3», RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.

[TLSBCP] Sheffer, Y., Holz, R., and P. Saint-Andre, «Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)», BCP 195, RFC 7525, DOI 10.17487/RFC7525, May 2015, <https://www.rfc-editor.org/info/rfc7525>.

12.2. Дополнительная литература

[ALT-SVC] Nottingham, M., McManus, P., and J. Reschke, «HTTP Alternative Services», RFC 7838, DOI 10.17487/RFC7838, April 2016, <https://www.rfc-editor.org/info/rfc7838>.

[BREACH] Gluck, Y., Harris, N., and A. Prado, «BREACH: Reviving the CRIME Attack», 12 July 2013, <https://breachattack.com/resources/BREACH%20-%20SSL,%20gone%20in%2030%20seconds.pdf>.

[DNS-TERMS] Hoffman, P., Sullivan, A., and K. Fujiwara, «DNS Terminology», BCP 219, RFC 8499, DOI 10.17487/RFC8499, January 2019, <https://www.rfc-editor.org/info/rfc8499>.

[HTTP-PRIORITY] Oku, K. and L. Pardue, «Extensible Prioritization Scheme for HTTP», RFC 9218, DOI 10.17487/RFC9218, June 2022, <https://www.rfc-editor.org/info/rfc9218>.

[HTTP/1.1] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «HTTP/1.1», STD 99, RFC 9112, DOI 10.17487/RFC9112, June 2022, <https://www.rfc-editor.org/info/rfc9112>.

[NFLX-2019-002] Netflix, «HTTP/2 Denial of Service Advisory», 13 August 2019, <https://github.com/Netflix/security-bulletins/blob/master/advisories/third-party/2019-002.md>.

[PRIVACY] Cooper, A., Tschofenig, H., Aboba, B., Peterson, J., Morris, J., Hansen, M., and R. Smith, «Privacy Considerations for Internet Protocols», RFC 6973, DOI 10.17487/RFC6973, July 2013, <https://www.rfc-editor.org/info/rfc6973>.

[RFC1122] Braden, R., Ed., «Requirements for Internet Hosts — Communication Layers», STD 3, RFC 1122, DOI 10.17487/RFC1122, October 1989, <https://www.rfc-editor.org/info/rfc1122>.

[RFC3749] Hollenbeck, S., «Transport Layer Security Protocol Compression Methods», RFC 3749, DOI 10.17487/RFC3749, May 2004, <https://www.rfc-editor.org/info/rfc3749>.

[RFC6125] Saint-Andre, P. and J. Hodges, «Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS)», RFC 6125, DOI 10.17487/RFC6125, March 2011, <https://www.rfc-editor.org/info/rfc6125>.

[RFC6585] Nottingham, M. and R. Fielding, «Additional HTTP Status Codes», RFC 6585, DOI 10.17487/RFC6585, April 2012, <https://www.rfc-editor.org/info/rfc6585>.

[RFC7323] Borman, D., Braden, B., Jacobson, V., and R. Scheffenegger, Ed., «TCP Extensions for High Performance», RFC 7323, DOI 10.17487/RFC7323, September 2014, <https://www.rfc-editor.org/info/rfc7323>.

[RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., «Hypertext Transfer Protocol Version 2 (HTTP/2)», RFC 7540, DOI 10.17487/RFC7540, May 2015, <https://www.rfc-editor.org/info/rfc7540>.

[RFC8441] McManus, P., «Bootstrapping WebSockets with HTTP/2», RFC 8441, DOI 10.17487/RFC8441, September 2018, <https://www.rfc-editor.org/info/rfc8441>.

[RFC8740] Benjamin, D., «Using TLS 1.3 with HTTP/2», RFC 8740, DOI 10.17487/RFC8740, February 2020, <https://www.rfc-editor.org/info/rfc8740>.

[TALKING] Huang, L., Chen, E., Barth, A., Rescorla, E., and C. Jackson, «Talking to Yourself for Fun and Profit», 2011, <https://www.adambarth.com/papers/2011/huang-chen-barth-rescorla-jackson.pdf>.

Приложение A. Запрещённые шифры TLS 1.2

Реализация HTTP/2 может считать согласование любого из приведённых ниже шифров для TLS 1.2 ошибкой соединения (параграф 5.4.1) типа INADEQUATE_SECURITY.

    TLS_NULL_WITH_NULL_NULL
    TLS_RSA_WITH_NULL_MD5
    TLS_RSA_WITH_NULL_SHA
    TLS_RSA_EXPORT_WITH_RC4_40_MD5
    TLS_RSA_WITH_RC4_128_MD5
    TLS_RSA_WITH_RC4_128_SHA
    TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
    TLS_RSA_WITH_IDEA_CBC_SHA
    TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
    TLS_RSA_WITH_DES_CBC_SHA
    TLS_RSA_WITH_3DES_EDE_CBC_SHA
    TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
    TLS_DH_DSS_WITH_DES_CBC_SHA
    TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA
    TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
    TLS_DH_RSA_WITH_DES_CBC_SHA
    TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA
    TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
    TLS_DHE_DSS_WITH_DES_CBC_SHA
    TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
    TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
    TLS_DHE_RSA_WITH_DES_CBC_SHA
    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
    TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
    TLS_DH_anon_WITH_RC4_128_MD5
    TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA
    TLS_DH_anon_WITH_DES_CBC_SHA
    TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
    TLS_KRB5_WITH_DES_CBC_SHA
    TLS_KRB5_WITH_3DES_EDE_CBC_SHA
    TLS_KRB5_WITH_RC4_128_SHA
    TLS_KRB5_WITH_IDEA_CBC_SHA
    TLS_KRB5_WITH_DES_CBC_MD5
    TLS_KRB5_WITH_3DES_EDE_CBC_MD5
    TLS_KRB5_WITH_RC4_128_MD5
    TLS_KRB5_WITH_IDEA_CBC_MD5
    TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA
    TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA
    TLS_KRB5_EXPORT_WITH_RC4_40_SHA
    TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5
    TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5
    TLS_KRB5_EXPORT_WITH_RC4_40_MD5
    TLS_PSK_WITH_NULL_SHA
    TLS_DHE_PSK_WITH_NULL_SHA
    TLS_RSA_PSK_WITH_NULL_SHA
    TLS_RSA_WITH_AES_128_CBC_SHA
    TLS_DH_DSS_WITH_AES_128_CBC_SHA
    TLS_DH_RSA_WITH_AES_128_CBC_SHA
    TLS_DHE_DSS_WITH_AES_128_CBC_SHA
    TLS_DHE_RSA_WITH_AES_128_CBC_SHA
    TLS_DH_anon_WITH_AES_128_CBC_SHA
    TLS_RSA_WITH_AES_256_CBC_SHA
    TLS_DH_DSS_WITH_AES_256_CBC_SHA
    TLS_DH_RSA_WITH_AES_256_CBC_SHA
    TLS_DHE_DSS_WITH_AES_256_CBC_SHA
    TLS_DHE_RSA_WITH_AES_256_CBC_SHA
    TLS_DH_anon_WITH_AES_256_CBC_SHA
    TLS_RSA_WITH_NULL_SHA256
    TLS_RSA_WITH_AES_128_CBC_SHA256
    TLS_RSA_WITH_AES_256_CBC_SHA256
    TLS_DH_DSS_WITH_AES_128_CBC_SHA256
    TLS_DH_RSA_WITH_AES_128_CBC_SHA256
    TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
    TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA
    TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA
    TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA
    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
    TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA
    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
    TLS_DH_DSS_WITH_AES_256_CBC_SHA256
    TLS_DH_RSA_WITH_AES_256_CBC_SHA256
    TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
    TLS_DH_anon_WITH_AES_128_CBC_SHA256
    TLS_DH_anon_WITH_AES_256_CBC_SHA256
    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
    TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA
    TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA
    TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA
    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
    TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA
    TLS_PSK_WITH_RC4_128_SHA
    TLS_PSK_WITH_3DES_EDE_CBC_SHA
    TLS_PSK_WITH_AES_128_CBC_SHA
    TLS_PSK_WITH_AES_256_CBC_SHA
    TLS_DHE_PSK_WITH_RC4_128_SHA
    TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
    TLS_DHE_PSK_WITH_AES_128_CBC_SHA
    TLS_DHE_PSK_WITH_AES_256_CBC_SHA
    TLS_RSA_PSK_WITH_RC4_128_SHA
    TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
    TLS_RSA_PSK_WITH_AES_128_CBC_SHA
    TLS_RSA_PSK_WITH_AES_256_CBC_SHA
    TLS_RSA_WITH_SEED_CBC_SHA
    TLS_DH_DSS_WITH_SEED_CBC_SHA
    TLS_DH_RSA_WITH_SEED_CBC_SHA
    TLS_DHE_DSS_WITH_SEED_CBC_SHA
    TLS_DHE_RSA_WITH_SEED_CBC_SHA
    TLS_DH_anon_WITH_SEED_CBC_SHA
    TLS_RSA_WITH_AES_128_GCM_SHA256
    TLS_RSA_WITH_AES_256_GCM_SHA384
    TLS_DH_RSA_WITH_AES_128_GCM_SHA256
    TLS_DH_RSA_WITH_AES_256_GCM_SHA384
    TLS_DH_DSS_WITH_AES_128_GCM_SHA256
    TLS_DH_DSS_WITH_AES_256_GCM_SHA384
    TLS_DH_anon_WITH_AES_128_GCM_SHA256
    TLS_DH_anon_WITH_AES_256_GCM_SHA384
    TLS_PSK_WITH_AES_128_GCM_SHA256
    TLS_PSK_WITH_AES_256_GCM_SHA384
    TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
    TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
    TLS_PSK_WITH_AES_128_CBC_SHA256
    TLS_PSK_WITH_AES_256_CBC_SHA384
    TLS_PSK_WITH_NULL_SHA256
    TLS_PSK_WITH_NULL_SHA384
    TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
    TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
    TLS_DHE_PSK_WITH_NULL_SHA256
    TLS_DHE_PSK_WITH_NULL_SHA384
    TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
    TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
    TLS_RSA_PSK_WITH_NULL_SHA256
    TLS_RSA_PSK_WITH_NULL_SHA384
    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
    TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256
    TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256
    TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256
    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
    TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256
    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
    TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256
    TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256
    TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256
    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
    TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256
    TLS_EMPTY_RENEGOTIATION_INFO_SCSV
    TLS_ECDH_ECDSA_WITH_NULL_SHA
    TLS_ECDH_ECDSA_WITH_RC4_128_SHA
    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
    TLS_ECDHE_ECDSA_WITH_NULL_SHA
    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
    TLS_ECDH_RSA_WITH_NULL_SHA
    TLS_ECDH_RSA_WITH_RC4_128_SHA
    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
    TLS_ECDHE_RSA_WITH_NULL_SHA
    TLS_ECDHE_RSA_WITH_RC4_128_SHA
    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
    TLS_ECDH_anon_WITH_NULL_SHA
    TLS_ECDH_anon_WITH_RC4_128_SHA
    TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA
    TLS_ECDH_anon_WITH_AES_128_CBC_SHA
    TLS_ECDH_anon_WITH_AES_256_CBC_SHA
    TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA
    TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA
    TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA
    TLS_SRP_SHA_WITH_AES_128_CBC_SHA
    TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA
    TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA
    TLS_SRP_SHA_WITH_AES_256_CBC_SHA
    TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA
    TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA
    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
    TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
    TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
    TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
    TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
    TLS_ECDHE_PSK_WITH_RC4_128_SHA
    TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
    TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
    TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
    TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
    TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
    TLS_ECDHE_PSK_WITH_NULL_SHA
    TLS_ECDHE_PSK_WITH_NULL_SHA256
    TLS_ECDHE_PSK_WITH_NULL_SHA384
    TLS_RSA_WITH_ARIA_128_CBC_SHA256
    TLS_RSA_WITH_ARIA_256_CBC_SHA384
    TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256
    TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384
    TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256
    TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384
    TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256
    TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384
    TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256
    TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384
    TLS_DH_anon_WITH_ARIA_128_CBC_SHA256
    TLS_DH_anon_WITH_ARIA_256_CBC_SHA384
    TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256
    TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384
    TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256
    TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384
    TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256
    TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384
    TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256
    TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384
    TLS_RSA_WITH_ARIA_128_GCM_SHA256
    TLS_RSA_WITH_ARIA_256_GCM_SHA384
    TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256
    TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384
    TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256
    TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384
    TLS_DH_anon_WITH_ARIA_128_GCM_SHA256
    TLS_DH_anon_WITH_ARIA_256_GCM_SHA384
    TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256
    TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384
    TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256
    TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384
    TLS_PSK_WITH_ARIA_128_CBC_SHA256
    TLS_PSK_WITH_ARIA_256_CBC_SHA384
    TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256
    TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384
    TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256
    TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384
    TLS_PSK_WITH_ARIA_128_GCM_SHA256
    TLS_PSK_WITH_ARIA_256_GCM_SHA384
    TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256
    TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384
    TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256
    TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384
    TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
    TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
    TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
    TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
    TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
    TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
    TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
    TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
    TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
    TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
    TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256
    TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384
    TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256
    TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384
    TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256
    TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384
    TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
    TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
    TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
    TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
    TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
    TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
    TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
    TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
    TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
    TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
    TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
    TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
    TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
    TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
    TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
    TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
    TLS_RSA_WITH_AES_128_CCM
    TLS_RSA_WITH_AES_256_CCM
    TLS_RSA_WITH_AES_128_CCM_8
    TLS_RSA_WITH_AES_256_CCM_8
    TLS_PSK_WITH_AES_128_CCM
    TLS_PSK_WITH_AES_256_CCM
    TLS_PSK_WITH_AES_128_CCM_8
    TLS_PSK_WITH_AES_256_CCM_8

Примечание. Список шифров составлен на основе набора зарегистрированных шифров TLS на момент разработки [RFC7540]. Список включает шифры, не предоставляющие обмен эфемерными ключами, а также шифры, основанные пустом (null), потоковом и блочном шифровании TLS (см. параграф 6.2.3 в [TLS12]). Могут быть заданы дополнительные шифры с такими свойствами, которые не будут запрещены явно.

Дополнительные сведения приведены в параграфе 9.2.2.

Приложение B. Отличия от RFC 7540

  • Использование TLS 1.3 было задано на основе [RFC8740], отменённого данным документом.

  • Схема приоритетов из RFC 7540 устарела. Сохранены определения формата кадра PRIORITY и полей приоритета в кадрах HEADERS, а также правила отправки и получения кадров PRIORITY, но семантика полей описана только в RFC 7540. Схема сигнализации приоритета из RFC 7540 оказалась неуспешной и рекомендуется более простая сигнализация [HTTP-PRIORITY].

  • Механизм HTTP/1.1 Upgrade устарел и исключён из этого документа. Он не был широко развернут, поскольку пользователи HTTP/2 с открытым текстом предпочитали реализацию предварительных сведений.

  • Сужена проверка имён и значений полей, с точным указанием, когда она обязательна для посредников, и изменены сообщения об ошибках в запросах с рекомендацией передавать коды статуса группы 400.

  • Диапазоны кодов установок и типов кадров, зарезервированные для экспериментов (Experimental Use) сделаны доступными для общего пользования.

  • Специфичные для соединения поля заголовка, которые были запрещены, указаны более точно и полно.

  • Значения Host и :authority больше не могут различаться (запрет).

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

Внесены также редакционные изменения. В частности, поменялась терминология и структура документа в результате изменения семантического ядра HTTP [HTTP]. Документы теперь включают некоторые концепции, заданные в RFC 7540, такие как код статуса 421 и слияние (coalescing) соединений.

Благодарности

Заслуги внесения нетривиального вклада в этот документ принадлежат большому числу людей, годами участвовавших в работе группы HTTP. В [RFC7540] приведён более полный список людей, заслуживающих признания за их вклад.

Участники работы

Mike Belshe и Roberto Peon создали текст, послуживший основой для этого документа.

Адреса авторов

Martin Thomson (editor)
Mozilla
Australia
Email: mt@lowentropy.net
 
Cory Benfield (editor)
Apple Inc.
Email: cbenfield@apple.com

Перевод на русский язык

nmalykh@protokols.ru


1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

3В оригинале ошибочно сказано STREAM, см. https://www.rfc-editor.org/errata/eid7013. Прим. перев.

Рубрика: RFC | Оставить комментарий

RFC 9112 HTTP/1.1

Internet Engineering Task Force (IETF)                  R. Fielding, Ed.
Request for Comments: 9112                                         Adobe
STD: 99                                               M. Nottingham, Ed.
Obsoletes: 7230                                                   Fastly
Category: Standards Track                                J. Reschke, Ed.
ISSN: 2070-1721                                               greenbytes
                                                               June 2022

HTTP/1.1

PDF

Аннотация

Протокол передачи гипертекста (Hypertext Transfer Protocol или HTTP) — это протокол прикладного уровня без поддержки состояний, предназначенный для распределенных систем групповой работы с гипертекстовой информацией. Этот документ задаёт синтаксис сообщений HTTP/1.1, разбор сообщений, управление соединениями и связанные с этим вопросы безопасности.

Этот документ отменяет некоторые части RFC 7230.

Статус документа

Документ относится к категории Internet Standards Track.

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG2. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке https://www.rfc-editor.org/info/rfc9112.

Авторские права

Copyright (c) 2022. Авторские права принадлежат IETF Trust и лицам, указанным в качестве авторов документа. Все права защищены.

К документу применимы права и ограничения, указанные в BCP 78 и IETF Trust Legal Provisions и относящиеся к документам IETF (http://trustee.ietf.org/license-info), на момент публикации данного документа. Прочтите упомянутые документы внимательно. Фрагменты программного кода, включённые в этот документ, распространяются в соответствии с упрощённой лицензией BSD, как указано в параграфе 4.e документа IETF Trust Legal Provisions, без каких-либо гарантий (как указано в Revised BSD License).

Этот документ может содержать материалы из документов IETF или участников IETF3, опубликованных или публично доступных до 10 ноября 2008 г. Лица, контролирующие авторские права на некоторые из таких материалов могли не предоставить IETF Trust прав на изменение таких материалов вне контекста стандартизации IETF4. Без получения соответствующей лицензии от лиц, контролирующих авторские права на такие материалы, этот документ не может быть изменён вне контекста стандартизации IETF, а также не могут открываться производные работы за пределами контекста стандартизации. Исключением является лишь форматирование документа для публикации в качестве RFC или перевод на другие языки.

1. Введение

HTTP — это протокол прикладного уровня «запрос-отклик» без поддержки состояний, использующий расширяемую семантику и самоописательные сообщения для гибкого взаимодействия с сетевыми гипертекстовыми информационными системами. HTTP/1.1 определён в:

  • этом документе;

  • HTTP Semantics [HTTP];

  • HTTP Caching [CACHING].

Этот документ описывает способы передачи семантики HTTP с применением синтаксиса сообщений HTTP/1.1, обрамление (framing) и механизмы управления соединениями. Цель состоит в задании полного набора требваний к синтаксическим анализаторам (parser) HTTP/1.1 и посредникам при пересылке сообщений.

Документ отменяет части RFC 7230, относящиеся к сообщениям HTTP/1.1 и управлению соединениями. Перечени отличий приведён в Приложении C.3. Остальные части RFC 7230 отменены документом HTTP Semantics [HTTP].

1.1. Уровни требований

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

Критерии соответствия и обработка ошибок рассмотрены в разделе 2 [HTTP].

1.2. Синтаксические обозначения

В этом документе применяется расширенная нотация Бэкуса-Наура (Augmented Backus-Naur Form или ABNF) [RFC5234] , дополненная обозначениями для строк с учётом регистра символов, определённых в [RFC7405]. Используется также расширение списков, определённое в параграфе 5.6.1 [HTTP], которое позволяет компактно определять списки, разделяемых запятыми элементов с использованием оператора # (подобно указанию повтора оператором *). В Приложении A приведена сводная грамматика со всеми расширениями операторов списка, добавленными в ABNF. По традиции имена правил ABNF с префиксом obs- обозначают устаревшие правила, указанные по историческим причинам.

Указанные далее базовые правила включены по ссылкам, как задано в Приложении B.1 к [RFC5234]: ALPHA (буквы), CR (возврат каретки), CRLF (CR LF), CTL (управление), DIGIT (десятичные цифры 0-9), DQUOTE (двойные кавычки), HEXDIG (шестнадцатеричные цифры 0-9/A-F/a-f), HTAB (горизонтальная табуляция), LF (перевод строки), OCTET (любая 8-битовая последовательность данных), SP (пробел), VCHAR (любой печатный символ US-ASCII).

Ниже указаны правила, заданные в [HTTP].

     BWS           = <BWS, см. [HTTP], параграф 5.6.3>
     OWS           = <OWS, см. [HTTP], параграф 5.6.3>
     RWS           = <RWS, см. [HTTP], параграф 5.6.3>
     absolute-path = <absolute-path, см. [HTTP], параграф 4.1>
     field-name    = <field-name, см. [HTTP], параграф 5.1>
     field-value   = <field-value, см. [HTTP], параграф 5.5>
     obs-text      = <obs-text, см. [HTTP], параграф 5.6.4>
     quoted-string = <quoted-string, см. [HTTP], параграф 5.6.4>
     token         = <token, см. [HTTP], параграф 5.6.2>
     transfer-coding = <transfer-coding, см. [HTTP], параграф 10.1.4>

Ниже указаны правила, заданные в [URI].

     absolute-URI  = <absolute-URI, см. [URI], параграф 4.3>
     authority     = <authority, см. [URI], параграф 3.2>
     uri-host      = <host, см. [URI], параграф 3.2.2>
     port          = <port, см. [URI], параграф 3.2.3>
     query         = <query, см. [URI], параграф 3.4>

2. Сообщение

Клиенты и серверы HTTP/1.1 взаимодействуют путём обмена сообщениями. Базовая терминология и основные концепции HTTP представлены в разделе 3 [HTTP].

2.1. Формат сообщения

Сообщение HTTP/1.1 состоит из стартовой строки (start-line), за которой следуют символы CRLF и последовательность октетов в формате, похожем на формат сообщений Internet (Internet Message Format) [RFC5322] — строки полей заголовков (необязательно), называемые далее просто заголовками или разделом заголовков, пустая строка, завершающая раздел заголовков и (необязательное) тело сообщения.

     HTTP-message   = start-line CRLF
                      *( field-line CRLF )
                      CRLF
                      [ message-body ]

Сообщение может быть запросом клиента к северу или откликом сервера. Синтаксически эти типы сообщения различаются лишь стартовой строкой (request-line для запросов, status-line для откликов) и алгоритмом определения размера тела сообщения (раздел 6).

     start-line     = request-line / status-line

Теоретически клиент может получать запросы, а сервер — отклики, различая их по формату start-line. На практике серверы ожидают только запросы (отклик считается запросом с недействительным методом), а клиенты — отклики.

В HTTP применяются некоторые элементы протокола, похожие на многоцелевые расширения электронной почты (Multipurpose Internet Mail Extension или MIME) [RFC2045]. Различия между HTTP и MIME рассмотрены в Приложении B.

2.2. Разбор сообщения

Обычная процедура разбора сообщения HTTP состоит из чтения start-line в структуру, чтения каждой строки полей заголовка в хэш-таблицу по именам полей до пустой строки и затем использование разобранных данных для определения наличия тела в сообщении. Если указано тело сообщения, оно считывается как поток, пока не будет получено число октетов, равное размеру тела, или сообщение не будет закрыто.

Получатель должен разбирать сообщение HTTP как последовательность октетов с кодировкой, являющейся надмножеством US-ASCII [USASCII]. Разбор сообщения HTTP как потока символов Unicode без учёта конкретной кодировки создаёт уязвимости защиты из-за различий в способах обработки строк библиотеками недействительных многобайтовых последовательностей, содержащих октет LF (%x0A). Строковые синтаксические анализаторы можно безопасно применять в элементах протокола только после извлечения элемента из сообщения, например, для поля заголовка после того, как разбор сообщения разделит строки полей.

Хотя завершением start-line и строк полей служит последовательность CRLF, получатель может считать символ LF завершением строки, игнорируя предшествующий символ CR. Отправителю недопустимо генерировать «голый» символ CR (CR без следующего сразу за ним LF) в элементах протокола, отличных от содержимого. Получатель такого голого CR должен считать элемент недействительным или заменять одиночный символ CR пробелом (SP) перед обработкой элемента или пересылкой сообщения.

Старые реализации пользовательских агентов HTTP/1.0 могут передавать лишние символы CRLF после запроса POST в качестве обхода для некоторых ранних серверных приложений, которые не могут читать содержимое тела сообщения без завершения строки в конце. Пользовательскому агенту HTTP/1.1 недопустимо добавлять лишние CRLF в начале или в конце запроса. Если желательно завершать тело сообщения символами завершения строки, агент пользователя должен учитывать завершающие октеты CRLF в размере тела сообщения.

Для отказоустойчивости серверу, ожидающему получения и разбора request-line, следует игнорировать по меньшей мере одну пустую строку (CRLF), полученную до request-line.

Отправителю недопустимо включать пробельные символы между start-line и первым полем заголовка. При получении пробелов между start-line и первым полем заголовка сообщение должно отбрасываться как недействительное или строки с пробелами в начале должны восприниматься без дальнейшей обработки (т. е. игнорироваться целиком и последующие строки с пробелами в начале, пока не будет получено корректное поле заголовка или не завершится раздел заголовков). Отклонение или исключение обработки недействительных строк с пробелами в начале нужно для предотвращения их ошибочной интерпретации нисходящими получателями, которые могут быть уязвимы для атак с контрабандой запросов (параграф 11.2) или расщеплением откликов (параграф 11.1).

Когда сервер, прослушивающий лишь запросные сообщения HTTP или обрабатывающий то, что представляется запросом по строке start-line, получает последовательность октетов, не соответствующую грамматике сообщений HTTP, за исключением указанных выше случаев, ему следует генерировать отклик с кодом 400 (Bad Request) и закрывать соединение.

2.3. Версия HTTP

В HTTP используется схема нумерации <major>.<minor> для указания версии протокола. Эта спецификация определяет версию 1.1. Семантика номеров версий HTTP описана в параграфе 2.5 [HTTP].

Версия сообщения HTTP/1.x указывается полем HTTP-version в строке start-line (регистр символов учитывается).

     HTTP-version  = HTTP-name "/" DIGIT "." DIGIT
     HTTP-name     = %s"HTTP"

При передаче сообщения HTTP/1.1 получателю HTTP/1.0 [HTTP/1.0] или получателю с неизвестной версией сообщение HTTP/1.1 строится так, чтобы его можно было интерпретировать как действительное сообщение HTTP/1.0, если игнорировать все более новые поля. Данная спецификация вносит требования к версии получателя для некоторых новых функций и соответствующий спецификации отправитель будет использовать только совместимые функции, пока не определит, что получатель поддерживает HTTP/1.1 (по конфигурации или принятому сообщению).

Посредники, обрабатывающие сообщения HTTP (все посредники, кроме выступающих в качестве туннелей), должны передавать своё значение HTTP-version в пересылаемых пакетах, если только версия не снижена намеренно для обхода проблем в восходящем направлении. Иными словами, посредникам не разрешается вслепую пересылать start-line, не убедившись, что версия протокола в данном сообщении соответствует версии, которую поддерживает посредник как при получении, так и при отправке сообщений. Пересылка сообщения HTTP без переписывания HTTP-version может приводить к коммуникационным ошибкам, если получатели в нисходящем направлении используют версию отправителя сообщения для определения функций, которые можно безопасно использовать для последующего взаимодействия с отправителем.

Отправитель может передавать отклик HTTP/1.0 на запрос HTTP/1.1, если он знает или предполагает, что клиент некорректно реализует спецификацию HTTP и не способен корректно обрабатывать отклики более поздних версий, например, клиент не может корректно разобрать номер версии или известно, что посредник вслепую пересылает HTTP-version даже при несоответствии данной младшей (minor) версии протокола. Такое понижение версии протокола не следует применять, пока оно не вызвано конкретными атрибутами клиента или поля заголовка запроса (например, User-Agent) не совпадают однозначно со значениями, переданные клиентом, об ошибках которого известно.

3. Строка запроса

Строка request-line начинается с маркера метода, за которым следует 1 пробел (SP), цель запроса (request-target), ещё 1 пробел и версия протокола.

     request-line   = method SP request-target SP HTTP-version

Хотя правила грамматики request-line требуют разделять элементы строки одиночным октетом SP, получатели могут выполнять разбор по границам слов, обозначенным пробельными символами, считая любую форму пробельных символов, кроме завершения строки CRLF, разделителем SP и игнорируя предшествующий или последующий пробельный символ. К пробельным символам относятся SP, HTAB, VT (%x0B), AH (%x0C), отдельный (bare) символ CR. Однако небрежный синтаксический анализ может приводить к уязвимостям защиты (контрабанда запросов), если имеется несколько получателей сообщения со своим уникальным пониманием отказоустойчивости (см. параграф 11.2).

HTTP не задаёт предопределённого ограничения на размер request-line, как указано в параграфе 2.3 [HTTP]. Серверу, получившему элемент method, размер которого превышает размер любого реализуемого им метода, следует отвечать кодом статуса 501 (Not Implemented). Сервер, получивший элемент request-target с размером больше размера URI, который он готов анализировать, должен отвечать кодом 414 (URI Too Long) (см. параграф 15.5.15 в [HTTP]).

На практике встречаются специальные ограничения на размер request-line. Всем отправителям и получателям HTTP рекомендуется поддерживать размер request-line хотя бы в 8000 октетов.

3.1. Метод

Маркер метода указывает метод запроса, применяемого к целевому ресурсу. Регистр символов не учитывается.

     method         = token

Методы запроса, определённые этой спецификацией, приведены в разделе 9 [HTTP], вместе со сведениями о реестре методов HTTP и регистрации новых методов.

3.2. Цель запроса

Элемент request-target указывает целевой ресурс для выполнения запроса. Клиент выводит request-target из URI желаемой цели. Применяется четыре различных формата request-target в зависимости от метода запроса и предназначенности для прокси.

     request-target = origin-form
                    / absolute-form
                    / authority-form
                    / asterisk-form

Пробельные символы в request-target не допускаются. К сожалению некоторые пользовательские агенты не могут корректно представить или исключить пробельные символы, имеющиеся в гипертекстовых ссылках, что ведёт к передаче запрещённых символов в request-target некорректно сформированной request-line. Получателям недействительной request-line следует отвечать кодом ошибки 400 (Bad Request) или кодом перенаправления 301 (Moved Permanently) с корректным кодированием request-target. Получателю не следует пытаться автоматически исправить строку и обработать запрос без перенаправления, поскольку недействительная строка request-line может быть создана намеренно для обхода фильтров защиты в цепочке запросов.

Клиент должен включать поле (параграф 7.2 в [HTTP]) во все запросные сообщения HTTP/1.1. Если URI цели включает компонент authority, клиент должен передать в поле Host значение, идентичное authority, за исключением субкомпонента userinfo и разделителя @ (параграф 4.2 в [HTTP]). Если компонент authority отсутствует или не определён для URI цели, клиент должен передать поле Host с пустым значением.

Сервер должен отвечать кодом 400 (Bad Request) на любое запросное сообщение HTTP/1.1 без поля заголовка Host, с полем Host в несколько строк или недействительным значением в этом поле.

3.2.1. origin-form

Наиболее распространённой формой request-target является origin-form.

     origin-form    = absolute-path [ "?" query ]

При подаче запроса (кроме CONNECT и OPTIONS для всего сервера, см. ниже) непосредственно серверу-источнику клиент должен передавать в качестве request-target только абсолютный путь и компоненты запроса URI цели. Если в URI цели компонент пути пуст, клиент должен передать в качестве пути символ / в origin-form строки request-target. Передаётся также поле заголовка Host, как указано в параграфе 7.2 [HTTP]. Например, клиент, желающий извлечь содержимое ресурса, указанного http://www.example.org/where?q=now, непосредственно с сервера-источника, будет создавать (или использовать имеющееся) соединение TCP с портом 80 хоста www.example.org и передавать строки

   GET /where?q=now HTTP/1.1
   Host: www.example.org

за которыми следует остальная часть запросного сообщения.

3.2.2. absolute-form

При запросе (кроме CONNECT и OPTIONS для всего сервера, см. ниже) к прокси клиент должен передать URI цели в absolute-form как request-target.

     absolute-form  = absolute-URI

Прокси предлагается обслужить этот запрос из действительного кэша (при возможности) или отправить такой же запрос от имени клиента на следующий приёмный прокси-сервер или сервер-источник, указанный request-target. Требования к такой «пересылке» сообщений приведены в параграфе 7.6 [HTTP].

Пример absolute-form для request-line имеет вид

   GET http://www.example.org/pub/WWW/TheProject.html HTTP/1.1

Клиент должен передавать поле запроса Host в щапросе HTTP/1.1, даже если request-target является absolute-form, поскольку это позволяет передавать Host через древние прокси HTTP/1.0, которые могут не поддерживать Host.

Когда прокси получает запрос с absolute-form для request-target, он должен игнорировать полученное поле заголовка Host (при наличии) и заменять его сведениями о хосте из request-target. Прокси, пересылающий такой запрос, должен генерировать новое поле заголовка Host на основе полученного request-target вместо пересылки исходного поля Host.

Когда сервер-источник получает запрос с absolute-form для request-target, он должен игнорировать полученное поле Host (при наличии) и вместо этого использовать сведения о хосте из request-target. Если в request-target нет компонента authority, будет передаваться пустое поле Host.

Сервер должен воспринимать absolute-form в запросах, хотя большинство клиентов HTTP/1.1 передаёт absolute-form только для прокси.

3.2.3. authority-form

Форма authority-form для request-target применяется лишь в запросах CONNECT (параграф 9.3.6 в [HTTP]) и включает лишь uri-host и номер порта целевой точки туннеля через двоеточие (:).

     authority-form = uri-host ":" port

При подаче запроса CONNECT для организации туннеля через один или несколько прокси клиент должен передавать в качестве request-target только хост и порт для целевой точки туннеля. Клиент получает их из компонента authority в URI цели, указывая принятый по умолчанию порт, если тот не задан в URI цели. Например, запрос CONNECT к http://www.example.com будет иметь вид

   CONNECT www.example.com:80 HTTP/1.1
   Host: www.example.com

3.2.4. asterisk-form

Форма asterisk-form для request-target применяется лишь в запросах OPTIONS на уровне сервера (параграф 9.3.7 в [HTTP]).

     asterisk-form  = "*"

Когда клиент хочет передать запрос OPTIONS для сервера в целом, а не конкретного именованного ресурса на этом сервере, он должен указать в request-target только символ * (%x2A). Например,

   OPTIONS * HTTP/1.1

Если прокси получает запрос OPTIONS с absolute-form для request-target, где URI имеет пустой путь и нет компонента запроса, последний прокси в цепочке запроса должен передать request-target * при пересылке запроса указанному серверу-источнику. Например, запрос

   OPTIONS http://www.example.org:8001 HTTP/1.1

будет пересылаться финальным прокси в виде

   OPTIONS * HTTP/1.1
   Host: www.example.org:8001

после соединения с поротом 8001 хоста www.example.org.

3.3. Восстановление Target URI

URI цели, это request-target, если request-target имеет форму absolute-form. В этом случае сервер будет разбирать URI по базовым компонентам для дальнейшей оценки. В иных случаях сервер по контексту соединения и различным частям запросного сообщения восстанавливает URI для идентификации целевого ресурса (параграф 7.1 в [HTTP]):

  • Если конфигурация сервера предусматривает фиксированную схему URI или схема предоставляется доверенным выходным (outbound) шлюзом, эта схема применяется для URI цели. Это часто встречается в больших системах, поскольку шлюзовой сервер получает контекст соединения от клиента и заменяет его своим соединением с принимающим (inbound) сервером. В ином случае при получении запроса по защищённому соединению для URI цели используется схема https, по незащищённому — http.

  • Если request-target имеет форму authority-form, компонентом authority в URI цели является request-target, в иных случаях — значение поля заголовка Host. Если поля Host нет в заголовке, он пусто или недействительно, authority в URI цели остаётся пустым.

  • Если request-target имеет форму authority-form или asterisk-form, комбинация компонентов path и query в URI цели будет пустой, в ином случае — request-target.

  • Компоненты восстановленного URI цели после описанного выше их определения могут быть объединены в форму absolute-URI путём конкатенации схемы, ://, authority и комбинации компонентов path и query.

Пример 1. Сообщение, полученное через защищённое соединение

   GET /pub/WWW/TheProject.html HTTP/1.1
   Host: www.example.org

имеет URI цели https://www.example.org/pub/WWW/TheProject.html.

Пример 2. Сообщение, полученное через незащищённое соединение

   OPTIONS * HTTP/1.1
   Host: www.example.org:8080

имеет URI цели http://www.example.org:8080

Если компонент authority в URI цели пуст, а схема URI требует непустого значения (как в случае http и https), сервер может отклонить запрос или определить, применимо ли заданное по умолчанию значение, соответствующее контексту входящего сообщения. Контекст может включать такие детали, как адрес и порт, применяемая защита, заданные локально сведения, относящиеся к конфигурации этого сервера. Пустой компонент authority заменяется принятым по умолчанию перед дальнейшей обработкой запроса.

Подстановка принятого по умолчанию значения authority в контексте защищённого соединения по своей сути небезопасна, если есть какой-либо шанс, что предполагаемые полномочия агента пользователя отличаются от принятых по умолчанию. Сервер, способный однозначно определить authority из контекста запроса, может без риска использовать своё отождествление в качестве принятого по умолчанию. Как вариант, может оказаться лучше перенаправить запрос на безопасный ресурс, который объясняет, как обрести нового клиента.

Отметим, что восстановление URI цели от клиента — это лишь половина процесса идентификации целевого ресурса. Другой половиной является определение того, указывает ли URI цели ресурс, для которого сервер готов и способен передать отклик, как указано в параграфе 7.4 [HTTP].

4. Строка статуса

Первой строкой сообщения-отклика является status-line, содержащая версию протокола, пробел(SP), код статуса, ещё один пробел и необязательный текст с описанием кода статуса.

     status-line = HTTP-version SP status-code SP [ reason-phrase ]

Хотя правило грамматики status-line требует отделять каждый элемент одним октетом SP, получатели могут выполнять разбор про пробельным символам границ слов и считать любой пробельный символ (кроме завершения строки) разделителем SP, игнорирую предшествующие и следующие за ним пробельные октеты SP, HTAB, VT (%x0B), AH (%x0C), отдельный символ CR. Однако такой снисходительный разбор может приводить к уязвимостям защиты при наличии нескольких получателей, каждый из которых по своему понимает отказоустойчивость (см. параграф 11.1).

Элемент status-code являет трехзначным целым числом, описывающим результат попытки сервера понять и выполнить соответствующий запрос клиента. Остальную часть запросного сообщения получатель разбирает и интерпретирует в соответствии с семантикой, указанной кодом статуса, если получатель его понимает, или в соответствии с классом кода, если конкретный код статуса не понятен.

     status-code    = 3DIGIT

Коды статуса HTTP описаны в разделе 15 [HTTP] с разбивкой их на классы. Приведены также соображения по определению новых кодов и описан реестр IANA для сбора таких определений.

Элемент reason-phrase служит лишь для текстового описания, связанного с числовым кодом статуса, в основном из уважения к ранним протоколам приложений Internet, которые более часто применялись с интерактивными текстовыми клиентами.

     reason-phrase  = 1*( HTAB / SP / VCHAR / obs-text )

Клиенту следует игнорировать содержимое reason-phrase, поскольку оно не является надёжным источником информации (оно может транслироваться в локальный язык, переопределяться посредниками или отбрасываться при пересылке через другие версии HTTP). Сервер должен включать пробел после status-code, даже если reason-phrase не указывается (строка status-line завершается пробелом).

5. Синтаксис полей

Каждая строка поля состоит из имени поля (без учёта регистра символов), двоеточия (:),необязательных начальных пробельных символов, значения поля и необязательных пробельных символов в конце.

     field-line   = field-name ":" OWS field-value OWS

Правила разбора значений полей заданы в параграфе 5.5 [HTTP]. В этом разделе описывается базовый синтаксис включения полей заголовков в сообщения HTTP/1.1 и извлечения полей из заголовков.

5.1. Разбор строки поля

Сообщения разбираются по общему алгоритму, независимо от имён отдельных полей. Содержимое значения данной строки поля не разбирается до более позднего этапа интерпретации сообщения (обычно после обработки всего раздела полей в сообщении). Не разрешается включать пробельные символы между именем поля и двоеточием (:). В прошлом различия при обработке таких пробельных символов приводили к уязвимостям защиты в процессе маршрутизации запроса и обработки отклика. Сервер должен отвергать с кодом статуса 400 (Bad Request) любые полученные запросные сообщения с пробельными символами между именем поля заголовка и двоеточием. Прокси должны удалять такие символы из сообщений с откликами до пересылки сообщения в нисходящем направлении.

Перед значением поля и после него могут помещаться пробельные символы (optional whitespace ил OWS). Предпочтительно включать один символ SP перед значением для удобства чтения человеком. Значение не включает пробельных символов в начале или в конце и OWS до первого непробельного октета или после последнего значения поля исключаются синтаксическим анализатором при извлечении значения из строки поля.

5.2. Устаревшая фальцовка строк

Исторически сложилось так, что значения полей HTTP/1.x можно было растягивать на несколько строк, предваряя каждую дополнительную строку символом пробела или горизонтальной табуляции (obs-fold). Эта спецификация отказывается от такой фальцовки строк везде, кроме типа носителя message/http (параграф 10.1).

     obs-fold     = OWS CRLF RWS ; устаревшая фальцовка строки

Отправителю недопустимо создавать сообщения с фальцовкой строк (т. е. значениями строк полей, соответствующими правилу obs-fold), если они не предназначены для упаковки в носитель типа message/http.

Сервер, получивший obs-fold в запросном сообщении вне контейнера message/http, должен отвергнуть это сообщение, возвращая код 400 (Bad Request) предпочтительно с пояснением недопустимости устаревшей фальцовки, или заменить все obs-fold одним или несколькими октетами SP до интерпретации значения поля или пересылки сообщения в нисходящем направлении.

Прокси или шлюз, получивший obs-fold в сообщении-отклике вне контейнера message/http, должен отбросить сообщение и заменить его откликом (Bad Gateway) предпочтительно с пояснением недопустимости устаревшей фальцовки, или заменить все obs-fold одним или несколькими октетами SP до интерпретации значения поля или пересылки сообщения в нисходящем направлении.

Агент пользователя, получивший obs-fold в сообщении-отклике вне контейнера message/http, должен заменить все obs-fold одним или несколькими октетами SP до интерпретации значения поля.

6. Тело сообщения

Тело сообщения HTTP/1.1 (при наличии) служит для передачи содержимого (параграф 6.4 в [HTTP]) запроса или отклика. Тело сообщения идентично содержимому, если не применяется транспортное кодирование (параграф 6.1).

     message-body = *OCTET

Правила определения наличия содержимого в сообщении HTTP/1.1 различаются для запросов и откликов.

Наличие тела сообщения в запросе указывается полем Content-Length или Transfer-Encoding. Обрамление запросных сообщений зависит от семантики метода.

Наличие тела сообщения в отклике (см. параграф 6.3) зависит от метода запроса, породившего отклик, и кода статуса в отклике в соответствии с семантикой HTTP (параграф 6.4.1 в [HTTP]).

6.1. Transfer-Encoding

В поле заголовка Transfer-Encoding содержится список имён транспортного кодирования, соответствующий последовательности имён транспортного кодирования которые применены (или будут применены) к содержимому для формирования тела сообщения. Определения транспортного кодирования даны в разделе 7.

     Transfer-Encoding = #transfer-coding ; см. параграф 10.1.4 в [HTTP]

Поле Transfer-Encoding аналогично Content-Transfer-Encoding в MIME, разработанному для обеспечения безопасной доставки двоичных данных через 7-битовый транспортный сервис ([RFC2045], раздел 6). Однако безопасная доставка для чистого 8-битового транспортного протокола отличается. В случае HTTP назначение Transfer-Encoding состоит в основном в обеспечении точного разграничения создаваемого динамически содержимого, а также для различения кодирования, применяемого лишь при передаче, от кодирования, являющегося характеристикой выбранного представления.

Получатель должен уметь разобрать блочное (chunk) транспортное кодирование (параграф 7.1), поскольку оно играет важную роль в обрамлении сообщений, когда размер содержимого не известен заранее. Отправителю недопустимо применять блочное транспортное кодирование для тела сообщения (т. е. создавать блоки из блочных сообщений не разрешается). Если применяется транспортное кодирование, отличное от блочного, отправитель должен применять блочное кодирование в качестве окончательного транспортного кодирования для обеспечения подобающего обрамления сообщения. Если отличное от блочного транспортное кодирование применяется для содержимого отклика, отправитель должен использовать блочное транспортное кодирование в качестве финального или прервать сообщение, разрывая соединение. Например,

   Transfer-Encoding: gzip, chunked

указывает, что содержимое сжато с помощью gzip и организовано в блоки с применением блочного кодирования при формировании тела сообщения.

В отличие от Content-Encoding (параграф 8.4.1 в [HTTP]), Transfer-Encoding является свойством сообщения, а не представления. Любой получатель в цепочке запрос-отклик может декодировать транспортное кодирование или применить дополнительное транспортное кодирование к телу сообщения при условии внесения соответствующих изменений в значение поля Transfer-Encoding. Дополнительные сведения о параметрах кодирования могут предоставляться другими полями заголовка, не заданными этой спецификацией.

Поле Transfer-Encoding может передаваться в отклике на запрос HEAD или в отклике 304 (Not Modified) (параграф 15.4.5 в [HTTP]) на запрос GET, не включающих тела сообщения, для указания того, что сервер-источник применил бы кодирование сообщения, если бы запрос был безусловным GET. Такая индикация не требуется, поскольку любой получатель в цепочке отклика (включая сервер-источник) может удалять транспортное кодирование, если оно не нужно.

Серверу недопустимо передавать поле заголовка в откликах с кодом 1xx (Informational) или 204 (No Content), а также в откликах с кодами 2xx (Successful) на запрос CONNECT (параграф 9.3.6 в [HTTP]).

Серверу, получившему запросное сообщение с непонятным транспортным кодированием, следует возвращать отклик 501 (Not Implemented).

Поле Transfer-Encoding было добавлено в HTTP/1.1. Обычно предполагается, что реализации, анонсирующие поддержку только HTTP/1.0, не понимают, как обрабатывать содержимое с транспортным кодированием, а сообщение HTTP/1.0 с Transfer-Encoding говорит, скорей всего, об отсутствии подобающей обработки при доставке.

Клиенту недопустимо передавать запросы с полем Transfer-Encoding, пока он не знает, что сервер обслуживает запросы HTTP/1.1 (или более поздних младших версий). Такие сведения могут предоставляться в виде конкретной пользовательской конфигурации или путём сохранения версии полученного ранее отклика. Серверу недопустимо передавать отклик с полем Transfer-Encoding, если соответствующий запрос не указывает версию HTTP/1.1 (или более позднюю младшую версию).

Ранние реализации Transfer-Encoding иногда отправляли блочное транспортное кодирование для обрамления сообщений и оценочное поле заголовка Content-Length для использования в индикаторах выполнения. Именно поэтому поле Transfer-Encoding задано как переопределяющее поле Content-Length, а не взаимно несовместимое с ним. К сожалению, пересылка такого сообщения может вызывать уязвимости, связанные с контрабандой (параграф 11.2) или расщеплением запросов (параграф 11.1), если какой-либо из последующих получателей не может разобрать сообщение в соответствии с этой спецификацией, особенно если получатель нисходящего направления поддерживает только HTTP/1.0.

Сервер может отвергать запрос, содержащий оба поля Content-Length и Transfer-Encoding или обрабатывать его с соответствии с полем Transfer-Encoding. В любом случае сервер должен закрыть соединение после ответа на такой запрос во избежание возможных атак.

Сервер или клиент, получивший сообщение HTTP/1.0 с полем заголовка Transfer-Encoding, должен трактовать его как сообщение с ошибочным обрамлением даже при наличии Content-Length и закрывать соединение после обработки сообщения. Отправитель сообщения может сохранить в буфере часть сообщения, которую можно ошибочно интерпретировать при последующем использовании сообщения.

6.2. Content-Length

Если в сообщении нет поля Transfer-Encoding, поле заголовка Content-Length (параграф 8.6 в [HTTP]) может указать предполагаемый размер содержимого десятичным значением числа октетов. Для сообщений с содержимым поле Content-Length предоставляет требуемые сведение об обрамлении для определения конца данных (и сообщения). Для сообщений без содержимого Content-Length указывает размер выбранного представления (параграф 8.6 в [HTTP]).

Отправителю недопустимо передавать поле заголовка Content-Length в сообщениях с полем Transfer-Encoding.

Примечание. HTTP использует поле Content-Length для обрамления сообщений не так, как это принято в MIME, где это необязательное поле применяется только для типа носителя message/external-body.

6.3. Размер тела сообщения

Размер тела определяется одним из показанных ниже способов (в порядке предпочтения.

  1. Любой отклик на запрос HEAD и любой отклик с кодом 1xx (Informational), 204 (No Content), 304 (Not Modified) всегда завершается первой пустой строкой после полей заголовков, независимо от присутствующих в сообщении полей заголовков, поэтому не может включать тело сообщения или раздел трейлеров.

  2. Любой отклик 2xx (Successful) на запрос CONNECT предполагает, что соединение становится туннелем сразу после пустой строки, завершающей поля заголовка. Клиент должен игнорировать заголвока Content-Length и Transfer-Encoding в таком сообщении.

  3. В сообщении с полями Transfer-Encoding и Content-Length поле Transfer-Encoding переопределяет Content-Length. Такое сообщение может указывать попытку контрабанды (параграф 11.2) или расщепления запроса (параграф 11.1) и должно обрабатываться как ошибка. Посредник ACK, решивший переслать такое сообщение, должен удалить из него поле Content-Length и обработать Transfer-Encoding (см. ниже) до пересылки сообщения в нисходящем направлении.

  4. Если имеется поле заголовка Transfer-Encoding и финальным транспортным кодированием является блочное (параграф 7.1), размер тела сообщения определяется считыванием и декодированием блочных данных, пока транспортное кодирование не укажет завершение данных.

    Если в отклике имеется Transfer-Encoding и финальным транспортным кодированием не является блочное, размер тела сообщения определяется считыванием из соединения до его закрытия сервером.

    Если в запросе имеется Transfer-Encoding и финальным транспортным кодированием не является блочное, размер тела сообщения невозможно определить надёжно и сервер должен отвечать кодом 400 (Bad Request), а затем закрывать соединение.

  5. Если сообщение получено без Transfer-Encoding и с недействительным полем Content-Length, кадрирование сообщения недействительно и получатель должен считать это неисправимой ошибкой, если только значение поля не было успешно разобрано как список значений через запятые (параграф 5.6.1 в [HTTP]), в котором все значения действительны и одинаковы (в этом случае сообщение обрабатывается с этим единственным значением поля Content-Length). Если неисправимая ошибка встречена в запросном сообщении, сервер должен ответить кодом 400 (Bad Request) и закрыть соединение. Если это сообщение-отклик, полученное прокси, тот должен закрыть соединение, отбросить полученное сообщение и передать клиенту отклик 502 (Bad Gateway). Если это сообщение-отклик, полученное агентом пользователя, тот должен закрыть соединение с сервером и отбросить полученное сообщение.

  6. Если имеется действительное поле заголовка Content-Length без Transfer-Encoding, предполагается, что десятичное значение поля указывает размер тела сообщения в октетах. Если отправитель закрывает соединение или у получателя возникает тайм-аут до получения указанного числа октетов, получатель должен считать сообщение неполным и закрыть соединение.

  7. Если это запросное сообщение и ни одно из приведённых выше условий не выполняется, тело сообщения имеет размер 0 (в сообщении нет тела).

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

Поскольку нет возможности отличить успешно завершённое сообщение от ограниченного закрытием соединения отклика, принятого частично из-за отказа в сети, серверу следует генерировать сообщение, граница которого задана кодированием или размером. Функция ограничения сообщения закрытием соединения предназначена в основном для совместимости с HTTP/1.0.

Примечание. Запросные сообщения никогда не завершаются закрытием соединения, поскольку они всегда явно кадрируются размером или транспортным кодированием и отсутствие их подразумевает, что запрос завершается сразу после раздела заголовков.

Сервер может отклонить запрос, содержащий тело сообщения без Content-Length, откликом 411 (Length Required).

Если не применяется транспортное кодирование, отличное от блочного, клиенту, передающему запрос с телом сообщения, следует использовать при известном заранее размере тела сообщения действительное поле Content-Length, а не блочное транспортное кодирование, поскольку некоторые из существующих служб отвечают на блочное кодирование кодом 411 (Length Required) даже если они понимают блочное транспортное кодирование. Обычно это обусловлено тем, что такие службы реализуются через шлюз, которому нужно заранее знать размер, а сервер не может или не хочет буферизовать запрос целиком до его обработки.

Агент пользователя, передающий запрос с телом сообщения, должен передать действительное поле заголовка Content-Length или использовать блочное транспортное кодирование. Клиенту недопустимо использовать блочное транспортное кодирование, если он не знает, что сервер будет обрабатывать запросы HTTP/1.1 (или более поздние). Такие сведения могут быть получены из конкретной пользовательской конфигурации или в результате запоминания полученного ранее отклика.

Если финальный отклик на последний запрос в соединении был получен полностью и остались дополнительные данные для чтения, агент пользователя может отбросить оставшиеся данные или попытаться определить являются ли они частью предшествующего тела сообщения, что может произойти из-за некорректного значения Content-Length. Клиенту недопустимо обрабатывать, кэшировать или пересылать такие дополнительные данные как отдельный отклик, поскольку такое поведение может привести к отравлению кэша.

7. Транспортное кодирование

Имена транспортного кодирования служат для индикации кодировочного преобразования, которое было, могло быть или может потребоваться применить к сообщению для обеспечения безопасной транспортировки через сеть. Это отличается от кодирования содержимого тем, что транспортное кодирование является свойством сообщения, а не передаваемого представления.

В именах транспортного кодирования не учитывается регистр символов, а имена должны регистрироваться в реестре HTTP Transfer Coding, как указано в параграфе 7.3. Они указываются в полях заголовка Transfer-Encoding (параграф 6.1) и TE (параграф 10.1.4 в [HTTP]) (последнее также задаёт грамматику transfer-coding).

7.1. Блочное транспортное кодирование

Блочное (chunked) транспортное кодирование оборачивает содержимое для передачи в форме последовательности блоков (chunk), каждый из которых содержит индикатор размера, на которыми может следовать необязательный раздел с полями трейлера. Это позволяет передавать потоки содержимого неизвестного размера в виде последовательности буферов ограниченного размера, давая отправителю возможность сохранять соединение, а получателю — знать, когда сообщение получено целиком.

     chunked-body   = *chunk
                      last-chunk
                      trailer-section
                      CRLF

     chunk          = chunk-size [ chunk-ext ] CRLF
                      chunk-data CRLF
     chunk-size     = 1*HEXDIG
     last-chunk     = 1*("0") [ chunk-ext ] CRLF

     chunk-data     = 1*OCTET ; последовательность октетов размером chunk-size

Поле chunk-size — это строка шестнадцатеричных цифр, указывающая размер chunk-data в октетах. Блочное транспортное кодирование завершается блоком с chunk-size = 0, после чего может следовать раздел трейлеров, а затем пустая строка.

Получатель должен быть способен разбирать и декодировать блочное транспортное кодирование.

HTTP/1.1 не задаёт средств ограничения на размер блочного отклика, чтобы посредник мог быть уверен в буферизации всего отклика. Кроме того, очень большой размер блоков может приводить к переполнению или потере точности, если их значения не будут точно представлены в принимающей реализации. Поэтому получатели должны предусматривать большие шестнадцатеричные числа и предотвращать ошибки разбора в результате переполнения при преобразовании чисел или потери точности при представлении целых чисел.

Блочное кодирование не предусматривает каких-либо параметров и их наличие следует считать ошибкой.

7.1.1. Расширения блоков

Блочное кодирование разрешает включать расширения в каждый блок сразу после chunk-size для предоставления метаданных блока (например, подписи или хэша), сведений об управлении или изменения размера тела сообщения.

     chunk-ext      = *( BWS ";" BWS chunk-ext-name
                         [ BWS "=" BWS chunk-ext-val ] )

     chunk-ext-name = token
     chunk-ext-val  = token / quoted-string

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

Получатель должен игнорировать нераспознанные расширения. Сервер должен ограничивать суммарный размер расширений блока в запросе разумным значением, как это делается для размера и тайм-аутов в других частях сообщения, и генерировать подходящий отклик 4xx (Client Error) в случае превышения размера.

7.1.2. Раздел трейлеров

Раздел трейлеров позволяет отправителю включать дополнительные поля в конце блочного сообщения для представления метаданных, которые могут создаваться динамически при отправке сообщения, такие как проверка целостности сообщения, цифровая подпись, статус постобработки. Корректное использование и ограничения для полей трейлера описаны в параграфе 6.5 [HTTP].

     trailer-section   = *( field-line CRLF )

Получатель, удаляющий блочное кодирование из сообщения, может селективно сохранять или отбрасывать полученные поля трейлеров. Получатель, сохраняющий полученные поля, должен сохранять/пересылать поля трейлера отдельно от полей заголовка или сливать их с разделом заголовка. Получателю недопустимо сливать полученные поля трейлера с заголовком, если только определение соответствующего поля заголовка явно не разрешает это, указывая способ безопасного слияния.

7.1.3. Декодирование

Ниже представлен псевдокод декодирования блочного транспортного кодирования.

     length := 0
     считывание chunk-size, chunk-ext (при наличии) и CRLF
     пока (chunk-size > 0) {
        считывание chunk-data и CRLF
        добавление chunk-data в конец содержимого
        length := length + chunk-size
        считывание chunk-size, chunk-ext (if any) и CRLF
     }
     считывание трейлера
     пока (трейлер не пуст) {
        если (поля трейлера сохраняются/пересылаются forwarded separately) {
            поле трейлера добавляется в конец имеющихся трейлерных полей
        }
        иначе если (поле трейлера понятно и задано как сливаемое) {
            слияние поля трейлера с имеющимися
        }
        иначе {
            отбрасывание поля трейлера
        }
        считывание поля трейлера
     }
     Content-Length := length
     Удаление chunked из Transfer-Encoding

7.2. Транспортное кодирование со сжатием

Указанные ниже имена транспортного кодирования со сжатием совпадают с именами соответствующих алгоритмов.

   compress (и x-compress), см. параграф 8.4.1.1 в [HTTP].
   deflate, см. параграф 8.4.1.2 в [HTTP].
   gzip (и x-gzip), см. параграф 8.4.1.3 в [HTTP].

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

7.3. Реестр транспортного кодирования

Реестр HTTP Transfer Coding Registry (https://www.iana.org/assignments/http-parameters) определяет пространство имён транспортного кодирования. Каждая запись реестра должна включать поля:

  • имя;

  • описание;

  • указатель на текст спецификации.

Именам транспортного кодирования недопустимо совпадать с именами кодирования содержимого (параграф 8.4.1 в [HTTP]), если только в них не применяется идентичное кодирующее преобразование, как для сжатия (параграф 7.2).

Поле заголовка TE (параграф 10.1.4 в [HTTP]) использует псевдопараметр q как значение ранга при наличии нескольких приемлемых вариантов транспортного кодирования. В будущих регистрациях транспортного кодирования не следует задавать параметров с именем q (в любом регистре), чтобы не возникало неоднозначности.

Значения добавляются в пространство имён по процедуре IETF Review (параграф 4.8 в [RFC8126]) и должны соответствовать назначению транспортного кодирования, заданному в этой спецификации.

Использовать имена программ для идентификации форматов кодирования нежелательно и не рекомендуется для будущих вариантов кодирования.

7.4. Согласование транспортного кодирования

Поле TE (параграф 10.1.4 в [HTTP]) служит в HTTP/1.1 для указания методов транспортного кодирования в откликах, которые клиент готов воспринимать в дополнение к блочному кодированию (chunked), и готовности сохранять поля трейлера в блочном транспортном кодировании. Клиенту недопустимо передавать имя блочного транспортного кодирования в TE, это кодирование получатели HTTP/1.1 воспринимают всегда. Ниже приведены три примера TE.

   TE: deflate
   TE:
   TE: trailers, deflate;q=0.5

Если приемлемо несколько вариантов транспортного кодирования, клиент может ранжировать их, используя параметр q (в любом регистре, подобно использованию с полях согласования содержимого, см. параграф 12.4.2 в [HTTP]). Ранг указывается действительным числом из диапазона 0 — 1 и 0,001 соответствует низшему рангу, а 1 — наиболее предпочтительному. Значение 0 указывает неприемлемый вариант (not acceptable).

Если значение поля TE пусто или TE нет совсем, единственным вариантом транспортного кодирования является блочное (chunked). Сообщения без транспортного кодирования воспринимаются всегда. Ключевое слово trailers указывает, что отправитель не будет отбрасывать поля трейлера, как описано в параграфе 6.5 [HTTP].

Поскольку поле заголовка TE относится только к непосредственному соединению, отправитель TE должен также передавать опцию соединения TE в поле заголовка Connection (параграф 7.6.1 в [HTTP]), чтобы предотвратить пересылку поля заголовка TE посредниками, которые не поддерживают семантику этого поля.

8. Обработка неполных сообщений

Сервер, получивший неполное сообщение с запросом (обычно из-за его отмены или возникновения тайм-аута) может передать сообщение об ошибке перед закрытием соединения. Клиент, получивший неполное сообщение с откликом, что может быть вызвано преждевременным закрытием соединения или отказом при декодировании предположительно блочного кодирования, должен записать сообщение как неполное. Требования к кэшированию неполных откликов приведены в параграфе 3.3 [CACHING].

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

Тело сообщения с блочным транспортным кодированием неполно, если не был получен блок нулевого размера, завершающий кодирование. Сообщение с действительным Content-Length неполно, если размер принятого сообщения в октетах меньше значения Content-Length. Отклик без блочного транспортного кодирования и Content-Length прерывается закрытием соединения и (при получении раздела заголовков в целости и сохранности) считается полным, если базовое соединение не указало ошибку (например, неполное закрытие в TLS оставит отклик неполным, как описано в параграфе 9.8).

9. Управление соединениями

Обмен сообщениями HTTP не зависит от базовых протоколов соединений транспортного и сеансового уровня. HTTP лишь предполагает надёжный транспорт с упорядоченной доставкой запросов и соответствующих откликов. Отображение запросов и откликов HTTP на блоки данных базового транспортного протокола выходит за рамки этой спецификации.

Как указано в параграфе 7.3 [HTTP], конкретные транспортные протоколы, используемые для взаимодействий HTTP, определяются конфигурацией клиента и URI цели. Например, схема URI http (параграф 4.2.1 в [HTTP]) указывает принятое по умолчанию соединение TCP по протоколу IP через принятый по умолчанию порт TCP 80, но клиент может быть настроен на работу через прокси с другим соединением, портом или протоколом.

Предполагается, что реализации HTTP будут управлять соединениями, включая поддержку состояния имеющегося соединения, организацию нового соединения или использование имеющегося, обработку сообщений, полученных в соединении, и завершение каждого соединения. Большинство клиентов поддерживает множество параллельных соединений, включая несколько соединений на сервер. Большинство серверов спроектировано для поддержки тысяч одновременных соединений с контролем очередей запросов для беспристрастного использования и предотвращения DoS5-атак.

9.1. Организация соединения

Описание организации соединений по различным протоколам транспортного и сеансового уровня. Каждое соединение HTTP отображается на одно базовое транспортное соединение.

9.2. Связывание отклика с запросом

HTTP/1.1 не включает идентификаторов запроса для связывания данного запросного сообщения с соответствующими сообщениями откликов. В результате протокол полагается на точное соответствие порядка откликов порядку отправки запросов в том же соединении. Более одного отклика на запрос приходит лишь в том случае, когда финальному отклику на запрос предшествует один или несколько информационных откликов (1xx, см. параграф 15.2 в [HTTP]) на тот же запрос.

Клиент у которого остаётся более одного запроса в соединении, должен поддерживать список остающихся запросов в порядке их передачи, а также должен связывать каждое полученное через это соединение сообщение с первым оставшимся запросом, для которого ещё не получен финальный (не 1xx) отклик. Если клиент получает данные, для которых нет оставшегося запроса, ему недопустимо считать эти данные действительным откликом и следует закрыть соединение, поскольку разграничение сообщений становится неоднозначным, если только данные не состоят или из одной или нескольких последовательностей CRLF (они могут отбрасываться в соответствии с параграфом 2.2).

9.3. Сохраняемое соединение

В HTTP/1.1 по умолчанию используются сохраняемые (persistent) соединения, что позволяет передавать через одно соединение множество запросов и откликов. Реализациям HTTP следует поддерживать сохраняемые соединения.

Получатель определяет является ли соединение постоянным по версии протокола и полю заголовка Connection (параграф 7.6.1 в [HTTP]) в полученном последним сообщении как указано ниже (до первого совпадения).

  • При наличии опции соединения close (параграф 9.6), соединение не сохраняется после текущего отклика.

  • Для протокола HTTP/1.1 (или выше) соединение сохраняется после текущего отклика.

  • Если указан протокол HTTP/1.0 и имеется опция соединения keep-alive получатель не является прокси или сообщение является откликом и получатель хочет соблюдать механизм HTTP/1.0 keep-alive, соединение сохраняется после текущего отклика.

  • Соединение закрывается после текущего отклика.

Не поддерживающий сохраняемые соединения клиент должен передавать опцию close в каждом запросном сообщении. Сервер, поддерживающий сохраняемые соединения, должен передавать опцию close в каждом сообщении-отклике, не имеющем кода статуса 1xx (Informational). Клиент может передавать дополнительные запросы на сохранения соединений, пока им не отправлена или не получена опция соединения close или не получен отклик HTTP/1.0 без опции соединения keep-alive.

Для сохранения соединения все сообщения в нем должны иметь определённый размер сообщения (т. е. размер не определяется закрытием соединения), как описано в разделе 6. Сервер должен прочитать тело запросного сообщения целиком или закрыть соединение после отправки отклика, в противном случае оставшиеся данные для сохраняемого сообщения будут ошибочно считаться следующим запросом. Клиент должен целиком прочитать тело сообщения-отклика, если он намерен использовать это же сообщение для последующего запроса.

Прокси-серверу недопустимо поддерживать постоянные соединения с клиентом HTTP/1.0 (см. Приложение C.2.2, где рассматриваются проблемы с полем заголовка Keep-Alive, используемым многими клиентами HTTP/1.0). Совместимость с клиентами HTTP/1.0 рассматривается в Приложении C.2.2.

9.3.1. Повторение запросов

Соединения могут закрываться в любой момент (намеренно или нет). Реализации должны предвидеть необходимость восстановления после асинхронных событий закрытия. Условия, при которых клиент может автоматически повторять остающиеся запросы, указаны в параграфе 9.2.2 [HTTP].

9.3.2. Конвейеры

Клиент, поддерживающий сохранение соединений, может организовать конвейер (pipeline) своих запросов (т. е. передать несколько запросов, не ожидая каждого отклика). Сервер может обрабатывать конвейерные запросы параллельно, если все они используют безопасный метод (параграф 9.2.1 в [HTTP]), но он должен передавать соответствующие отклики в порядке получения запросов.

Клиенту, применяющему конвейер запросов, следует повторять безответные запросы, если соединение было закрыто до получения всех соответствующих откликов. При повторе конвейерных запросов после неудачного соединения (соединения, не закрытого явно сервером в его последнем полном отклике), клиенту недопустимо создавать конвейер сразу после организации соединения, поскольку первый запрос, оставшийся от прежнего конвейера, мог вызвать отклик об ошибке, который снова будет потерян, если передать несколько запросов по преждевременно закрытому соединению (см. проблему сброса TCP в параграфе 9.6).

Идемпотентные методы (параграф 9.2.2 в [HTTP]) важны для конвейеров, поскольку они могут автоматически повторяться при отказе соединения. Агенту пользователя не следует применять конвейер запросов после неидемпотентного метода, пока не получен код статуса финального отклика, если только у пользовательского агента нет средств обнаружения и восстановления после частичных отказов, связанных с последовательностью конвейера.

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

9.4. Одновременные соединения

Клиент должен ограничивать число одновременно открытых соединений, поддерживаемых с данным сервером.

Прежние версии HTTP задавали конкретное число одновременно открытых соединений, но это не подошло для многих приложений. Поэтому данные спецификация не задаёт конкретного максимума для числа соединений, взамен предлагая клиентам быть консервативными при создании множества соединений. Несколько соединений обычно используется для предотвращения блокировки head-of-line, когда требующий значительной обработки и/или передачи очень большого объёма информации запрос может препятствовать обработке последующих запросов в том же соединении. Однако для каждого соединения нужно выделять ресурсы. Кроме того, использование множества соединений может приводить к нежелательным побочным эффектам в загруженных сетях, а также в иных ситуациях, поскольку совокупная, изначально синхронизированная передача может вызывать перегрузку, которая не возникла бы при меньшем числе соединений.

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

9.5. Отказы и тайм-ауты

У серверов обычно имеется тот или иной тайм-аут, по достижении которого они прекращают поддержку неактивных соединений. Прокси-серверы могут использовать большее значение, поскольку вероятно, что клиент может организовывать больше соединений через один прокси-сервер. Использование сохраняемых соединений не задаёт требований к наличию и величине такого тайм-аута как для клиентов, так и для серверов.

Клиенту или серверу, желающему закрыть соединение по тайм-ауту, следует выполнить аккуратное завершение соединения. Реализациям следует постоянно отслеживать открытые соединения на предмет получения сигналов о закрытии и подобающей реакции на них, поскольку оперативное закрытие соединений обеими сторонами позволяет освободить выделенные для соединений ресурсы.

Клиент, сервер или прокси может закрыть транспортное соединение в любой момент. Клиент может начать передачу нового запроса в тот момент, когда сервер решит закрыть бездействующее (idle) соединение. С точки зрения сервера соединение закрывается во время бездействия, а с точки зрения клиент — при запросе.

Серверу следует поддерживать сохраняемые соединения, пока это возможно, и разрешать механизмам управления потоком данных базового транспорта обрабатывать временные перегрузки вместо прерывания соединений, ожидая повтора попытки клиентом. Прерывание соединения может усугублять перегрузку сети или загрузку сервера.

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

9.6. Разрыв соединения

Опция соединения close задана в качестве сигнала о том, что отправитель будет закрывать соединение после выполнения запроса. Отправителю следует передавать поле заголовка Connection (параграф 7.6.1 в [HTTP]) с опцией соединения close, когда он намерен закрыть соединение. Например,

   Connection: close

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

Клиенту, передавшему опцию соединения close, недопустимо передавать последующие запросы в это соединение и он должен закрыть соединение после приёма финального сообщения с откликом, соответствующего этому запросу. Сервер, получивший опцию соединения close, должен инициировать закрытие соединения (см. ниже) после отправки финального отклика на запрос с опцией close. Серверу следует передавать опцию соединения close в финальном отклике в данном соединении и недопустимо обрабатывать какие-либо запросы, полученные через это соединение. Сервер, передавший опцию соединения close, должен инициировать закрытие соединения (см. ниже) после отправки отклика с опцией close и недопустимо обрабатывать какие-либо запросы, полученные через это соединение.

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

При незамедлительном закрытии соединения сервером возникает риск того, что клиент не сможет прочитать последний отклик HTTP. Если сервер получит от клиента дополнительные данные через полностью закрытое соединение (например, другой запрос, переданный клиентом до получения отклика от сервера), серверный стек TCP будет передавать клиенту пакет сброса, который, к сожалению, может удалить у клиента неподтвержденные входные буферы до их прочтения и интерпретации клиентским анализатором HTTP. Для предотвращения проблемы сброса TCP серверы обычно закрывают соединение поэтапно. Сначала сервер закрывает только строну записи (half-close) с соединении с чтением и записью, продолжая читать данные из соединения, пока не получит от клиента соответствующее закрытие или не будет уверен, что его стек TCP получил от клиента подтверждения пакетов с последним откликом сервера. После этого сервер закрывает соединение полностью. Сведений о возникновении проблемы сброса а других протоколах (не TCP) нет.

Отметим, что закрытие клиентом соединения TCP наполовину, не означает, что этот клиент больше не заинтересован в отклике. В общем случае на транспортные сигналы полагаться нельзя, поскольку HTTP/1.1 не зависит от транспорта.

9.7. Инициирование соединения TLS

Концептуально HTTP/TLS — это просто передача сообщений HTTP через соединения, защищённые TLS [TLS13].

Клиент HTTP является также клиентом TLS. Он инициирует соединение с сервером через подходящий порт и передаёт сообщение TLS ClientHello для начала согласования TLS. По завершении согласования TLS клиент может инициировать первый запрос HTTP. Все данные HTTP должны передаваться как данные приложения TLS, а в остальном это рассматривается как обычное соединение HTTP (включая возможность многократного использования сохраняемых соединений).

9.8. Закрытие соединения TLS

TLS использует обмен сигналами (не ошибка) о закрытии соединения, что это было безопасно (параграф 6.1 в [TLS13]). При получении действительного сигнала о закрытии, реализация может быть уверена, что не получит данных через это соединение. Когда реализация знает, что она больше не будет передавать или принимать данные сообщений, в которых она заинтересована (обычно путём обнаружения границ сообщений HTTP), она может генерировать»неполное закрытие» (incomplete close), передавая сигнал о закрытии и закрывая соединение без получения соответствующего сигнала о закрытии от своего партнёра.

Неполное закрытие не ставит под сомнение безопасность уже полученных данных, но может говорить о возможности отсечки последующих данных. Поскольку TLS не знает напрямую о кадрировании сообщений HTTP, нужно проверять сами данные HTTP для определения полноты сообщений. Обработка неполных сообщений описана в раздел 8.

Клиенту, столкнувшемуся с неполным завершением, следует считать завершёнными все отклики, для которых получено что-либо из указанного:

  1. объем данных, указанный полем Content-Length;

  2. завершающий блок нулевого размера (при использовании блочного транспортного кодирования).

Отклик, для которого не используется блочного транспортного кодирования и Content-Length, считается полным лишь при получении действительного сигнала о закрытии. Признание неполного сообщения полным может открывать реализацию для атак.

Клиенту, обнаружившему неполное закрытие, следует выполнить аккуратное восстановление.

Клиент должен передать сигнал о закрытии перед закрытием соединения. Клиент, не ожидающий приёма дополнительных данных может не ждать от сервера сигнала закрытия и просто закрыть соединение, вызывая неполное закрытие на стороне сервера.

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

Сервер должен пытаться инициировать обмен сигналами о закрытии с клиентом до закрытия соединения. Сервер может закрыть соединение после передачи сигнала о закрытии, вызывая неполное закрытие на стороне клиента.

10. Встраивание сообщений как данных

10.1. Тип носителя message/http

Тип носителя message/http может служить для передачи одного сообщения с запросом или откликом HTTP при условии соблюдения ограничений MIME для типов message в части размера и кодирования. Из-за ограничений на размер строк для типа message/http разрешается применять фальцовку строк (obs-fold), как описано в параграфе 5.2, для передачи значения поля в нескольких строках. Получатель данных message/http при восприятии сообщения должен заменять устаревшую фальцовку строк одним или несколькими символами SP.

Имя типа

message

Имя субтипа

http

Требуемые параметры

нет

Необязательные параметры

version, msgtype

version

Номер версии HTTP во вложенном сообщении (например, 1.1). Если номер не указан, версию можно определить из первой строки тела.

msgtype

Тип сообщения — request или response. Если тип не указан, его можно определить из первой строки тела.

Кодировки

Только 7bit, 8bit или binary.

Вопросы безопасности

См. раздел 11.

Вопросы совместимости

Нет

Опубликованная спецификация

RFC 9112 (параграф 10.1).

Приложения, использующие этот тип носителя

Не заданы.

Вопросы идентификации фрагментов

Не применимо.

Дополнительные сведения

Magic number(s)

Не применимо.

Запрещённые имена псевдонимов

Не применимо.

Расширения имён файлов

Не применимо.

Коды типа файлов Macintosh

Не применимо.

Контактные данные для получения дополнительных сведений

См. раздел «Адреса авторов».

Предусмотренное использование

Общее назначение

Ограничения на использование

Нет

Автор

См. раздел «Адреса авторов».

Контролёр изменений

IESG

10.2. Тип носителя application/http

Тип носителя application/http может служить для передачи вложенного конвейера с одним или несколькими запросами или откликами HTTP (без смешивания).

Имя типа

message

Имя субтипа

http

Требуемые параметры

нет

Необязательные параметры

version, msgtype

version

Номер версии HTTP во вложенном сообщении (например, 1.1). Если номер не указан, версию можно определить из первой строки тела.

msgtype

Тип сообщения — request или response. Если тип не указан, его можно определить из первой строки тела.

Кодировки

HTTP messages enclosed by this type are in «binary» format; use of an appropriate Content-Transfer-Encoding is required when transmitted via email.

Вопросы безопасности

См. раздел 11.

Вопросы совместимости

Нет

Опубликованная спецификация

RFC 9112 (параграф 10.2).

Приложения, использующие этот тип носителя

Не заданы.

Вопросы идентификации фрагментов

Не применимо.

Дополнительные сведения

Запрещённые имена псевдонимов

Не применимо.

Magic number(s)

Не применимо.

Расширения имён файлов

Не применимо.

Коды типа файлов Macintosh

Не применимо.

Контактные данные для получения дополнительных сведений

См. раздел «Адреса авторов».

Предусмотренное использование

Общее назначение

Ограничения на использование

Нет

Автор

См. раздел «Адреса авторов».

Контролёр изменений

IESG

11. Вопросы безопасности

Этот раздел информирует разработчиков, поставщиков информации и пользователей о вопросах безопасности, связанных с синтаксисом и обработкой сообщений HTTP. Вопросы безопасности, связанные семантиков, содержимым и маршрутизацией HTTP, рассмотрены [HTTP].

11.1. Расщепление откликов

Расщепление откликов (внедрение CRLF) — это распространённый метод, используемый в разных атаках на Web и основанный на построчной природе сообщений HTTP и упорядоченной связи упорядоченных запросов с откликами в сохраняемых соединениях [Klein]. Этот метод может быть особо опасным при прохождении запросов через общий кэш.

Расщепление откликов использует уязвимость серверов (обычно серверов приложений), где злоумышленник может передать закодированные данные внутри того или иного параметра запроса, который будет потом декодирован и возвращён (echo) в любом из полей заголовка отклика. Если декодированные данные выглядят как завершение отклика и начало следующего, значит отклик расщеплён и содержимое и содержимое того, что представляется вторым откликом, контролируется атакующим. Затем злоумышленник может выполнить любой другой запрос по тому же сохраняемому соединению и обмануть получателей (включая посредников), заставив их поверить, что вторая половина разделённого отклика является полномочным откликом на второй запрос. Например, параметр в request-target может быть прочитан сервером приложения и снова использован в перенаправлении, в результате чего параметр будет повторён в поле заголовка отклика Location. Если параметр декодируется приложением и не закодирован должным образом при включении в поле отклика, атакующий может внедрить закодированные октеты CRLF и другое содержимое, что сделает один отклик приложения выглядящим как два или несколько откликов.

Обычная защита от расщепления откликов заключается в фильтрации запросов на предмет данных, представляющихся закодированными CR и LF (например, %0D и %0A). Однако это предполагает, что сервер приложений декодирует лишь URI, а не менее понятные преобразования данных, такие как смена кодировки, трансляция сущностей XML, декодирование base64, переформатирование sprintf и т. п. Более эффективная защита обеспечивается предотвращением отправки CR и LF в разделе заголовков чем-либо, кроме библиотек ядра протокола сервера, что означает возможность вывода полей заголовков только для API, которые фильтруют непригодные октеты и не позволяют серверам приложений напрямую писать в поток протокола.

11.2. Контрабанда запросов

Контрабандой (smuggling) запросов [Linhart] называют метод, использующий различия при разборе у разных получателей для сокрытия дополнительных запросов (которые иначе могут блокироваться или запрещаться правилами) в безобидном на первый взгляд запросе. Как и расщепление откликов, контрабанда запросов может приводить к различным атакам на HTTP. В этой спецификации заданы новые требования к разбору запросов, в частности, к кадрированию сообщений (параграф 6.3) для снижения эффективности контрабанды запросов.

11.3. Целостность сообщений

HTTP не задаёт конкретных механизмов обеспечения целостности сообщений, полагаясь на возможности обнаружения ошибок в базовых транспортных протоколах и использование размера или блочного кодирования для определения полноты. Исторически отсутствие одного механизма контроля целостности оправдывалось неформальной природой большинства взаимодействий HTTP. Однако широкое распространение HTTP как механизма доступа к информации привело к расширению использования в средах, где проверка целостности сообщений имеет решающее значение.

Механизмы, обеспечиваемые схемой https, такие как аутентифицированное шифрование, обеспечивают защиту от изменения сообщений. Однако требуется следить за тем, чтобы закрытие соединения не могло использоваться для отсечки сообщений (см. параграф 9.8). Пользовательские агенты могут отказываться воспринимать неполные сообщения или обрабатывать их особо. Например, браузер, служащий для просмотр истории болезни или сведений о взаимодействии лекарств, должен информировать пользователя, когда протокол обнаруживает, что сведения неполны, устарели или повреждены при передаче. Такие механизмы можно включать селективно через расширения пользовательского агента или включение в отклик метаданных для контроля целостности.

Схема http не обеспечивает защиты от случайного или преднамеренного изменения сообщений.

Расширения протокола могут служить для снижения риска нежелательного изменения сообщений посредниками даже при использовании схемы https. Целостность можно обеспечить с помощью кодов аутентификации, добавляемых в сообщения через расширяемые поля метаданных.

11.4. Конфиденциальность сообщений

HTTP полагается на базовый транспортный протокол для обеспечения конфиденциальности, когда это желательно. Протокол HTTP специально создан независимым от транспортного протокола, чтобы его можно было использовать со многими формами шифрованных соединений, выбор которых определяет схема URI или конфигурация пользовательского агента. Схему https можно применять для указания ресурсов, которые требуют конфиденциального соединения, как описано в параграфе 4.2.2 [HTTP].

12. Взаимодействие с IANA

Контролёром изменений для указанных ниже регистраций является IETF (iesg@ietf.org).

12.1. Регистрация имён полей

Агентство IANA добавило имена полей, приведённые в таблице 1, в реестр Hypertext Transfer Protocol (HTTP) Field Name Registry (https://www.iana.org/assignments/http-fields), как указано в параграфе 18.4 [HTTP].

Таблица .

 

Имя поля

Статус

Параграф

Комментарии

Close

permanent

9.6

(резерв)

MIME-Version

permanent

B.1

Transfer-Encoding

permanent

6.1

 

12.2. Регистрация типов носителей

Агентство IANA обновило реестр Media Types (https://www.iana.org/assignments/media-types) с добавлением записей, указанных в параграфах 10.1 и 10.2 для типов носителя message/http и application/http.

12.3. Регистрация транспортного кодирования

Агентство IANA обновило реестр HTTP Transfer Coding Registry (https://www.iana.org/assignments/http-parameters/) с процедурой регистрации, указанной в параграфе 7.3 и именами кодирования содержимого из таблицы 2.

Таблица .

 

Имя

Описание

Параграф

chunked

Передача в последовательности блоков (chunk)

7.1

compress

Формат данных UNIX compress [Welch]

7.2

deflate

Формат сжатия данных deflate [RFC1951] внутри формата данных zlib [RFC1950]

7.2

gzip

Формат файлов GZIP [RFC1952]

7.2

trailers

Резерв

12.3

x-compress

Устарело (псевдоним для compress)

7.2

x-gzip

Устарело (псевдоним для gzip)

7.2

 

Примечание. Имя кодирования trailers зарезервировано для предотвращения конфликтов с ключевым словом trailers в поле заголовка TE (параграф 10.1.4 в [HTTP]).

12.4. Регистрация ALPN Protocol ID

Агентство IANA обновило реестр TLS Application-Layer Protocol Negotiation (ALPN) Protocol IDs (https://www.iana.org/assignments/tls-extensiontype-values/) приведённым в таблице 3 значением.

Таблица .

 

Протокол

Идентификационная сигнатура

Документ

HTTP/1.1

0x68 0x74 0x74 0x70 0x2f 0x31 0x2e 0x31 (http/1.1)

RFC 9112

 

13. Литература

13.1. Нормативные документы

[CACHING] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «HTTP Caching», STD 98, RFC 9111, DOI 10.17487/RFC9111, June 2022, <https://www.rfc-editor.org/info/rfc9111>.

[HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «HTTP Semantics», STD 97, RFC 9110, DOI 10.17487/RFC9110, June 2022, <https://www.rfc-editor.org/info/rfc9110>.

[RFC1950] Deutsch, P. and J-L. Gailly, «ZLIB Compressed Data Format Specification version 3.3», RFC 1950, DOI 10.17487/RFC1950, May 1996, <https://www.rfc-editor.org/info/rfc1950>.

[RFC1951] Deutsch, P., «DEFLATE Compressed Data Format Specification version 1.3», RFC 1951, DOI 10.17487/RFC1951, May 1996, <https://www.rfc-editor.org/info/rfc1951>.

[RFC1952] Deutsch, P., «GZIP file format specification version 4.3», RFC 1952, DOI 10.17487/RFC1952, May 1996, <https://www.rfc-editor.org/info/rfc1952>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC5234] Crocker, D., Ed. and P. Overell, «Augmented BNF for Syntax Specifications: ABNF», STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, <https://www.rfc-editor.org/info/rfc5234>.

[RFC7405] Kyzivat, P., «Case-Sensitive String Support in ABNF», RFC 7405, DOI 10.17487/RFC7405, December 2014, <https://www.rfc-editor.org/info/rfc7405>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[TLS13] Rescorla, E., «The Transport Layer Security (TLS) Protocol Version 1.3», RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.

[URI] Berners-Lee, T., Fielding, R., and L. Masinter, «Uniform Resource Identifier (URI): Generic Syntax», STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, <https://www.rfc-editor.org/info/rfc3986>.

[USASCII] American National Standards Institute, «Coded Character Set — 7-bit American Standard Code for Information Interchange», ANSI X3.4, 1986.

[Welch] Welch, T., «A Technique for High-Performance Data Compression», IEEE Computer 17(6), DOI 10.1109/MC.1984.1659158, June 1984, <https://ieeexplore.ieee.org/document/1659158/>.

13.2. Дополнительная литература

[HTTP/1.0] Berners-Lee, T., Fielding, R., and H. Frystyk, «Hypertext Transfer Protocol — HTTP/1.0», RFC 1945, DOI 10.17487/RFC1945, May 1996, <https://www.rfc-editor.org/info/rfc1945>.

[Klein] Klein, A., «Divide and Conquer — HTTP Response Splitting, Web Cache Poisoning Attacks, and Related Topics», March 2004, <https://packetstormsecurity.com/papers/general/whitepaper_httpresponse.pdf>.

[Linhart] Linhart, C., Klein, A., Heled, R., and S. Orrin, «HTTP Request Smuggling», June 2005, <https://www.cgisecurity.com/lib/HTTP-Request-Smuggling.pdf>.

[RFC2045] Freed, N. and N. Borenstein, «Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies», RFC 2045, DOI 10.17487/RFC2045, November 1996, <https://www.rfc-editor.org/info/rfc2045>.

[RFC2046] Freed, N. and N. Borenstein, «Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types», RFC 2046, DOI 10.17487/RFC2046, November 1996, <https://www.rfc-editor.org/info/rfc2046>.

[RFC2049] Freed, N. and N. Borenstein, «Multipurpose Internet Mail Extensions (MIME) Part Five: Conformance Criteria and Examples», RFC 2049, DOI 10.17487/RFC2049, November 1996, <https://www.rfc-editor.org/info/rfc2049>.

[RFC2068] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., and T. Berners-Lee, «Hypertext Transfer Protocol — HTTP/1.1», RFC 2068, DOI 10.17487/RFC2068, January 1997, <https://www.rfc-editor.org/info/rfc2068>.

[RFC2557] Palme, J., Hopmann, A., and N. Shelness, «MIME Encapsulation of Aggregate Documents, such as HTML (MHTML)», RFC 2557, DOI 10.17487/RFC2557, March 1999, <https://www.rfc-editor.org/info/rfc2557>.

[RFC5322] Resnick, P., Ed., «Internet Message Format», RFC 5322, DOI 10.17487/RFC5322, October 2008, <https://www.rfc-editor.org/info/rfc5322>.

[RFC7230] Fielding, R., Ed. and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing», RFC 7230, DOI 10.17487/RFC7230, June 2014, <https://www.rfc-editor.org/info/rfc7230>.

[RFC8126] Cotton, M., Leiba, B., and T. Narten, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.

Приложение A. Сводка ABNF

В приведённой ниже сводке ABNF указаны правила below, расширяемые в соответствии с параграфом 5.6.1 в [HTTP].

   BWS = <BWS, см. [HTTP], параграф 5.6.3>
   HTTP-message = start-line CRLF *( field-line CRLF ) CRLF [
    message-body ]
   HTTP-name = %x48.54.54.50 ; HTTP
   HTTP-version = HTTP-name "/" DIGIT "." DIGIT

   OWS = <OWS, см. [HTTP], параграф 5.6.3>

   RWS = <RWS, см. [HTTP], параграф 5.6.3>

   Transfer-Encoding = [ transfer-coding *( OWS "," OWS transfer-coding
    ) ]

   absolute-URI = <absolute-URI, см. [URI], параграф 4.3>
   absolute-form = absolute-URI
   absolute-path = <absolute-path, см. [HTTP], параграф 4.1>
   asterisk-form = "*"
   authority = <authority, см. [URI], параграф 3.2>
   authority-form = uri-host ":" port

   chunk = chunk-size [ chunk-ext ] CRLF chunk-data CRLF
   chunk-data = 1*OCTET
   chunk-ext = *( BWS ";" BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val
    ] )
   chunk-ext-name = token
   chunk-ext-val = token / quoted-string
   chunk-size = 1*HEXDIG
   chunked-body = *chunk last-chunk trailer-section CRLF

   field-line = field-name ":" OWS field-value OWS
   field-name = <field-name, см. [HTTP], параграф 5.1>
   field-value = <field-value, см. [HTTP], параграф 5.5>

   last-chunk = 1*"0" [ chunk-ext ] CRLF

   message-body = *OCTET
   method = token

   obs-fold = OWS CRLF RWS
   obs-text = <obs-text, см. [HTTP], параграф 5.6.4>
   origin-form = absolute-path [ "?" query ]

   port = <port, см. [URI], параграф 3.2.3>

   query = <query, см. [URI], параграф 3.4>
   quoted-string = <quoted-string, см. [HTTP], параграф 5.6.4>

   reason-phrase = 1*( HTAB / SP / VCHAR / obs-text )
   request-line = method SP request-target SP HTTP-version
   request-target = origin-form / absolute-form / authority-form /
    asterisk-form

   start-line = request-line / status-line
   status-code = 3DIGIT
   status-line = HTTP-version SP status-code SP [ reason-phrase ]

   token = <token, см. [HTTP], параграф 5.6.2>
   trailer-section = *( field-line CRLF )
   transfer-coding = <transfer-coding, см. [HTTP], параграф 10.1.4>

   uri-host = <host, см. [URI], параграф 3.2.2>

Приложение B. Различия между HTTP и MIME

В HTTP/1.1 используются многие конструкции, определённые для формата сообщений Internet [RFC5322] и многоцелевых почтовых расширений (Multipurpose Internet Mail Extensions или MIME) [RFC2045], чтобы тело сообщения можно было передавать в разных открытых представлениях с расширяемыми полями. Однако некоторые из таких конструкций были переосмыслены для лучшего соответствия потребностям интерактивных коммуникаций, что привело к некоторым отличиям при обработке конструкций MIME в HTTP. Эти отличия были внимательно рассмотрены для оптимизации производительности по сравнению с двоичными соединениями, предоставления большей свободы использования новых типов носителей, упрощения сравнения данных и адаптации к базовым реализациям.

В этом приложении описаны конкретные аспекты отличий HTTP от MIME. Прокси и шлюзы в среде со строгими требованиями MIME должны учитывать эти различия и при необходимости выполнять соответствующие преобразования.

B.1. MIME-Version

Протокол HTTP не соответствует MIME, однако сообщения могут включать одно поле заголовка MIME-Version для указания версии протокола MIME, использованной для создания сообщения. Поле MIME-Version говорит, что сообщение полностью совместимо с протоколом MIME (как задано в [RFC2045]). Отправитель отвечает за обеспечения полного соответствия (когда это возможно) при экспорте сообщений HTTP в строгие среды MIME.

B.2. Преобразование в каноническую форму

MIME требует преобразования части тела сообщения почты Internet преобразовывалась в каноническую форму до передачи, как указано в разделе 4 [RFC2049], а в содержимом типа text требуется представлять перевод строк символами CRLF с запретом использования CR и LF вне переноса строк [RFC2046]. HTTP не запрещает применять CRLF и отдельные символы CR или LF для указания завершения строки в содержимом.

Прокси и шлюзы HTTP, передающие в строгую среду MIME должны транслировать все переводы строк внутри носителя типа text в каноническую форму RFC 2049 (CRLF). Однако это может осложняться наличием поля Content-Encoding и тем, что HTTP разрешает использовать некоторые кодировки, где не применяются октеты 13 и 10 для представления CR и LF, соответственно.

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

B.3. Преобразование форматов дат

В HTTP/1.1 применяется ограниченный набор форматов дат (параграф 5.6.7 в [HTTP]) для упрощения сравнения дат. Прокси и шлюзы, принимающие от других протоколов, должны поверять соответствие полей заголовка Date в сообщениях одному из форматов HTTP/1.1 и при необходимости преобразовывать поля.

B.4. Преобразование Content-Encoding

В MIME нет эквивалента поля заголовка HTTP Content-Encoding. Поскольку это поле служит модификатором типа носителя, прокси и шлюзы из HTTP в совместимые с MIME протоколы должны менять значение поля заголовка Content-Type или декодировать представление до пересылки сообщения. Некоторые экспериментальные варианты применения поля Content-Type для почты Internet используют параметр media-type ;conversions=<content-coding> для выполнения функции, эквивалентной Content-Encoding, однако этот параметр не является стандартным для MIME.

B.5. Преобразование Content-Transfer-Encoding

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

B.6. MHTML и ограничения размера строк

Реализации HTTP, имеющие общий код с реализациями MHTML [RFC2557], должны принимать во внимание ограничения MIME на размер строк. Поскольку в HTTP таких ограничений нет, фальцовка строк в HTTP не применяется. Сообщения MHTML, передаваемые через HTTP, соответствуют всем соглашениям MHTML, включая ограничение размера строк, фальцовку и т. п., поскольку HTTP доставляет тело сообщений без изменения и (за исключением типа multipart/byteranges, см. параграф 14.6 в [HTTP]) не интерпретирует содержимое и строки заголовков MIME, которые могут содержаться в нём.

Приложение C. Отличия от предшествующих RFC

C.1. Отличия от HTTP/0.9

Поскольку в HTTP/0.9 не поддерживаются поля заголовков запроса, здесь нет возможности поддерживать виртуальные хосты по именам (выбор ресурса по значению поля Host). Серверы, реализующие поддержку виртуальных хостов по именам, должны отключить использование HTTP/0.9. Большинство запросов, выглядящих как HTTP/0.9, на деле являются некорректно построенными запросами HTTP/1.x, обусловленными неверным кодированием клиентом цели запроса (request-target).

C.2. Отличия от HTTP/1.0

C.2.1. Многодомные Web-серверы

Требование к клиентам и серверам поддерживать поле заголовка Host (параграф 7.2 в [HTTP]), сообщать об ошибке при его отсутствии в запросе HTTP/1.1 и воспринимать абсолютные URI (параграф 3.2), является наиболее важным изменением, внесённым HTTP/1.1.

Старые клиенты HTTP/1.0 предполагали взаимно-однозначное соответствие адресов IP и серверов и не было механизма определить нужный сервер кроме адреса IP, по которому передан запрос. Поле заголовка Host было добавлено при разработке HTTP/1.1 и, хотя оно было быстро реализовано в большинстве браузеров HTTP/1.0, для полной адаптации к HTTP/1.1 были внесены дополнительные требования ко всем запросам. На момент создания этого документа большинство служб на основе HTTP уже зависело от поля Host для нацеливания запросов.

C.2.2. Соединения Keep-Alive

В HTTP/1.0 каждое соединение организуется клиентом перед запросом и закрывается сервером после отправки отклика. Однако некоторые реализации применяли явно согласованный (Keep-Alive) вариант сохраняемых соединений, описанный в параграфе 19.7.1 [RFC2068]. Некоторые клиенты и серверы могут захотеть совместимости с этими подходами к постоянным соединениям, явно согласовывая их с помощью поля заголовка запроса Connection: keep-alive. Однако часть экспериментальных реализаций сохраняемых соединений HTTP/1.0 оказалась ошибочной, например, при непонимании прокси-сервером HTTP/1.0 поля Connection он мог ошибочно пересылать поле заголовка следующему приёмному (inbound) серверу, что вело к зависанию (hung) соединения.

Одной из попыток решения было введение поля заголовка Proxy-Connection, предназначенного специально для прокси. На деле это оказалось неэффективным, поскольку прокси зачастую работают на нескольких уровнях, что снова ведёт к возникновению описанной выше проблемы. В результате клиентам рекомендуется не применять поле Proxy-Connection в каких-либо запросах.

Клиентам также рекомендуется аккуратно относиться к использованию поля Connection: keep-alive в запросах. Хотя оно и позволяет организовать постоянные соединения с серверами HTTP/1.0, использующие их клиенты должны следить за «повисшими» (hung) соединениями (они указывают, что клиент должен прекратить отправку этого поля) и этот механизм вообще не должен использоваться клиентами при работе через прокси.

C.2.3. Введение поля Transfer-Encoding

В HTTP/1.1 добавлено поле заголовка Transfer-Encoding (параграф 6.1). Транспортное кодирование должно декодироваться до пересылки сообщения HTTP по протоколу, соответствующему MIME.

C.3. Отличия от RFC 7230

Большинство разделов, посвящённых целям разработки HTTP, истории, архитектуре, критериям соответствия, версиям протокола, URI, маршрутизации сообщений и полям заголовков, перенесены в [HTTP]. Этот документ был сведён к синтаксису сообщений и требованиям к поддержке соединений, характерным для HTTP/1.1.

Использование «голых» символов CR вне содержимого запрещено (параграф 2.2).

Изменено определение ABNF для authority-form с заменой общей формы компонента authority в URI (с необязательным указанием порта) на конкретную форму host:port, требуемую для CONNECT (параграф 3.2.3).

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

В ABNF для блочных (chunk) расширений снова добавлены «плохие» пробелы вокруг символов ; и =, исключённые в [RFC7230], поскольку это исключение стало препятствием для имеющихся реализаций (параграф 7.1.1).

Семантика полей трейлера выходит за рамки блочного транспортного кодирования. Был обновлён алгоритм декодирования для chunked (параграф 7.1.3), чтобы поощрять сохранение/пересылку полей трейлера отдельно от полей заголовка, разрешать слияние заголовка и трейлера, когда получатель знает, что определения соответствующих полей позволяют это и отбрасывать поля трейлера в ином случае. Трейлерная часть сейчас называется разделом трейлеров, чтобы быть более согласованной с разделом заголовков и отличаться от тела сообщения (параграф 7.1.2).

Запрещены параметры транспортного кодирования с именем q во избежание путаницы с использованием рангов в поле заголовка TE (параграф 7.3).

Благодарности

См. одноимённый раздел в [HTTP].

Предметный указатель

Адреса авторов

Roy T. Fielding (editor)
Adobe
345 Park Ave
San Jose, CA 95110
United States of America
Email: fielding@gbiv.com
URI: https://roy.gbiv.com/
 
Mark Nottingham (editor)
Fastly
Prahran
Australia
Email: mnot@mnot.net
URI: https://www.mnot.net/
 
Julian Reschke (editor)
greenbytes GmbH
Hafenweg 16
48155 Münster
Germany
Email: julian.reschke@greenbytes.de
URI: https://greenbytes.de/tech/webdav/

Перевод на русский язык

nmalykh@protokols.ru


1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

3В оригинале — IETF Contributions. Прим. перев.

4В оригинале — IETF Standards Process. Прим. перев.

5Denial-of-service — отказ в обслуживании.

Рубрика: RFC | Оставить комментарий

RFC 9111 HTTP Caching

Internet Engineering Task Force (IETF)                  R. Fielding, Ed.
Request for Comments: 9111                                         Adobe
STD: 98                                               M. Nottingham, Ed.
Obsoletes: 7234                                                   Fastly
Category: Standards Track                                J. Reschke, Ed.
ISSN: 2070-1721                                               greenbytes
                                                               June 2022

HTTP Caching

Кэширование HTTP

PDF

Аннотация

Протокол передачи гипертекста (Hypertext Transfer Protocol или HTTP) является протоколом прикладного уровня без поддержки состояний для распределенных гипертекстовых информационных систем коллективной работы. Этот документ определяет кэширование HTTP и связанные с ним поля заголовков, управляющие поведением кэша или указывающие кэшируемые сообщения с откликами.

Этот документ отменяет действие RFC 7234.

Статус документа

Документ относится к категории Internet Standards Track.

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG2. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке https://www.rfc-editor.org/info/rfc9111.

Авторские права

Copyright (c) 2022. Авторские права принадлежат IETF Trust и лицам, указанным в качестве авторов документа. Все права защищены.

К документу применимы права и ограничения, указанные в BCP 78 и IETF Trust Legal Provisions и относящиеся к документам IETF (http://trustee.ietf.org/license-info), на момент публикации данного документа. Прочтите упомянутые документы внимательно. Фрагменты программного кода, включённые в этот документ, распространяются в соответствии с упрощённой лицензией BSD, как указано в параграфе 4.e документа IETF Trust Legal Provisions, без каких-либо гарантий (как указано в Revised BSD License).

Этот документ может содержать материалы из документов IETF или участников IETF3, опубликованных или публично доступных до 10 ноября 2008 г. Лица, контролирующие авторские права на некоторые из таких материалов могли не предоставить IETF Trust прав на изменение таких материалов вне контекста стандартизации IETF4. Без получения соответствующей лицензии от лиц, контролирующих авторские права на такие материалы, этот документ не может быть изменён вне контекста стандартизации IETF, а также не могут открываться производные работы за пределами контекста стандартизации. Исключением является лишь форматирование документа для публикации в качестве RFC или перевод на другие языки.

1. Введение

HTTP является протоколом прикладного уровня «запрос-отклик» без поддержки состояний, который использует расширяемую семантику и самоописательные сообщений для гибкого взаимодействия с сетевыми гипертекстовыми информационными системами. Обычно протокол применяется в распределенных информационных системах, где кэширование откликов может повышать производительность. Этот документ задаёт аспекты HTTP, связанные с кэшированием и повторным использованием сообщений с откликами.

Кэш HTTP — это локальное хранилище сообщений с откликами и подсистема управления хранением, извлечением и удалением записей кэша. Кэш сохраняет кэшируемые отклики для снижения времени отклика и расхода пропускной способности при повторении эквивалентных запросов. Любой клиент или сервер может использовать кэш, но не при работе в качестве туннеля (параграф 3.7 в [HTTP]).

Общим (shared) называется кэш, который сохраняет отклики для повторного использования не только одним пользователем. Общий кэш обычно (но не всегда) развёртывается как часть устройства-посредника. Частным (private) называется кэш, выделенный для одного пользователя, что чато реализуется как компонент пользовательского агента.

Целью кэширования HTTP является существенное повышение производительности за счёт неоднократного использования отклика на предшествующее сообщение для выполнения текущего запроса. Кэш считает сохранённый отклик свежим (см. параграф 4.2), если его можно использовать без проверки (пригодности кэшированного отклика для данного запроса). Свежий отклик в кэше может сокращать задержку и загрузку сети при каждом его использовании. Если кэшированный отклик не является свежим, он все равно может использоваться, если проверка может обновить его (параграф 4.3) или источник не доступен (параграф 4.2.4).

Этот документ отменяет RFC 7234, сводка отличий приведена в Приложении B.

1.1. Уровни требований

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

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

1.2. Обозначения синтаксиса

В этой спецификации применяется нотация дополненных форм Бэкуса-Наура (Augmented Backus-Naur Form или ABNF) [RFC5234], расширенная для поддержки строк с учётом регистра символов [RFC7405]. Используется также набор расширений, заданных в параграфе 5.6.1 [HTTP], который позволяет компактно определять списки с разделением запятыми, используя оператор # (подобно указанию повтора оператором *). В Приложении A представлена сводная грамматика операций со списками в стандартной нотации ABNF.

1.2.1. Импортированные правила

Базовое правило DIGIT (decimal 0-9) указано ссылкой на Приложении B.1 к [RFC5234].

В [HTTP] заданы указанные ниже правила

     HTTP-date     = <HTTP-date, [HTTP], параграф 5.6.7>
     OWS           = <OWS, [HTTP], параграф 5.6.3>
     field-name    = <field-name, [HTTP], параграф 5.1>
     quoted-string = <quoted-string, [HTTP], параграф 5.6.4>
     token         = <token, [HTTP], параграф 5.6.2>

1.2.2. Delta-seconds

Правило delta-seconds задаёт неотрицательное целое число, представляющее время в секундах.

     delta-seconds  = 1*DIGIT

Получатель, анализирующий значение delta-seconds и преобразующий его в двоичную форму, должен использовать арифметический тип размером не менее 31 бита из диапазона неотрицательных целых чисел. Если кэш получает значение delta-seconds больше максимального значения, которое он может представить, или при последующих вычислениях возникает переполнение, кэш должен принять значение 2147483648 (231) или наибольшее целое число, которое он может удобно представить.

Примечание. Значение 2147483648 приведено здесь по историческим причинам, оно представляет бесконечность (более 68 лет) и его не обязательно хранить в двоичной форме. Реализация может выдавать его в виде строки в случае переполнения, даже если вычисления выполняются с арифметическим типом, не способным напрямую представить это число. Важно обнаружить переполнение и не считать результат отрицательным значением при последующих расчётах.

2. Обзор операций кэширования

Корректная работа кэша позволяет сохранить семантику передач HTTP, сокращая объем передаваемых по сети данных за счёт использования кэша. Базовая терминология и концепции HTTP описаны в разделе 3 [HTTP].

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

Ключ кэша (cache key) — это информация, которую кэш использует для выбора отклика и которая включает, по меньшей мере, метод запроса и URI, использованные для извлечение сохранённого отклика. Метод определяет обстоятельства, при которых этот отклик можно использовать для выполнения последующих запросов. Однако многие из современных кэшей HTTP кэшируют лишь отклики GET и поэтому в качестве ключа применяется лишь URI.

В кэше может храниться несколько откликов для цели запроса, являющейся предметом согласования содержимого. Кэш различает эти отклики путём включения в ключ некоторых полей заголовка исходного запрос, используя сведения из поля заголовка отклика Vary, как описано в параграфе 4.1. Кэш может включать в ключ дополнительный материал. Например, кэш пользовательского агента может включать отождествление ссылающегося сайта, тем самым «удваивая ключ» что позволяет избежать некоторых рисков приватности (см. параграф 7.2).

Чаще всего в кэшах хранятся успешные результаты запросов на извлечение, например, отклики 200 (OK) на запрос GET, содержащие представление целевого ресурса (параграф 9.3.1 в [HTTP]). Однако могут сохраняться перенаправления, отрицательные (например, 404 (Not Found)) и неполные (например, 206 (Partial Content)) результаты, а также отклики для методов, отличных от GET, если определение метода разрешает такое кэширование и задаёт что-либо пригодное в качестве ключа кэша.

Кэш является «отсоединённым», если он не может связаться с сервером-источником или иным способом найти путь пересылки для запроса. Отсоединённый кэш может в некоторых обстоятельствах обслуживать устаревшие отклики (параграф 4.2.4).

3. Сохранение откликов в кэше

Отклики недопустимо сохранять в кеше, если не выполняются указанные ниже условия:

  • метод запроса понятен для кэша;

  • код статуса в отклике является окончательным (см. раздел 15 в [HTTP]);

  • отклик имеет код статуса 206 или 304 или присутствует директива must-understand (см. параграф 5.2.2.3); кэш понимает код статуса в отклике;

  • если в отклике нет директивы no-store (см. параграф 5.2.2.5);

  • если кэш является общим и директива private в отклике отсутствует или позволяет общему кэшу сохранять изменённый отклик (см. параграф 5.2.2.7);

  • если кэш является общим и поля заголовка Authorization нет в запросе (см. параграф 11.6.2 в [HTTP]) или в отклике имеется директива, явно разрешающая общее кэширование(см. параграф 3.5);

  • отклик содержит хотя бы одно из перечисленного ниже:

    • директива public (см. параграф 5.2.2.9);

    • директива private, если кэш не является общим (см. параграф 5.2.2.7);

    • поле заголовка Expires (см. параграф 5.3);

    • директива max-age (см. параграф 5.2.2.1);

    • директива s-maxage, если кэш является общим (см. параграф 5.2.2.10);

    • расширение, разрешающее кэширование(см. параграф 5.2.3); or

    • код статуса, определённый как эвристически кэшируемый (см. параграф 4.2.2).

Отметим, что расширение кэша может переопределять любое из этих требований (см. параграф 5.2.3).

В этом контексте кэш считается понимающим метод запроса или код статуса в отклике, если он распознает и реализует всё связанное с кэшированием поведение.

Отметим, что при нормальной работе некоторые системы кэширования не будут сохранять отклики, не имеющие ни валидатора кэша, ни явного срока действия, поскольку хранить такие отклики обычно бесполезно, но не запрещено.

3.1. Сохранение полей заголовков и трейлеров

Кэш должен включать при сохранении все полученные поля заголовка отклика (в том числе, нераспознанные), это гарантирует, что новые поля заголовков HTTP будут внедрены. Однако имеется ряд исключений.

  • Поле заголовка Connection и имена указанных в нем полей (в соответствии с параграфом 7.6.1 в [HTTP]) должны удаляться перед пересылкой сообщения. Это может быть выполнено перед сохранением.

  • Семантика некоторых полей требует их удаления перед пересылкой сообщения и это может быть выполнено до сохранения (см. примеры в параграфе 7.6.1 [HTTP]).

  • Директивы кэширования no-cache (параграф 5.2.2.4) и private (параграф 5.2.2.7) могут иметь аргументы, препятствующие сохранению полей заголовка всеми или общими кэшами, соответственно.

  • Поля заголовков, специфичные для прокси, используемого кэшем при пересылке запроса, сохранять недопустимо, если только кэш не включает отождествление прокси в ключ кэша. Фактически это ограничивается полями Proxy-Authenticate (параграф 11.7.1 в [HTTP]), Proxy-Authentication-Info (параграф 11.7.3 в [HTTP]), Proxy-Authorization (параграф 11.7.2 в [HTTP]).

Кэш может сохранять поля трейлера отдельно от полей заголовка или отбрасывать их. В кэше недопустимо объединять поля трейлера с полями заголовка.

3.2. Обновление сохранённых полей заголовков

В некоторых ситуациях кэш должен обновлять сохранённые поля заголовков по другому (обычно, более новому) отклику, например, в случаях, описанных в параграфах 3.4, 4.3.4, 4.3.5. В таких случаях кэш должен добавлять каждое поле заголовка из представленного отклика (за исключением указанных ниже) в сохранённый отклик с заменой уже имеющихся в нем полей.

  • Поля заголовка, ожидаемые от хранилища (параграф 3.1).

  • Поля заголовка, от которых зависит сохранённый в кэше отклик, как описано ниже.

  • Поля заголовка, автоматически обрабатываемые и удаляемые получателем, как описано ниже.

  • Поле заголовка Content-Length.

В некоторых случаях в кэше (особенно у пользовательских агентов) хранятся результаты обработки полученного отклика, а не сам отклик, и обновление полей заголовков, влияющих на обработку, может приводить к несогласованному поведению и проблемам безопасности. В таких ситуациях кэш может исключать такие поля заголовка из обновления, но следует ограничиваться исключением лишь полей, которые влияют на целостность сохранённого отклика. Например, браузер может декодировать содержимое отклика при его получении, что приведёт к разрыву связи между сохраняемыми данными и метаданными исходного отклика. Обновление сохранённых метаданных с использованием другого поля заголовка Content-Encoding может вызвать проблемы. Аналогично, браузер может хранить дерево HTML после разбора, а не содержимое, принятое в отклике и обновление поля заголовка Content-Type в этом случае будет невозможным, поскольку любые допущения о формате, принятые при разборе, окажутся недействительными.

Кроме того, некоторые поля, например, Content-Range, автоматически обрабатываются и удаляются реализацией HTTP. Реализации могут автоматически опускать такие поля, даже если они на деле не обрабатываются.

Отметим, что префикс Content-* не является сигналом об исключении поля заголовка из обновления, это соглашение предназначено для полей заголовков MIME, а не HTTP.

3.3. Сохранение неполных откликов

Если метод запроса — GET, код статуса в отклике — 200 (OK) и раздел заголовков запроса получен целиком, в кэше можно сохранить неполный отклик (параграф 6.1 в [HTTP]), если при записи неполнота будет указана. Аналогично, можно сохранить отклик 206 (Partial Content) как неполный отклик 200 (OK). Однако в кэше недопустимо сохранять неполные отклики или отклики с частью содержимого, если в них нет полей заголовка Range и Content-Range или непонятны единицы диапазона в этих полях.

Кэш может дополнять сохранённые неполные отклик, выполняя последующий запрос диапазона (параграф 14.2 в [HTTP]) и объединяя отклик о его успехе с сохраненным откликом, как указано в параграфе 3.4. В кэше недопустимо использовать неполный отклик на запрос, пока этот отклик не был завершён, или запрос не являлся частичным с указанием диапазона, полностью включённого в неполный отклик. Кэшу недопустимо передавать частичный отклик клиенту без явной маркировки его кодом статуса 206 (Partial Content).

3.4. Объединение частичного содержимого

Отклик может передавать лишь часть представления, если соединение разорвано преждевременно или в запросе указано одно или несколько полей Range (параграф 14.2 в [HTTP]). После нескольких таких передач в кэше может оказаться несколько диапазонов одного представления. Кэш может объединить эти диапазоны в один сохранённый отклик и использовать его для выполнения будущих запросов, если в них будет тот же строгий валидатор и кэш соответствует требованиям клиента из параграфа 15.3.7.3 в [HTTP]. При создании объединённого отклика из сохранённых откликов кэш должен обновить поля заголовка сохраняемого отклика, используя поля из нового отклика, как указано в параграфе 3.2.

3.5. Сохранение откликов на аутентифицированные запросы

В общем кэше недопустимо использовать кэшированный отклик на запрос с полем заголовка Authorization (параграф 11.6.2 в [HTTP]) для выполнения последующих запросов, если отклик не содержит поля Cache-Control с директивой (параграф 5.2.2), разрешающей сохранение в общем кэше, и соответствии этого кэша требованиям директивы для данного отклика. В этой спецификации заданы директивы с таким эффектом: must-revalidate (параграф 5.2.2.2), public (параграф 5.2.2.9), s-maxage (параграф 5.2.2.10).

4. Создание откликов из кэша

При представлении запроса кэшу недопустимо использовать сохранённый отклик, если не выполняются все указанные ниже условия.

  • Представленное значение URI цели (параграф 7.1 в [HTTP]) совпадает с сохраненным откликом.

  • Связанный с сохраненным откликом метод запроса позволяет использовать отклик для представленного запроса.

  • Поля заголовка запроса, указанные в сохранённом отклике (при наличии) совпадают с представленными полями (см. параграф 4.1).

  • В сохранённом отклике нет директивы no-cache (параграф 5.2.2.4), если только он не был успешно проверен (параграф 4.3).

  • Сохранённый отклик является одним из указанных ниже:

    • fresh (см. параграф 4.2);

    • разрешён для обслуживания при устаревании (см. параграф 4.2.4);

    • успешно обновлён (см. параграф 4.3).

Отметим, что расширение кэша может переопределять любые из указанных требований (см. параграф 5.2.3).

Когда сохранённый отклик используется для выполнения запроса без проверки, кэш должен генерировать поле заголовка Age (параграф 5.1), заменяя любое имеющееся в отклике значение на current_age из сохранённого отклика (см. параграф 4.2.3).

Кэш должен записывать запросы к серверу-источнику с небезопасными методами (параграф 9.2.1 в [HTTP]), т. е. ему не разрешается генерировать отклик на такой запрос до пересылки запроса и получения соответствующего отклика. Следует также отметить, что небезопасные запросы могут аннулировать уже сохранённые отклики (см. параграф 4.4).

Кэш может использовать сохранённый или сохраняемый отклик для выполнения нескольких запросов при условии разрешения на повторное использование данного отклика для этих запросов. Это позволяет кэшу сворачивать (collapse) запросы, т. е. объединять несколько входящих запросов в один пересылаемый запрос при отсутствии записи в кэше, снижая тем самым нагрузку на сеть и сервер-источник. Однако, если кэш не может использовать возвращённый отклик для части или всех свёрнутых запросов, ему потребуется переслать запросы для их выполнения, что может приводить к дополнительным задержкам.

Если хранится более одного подходящего отклика, кэш должен выбрать последний (по полю заголовка Date) и может также переслать запрос с Cache-Control: max-age=0 или Cache-Control: no-cache для выбора используемого отклика.

Кэш без часов (параграф 5.6.7 в [HTTP]) должен перепроверять сохранённые отклики при каждом их использовании.

4.1. Расчёт ключей кэша с полем заголовка Vary

При получении кэшем запроса, который можно выполнить по сохранённому отклику, и этот отклик включает поле заголовка Vary (параграф 12.5.5 в [HTTP]), недопустимо использовать сохранённый отклик без проверки совпадения полей нового запроса, указанных Vary, с соответствующими полями исходного запроса (вызвавшего сохранение отклика). Поля двух запросов считаются совпадающими лишь в том случае, когда поля первого запроса могут быть преобразованы в поля второго с использованием любого из указанных ниже методов:

  • добавление или удаление пробелов, разрешённое синтаксисом поля заголовка;

  • объединение нескольких строк заголовка с одноимённым полем (см. параграф 5.2 в [HTTP]);

  • нормализация полей обоих заголовков так, чтобы они имели идентичную семантику в соответствии со спецификацией поля (например, смена порядка значений, если он не важен, смена регистра, когда он не учитывается).

Если поле заголовка (после указанной нормализации) отсутствует в запросе, оно может соответствовать только отсутствию поля и в другом запросе. Сохранённый запрос с полем заголовка Vary, содержащим *, никогда не будет соответствовать.

Если совпадает несколько сохранённых откликов, кэш должен выбрать один из них. Если для указанного поля заголовка имеется механизм ранжирования (например, qvalue в Accept или похожих полях), этот механизм можно использовать для выбора предпочтительного отклика. Если такого механизма нет или предпочтения одинаковы, выбирается наиболее свежий отклик (по полю Date), как указано в разделе 4.

Некоторые ресурсы ошибочно опускают поле Vary в принятом по умолчанию отклике (т. е. в отклике на запрос без предпочтений), в результате чего этот отклик выбирается для последующих запросов даже при наличии более предпочтительного отклика. Когда в кэше имеется несколько сохранённых откликов для URI цели и в каких-либо из них нет поля Vary, кэшу следует выбирать наиболее свежий (см. параграф 4.2.3) отклик с действительным полем Vary.

Если нет соответствующего сохранённого отклика, кэше не может выполнить представленный запрос. Обычно такой запрос пересылается серверу-источнику, возможно, с добавлением предварительных условий для описания откликов, имеющихся в кэше (параграф 4.3).

4.2. fresh

«Свежим» считается отклик, возраст которого ещё не превысил срок свежести. Иные отклики считаются старыми. Сроком свежести отклика считается интервал времени между генерацией отклика сервером-источником и завершением срока действия. Явным сроком действия ACK называют время, по истечении которого сервер-источник считает, что сохранённый отклик больше не может использоваться кэшем без дополнительной проверки, а эвристический срок действия задаётся кэшем при недоступности явного срока действия. Возрастом отклика называют время, прошедшее с момента его создания или успешной проверки сервером-источником. Свежий отклик может применяться для ответов на последующие запросы без обращения к северу-источнику, что повышает эффективность.

Основным механизмом проверки свежести отклика является явно указанный сервером-источником срок свежести в поле заголовка Expires (параграф 5.3) или директиве отклика max-age (параграф 5.2.2.1). Обычно сервер-источник назначает откликам явное время завершения срока действия в будущем, полагая, что представление вряд ли изменится семантически значимым образов в течение срока действия. Если сервер-источник хочет заставить кэш проверять каждый запрос, он может указать завершение срока действия в прошлом, чтобы указать, что отклик уже устарел. Соответствующий спецификации кэш обычно проверяет устаревшие отклики перед применением для последующих запросов (см. параграф 4.2.4).

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

      response_is_fresh = (freshness_lifetime > current_age)

Параметр freshness_lifetime задан в параграфе 4.2.1, current_age — в параграфе 4.2.3.

Клиенты могут передавать запросы с директивами max-age или min-fresh (параграф 5.2.1) для указания ограничений при расчёте свежести соответствующего отклика. Однако кэш не обязан соблюдать их. При расчёте свежести следует избегать общих проблем анализа дат, указанных ниже.

  • Хотя все форматы дат задают учёт регистра символов, получателю кэша следует сравнивать значения полей без учёта регистра.

  • Если внутренняя реализация часов у получателя кэша имеет меньшее разрешение, чем значение HTTP-date, получатель должен представить дату Expires как ближайшее время не позже полученного значения.

  • Получателю кэша недопустимо разрешать влияние локального часового пояса при расчёте и сравнении возраста или срока действия.

  • Получателю кэша следует считать даты с обозначением часового пояса, отличным от GMT, недействительными для расчёта срока действия.

Отметим, что свежесть относится только к работе кэша и не может служить для того, чтобы вынудить агент пользователя обновить своё отображение или заново загрузить ресурс. Различия между кэшированием и механизмами истории рассмотрены в разделе 6.

4.2.1. Расчёт срока свежести

Кэш может рассчитывать срок свежести (freshness_lifetime) отклика по приведённым ниже правилам до совпадения.

  • Если кэш является общим и имеется директива s-maxage (параграф 5.2.2.10) применяется её значение.

  • При наличии в отклике директивы max-age (параграф 5.2.2.1) применяется её значение.

  • При наличии поля заголовка Expires (параграф 5.3) применяется его значение за вычетом значения поля Date в отклике (времени приёма сообщения, если этого поля нет, как указано в параграфе 6.6.1 [HTTP])

  • В иных случаях явный срок свежести не указан и можно применять эвристическое значение (параграф 4.2.2).

Отметим, что этот расчёт предназначен для снижения расхождения часов путём использования сведений о времени от сервера-источника, когда это возможно.

При наличии более одного значения (например, двух строк поля Expires или нескольких директив Cache-Control: max-age) применяется первое из них или отклик считается устаревшим. Если директивы конфликтуют (например, имеются max-age и no-cache ), следует применять более ограничительную из них. Кэшу рекомендуется считать устаревшими отклики с недействительным сроком свежести (например, max-age с нецелочисленным значением).

4.2.2. Расчёт эвристической свежести

Серверы-источники не всегда явно указывают срок свежести, поэтому кэш может назначать в таких случаях эмпирическое значение срока на основе алгоритмов, использующих значения других полей (например, Last-Modified) для правдоподобной оценки срока свежести. Эта спецификация не задаёт конкретный алгоритм, но вносит ограничения на результат для худших случаев.

Кэшу недопустимо применять эвристику для определения свежести при наличии в сохранённом отклике явного срока свежести. В соответствии с требованием раздела 3 эвристика может применяться лишь для откликов без явного срока свежести, в который коды статуса указаны как эвристически кэшируемые (см. параграф 15.1 в [HTTP]), и откликов без явного срока свежести, помеченных как кэшируемые (например, с помощью директивы public).

Отметим, что в прежних спецификациях эвристически кэшируемые отклики назывались кэшируемыми по умолчанию.

Если в отклике имеется поле заголовка Last-Modified (параграф 8.8.2 в [HTTP]), кэшу рекомендуется использовать значение эвристического срока свежести, которое не превышает некую долю прошедшего с этого момента времени (обычно используется 10%).

Примечание. Предыдущая версия спецификации HTTP (параграф 13.9 в [RFC2616]) запрещала кэшам вычислять эвристический срок свежести для URI с компонентами запроса (т. е. включающими ?). На практике это не получило широкого распространения, поэтому серверам-источникам рекомендуется передавать явные директивы (например, Cache-Control: no-cache) для предотвращения кэширования.

4.2.3. Расчёт возраста

Поле заголовка Age служит для передачи оценки возраста сообщения с откликом, полученного из кэша. Age содержит оценку кэшем числа секунд с момента генерации или проверки отклика сервером-источником, которая определяется суммой времени пребывания этого отклика в каждом кэше на пути от сервера-источника и времени, затраченного на передачу через сеть. При расчёте Age применяются указанные ниже данные.

age_value

Значение поля заголовка Age (параграф 5.1) в пригодной для арифметических действий форме или 0 (при недоступности.

date_value

Значение поля заголовка Date в пригодной для арифметических действий форме. Определение поля и требования к откликам без него приведены в параграфе 6.6.1 [HTTP].

now

Текущее время по часам реализации (параграф 5.6.7 в [HTTP]).

request_time

Значение часов в момент запроса, вызвавшего сохранённый отклик.

response_time

Значение часов в момент получения отклика.

Возвраст отклика можно рассчитать двумя полностью независимыми способами.

  1. Видимый возраст apparent_age = response_time и date_value, если часы реализации достаточно точно синхронизированы с часами сервера-источника. При получении отрицательного значения принимается 0.

  2. Уточнённый возраст corrected_age_value, если все кэши на пути реализуют HTTP/1.1 или выше. Кэш должен интерпретировать это значение относительно времени инициирования запроса, а не времени приёма отклика.

     apparent_age = max(0, response_time - date_value);
     response_delay = response_time - request_time;
     corrected_age_value = age_value + response_delay;

Значение corrected_age_value может применяться как corrected_initial_age. В ситуациях, где имеются очень старые реализации кэшей, некорректно устанавливающие Age, значение corrected_initial_age может вычисляться более консервативно как

corrected_initial_age = max(apparent_age, corrected_age_value);

Значение current_age для сохранённого отклика можно после этого рассчитать путём сложения corrected_initial_age с числом секунд с момента последнего обновления сохранённого отклика сервером источником.

     resident_time = now - response_time;
     current_age = corrected_initial_age + resident_time;

4.2.4. Работа с устаревшими откликами

Устаревшим (stale) считается отклик, явно содержащий сведения об истечении срока действия или разрешающий эвристическую оценку срока действия, которая указывает его несвежесть в соответствии с расчётами из параграфа 4.2.

Кэшу недопустимо генерировать устаревший отклик, если это запрещено явной директивой в протоколе (например, no-cache, must-revalidate, применимой директивой s-maxage или proxy-revalidate, см. параграф 5.2.2). Кэшу недопустимо генерировать устаревший отклик, если кэш не отсоединён или это не разрешено явно клиентом или сервером-источником (например, директивой max-stale из параграфа 5.2.1, директивами расширения вроде описанных в [RFC5861] или конфигурацией в соответствии с отдельным (out-of-band) соглашением.

4.3. Проверка

При наличии в кэше хотя бы одного сохранённого отклика для запрошенного URI и невозможности применить его (например, по причине несвежести или невозможности выбрать, см. параграф 4.1), можно использовать механизм условного запроса (раздел 13 в [HTTP]) при пересылке, чтобы дать следующему приёмному серверу возможность выбрать пригодный для использования сохранённый отклик, обновляющий обрабатываемые сохранённые метаданные или заменяющий сохранённый отклик(и). Это процесс называется проверкой или перепроверкой сохранённого отклика.

4.3.1. Передача запроса на проверку

При создании условного запроса на проверку кэш начинает с запроса, который он пытается выполнить, или (если запрос создаётся независимо) синтезирует запрос, используя сохранённый отклик путём копирования метода, URI цели и полей заголовка, указанных полем заголовка Vary (параграф 4.1). Затем в запрос включается одно или несколько полей заголовка с условиями. Эти поля содержат валидатор данных, полученный из сохранённых откликов с тем же URI. Обычно включаются лишь сохранённые отклики с тем же ключом кэша, хотя разрешается проверять отклики, которые невозможно выбрать с помощью передаваемых полей заголовка запроса (см. параграф 4.1).

Поля условий из заголовка сравниваются получателями для определение наличия сохранённого отклика, эквивалентного текущему представлению ресурса. Одним из валидаторов является метка времени из поля заголовка Last-Modified (параграф 8.8.2 в [HTTP]), которую можно указать в поле заголовка If-Modified-Since для проверки отклика или в поле If-Unmodified-Since или If-Range для выбора представления (т. е. клиент обращается к конкретному полученному ранее представлению по этой метке). Другим валидатором является тег сущности в поле заголовка ETag (параграф 8.8.3 в [HTTP]). Один или несколько тегов сущностей, указывающих сохранённые отклики, можно использовать в поле заголовка If-None-Match для проверки отклика или в поле If-Match или If-Range для выбора представления (т. е. клиент указывает конкретно одно или несколько ранее полученных представлений с теми же тегами сущности).

При генерации условного запроса для проверки:

  • должны передаваться соответствующие теги сущностей (в If-Match, If-None-Match, If-Range), если такие теги были представлены в проверяемых сохранённых откликах;

  • следует передавать значение Last-Modified (в If-Modified-Since), если запрос не относится к проверяемому поддиапазону и отклик содержит значение Last-Modified;

  • можно передавать значение Last-Modified (в If-Unmodified-Since или If-Range), если запрос относится к поддиапазону, проверяется один сохранённый отклик и он содержит только Last-Modified (без тега сущности).

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

4.3.2. Обработка полученных запросов на проверку

Каждый клиент в цепочке запросов может иметь свой кэш, поэтому обычно кэш посредника получает условные запросы от других (передающих — outbound) кэшей. Некоторые пользовательские агенты тоже применяют условные запросы для ограничения передачи данных, чтобы принимать лишь недавно обновлённые представления или завершать передачу полученного частично представления.

Если кэш получает запрос, который можно выполнить путём повторного использования сохранённого отклика 200 (OK) или 206 (Partial Content) в соответствии с параграфом 4, ему следует оценить и применить поля заголовка с условиями по имеющимся валидаторам, содержащимся в сохранённом запросе. Кэшу недопустимо оценивать условные поля заголовков, применимые лишь к серверу-источнику, а также поля, встречающиеся в запросе с семантикой, невыполнимой с кэшированным откликом, или в запросе с целевым ресурсом, для которого нет сохранённых откликов. Такие условия, вероятно, предназначены для другого принимающего (inbound) сервера.

Корректная оценка условных запросов кэшем зависит от полученных полей заголовка с условиями и их приоритета. Поля заголовка If-Match и If-Unmodified-Since не применимы к кэшу, поэтому запрос должен пересылаться источнику, а поле If-None-Match имеет преимущество перед If-Modified-Since. Полная спецификация приоритетов условий приведена в параграфе 13.2.2 [HTTP]5.

Запрос с полем If-None-Match (параграф 13.1.2 в [HTTP]) указывает, что клиент хочет сравнить один или несколько сохранённых у него откликов с сохраненным откликом, выбранным кэшем (в соответствии с параграфом 4). Если этого поля нет, но имеется поле If-Modified-Since (параграф 13.1.3 в [HTTP]), запрос показывает, что клиент хочет проверить один или несколько сохранённых им откликов по датам изменения.

Если запрос содержит поле заголовка If-Modified-Since, а в сохранённом отклике нет поля Last-Modified, для проверки условий следует использовать поле Date из сохранённого отклика (или время получения этого отклика, если Date нет).

Кэш, поддерживающий частичные отклики на запросы с диапазоном в соответствии с параграфом 14.2 в [HTTP], должен сравнивать полученное поле заголовка If-Range (параграф 13.1.5 в [HTTP]) с выбранным им откликом.

Когда кэш решает переслать запрос на перепроверку своих сохранённых откликов для запроса со списком тегов сущностей If-None-Match, он может объединить полученный список со списком тегов сущностей из сохранённого им набора откликов (свежих и старых) и передать совокупный список как замену поля If-None-Match в пересылаемом запросе. Если сохранённый отклик включает лишь часть содержимого, кэшу недопустимо включать свой тег сущности в объединение, если только запрос с диапазоном не был полностью выполнен сохраненным частичным откликом. Если отклик на пересланный запрос имеет код 304 (Not Modified) и содержит поле ETag с тегом сущности, отсутствующим в списке клиента, кэш должен генерировать отклик 200 (OK) для клиента, используя соответствующий сохранённый отклик, обновленный метаданными из отклика 304 (параграф 4.3.4).

4.3.3. Обработка откликов о проверке

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

  • Код 304 (Not Modified) указывает, что сохранённый отклик можно обновить и использовать снова (параграф 4.3.4).

  • Полный отклик (включающий содержимое) показывает, что не подходит ни один из сохранённых откликов, отмеченных в условном запросе. Кэш должен использовать для выполнения запроса полный отклик и может сохранить этот отклик в соответствии со своими ограничениями (см. раздел 3).

  • Если кэш получает код 5xx (Server Error) при попытке проверить отклик, он может переслать полученный отклик запрашивающему клиенту или действовать как при отсутствии отклика от сервера. Во втором случае кэш может передать сохранённый ранее отклик с учётом ограничений (параграф 4.2.4) или повторить запрос на проверку.

4.3.4. Обновление сохранённых откликов после проверки

Когда кэш получает отклик 304 (Not Modified), ему необходимо идентифицировать сохранённые отклики, которые можно обновить по этому отклику, и выполняет обновления. В исходный набор для обновления входят отклики, которые могли быть выбраны для данного запроса, т. е. соответствующие требованиям раздела 4, за исключением последнего требования быть свежими, подходящими для обслуживания несвежих или просто обновлёнными. Затем отклики исходного набора фильтруются по приведённым ниже условиям (до первого совпадения).

  • Если новый отклик содержит хотя бы один строгий валидатор (см. параграф 8.8.1 в [HTTP]), каждый из этих валидаторов указывает выбранное представление для обновления. Обновление применяется ко всем сохраненным откликам, имеющим один из таких строгих валидаторов. Если ни в одном из откликов исходного набора нет таких строгих валидаторов, кэшу недопустимо использовать новый отклик для обновления.

  • Если в новом отклике нет строгих валидаторов, но имеется хотя бы один слабый валидатор и эти валидаторы соответствуют одному из откликов исходного набора, для обновления указывается последний из соответствующих сохранённых откликов.

  • Если в новом отклике совсем нет валидаторов (например, когда клиент генерирует запрос If-Modified-Since по источнику, отличному от поля Last-Modified в заголовке отклика) и в исходном наборе имеется лишь один сохранённый отклик, в котором тоже нет валидатора, сохранённый отклик указывается для обновления.

Для каждого идентифицированного сохранённого отклика кэш должен обновить поля заголовка значениями полей из отклика 304 (Not Modified), как указано в параграфе 3.2.

4.3.5. Обновление откликов с HEAD

Отклик для метода HEAD идентичен отклику на запрос GET, но не передаёт содержимого. Это свойство откликов HEAD может служить для аннулирования или обновления кэшированных откликов GET при недоступности более эффективного механизма условных запросов (из-за отсутствия валидаторов в сохранённом отклике) или передача содержимого нежелательна даже при его изменении.

Когда кэш выполняет входящий запрос HEAD для URI цели и получает отклик 200 (OK), ему следует обновить или аннулировать каждый из сохранённых откликов GET, которые могли быть выбраны для этого запроса (параграф 4.1). Для каждого из сохранённых откликов, который мог быть выбран, кэшу следует обновить сохранённый отклик, как описано ниже, если сохранённый отклик и отклик HEAD имеют совпадающие значения любых полученных полей валидаторов (ETag и Last-Modified) и отклик HEAD имеет поле заголовка Content-Length, значение которого соответствует Content-Length в сохранённом отклике. В противном случае кэшу следует считать сохранённый отклик устаревшим.

Если кэш обновляет сохранённый отклик по метаданным из отклика HEAD, он должен использовать для обновления поля заголовка из отклика HEAD (см. параграф 3.2).

4.4. Аннулирование сохранённых откликов

Поскольку небезопасные методы запросов (параграф 9.2.1 в [HTTP]), такие как PUT, POST и DELETE могут изменять состояние сервера-источника, промежуточные кэши должны аннулировать сохранённые отклики для поддержки актуальности их содержимого. Кэш должен аннулировать URI цели (параграф 7.1 в [HTTP]) при получении не связанного с ошибкой кода статуса в отклике на небезопасный метод (включая методы, о безопасности которых не известно) и может аннулировать другие URI в таких случаях. В частности, кандидатами на аннулирование являются URI в полях заголовка Location и Content-Location (при наличии), другие URI могут обнаруживаться механизмами, не заданными в этом документе. Однако кэшу недопустимо инициировать аннулирование при этих условиях, если источник (параграф 4.3.1 в [HTTP]) из URI для аннулирования отличается от URI цели (параграф 7.1 в [HTTP]). Это помогает предотвратить DoS6-атаки.

Аннулирование означает, что кэш будет удалять сохранённые отклики с URI цели, совпадающим с данным URI или помечать их как недействительные и нуждающиеся в обязательной проверке перед отправкой в ответ на запрос.

Не связанными с ошибками откликами считаются отклики с кодами статуса 2xx (Successful) и 3xx (Redirection).

Отметим, что это не гарантирует глобальное аннулирование всех соответствующих откликов и меняющие состояние запросы будут аннулировать лишь отклики в кэшах, через которые эти запросы проходят.

5. Определения полей

В этом разделе определяется синтаксис и семантика полей HTTP, связанных с кэшированием.

5.1. Age

Поле заголовка откликов Age передаёт оценку отправителем времени, прошедшего с момента генерации или успешной проверки сервером-источником. Значение Age рассчитывается в соответствии с параграфом 4.2.3.

     Age = delta-seconds

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

Хотя поле определено как одиночное, кэшу, встретившему сообщение со списочным полем Age, следует взять из списка первой значение и отбросить остальные. Если значение поля (после отбрасывания лишнего) является недействительным (например, не является неотрицательным целым числом), кэшу следует игнорировать поле.

Наличие поля Age подразумевает, что этот отклик не был создан или проверен сервером для данного запроса. Однако отсутствие Age не подразумевает контакта с источником.

5.2. Cache-Control

Поле заголовка Cache-Control служит для перечисления директив для кэшей в цепочке запрос-отклик. Директивы кэша являются однонаправленными в том смысле, что наличие директивы в запросе не предполагает её включения в отклик. Сведения об обработке директив Cache-Control, определённых в других местах, приведены в параграфе 5.2.3.

Прокси (независимо от реализации в них кэша) должны передавать директивы кэширования в пересылаемых откликах, независимо от их значимости для данного приложения, поскольку директивы могут применяться для всех получателей в цепочке запрос-отклик. Невозможно задать директиву только для конкретного кэша.

Директивы кэширования задаются маркером (без учёта регистра символов) и могут иметь аргумент, который может быть задан маркером или строкой в кавычках. Для определённых ниже директив с аргументами получатель должен воспринимать обе формы, даже если при генерации требуется определённая форма.

     Cache-Control   = #cache-directive
     cache-directive = token [ "=" ( token / quoted-string ) ]

Для описанных ниже директив аргументы не определены (не разрешены), если явно не указано иное.

5.2.1. Директивы запроса

Далее определены директивы кэширования для запроса. Они не обязательны и кэш может не реализовать их.

5.2.1.1. max-age

Синтаксис аргумента

      delta-seconds (см. параграф 1.2.2)

Директива запроса max-age указывает, что клиент предпочитает отклике с возрастом не более заданного аргументом директивы числа секунд. Отсутствие директивы запроса max-stale указывает, что клиент не хочет получать устаревшие отклики. Аргумент этой директивы использует маркерную форму, например, max-age=5, а не max-age=»5″. Отправителю недопустимо использовать строку в кавычках.

5.2.1.2. max-stale

Синтаксис аргумента

      delta-seconds (см. параграф 1.2.2)

Директива запроса max-stale указывает, что клиент воспримет отклик с истёкшим сроком свежести. Присутствие значения говорит о том, что клиент готов воспринимать отклики, срок свежести которых истёк не более указанного числа секунд назад. Если значение max-stale не задано, клиент будет воспринимать устаревшие отклики с любым возрастом. Аргумент этой директивы использует маркерную форму, например, max-stale=10, а не max-stale=»10″. Отправителю недопустимо использовать строку в кавычках.

5.2.1.3. min-fresh

Синтаксис аргумента

      delta-seconds (см. параграф 1.2.2)

Директива запроса min-fresh указывает, что клиент предпочитает отклики со сроком свежести не меньше суммы текущего возраста и указанного аргументом числа секунд, т. е. отклики, которые будут сохранять свежесть ещё в течение указанного числа секунд. Аргумент этой директивы использует маркерную форму, например, min-fresh=20, а не min-fresh=»20″. Отправителю недопустимо использовать строку в кавычках.

5.2.1.4. no-cache

Директива запроса no-cache говорит, что клиент предпочитает не использовать для выполнения запроса сохранённые отклики без успешной проверки сервером-источником.

5.2.1.5. no-store

Директива запроса no-store указывает, что кэшу недопустимо сохранять какую-либо часть запроса и отклика на него. Директива применяется как для приватных, так и для общих кэшей. Недопустимость сохранения в этом контексте означает, что кэшу недопустимо намеренно записывать информацию в энергонезависимое хранилище и он должен приложить максимум усилий для удаления информации из временного хранилища как можно быстрее после её пересылки. Эта директива не является надёжным и достаточным средством обеспечения приватности. В частности, вредоносные или скомпрометированные кэши могут не распознавать или не исполнять эту директиву, а коммуникационные сети могут быть доступны для прослушивания.

Отметим, что при выполнении запроса с такой директивой из кэша она не применяется к уже сохранённому отклику.

5.2.1.6. no-transform

Директива запроса no-transform указывает, что клиент просит посредников избегать преобразования содержимого (параграф 7.7 в [HTTP].

5.2.1.7. only-if-cached

Директива запроса only-if-cached указывает, что клиент хочет получить только сохранённый отклик. Кэшу, соблюдающему эту директиву следует при её получении отвечать сохраненным откликом, соответствующим другим ограничениям для запроса или кодом 504 (Gateway Timeout).

5.2.2. Директивы отклика

Далее определены директивы кэширования для отклика. Кэш должен подчиняться директивам Cache-Control, заданным здесь.

5.2.2.1. max-age

Синтаксис аргумента

      delta-seconds (см. параграф 1.2.2)

Директива отклика max-age указывает, что отклик будет сочтён устаревшим, когда его возраст превысит заданное значение (в секундах). Аргумент этой директивы использует маркерную форму, например, max-age=5, а не max-age=»5″. Отправителю недопустимо использовать строку в кавычках.

5.2.2.2. must-revalidate

Директива отклика must-revalidate указывает, что после признания отклика устаревшим кэшу недопустимо использовать его для выполнения другого запроса до успешной проверки источником, как указано в параграфе 4.3.

Директива must-revalidate нужна для поддержки надёжной работы некоторых функций протокола. При любых обстоятельствах кэшу недопустимо игнорировать must-revalidate. В частности, если кэш отсоединён, он должен возвращать ошибку вместо использования старого отклика. В отклике следует указывать код статуса 504 (Gateway Timeout), если нет более подходящего кода.

Серверы должны использовать директиву must-revalidate тогда и только тогда, когда неспособность проверить запрос может вызвать некорректные действия, например, неисполнение финансовой транзакции.

Директива must-revalidate позволяет общему кэшу повторно использовать отклик на запрос с полем Authorization (параграф 11.6.2 в [HTTP]) при соблюдении указанного выше требования о проверке (параграф 3.5).

5.2.2.3. must-understand

Директива отклика must-understand ограничивает кэширование отклика случаями, когда кэш понимает и выполняет требования к этому коду статуса в отклике.

Отклику с директивой must-understand следует включать также директиву no-store. Когда кэш, реализующий директиву must-understand, получает отклик с такой директивой, ему следует игнорировать no-store, если он понимает и реализует требования к кэшированию для кода статуса.

5.2.2.4. no-cache

Синтаксис аргумента

      #field-name

Директива отклика no-cache в неполном формате (без аргумента) указывает, что отклик недопустимо использовать для выполнения любого другого запроса без его пересылки для проверки и получения отклика об успехе (см. параграф 4.3). Это позволяет серверу-источнику предотвратить использование отклика кэшем без связи с сервером, даже если кэш настроен на отправку устаревших откликов.

Полная форма директивы no-cache с аргументом, содержащим список имён полей, указывает, что кэш может использовать отклик для выполнения последующего запроса (при соблюдении других ограничений на кэширование), если перечисленные в аргументе поля заголовков исключены из последующего отклика или этот отклик успешно перепроверен сервером-источником (обновление или удаление этих полей). Это позволяет серверу-источнику предотвратить повторное использование некоторых полей заголовка в отклике, разрешая кэшировать остальное. Имена полей в аргументе не ограничены заданным этой спецификацией набором. Регистр символов не учитывается.

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

Примечание. Кэши часто обрабатываю полную директиву no-cache как неполную, т. е. специальная обработка полной формы не получила широкого распространения.

5.2.2.5. no-store

Директива отклика no-store указывает, что кэшу недопустимо сохранять какую либо часть отклика или соответствующего запроса, а также недопустимо использовать этот отклик для выполнения другого запроса.

Директива применяется как для приватных, так и для общих кэшей. Недопустимость сохранения в этом контексте означает, что кэшу недопустимо намеренно записывать информацию в энергонезависимое хранилище и он должен приложить максимум усилий для удаления информации из временного хранилища как можно быстрее после её пересылки. Эта директива не является надёжным и достаточным средством обеспечения приватности. В частности, вредоносные или скомпрометированные кэши могут не распознавать или не исполнять эту директиву, а коммуникационные сети могут быть доступны для прослушивания.

Отметим, что директива must-understand в некоторых случаях отменяет no-store (см. параграф 5.2.2.3).

5.2.2.6. no-transform

Директива отклика no-transform указывает, что посредникам (независимо от поддержки кэширования) недопустимо преобразовывать содержимое (см. параграф 7.7 в [HTTP]).

5.2.2.7. private

Синтаксис аргумента

      #field-name

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

Имена полей в аргументе не ограничены заданным этой спецификацией набором. Регистр символов не учитывается.

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

Примечание. Приватность в этом контексте относится лишь к местам сохранения отклика и не связана с сохранением приватности содержимого сообщения. Кэши часто обрабатываю полную директиву private как неполную, т. е. специальная обработка полной формы не получила широкого распространения.

5.2.2.8. proxy-revalidate

Директива отклика proxy-revalidate указывает, что после признания отклика устаревшим кэшу недопустимо использовать его для выполнения другого запроса до успешной проверки источником, как указано в параграфе 4.3. Это аналогично must-revalidate (параграф 5.2.2.2), но директива proxy-revalidate не применяется к приватным кэшам.

Отметим, что директива proxy-revalidate сама по себе не предполагает, что отклик является кэшируемым. Например, она может применяться вместе с директивой public (параграф 5.2.2.9), позволяя кэшировать отклик и требуя лишь перепроверки устаревших откликов в общем кэше.

5.2.2.9. public

Директива отклика public указывает, что кэш может сохранять отклик, даже если это запрещено иными средствами, с учётом ограничений, указанных в разделе 3. Иными словами, директива public явно помечает отклик как кэшируемый. Например, она разрешает общему кэшу повторно использовать отклик на запрос с полем заголовка Authorization (параграф 3.5).

Отметим, что директиву public не требуется добавлять в отклик, который уже является кэшируемым в соответствии с разделом 3. Если отклик с директивой public не имеет явных сведений о свежести, он будет эвристически кэшируемым (параграф 4.2.2).

5.2.2.10. s-maxage

Синтаксис аргумента

      delta-seconds (см. параграф 1.2.2)

Директива отклика s-maxage response указывает, что для общего кэша заданный этой директивой максимальный возраст переопределяет максимальный возраст, заданный директивой max-age или полем заголовка Expires.

Директива s-maxage принимает семантику директивы отклика proxy-revalidate (параграф 5.2.2.8) для общего кэша. Общему кэшу недопустимо повторно использовать устаревший отклик с директивой s-maxage для выполнения другого запроса, пока он не был успешно проверен источником, как указано в параграфе 4.3. Директива также разрешает общему кэшу повторно использовать отклик для запроса с полем Authorization с учётом приведённых выше требования к максимальному возрасту и перепроверке (параграф 3.5).

Аргумент этой директивы использует маркерную форму, например, s-maxage=10, а не s-maxage=10. Отправителю недопустимо использовать строку в кавычках.

5.2.3. Директивы расширения

Поле заголовка Cache-Control может быть расширено с помощью одной или нескольких директив расширения. Кэш должен игнорировать непонятные директивы кэширования.

Информационные расширения (не требующие смены поведения кэша) можно добавлять без изменения семантики других директив.

Расширения поведения предназначены для изменения имеющихся директив кэширования. Представляются сразу новая и старая директива, чтобы приложения, не понимающие новую директиву, могли вести себя в соответствии со старой, а понимающие новую директиву приложения — менять своё поведение с соответствии с новой директивой. Таким образом, расширения имеющихся директив кэширования можно вносить без нарушения работы существующих кэшей. Рассмотрим, например, гипотетическую директиву community, меняющую поведение для директивы private, разрешая (в дополнение к частным кэшам) кэшировать отклик в кеше, общем для указанного сообщества пользователей. Сервер-источник, разрешить сообществу UCI использовать приватные отклики в своём общем кэше может сделать это, включив в отклик Cache-Control: private, community=»UCI». Кэш, понимающий новую директиву, будет вести себя в соответствии с ней, прочие будут игнорировать её и следовать директиве private.

Для новых директив расширения следует рассмотреть определения:

  • трактовки неоднократного включения директивы;

  • применения директивы с аргументом и без аргумента;

  • когда требуется аргумент и к чему ведёт его отсутствие;

  • относится директива к запросам, откликам или обоим сразу.

5.2.4. Реестр директив кэширования

Реестр Hypertext Transfer Protocol (HTTP) Cache Directive Registry задаёт пространство имён для директив кэширования. Реестр доступен по ссылке <https://www.iana.org/assignments/http-cache-directives>.

Регистрация должна включать поля:

  • имя директивы кэширования;

  • указатель на текст спецификации.

Значения добавляются в пространство имён по процедуре IETF Review ([RFC8126], параграф 4.8).

5.3. Expires

Поле заголовка Expires указывает дату и время, после которого отклик считается устаревшим. Рассмотрение модели свежести откликов приведено в параграфе 4.2. Наличие поля Expires не предполагает, что исходный ресурс изменится или прекратит существование в указанное время, до или после него.

Значением поля Expires служит временная метка HTTP-date, определённая в параграфе 5.6.7 [HTTP]. Требования к разбору для кэша приведены в параграфе 4.2.

     Expires = HTTP-date

Например,

   Expires: Thu, 01 Dec 1994 16:00:00 GMT

Получатель кэша должен интерпретировать недействительные форматы дан (особенно 0) как время в прошлом (уже прошло).

Если отклик содержит поле заголовка Cache-Control с директивой max-age (параграф 5.2.2.1), получатель должен игнорировать поле заголовка Expires. Если отклик включает директиву s-maxage (параграф 5.2.2.10), получатель общего кэша должен игнорировать поле заголовка Expires. В обоих случаях значение поля Expires предназначено лишь для получателей, которые ещё не реализуют поле заголовка Cache-Control.

Серверу-источнику без часов (параграф 5.6.7 в [HTTP]) недопустимо создавать поле Expires, если только его значение не представляет фиксированный момент в прошлом (уже прошло) или не связано с ресурсом системой с часами.

Исторически в HTTP требовалось, чтобы значение поля Expires указывало не больше чем на 1 год в будущее. Хотя больший срок свежести сейчас не запрещается, было показано, что очень большие значения вызывают проблемы (например, переполнение часов, использующих 32-битовые значения времени) и многие кэше будут удалять отклик значительно раньше.

5.4. Pragma

Поле заголовка Pragma определено для кэшей HTTP/1.0, чтобы клиенты могли указывать для запроса no-cache (поле Cache-Control не было определено до HTTP/1.1). Однако поддержка Cache-Control не распространена широко, поэтому данная спецификация упраздняет поле Pragma.

Примечание. Поскольку смысл Pragma: no-cache в откликах не был задан, это поле не обеспечивает надёжной замены для Cache-Control: no-cache.

5.5. Warning

Поле заголовка Warning служило для передачи дополнительных сведений о статусе или преобразовании сообщения, которые могут не отображаться в коде статуса. Данная спецификация отменяет поле, поскольку оно редко применяется и не показывается пользователям. Те же сведения можно получить из других полей, таких как Age.

6. Связи с приложениями и другими кэшами

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

Требования этой спецификации не обязательно распространяются на использованием приложением данных после их извлечения из кэша HTTP. Например, механизм истории позволяет отображать предшествующее представление, даже когда срок его действия истёк, а приложение может использовать кэшированные данные по завершении срока их свежести. Эта спецификация не запрещает приложениям принимать кэширование HTTP во внимание, например, механизм истории может сообщать пользователю, что представление устарело или соблюдать директивы кэширования (скажем, Cache-Control: no-store).

Однако при кэшировании приложением данных не очевидным и не контролируемым пользователем способом, настоятельно рекомендуется определять отношение к директивам кэширования HTTP так, чтобы не удивлять авторов, ожидающих соблюдения семантики кэширования. Например, вполне разумное кэширование приложением «поверх» HTTP, позволяющее повторно использовать отклики с Cache-Control: no-store для запросов, которые напрямую связаны с получившим этот отклик запросом (скажем, созданных при загрузке той же страницы), скорей всего будет удивительно и непонятно для пользователей и авторов, если разрешить его применять для несвязанных запросов.

7. Вопросы безопасности

Этот раздел предназначен для информирования разработчиков, поставщиков информации и пользователей об известных проблемах безопасности, связанных с кэшированием HTTP. Более общее рассмотрение вопросов безопасности приведено в HTTP/1.1 (раздел 11 в [HTTP/1.1]) и HTTP Semantics (раздел 17 в [HTTP]).

Кэши открывают дополнительный фронт атак, поскольку содержимое кэша является привлекательной целью для вредоносного использования. Поскольку содержимое кэша сохраняется после завершения запроса HTTP, атаки на кэш могут раскрывать сведения спустя долгое время после того, как пользователь сочтёт его удаленным из сети. Поэтому содержимое кэша следует защищать как конфиденциальные сведения.

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

7.1. Отравление кэша

Сохранение вредоносного содержимого в кэше может расширять сферу влияния атакующего, охватывая множество пользователей. Такие атаки с отравлением кэша (cache poisoning) происходят, когда злоумышленник использует недостатки реализации, повышенные привилегии или иные методы внедрения откликов в кэш. Особенно эффективно это при использовании общего кэша для распространения вредоносного содержимого множеству клиентов.

Одним из базовых векторов атак с отравлением кэша является использование различий в разборе сообщений на прокси и пользовательских агентах. Требования для HTTP/1.1 в этой части приведены в параграфе 6.3 [HTTP/1.1].

7.2. Атаки по времени

Поскольку одним из основных назначений кэша является оптимизация производительности, использование кэша может приводить к «утечке» сведений о запрошенных ранее ресурсах. Например, если пользователь посетил сайт и его браузер кэшировал некоторые из откликов сайта, а затем пользователь перешёл на другой сайт, тот может попытаться загрузить отклики, которые по его сведениям имеются на первом сайте. Если они загрузятся быстро, можно предположить, что пользователь посетил сайт или даже конкретную страницу на нём. Такие атаки по времени (timing attack) можно смягчить, добавив в ключ кэша дополнительные сведения, такие как отождествление ссылающегося сайта (для предотвращения указанной выше атаки). Это иногда называют двойным ключом (double keying).

7.3. Кэширование деликатных сведений

Недостатки реализации и внедрения (часто вызванные ошибочным пониманием работы кэша) могут приводить к кэшированию деликатных или конфиденциальных сведений (например, свидетельств для аутентификации), открывая их для неуполномоченных сторон.

Отметим, что поле заголовка Set-Cookie [COOKIE] не препятствует кэширования и кэшированный отклик с полем Set-Cookie может использоваться (и это часто бывает) для выполнения последующих запросов к кэшам. Серверам, желающим контролировать кэширование таких откликов, рекомендуется создавать соответствующие поля Cache-Control в заголовках откликов.

8. Взаимодействие с IANA

Контролёром изменений для указанных ниже реестров является IETF (iesg@ietf.org) — Internet Engineering Task Force.

8.1. Регистрация имён полей

Агентство IANA обновило реестр Hypertext Transfer Protocol (HTTP) Field Name Registry <https://www.iana.org/assignments/http-fields>, как указано в параграфе 18.4 в [HTTP], с приведёнными в таблице 1 именами полей.

Таблица .

Имя

Статус

Параграф

Комментарии

Age

permanent

5.1

Cache-Control

permanent

5.2

Expires

permanent

5.3

Pragma

deprecated

5.4

Warning

obsoleted

5.5

8.2. Регистрация директив кэширования

Агентство IANA обновило реестр Hypertext Transfer Protocol (HTTP) Cache Directive Registry <https://www.iana.org/assignments/http-cache-directives> с процедурой регистрации, указанной в параграфе 5.2.4, и именами директив кэширования, приведёнными в таблице 2.

Таблица .

Директива

Параграф

max-age

5.2.1.1, 5.2.2.1

max-stale

5.2.1.2

min-fresh

5.2.1.3

must-revalidate

5.2.2.2

must-understand

5.2.2.3

no-cache

5.2.1.4, 5.2.2.4

no-store

5.2.1.5, 5.2.2.5

no-transform

5.2.1.6, 5.2.2.6

only-if-cached

5.2.1.7

private

5.2.2.7

proxy-revalidate

5.2.2.8

public

5.2.2.9

s-maxage

5.2.2.10

8.3. Реестр кодов предупреждений

Агентство IANA добавило в реестр Hypertext Transfer Protocol (HTTP) Warn Codes <https://www.iana.org/assignments/http-warn-codes> приведённое ниже примечание об отмене поля заголовка Warning.

Поле заголовка Warning (и применяемые в нем коды) признано устаревшим для HTTP в соответствии с [RFC9111].

9. Литература

9.1. Нормативные документы

[HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «HTTP Semantics», STD 97, RFC 9110, DOI 10.17487/RFC9110, June 2022, <https://www.rfc-editor.org/info/rfc9110>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC5234] Crocker, D., Ed. and P. Overell, «Augmented BNF for Syntax Specifications: ABNF», STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, <https://www.rfc-editor.org/info/rfc5234>.

[RFC7405] Kyzivat, P., «Case-Sensitive String Support in ABNF», RFC 7405, DOI 10.17487/RFC7405, December 2014, <https://www.rfc-editor.org/info/rfc7405>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

9.2. Дополнительная литература

[COOKIE] Barth, A., «HTTP State Management Mechanism», RFC 6265, DOI 10.17487/RFC6265, April 2011, <https://www.rfc-editor.org/info/rfc6265>.

[HTTP/1.1] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «HTTP/1.1», STD 99, RFC 9112, DOI 10.17487/RFC9112, June 2022, <https://www.rfc-editor.org/info/rfc9112>.

[RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, «Hypertext Transfer Protocol — HTTP/1.1», RFC 2616, DOI 10.17487/RFC2616, June 1999, <https://www.rfc-editor.org/info/rfc2616>.

[RFC5861] Nottingham, M., «HTTP Cache-Control Extensions for Stale Content», RFC 5861, DOI 10.17487/RFC5861, May 2010, <https://www.rfc-editor.org/info/rfc5861>.

[RFC7234] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Caching», RFC 7234, DOI 10.17487/RFC7234, June 2014, <https://www.rfc-editor.org/info/rfc7234>.

[RFC8126] Cotton, M., Leiba, B., and T. Narten, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.

Приложение A. Сводка ABNF

Ниже приведена сводка правил ABNF, расширенных в соответствии с параграфом 5.6.1 в [HTTP].

   Age = delta-seconds
   Cache-Control = [ cache-directive *( OWS "," OWS cache-directive ) ]
   Expires = HTTP-date
   HTTP-date = <HTTP-date, see [HTTP], Section 5.6.7>
   OWS = <OWS, see [HTTP], Section 5.6.3>
   cache-directive = token [ "=" ( token / quoted-string ) ]
   delta-seconds = 1*DIGIT
   field-name = <field-name, see [HTTP], Section 5.1>
   quoted-string = <quoted-string, see [HTTP], Section 5.6.4>
   token = <token, see [HTTP], Section 5.6.2>

Приложение B. Отличия от RFC 7234

Уточнена обработка дубликатов и конфликтующих директив кэширования (параграф 4.2.1).

Аннулирование URI в полях заголовка Location и Content-Location больше не требуется, но разрешено (параграф 4.4). Такое аннулирование запрещено, если источник отличается (раньше было хост) параграф 4.4).

Уточнена обработка недействительных и множественных значений поля Age (параграф 5.1).

Для некоторых директив кэширования, определённых в этой спецификации, задан более строгий запрет на генерацию значений в кавычках, так как стало известно о связанных с этим проблемах. Потребители расширений директив кэша больше не обязаны воспринимать обе формы (маркер и строка в кавычках), но всё равно должны корректно разбирать их для неизвестных расширений (параграф 5.2).

Уточнены директивы общего и приватного кэша, чтобы они не допускали повторного использования откликов ни при каких условиях (параграф 5.2.2).

Добавлена директива must-understand и от кэшей больше не требуется понимать семантику новых кодов статуса, если они не присутствуют (параграф 5.2.2.3).

Заголовок отклика Warning признан устаревшим. Большая часть сведений, поддерживаемых Warning, может быть получена проверкой отклика, остальные, хотя и могли быть полезными, служили лишь рекомендациями. На практике поле Warning не добавлялось кэшами и посредниками (параграф 5.5).

Благодарности

См. одноимённый раздел в [HTTP].

Предметный указатель

A

age
Age, поле заголовка

C

cache
cache key
Cache-Control, поле заголовка
collapsed requests

E

Expires, поле заголовка
explicit expiration time

F

Fields (поля)
Age
Cache-Control
Expires
Pragma
Warning
fresh
freshness lifetime

G

Grammar (грамматика)
Age
Cache-Control
DIGIT
Expires
cache-directive
delta-seconds

H

Header Fields (поля заголовка)
Age
Cache-Control
Expires
Pragma
Warning
heuristic expiration time
heuristically cacheable

M

max-age (директива кэша)
max-stale (директива кэша)
min-fresh (директива кэша)
must-revalidate (директива кэша)
must-understand (директива кэша)

N

no-cache (директива кэша) ,
no-store (директива кэша) ,
no-transform (директива кэша) ,

O

only-if-cached (директива кэша)

P

Pragma, поле заголовка
private (директива кэша)
private cache
proxy-revalidate (директива кэша)
public (директива кэша)

S

s-maxage (директива кэша)
shared cache
stale

V

validator

W

Warning, поле заголовка

Адреса авторов

Roy T. Fielding (editor)
Adobe
345 Park Ave
San Jose, CA 95110
United States of America
Email: fielding@gbiv.com
URI: https://roy.gbiv.com/
 
Mark Nottingham (editor)
Fastly
Prahran
Australia
Email: mnot@mnot.net
URI: https://www.mnot.net/
 
Julian Reschke (editor)
greenbytes GmbH
Hafenweg 16
48155 Münster
Germany
Email: julian.reschke@greenbytes.de
URI: https://greenbytes.de/tech/webdav/

Перевод на русский язык

nmalykh@protokols.ru


1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

3В оригинале — IETF Contributions. Прим. перев.

4В оригинале — IETF Standards Process. Прим. перев.

5В оригинале это предложение несколько отличается, см. https://www.rfc-editor.org/errata/eid7695. Прим. перев.

6Denial-of-service — отказ в обслуживании.

Рубрика: RFC | Оставить комментарий

RFC 9110 HTTP Semantics

Internet Engineering Task Force (IETF)                  R. Fielding, Ed.
Request for Comments: 9110                                         Adobe
STD: 97                                               M. Nottingham, Ed.
Obsoletes: 2818, 7230, 7231, 7232, 7233, 7235,                    Fastly
           7538, 7615, 7694                              J. Reschke, Ed.
Updates: 3864                                                 greenbytes
Category: Standards Track                                      June 2022
ISSN: 2070-1721

HTTP Semantics

Семантика HTTP

PDF

Аннотация

HTTP1 — это протокол прикладного уровня без поддержки состояний для распределенных систем гипертекстовой информации совместного использования. Этот документ описывает общую архитектуру HTTP, задаёт базовую терминологию и общие для всех версий аспекты протокола. В определения включены базовые элементы протокола, механизмы расширения и схемы унифицированных идентификаторов ресурсов (Uniform Resource Identifier или URI) http и https.

Этот документ обновляет RFC 3864 и отменяет RFC 2818, 7231, 7232, 7233, 7235, 7538, 7615, 7694, и часть 7230.

Статус документа

Документ относится к категории Internet Standards Track.

Документ является результатом работы IETF2 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG3. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке https://www.rfc-editor.org/info/rfc9110.

Авторские права

Copyright (c) 2022. Авторские права принадлежат IETF Trust и лицам, указанным в качестве авторов документа. Все права защищены.

К документу применимы права и ограничения, указанные в BCP 78 и IETF Trust Legal Provisions и относящиеся к документам IETF (http://trustee.ietf.org/license-info), на момент публикации данного документа. Прочтите упомянутые документы внимательно. Фрагменты программного кода, включённые в этот документ, распространяются в соответствии с упрощённой лицензией BSD, как указано в параграфе 4.e документа IETF Trust Legal Provisions, без каких-либо гарантий (как указано в Revised BSD License).

Этот документ может содержать материалы из документов IETF или участников IETF4, опубликованных или публично доступных до 10 ноября 2008 г. Лица, контролирующие авторские права на некоторые из таких материалов могли не предоставить IETF Trust прав на изменение таких материалов вне контекста стандартизации IETF5. Без получения соответствующей лицензии от лиц, контролирующих авторские права на такие материалы, этот документ не может быть изменён вне контекста стандартизации IETF, а также не могут открываться производные работы за пределами контекста стандартизации. Исключением является лишь форматирование документа для публикации в качестве RFC или перевод на другие языки.

1. Введение

1.1. Назначение

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

HTTP скрывает детали реализации сервиса, предоставляя клиентам унифицированный интерфейс, не зависящий от типа представляемых ресурсов. Серверам не нужно знать о целях каждого клиента, запросы могут рассматриваться изолированно без привязки к определённому типу клиента или предопределённой последовательности действий приложения. Это позволяет эффективно применять реализации общего назначения в разном контексте, упрощает взаимодействия и обеспечивает независимое развитие с течением времени.

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

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

1.2. История развития

HTTP является основным протоколом передачи информации по «всемирной паутине» (World Wide Web или WWW) с момента появления в 1990 г. Сначала это был тривиальный механизм для запросов с малой задержкой и одним методом (GET) для запроса передачи предусмотренного текстового документа, идентифицируемого путём к нему. По мере развития Web протокол HTTP был расширен для размещения запросов и откликов в сообщениях, передачи произвольных форматов данных с использованием типа носителя в стиле MIME и маршрутизации запросов через промежуточные узлы (посредники). В итоге эти протоколы были определены как HTTP/0.9 и HTTP/1.0 (см. [HTTP/1.0]).

Протокол HTTP/1.1 был разработан для совершенствования функций протокола при сохранении имеющегося синтаксиса на основе текстовых сообщений, что позволило улучшить функциональную совместимость, расширяемость и отказоустойчивость в Internet. Были добавлены разделитель данных по размеру для фиксированного и динамического (chunk) содержимого, единая модель для согласования содержимого, неанализируемые (opaque) валидаторы для условных запросов, средства управления кэшированием для лучшей согласованности, запросы диапазонов для частичных обновлений и принятые по умолчанию сохраняющиеся (persistent) соединения. Протокол HTTP/1.1 был представлен в 1995 г. и опубликован как Standards Track в 1997 г. [RFC2068], а затем пересмотрен в 1999 г. [RFC2616] и в 2014 ([RFC7230] — [RFC7235]).

В HTTP/2 ([HTTP/2]) добавлен мультиплексируемый сеансовый уровень поверх имеющихся протоколов TLS и TCP для обмена одновременными (параллельными) сообщениями HTTP с эффективным сжатием полей и выталкиванием (push) с сервера. HTTP/3 ([HTTP/3]) улучшает независимость одновременных соединений за счёт применения QUIC в качестве защищённого мультиплексируемого транспорта по протоколу UDP вместо TCP.

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

В данной редакции HTTP определение семантики (этот документ) и кэширования ([CACHING]) отделено от текущего синтаксиса обмена сообщениями HTTP/1.1 ([HTTP/1.1]) для независимого развития каждой из основных версий протокола с общей базовой семантикой.

1.3. Основная семантика

HTTP обеспечивает унифицированный интерфейс для взаимодействия с ресурсом () путем передачи сообщений, которые манипулируют представлением или переносят его (), независимо от типа, природы и реализации.

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

Семантика HTTP включает намерения, определяемые каждым методом запроса (), расширения, которые могут быть описаны в полях заголовка запросов, коды статуса, описывающие отклик (), и другие данные управления и метаданные ресурса, которые могут быть указаны в полях отклика. Семантика также включает метаданные представления, описывающие, как содержимое следует интерпретировать получателю, поля заголовков запроса, которые могут влиять на выбор содержимого, и различные алгоритмы выбора, которые совместно называют согласованием содержимого ().

1.4. Спецификации, отменённые этим документом

Таблица .

Название

Документ

Дополнительные сведения

HTTP Over TLS

[RFC2818]

HTTP/1.1 Message Syntax and Routing6

[RFC7230]

HTTP/1.1 Semantics and Content

[RFC7231]

HTTP/1.1 Conditional Requests

[RFC7232]

HTTP/1.1 Range Requests

[RFC7233]

HTTP/1.1 Authentication

[RFC7235]

HTTP Status Code 308 (Permanent Redirect)

[RFC7538]

HTTP Authentication-Info and Proxy-Authentication-Info Response Header Fields

[RFC7615]

HTTP Client-Initiated Content-Encoding

[RFC7694]

2. Соответствия

2.1. Синтаксические обозначения

В этом документе применяется расширенная нотация Бэкуса-Наура (Augmented Backus-Naur Form или ABNF) [RFC5234] , дополненная обозначениями для строк с учётом регистра символов, определённых в [RFC7405]. Используется также расширение списков, определённое в параграфе , которое позволяет компактно определять списки, разделяемых запятыми элементов с использованием оператора # (подобно указанию повтора оператором *). В Приложении A приведена сводная грамматика со всеми расширениями операторов списка, добавленными в ABNF. По традиции имена правил ABNF с префиксом obs- обозначают устаревшие правила, указанные по историческим причинам.

Указанные далее базовые правила включены по ссылкам, как задано в Приложении B.1 к [RFC5234]: ALPHA (буквы), CR (возврат каретки), CRLF (CR LF), CTL (управление), DIGIT (десятичные цифры 0-9), DQUOTE (двойные кавычки), HEXDIG (шестнадцатеричные цифры 0-9/A-F/a-f), HTAB (горизонтальная табуляция), LF (перевод строки), OCTET (любая 8-битовая последовательность данных), SP (пробел), VCHAR (любой печатный символ US-ASCII).

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

В этой спецификации применяются термины character (символ), character encoding scheme (схема кодирования символов), charset (набор символов), protocol element (элемент протокола) в соответствии с [RFC6365].

2.2. Обозначение требований

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

Данная спецификация нацеливает критерии соответствия в зависимости от роли участника коммуникаций HTTP. Поэтому требования предъявляются к отправителям, получателям, клиентам, серверам, пользовательским агентам, посредникам, серверам источникам, прокси, шлюзам и системам кэширования в зависимости от того, какое поведение будет ограничиваться требованиями. Дополнительные требования предъявляются к реализациям, владельцам ресурсов и регистрации элементов протокола, если они выходят за рамки отдельного взаимодействия.

Термин generate (генерировать) применяется вместо send (передавать), когда требования предъявляются только к реализации, создающей элемент протокола, а не к реализации, направляющей полученный элемент в нисходящем направлении (downstream).

Реализация считается соответствующей, если она удовлетворяет всем требованиям, связанных с ролями, которые она играет в HTTP.

Отправителю недопустимо генерировать элементы протокола, которые не соответствуют грамматике, заданной соответствующими правилами ABNF. В рамках данного сообщения отправителю недопустимо генерировать элементы протокола или варианты синтаксиса, которые разрешено генерировать лишь участникам с другой ролью (которой у отправителя данного сообщения нет).

Соответствие HTTP включает соответствие конкретному синтаксису сообщений используемой версии протокола и соответствие семантике передаваемых элементов протокола. Например, клиент может заявить соответствие HTTP/1.1, но не распознавать функций, требуемых от получателей HTTP/1.1, что вызовет отказ при взаимодействии с сервером, который настраивает свои ответы в соответствии с заявлением клиента. Свойства, отражающие выбор пользователя, такие как согласование содержимого и выбранные пользователем расширения, могут влиять на поведение приложений вне протокольного потока и отправка элементов протокола, не отражающих в точности выбор пользователя, будет сбивать того с толку и искажать сделанный выбор.

Если реализация не соответствует семантическим требованиям, получатели сообщений от этой реализации в конце концов найдут обходные пути для соответствующей корректировки поведения. Получатель может использовать такие обходные пути, оставаясь соответствующим данному протоколу, если эти обходные пути применяются лишь для некорректной реализации. Например, серверы часто сканируют часть значения поля User-Agent, а пользовательские агенты — значение поля Server для корректировки своего поведения применительно к известным ошибкам или неудачно выбранным значениям по умолчанию.

2.3. Требования к размерам

Получателю протокольного элемента следует анализировать его защищённо, предполагая, что он соответствует грамматике ABNF и помещается в буфер разумного размера.

В HTTP нет конкретных ограничений для размера многих элементов протокола, поскольку приемлемый размер может значительно варьироваться в зависимости от контекста внедрения и назначения реализации. Поэтому взаимодействие между отправителями и получателями зависит от общих ожиданий в части разумного размера элементов протокола. Более того, общепринятое представление о разумном размере некоторых элементов изменилось за три десятилетия использования HTTP и в будущем можно ожидать продолжения таких изменений.

Получатель, по меньшей мере, должен быть способен проанализировать и обработать элементы протокола, размер которых не меньше размера генерируемых элементов того же типа в других сообщениях. Например, сервер-источник, публикующий очень длинные ссылки URI для своих ресурсов, должен быть способен анализировать и обрабатывать ссылки такого же размера при из получении в качестве целевого URI.

Многие принятые элементы протокола анализируются лишь в той степени, которая требуется для идентификации и пересылки элемента в нисходящем направлении. Например, посредник может найти в принятом поле его имя и компоненты значения, а затем переслать элемент без дальнейшего анализа значения поля.

2.4. Обработка ошибок

Получатель должен интерпретировать полученный протокольный элемент в соответствии с семантикой, заданной для него в данной спецификации, включая её расширения, если получатель не определил (на основе опыта или конфигурации), что отправитель некорректно реализует то, что подразумевается этой семантикой. Например, сервер-источник может пренебрегать содержимым принятого поля заголовка Accept-Encoding, если поле заголовка User-Agent указывает конкретную версию реализации, для которой известно об отказах при получении определённых кодировок содержимого.

Если не указано иное, получатель может попытаться восстановить пригодный для использования элемент протокола из недействительной конструкции. HTTP не задаёт конкретных механизмов обработки ошибок за исключением случаев непосредственного влияния на безопасность, поскольку в разных применениях протокола нужны различные стратегии обработки ошибок. Например, Web-браузер может пожелать восстанавливать отклики, в которых поле заголовка Location не разбирается в соответствии с ABNF, а системы управления сетью могут считать все формы восстановления ошибок небезопасными.

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

2.5. Версия протокола

Номер версии HTTP состоит из 2 десятичных цифр, разделённых точкой (.). Первая цифра (старший номер) указывает синтаксис сообщений, вторая (младший номер) — наибольшую версию в рамках этой старшей версии, которой отправитель соответствует (способен понимать в будущих взаимодействиях).

Хотя базовая семантика HTTP не меняется от версии к версии, её представление «в линии» может меняться, поэтому номер версии HTTP изменяется при внесении несовместимых изменений в формат передачи в линии. Кроме того, HTTP разрешает вносить в протокол нарастающие (incremental) изменения, совместимые с прежними версиями, без смены версии протокола за счёт использования определённых точек расширения ().

Версия протокола целиком показывает соответствие отправителя набору требований, указанных в соответствующих спецификациях этой версии. Например, версия HTTP/1.1 определяется этим документом, HTTP Caching [CACHING] и HTTP/1.1 [HTTP/1.1].

Старший номер версии HTTP увеличивается при внесении в синтаксис сообщений несовместимых изменений. Младший номер увеличивается при внесении в протокол изменений, расширяющих семантику сообщений или вносящих дополнительные возможности для отправителя.

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

Когда старшая версия HTTP не определяет каких-либо младших версий, предполагается старшая версия 0. Это применяется при ссылках на протокол в элементах, которые требуют идентификатор младшей версии.

3. Термины и базовые концепции

Протокол HTTP был создан для архитектуры WWW и со временем был расширен для поддержки расширяемых потребностей мировых гипертекстовых систем. Большая часть этой архитектуры отражается в терминологии, применяемой для определения HTTP.

3.1. Ресурсы

Цели запросов HTTP именуются ресурсами (resource). HTTP не ограничивает природу ресурсов, а лишь задаёт интерфейс, который можно использовать для взаимодействия с ними. Большинство ресурсов идентифицируется с помощью URI, как описано в разделе .

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

HTTP опирается на стандарт унифицированных идентификаторов ресурсов [URI] для указания целевого ресурса () и связей между ресурсами.

3.2. Представления

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

HTTP разрешает сокрытие информации (information hiding) за своим унифицированным интерфейсом, определяя взаимодействие по отношению к переносимому представлению состояния ресурса вместо передачи самого ресурса. Это позволяет указанному URI ресурсу быть чем угодно, включая временные функции, такие как текущая погода в Laguna Beach, и в то же время потенциально предоставлять информацию, представляющую ресурс в момент генерации сообщения [REST].

Унифицированный интерфейс похож на окно, через которое можно наблюдать за чем-либо и действовать на этот объект лишь путём обмена сообщениями с независимым актором на другой стороне. Для представления (замещения) текущего или желаемого состояния этого объекта во взаимодействии нужна общая абстракция. Когда представление является гипертекстом, оно может обеспечивать представление состояния ресурса и инструкции по обработке, помогающие направить последующее взаимодействие с получателем.

Целевой ресурс может иметь или генерировать множество представлений, каждое из которых предназначено для отражения текущего состояния ресурса. Для выбора одного из таких представлений, наиболее подходящего для запроса, обычно применяется алгоритм, основанный на согласовании содержимого (). Выбранное представление обеспечивает данные и метаданные для оценки условных запросов () и создания содержимого для откликов 200 (OK), 206 (Partial Content) и 304 (Not Modified) на запросы GET ().

3.3. Соединения, клиенты и серверы

HTTP — это протокол клиент-сервер, работающий через соединение (connection) с гарантией доставки на транспортном или сеансовом уровне.

Клиентами (client) HTTP являются программы, которые организуют соединение с сервером для передачи одного или множества запросов HTTP. Сервер (server) HTTP — это программа, воспринимающая соединения для обслуживания запросов HTTP путём передачи откликов HTTP.

Термины клиент и сервер относятся только к ролям программ в конкретном соединении. Одна и та же программа может быть клиентом в одних соединениях и сервером — в других.

HTTP определяется как протокол без поддержки состояний, поэтому семантика каждого сообщения может быть понята изолированно и отношения между соединениями и сообщениями в них не влияют на интерпретацию сообщений. Например, запрос CONNECT (параграф 9.3.6) или запрос с полем заголовка Upgrade (параграф 7.8) может передаваться в любой момент, а не только в первом сообщении соединения. Многие реализации зависят от отсутствия состояний в HTTP для многократного использования соединений через прокси или динамического распределения загрузки между несколькими серверами.

Поэтому серверу недопустимо предполагать, что два запроса в одном соединении исходят от одного пользовательского агента, пока соединение не является защищённым и привязанным к такому агенту. Известны некоторые нестандартные расширения HTTP (например, [RFC4559]), нарушающие это требование, что ведёт к проблемам безопасности и совместимости.

3.4. Сообщения

HTTP — это протокол клиент-сервер без поддержки состояний для обмена сообщениями (message) через соединение. Термины отправитель (sender) и получатель (recipient) относятся к любой реализации, которая передаёт или принимает данное сообщение, соответственно.

Клиент передаёт запросы серверу в форме запросных сообщений (request message), содержащих метод (раздел 9) и цель запроса (параграф 7.1). Запрос может также включать поля заголовка (параграф 6.3) для модификаторов запроса, сведений о клиенте, метаданных представления, и содержимого (параграф 6.4), предназначенные для обработки в соответствии с методом, а также поля трейлера (параграф 6.5) для передачи сведений, собранных при отправке содержимого.

Сервер отвечает на запрос клиента передачей одного или нескольких откликов (response message) содержащих кода статуса (раздел 15). Отклик также может включать поля заголовка для сведений о сервере, метаданных ресурса и представления для интерпретации в соответствии с кодом статуса, а также поля трейлера для передачи сведений, собранных при отправке содержимого.

3.5. Пользовательские агенты

Термин пользовательский агент (user agent) означает любую клиентскую программу, способную инициировать запрос.

Наиболее популярной формой пользовательских агентов являются Web-браузеры общего назначения, но они составляют лишь малую часть реализаций агентов. Другими распространёнными пользовательскими агентами являются спайдеры (роботы, путешествующие по web), консольные инструменты, экраны рекламных щитов, бытовые приборы, весы, лампочки, сценарии обновления микрокода (firmware), мобильные приложения и коммуникационные устройства разных форм и размеров.

Статус пользовательского агента не подразумевает, что при передаче запроса человек напрямую взаимодействует с агентом. Во многих случаях пользовательские агенты устанавливаются и настраиваются для работы в фоновом режиме и сохранения результатов для последующего просмотра (или сохранения лишь части результатов, которые могут быть интересны или сообщают об ошибках). Спайдеры, например, обычно имеют URI для начала работы и настраиваются на определённое поведение при перемещении в Web как по графу гипертекста.

Многие пользовательские агенты не могут или избегают делать интерактивные предложения для своих пользователей или выдавать адекватные предупреждения по соображениям безопасности или приватности. В некоторых случаях, когда данные спецификация требует сообщать пользователю об ошибках, допускается ограничиваться выводом таких отчётов лишь в консоль ошибок или журнальный файл системы (log). Требования подтверждения автоматизированных действий пользователем перед выполнением, тоже могут выполняться через настройки конфигурации, опции рабочего режима или простое исключение небезопасных действий. Подтверждение не предполагает какого-либо конкретного пользовательского интерфейса или прерывания обычной обработки, если пользователь уже сделал свой выбор.

3.6. Сервер-источник

Сервером-источником (origin server) называют программу, которая может создавать полномочные отклики на данный целевой запрос. Наиболее популярной формой таких серверов являются большие публичные web-сайты. Однако, как и в случае приравнивания пользовательских агентов к браузерам, ошибочно считать все серверы-источники похожими. Распространёнными серверами-источниками являются блоки домашней автоматизации, настраиваемые компоненты сетей, офисные машины, автономные роботы, новостные ленты, дорожные камеры, системы с выбором рекламы в реальном масштабе времени, платформы передачи видео по запросам.

     запрос   >
UA ======================================= O
                            <   отклик

Рисунок 1.


Большинство взаимодействий HTTP состоит из запроса на получение (GET) для представления некого ресурса, указанного URI. В простейшем случае это может быть одно двухстороннее соединение (===) между пользовательским агентом (UA) и сервером-источником (O), как показано на рисунке 1.

3.7. Посредники

HTTP позволяет использовать посредников для выполнения требования через цепочку соединений. Имеется 3 основных формы посредников (intermediary) HTTP: прокси, шлюзы и туннели. В некоторых случаях один посредник может служить сервером-источником, прокси, шлюзом или туннелем, меняя поведение в зависимости от запроса.

     >             >             >             >
UA =========== A =========== B =========== C =========== O
           <             <             <             <

Рисунок 2.


На рисунке 2 показаны три посредника (A, B, C) между агентом пользователя и сервером-источником. Сообщение с запросом или откликом, проходящее через всю цепочку, будет встречать 4 отдельных соединения. Некоторые коммуникационные опции HTTP могут применяться только к соединению с ближайшим нетуннельным соседом, только к конечным точкам в цепочке или ко всем соединениям цепочки. Хотя на рисунке показано линейное соединение, каждый из участников цепочки может быть вовлечён одновременно во множество взаимодействий. Например, B может принимать запросы от множества клиентов, а не только от A, и/или пересылать запросы не только серверу C, в процессе обработки запроса A. Последующие запросы могут пойти по другим путям, зачастую на основе динамической конфигурации для распределения нагрузки.

Термины восходящий (upstream) и нисходящий (downstream) служат для описания направления потока сообщений — все сообщения передаются от восходящего к нисходящему. Термины входной (inbound) и исходящий (outbound) служат для описания направлений применительно к маршруту запроса — входной указывает направление к серверу-источнику, исходящий — к пользовательскому агенту.

Прокси (proxy) — это агент пересылки сообщений, выбираемый клиентом (обычно с помощью правил локальной конфигурации) для приёма запросов к некоторым типам абсолютных URI и попытки выполнить эти запросы путём трансляции через интерфейс HTTP. Некоторые трансляции являются минимальными, например, для запросов http URI, тогда как другие могут требовать трансляции в иные протоколы прикладного уровня или из таких протоколов. Прокси часто применяются для группировки HTTP-запросов организации через общего посредника в целях обеспечения безопасности, услуг аннотирования или общего кэширования. Некоторые прокси разработаны для применения преобразований к выбранным сообщениям или содержимому в процессе их пересылки, как описано в параграфе .

Шлюз (gateway, он же обратный прокси — reverse proxy) — это посредник, выступающий как сервер-источник для исходящих соединений, но транслирующий входящие запросы и пересылающий их как входящие на другой сервер или серверы. Шлюзы часть применяются для инкапсуляции унаследованных или недоверенных информационных услуг, повышения производительности серверов за счёт «ускоряющего» кэширования и обеспечения разделения или распределения нагрузки служб HTTP между множеством машин.

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

Туннель (tunnel) действует как «слепой» ретранслятор между двумя соединениями, не изменяя сообщений. Будучи активным, туннель не считается частью коммуникаций HTTP хотя он может быть инициирован HTTP-запросом. Туннель прекращает своё существование, когда обе стороны ретранслируемого соединения закрываются. Туннели служат для расширения виртуальных соединений через посредника, например, при использовании протокола защиты транспортного уровня (Transport Layer Security или TLS, [TLS13]) для организации конфиденциального взаимодействия через общий межсетевой экран-прокси.

Выше перечислены лишь те категории посредников, которые участвуют в коммуникациях HTTP. Имеются также посредники, работающие на нижележащих уровнях сетевого стека протоколов, фильтруя или перенаправляя трафик HTTP без ведома и разрешения отправителей сообщений. Сетевые посредники неотличимы (на уровне протокола) от злоумышленников на пути и часто препятствуют безопасности и создают проблемы взаимодействия из-за ошибочной трактовки семантики HTTP. Например, прокси-перехватчик (interception proxy) [RFC3040], называемый также прозрачным прокси (transparent proxy [RFC1919]) отличается от HTTP-прокси, поскольку клиент его не выбирает. Такой прокси фильтрует или перенаправляет исходящие пакеты TCP для порта 80 (иногда и трафик других портов). Перехватывающие прокси часто встречаются в точках доступа в публичные сети в качестве средств контроля подписка до того, как будет разрешено использование нелокальных услуг Internet, а также в корпоративных межсетевых экранах для принудительного исполнения правил использования сети.

3.8. Кэширование

Кэш (cache) — это локальное хранилище предыдущих сообщений-откликов, а также подсистема управления хранилищем откликов, их извлечением и удалением. В хранилище записываются кэшированные сообщения для сокращения времени отклика и расхода пропускной способности сети при повторных запросах. Любой клиент или сервер может развернуть свой кэш, хотя тот не может использоваться при работе в качестве туннеля.

Влияние кэширования заключается в сокращении цепочки запрос-отклик, если у одного из элементов цепочки имеется кэшированный отклик на такой запрос. На рисунке 3 показана цепочка для случая наличия в узле B кэшированной копии предыдущего отклика от O (через C), который не был кэширован UA или A.

     >             >
UA =========== A =========== B - - - - - - C - - - - - - O
           <             <

Рисунок 3.


Отклик является кэшируемым (cacheable), если кэш позволяет сохранить сообщение с откликом для использования при ответах на последующие запросы. Даже при возможности кэшировать отклик клиент или сервер-источник могут задать дополнительные ограничения на использование кэшированного отклика для конкретного запроса. Требования HTTP для поведения кэша и кэшируемых откликов заданы в [CACHING].

Имеется множество вариантов архитектуры и конфигурации систем кэширования, реализованных в Web и крупных организациях. Это включает национальные иерархии прокси-кэширования для сокращения расхода пропускной способности и снижения задержки, сети доставки содержимого, использующие кэширование на шлюзах для оптимизации регионального или глобального распределения откликов популярных сайтов, системы совместной работы, передающие кэшированные записи в групповом или широковещательном режиме для автономного (off-line) использования или в средах с высокой задержкой и т. п.

3.9. Пример обмена сообщениями

Ниже приведён пример типичного обмена сообщениями HTTP/1.1 при запросе GET () для URI http://www.example.com/hello.txt.

Запрос клиента

   GET /hello.txt HTTP/1.1
   User-Agent: curl/7.64.1
   Host: www.example.com
   Accept-Language: en, mi

Отклик сервера

   HTTP/1.1 200 OK
   Date: Mon, 27 Jul 2009 12:28:53 GMT
   Server: Apache
   Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
   ETag: "34aa387-d-1568eb00"
   Accept-Ranges: bytes
   Content-Length: 51
   Vary: Accept-Encoding
   Content-Type: text/plain

   Hello World! My content includes a trailing CRLF.

4. Идентификаторы в HTTP

В HTTP применяются унифицированные идентификаторы ресурсов (URI) [URI] для указания ресурсов (параграф 3.1).

4.1. Ссылки URI

Ссылки URI служат для указания целей запросов и перенаправлений, а также для определения взаимосвязей.

Определения URI-reference, absolute-URI, relative-part, authority, port, host, path-abempty, segment, query заимствованы из базового синтаксиса URI. Правило absolute-path определено для элементов протокола, которые могут соедержать непустой компонент пути. Это правили слегка отличается от path-abempty из RFC 3986, разрешающего пустые пути, и path-absolute, не разрешающего пути с префиксом //. Правило partial-URI задано для элементов протокола, которые могут содержать относительный идентификатор URI, но не фрагмент.

     URI-reference = <URI-reference, см. [URI], параграф 4.1>
     absolute-URI  = <absolute-URI, см. [URI], параграф 4.3>
     relative-part = <relative-part, см. [URI], параграф 4.2>
     authority     = <authority, см. [URI], параграф 3.2>
     uri-host      = <host, см. [URI], параграф 3.2.2>
     port          = <port, см. [URI], параграф 3.2.3>
     path-abempty  = <path-abempty, см. [URI], параграф 3.3>
     segment       = <segment, см. [URI], параграф 3.3>
     query         = <query, см. [URI], параграф 3.4>

     absolute-path = 1*( "/" segment )
     partial-URI   = relative-part [ "?" query ]

Каждый элемент протокола HTTP, разрешающий ссылки URI, указывает в своей ABNF-форме, разрешает ли он любую форму ссылок (URI-reference), только URI в абсолютной форме (absolute-URI), только путь и необязательные компоненты запроса (partial-URI) или какую-либо комбинацию предыдущих вариантов. Если не указано иное, ссылки URI анализируются относительно URI цели (параграф 7.1).

Всем отправителям и получателям рекомендуется поддерживать в элементах протокола URI размером по меньшей мере 8000 октетов. Отметим, что это значения учитывает обязательное увеличение некоторых структур и представления в линии в некоторых случаях (например, в строке запроса HTTP/1.1).

4.2. Связанные с HTTP схемы URI

IANA поддерживает реестр схем URI [BCP35] <https://www.iana.org/assignments/uri-schemes/>. В запросах может применяться любая схема URI, а присущие серверам HTTP схемы указаны в таблице .

Таблица .

 

Схема URI

Описание

Параграф

http

Hypertext Transfer Protocol

https

Hypertext Transfer Protocol Secure

 

Отметим, что наличие URI http или https не предполагает, что в указанном месте всегда имеется сервер HTTP, прослушивающий соединения. Кто угодно может ввести URI независимо от существования сервера или сопоставления сервером указанного идентификатора с ресурсом. Делегирование зарегистрированных имён и адресов IP создаёт объединённое пространство имён независимое от присутствия в нем серверов HTTP.

4.2.1. Схема http для URI

Этот документ определяет схему URI http для идентификаторов в иерархическом пространстве имён, управляемым потенциальным сервером-источником HTTP и прослушивающим соединения TCP ([TCP]) на данном порту.

     http-URI = "http" "://" authority path-abempty [ "?" query ]

Сервер-источник для URI http указывается компонентом authority, который включает идентификатор хоста ([URI], параграф 3.2.2) и может включать номер порта ([URI], параграф 3.2.3). Если номер порта пуст или не указан, применяется порт TCP 80 (зарезервирован для служб WWW). Источник определяет, кто имеет право полномочно отвечать на запросы к указанному ресурсу, как описано в параграфе 4.3.2.

Отправителю недопустимо генерировать URI http с пустым идентификатором хоста. Получатель такой ссылки URI должен отвергать её как недействительную.

Компонент иерархического пути и необязательный компонент запроса указывают целевой ресурс в пространстве имён сервера-источника.

4.2.2. Схема https для URI

Этот документ определяет схему URI https для идентификаторов в иерархическом пространстве имён, управляемым потенциальным сервером-источником HTTP и прослушивающим соединения TCP ([TCP]) на данном порту, а также способном организовать соединение TLS ([TLS13]) для защищённых коммуникаций HTTP. В этом контексте защищенность означает, что сервер аутентифицирован, как выступающий от имени указанного полномочного органа (authority) и все коммуникации HTTP с этим сервером имеют защиту конфиденциальности и целостности, приемлемую как для клиента, так и для сервера.

     https-URI = "https" "://" authority path-abempty [ "?" query ]

Сервер-источник для URI https указывается компонентом authority, который включает идентификатор хоста ([URI], параграф 3.2.2) и может включать номер порта ([URI], параграф 3.2.3). Если номер порта пуст или не указан, применяется порт TCP 443 ( зарезервирован для HTTP по протоколу TLS). Источник определяет, кто имеет право полномочно отвечать на запросы к указанному ресурсу, как описано в параграфе 4.3.3.

Отправителю недопустимо генерировать URI https с пустым идентификатором хоста. Получатель такой ссылки URI должен отвергать её как недействительную.

Компонент иерархического пути и необязательный компонент запроса указывают целевой ресурс в пространстве имён сервера-источника.

Клиент должен убедиться, что его запросы HTTP к ресурсу https защищены, до начала взаимодействия и он воспринимает лишь защищённые отклики на свои запросы. Отметим, что выбор криптографических механизмов, приемлемых для клиента и сервера, обычно согласовывается и может меняться с течением времени.

Ресурсы, доступные по схеме https не идентичны ресурсам со схемой http. Это разные источники со своими пространствами имён. Однако расширения HTTP, определённые как применимые ко всем источникам на одном хосте, такие как протокол Cookie [COOKIE], позволяют информации, установленной одной службой, влиять на взаимодействие с другими службами в соответствующей группе доменов хоста. Такие расширения должны разрабатываться с особой тщательностью для предотвращения случайного обмена информацией из защищённого соединения в незащищённом контексте.

4.2.3. Нормализация и сравнение

URI со схемой http или https нормализуются и сравниваются в соответствии с методами, указанными в разделе 6 [URI], с использованием принятых по умолчанию значений, описанных выше для каждой схемы. HTTP не требует использовать конкретный метод определения эквивалентности. Например, ключи кэша могут сравниваться как простые строки после нормализации по синтаксису или схеме.

Нормализация на основе схемы (параграф 6.2.3 в [URI]) для URI http и https включает дополнительные правила.

  • Если порт совпадает с принятым по умолчанию для схемы, с нормализованном виде компонент порта исключается.

  • При использовании в качестве цели запроса OPTIONS пустой компонент пути (path) эквивалентен абсолютному пути /, поэтому в нормализованной форме указывается путь /.

  • В компонентах scheme и host регистр символов не учитывается и обычно применяются строчные буквы. Остальные компоненты сравниваются с учётом регистра символов.

  • Символы, не входящие в число зарезервированных, эквивалентны соответствующим октетам %-кодирования и в нормализованной форме они не кодируются (параграфы 2.1 и 2.2 в [URI]).

Например, приведённые ниже идентификаторы URI эквивалентны.

      http://example.com:80/~smith/home.html
      http://EXAMPLE.com/%7Esmith/home.html
      http://EXAMPLE.com:/%7esmith/home.html

Два HTTP URI эквивалентных после нормализации (любым способом) могут считаться указывающими один ресурс, а нормализацию может выполнить любой компонент HTTP. Поэтому разные ресурсы не следует указывать HTTP URI эквивалентными после нормализации (с использованием любого метода из параграфа 6.2 в [URI]).

4.2.4. Запрет userinfo в URI

Базовый синтаксис URI для authority включает субкомпонент userinfo ([URI], параграф 3.2.1) для указания в URI сведений для проверки подлинности пользователя. В этом субкомпоненте использование формата user:password признано устаревшим. Некоторые реализации используют userinfo для внутренней настройки аутентификационных сведений, например, в опциях вызова команд, конфигурационных файлах или списках закладок, несмотря на то, что при этом может раскрываться имя пользователя и пароль.

Отправителям недопустимо генерировать субкомпонент userinfo (и его разделитель @) при создании в сообщении ссылки URI http или https в качестве целевого URI или значения поля.

Перед использованием ссылки URI http или https, полученной из недоверенного источника, получателю следует проверить субкомпонент userinfo и считать его наличие ошибкой. Скорее всего этот субкомпонент используется для сокрытия authority в фишинговой атаке.

4.2.5. Ссылки с идентификаторами-фрагментами

Идентификаторы-фрагменты позволяют опосредованно указать ресурс независимо от схемы URI, как указано в параграфе 3.5 [URI]. Одни элементы протокола, ссылающиеся на URI, позволяют включать фрагмент, другие — нет. Они различаются использованием правила ABNF для элементов, где фрагменты разрешены, в ином случае применяется специальное правило, исключающее фрагменты.

Примечание. Компонент идентификатора-фрагмента для является частью определения схемы URI (см. параграф 4.3 в [URI]), поэтому он не указан в определениях ABNF для схем URI http и https, приведённых выше.

4.3. Полномочный доступ

Полномочным (authoritative) доступом называется разыменование данного идентификатора с целью доступа к указанному ресурсу таким способом, который по мнению клиента является полномочным (контролируется владельцем ресурса). Процесс определения возможности доступа устанавливается схемой URI и зачастую при работе с базовым синтаксисом использует данные из компонентов URI, таких как authority. Однако полномочный доступ не ограничивается идентифицированным механизмом.

В параграфе 4.3.1 определена концепция источника (origin) в качестве вспомогательного средства для такого использования, а в последующих параграфах объясняется, как проверить полномочия партнёра представлять этот источник.

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

4.3.1. URI Origin

Поле источника (origin) для данного URI состоит из схемы (scheme), хоста (host) и порта (port) после приведения схемы и хоста к нижнему регистру и удаления начальных нулей в номере порта. Если порт не указан в URI, используется принятый по умолчанию номер. Например URI https://Example.Com/happy.js будет иметь origin

      { "https", "example.com", "443" }

что можно представить нормализованным префиксом URI с номером порта

      https://example.com:443

Каждое поле origin задаёт своё пространство имён и управляет сопоставлением идентификаторов из этого пространства с ресурсами. Отклики источника на корректные запросы с течением времени определяют семантику, связываемую пользователями с URI, и полезность этой семантики, что в конечном итоге преобразует эти механизмы в ресурс, на который пользователи могут ссылаться и обращаться к нему в будущем.

Два источника (origin) будут разными, если в них отличаются scheme, host или port. Даже если можно убедиться, что один субъект контролирует два разных источника (origin), пространства имён этих origin будут разными, пока не заданы явные псевдонимы полномочным для данного источника сервером.

Источники также используются внутри HTML и связанных с Web протоколов (не рассматриваются в этом документе), как описано в [RFC6454].

4.3.2. Источники http

Хотя HTTP не зависит от транспортного протокола, схема http (параграф 4.2.1) предназначена для связывания полномочий с тем, кто контролирует сервер-источник, прослушивающий соединения TCP на указанном порту хоста, заданного в компоненте authority. Это очень слабая привязка, поскольку она зависит от механизмов распознавания имён на стороне клиента и коммуникаций, которые могут быть не защищены от злоумышленников на пути. Тем не менее, это достаточный минимум для привязки идентификаторов http к серверу-источнику для согласованного распознавания в доверенной среде.

Если хост указан адресом IP, сервером-источником является прослушивающий (при наличии) указанный порт TCP на этом адресе IP. Если хост указан зарегистрированным именем, это имя является косвенным идентификатором для использования с системой распознавания имён, такой как DNS, для поиска адреса нужного сервера-источника.

Когда URI http используется в контексте, запрашивающем доступ к указанному ресурсу, клиент может пытаться получить доступ преобразуя идентификатор хоста в адрес IP, организуя соединение TCP с этим адресом на указанном порту и передавая через это соединение запросного сообщения HTTP с целью запроса, соответствующей клиентскому URI цели (параграф 7.1). Если сервер отвечает на такой запрос непромежуточным (non-interim) сообщением с откликом HTTP, как описано в параграфе 15, этот отклик считается полномочным для запроса клиента.

Отметим, что приведённый выше вариант не является единственным способом получения полномочного отклика и не подразумевает, что полномочный отклик требуется всегда (см. [CACHING]). Например, поле заголовка Alt-Svc [ALTSVC] позволяет серверу-источнику указать другие серверы, которые тоже будут полномочными для этого источника. Доступ к ресурсам, указанным http, может обеспечиваться протоколами, выходящими за рамки документа.

4.3.3. Источники https

Схема https (параграф 4.2.2) связывает полномочия на основе способности сервера использовать закрытый ключ, соответствующий сертификату, который клиент считает доверенным для указанного сервера-источника. Клиент обычно полагается на цепочку доверия, передаваемую от некой заранее согласованной или настроенной привязки доверия, чтобы считать сертификат доверенным (параграф 4.3.4).

В HTTP/1.1 и предшествующих версия клиент принимает полномочия сервера при взаимодействии по защищённому каналу конкретно с хостом-источником из URI. Организация соединения и проверка сертификата служат подтверждают полномочия.

В HTTP/2 и HTTP/3 клиент принимает полномочия сервера при организации защищённого соединения, если хост-источник в URI совпадает с любым из хостов, указанных в сертификате сервера и клиент считает, что он может открыть соединение с этим хостом для URI. На практике клиент делает запрос к DNS, чтобы проверить, что хост источника имеет тот же адрес IP, что и в организованном соединении. Это ограничение может быть снято сервером-источником передачей эквивалентного кадра ORIGIN [RFC8336].

Хост и порт цели запроса передаются в каждом запросе HTTP, указанием origin и отделением от других пространств имён, которые может контролировать тот же сервер (параграф 7.2). Источник должен убедиться, что любые услуги, предоставляемые с использованием закрытого ключа из его сертификата в равной степени ответственны за поддержку соответствующих пространство имён https или хотя бы готовы отклонять запросы, которые кажутся направленными не по назначению (параграф 7.4).

Сервер-источник может не обрабатывать запросы для некоторых целевых URI, даже имея для них полномочия. Например, при работе хоста с разными службами на разных порта (например, 443 и 8000) требуется проверка URI цели на сервере-источнике (даже через защищённое соединение), поскольку злоумышленник в сети может перебросить соединение с одного порта на другой. Отсутствие проверки целевого URI может позволить атакующему заменить отклик для одного целевого URI (скажем, https://example.com/foo) на кажущийся полномочным отклик из другого пора (например, https://example.com:8000/foo).

Отметим, что схема https не полагается на TCP и номер подключённого порта для восприятия полномочий, поскольку оба они являются внешними для защищённых коммуникаций и поэтому не могут считаться неизменными (definitive). Таким образом, взаимодействие HTTP может происходить по любому каналу, который защищён, как описано в параграфе 4.2.2, включая протоколы, не использующие TCP.

При использовании https URI в контексте, запрашивающем доступ к указанному ресурсу, клиент может пытаться получить доступ, преобразуя идентификатор хоста в адрес IP, организуя соединение TCP с указанным портом на этом адресе, обеспечивая сквозную защиту организацией TLS по протоколу TCP с защитой конфиденциальности и целостности и передавая через это соединение запрос HTTP с целью, соответствующей целевому URI клиента (параграф 7.1). Если сервер отвечает на такой запрос финальным (non-interim) откликом HTTP, как описано в параграфе 15, отклик считается полномочным для этого запроса клиента.

Отметим, что указанное выше не является способом получения полномочного отклика и не предполагает, что полномочный отклик нужен всегда (см. [CACHING]).

4.3.4. Проверка сертификатов https

Чтобы организовать защищённое соединение для разыменования URI, клиент должен убедиться, что отождествление сервера соответствует серверу-источнику из URI. Для предотвращения подмены (impersonation) сервера атакующим на пути или злоумышленником, контролирующим распознавание имён, требуется проверка сертификата. Для этого у клиента должен быть настроен набор привязок доверия.

В общем случае клиент должен проверить отождествление сервера, используя процесс, определённый в разделе 6 [RFC6125]. Клиент должен создать ссылочное определение из значения host от сервера. Если host содержит адрес IP (параграф 4.3.5), ссылочным отождествлением будет IP-ID, в ином случае host содержит имя, и отождествлением будет DNS-ID.

Клиентам недопустимо использовать ссылочное отождествление CN-ID. Как отмечено в параграфе 6.2.1 [RFC6125], тип CN-ID может применяться лишь старыми клиентами.

Клиент может быть специально настроен на восприятие альтернативной формы проверки отождествления сервера. Например, клиент может подключаться к серверу с динамическим адресом и именем хоста и ожидать от сервиса предоставления конкретного сертификата (или сертификата, соответствующего некому внешнему ссылочному отождествлению), а не сертификата, соответствующего источнику в целевом URI.

В особых случаях клиент может просто игнорировать отождествление сервера, но он должен понимать, что это открывает соединение для активных атак.

Если сертификат не действителен для источника целевого URI, агент пользователя должен получить перед обработкой подтверждение от пользователя (см. параграф 3.5) или разорвать соединение с ошибкой, указывающей непригодный сертификат. Автоматизированные клиенты должны записывать ошибку в подходящий журнал аудита (при наличии), а соединение следует разрывать (с ошибкой, указывающей непригодный сертификат). У таких клиентов может быть параметр конфигурации, отключающий эту проверку, но должен быть параметр, включающий её.

4.3.5. Ссылочное отождествление IP-ID

Сервер, идентифицируемый литералом IP-адреса в поле host внутри https URI, имеет ссылочное отождествление типа IP-ID. В ACK адресе IPv4 используется правило ABNF IPv4address, а в адресе IPv6 используется IP-literal с опцией IPv6address (см. параграф 3.2.2 в [URI]). Ссылочное отождествление IP-ID содержит декодированные байты адреса IP.

Адрес IPv4 состоит из 4 октетов, IPv6 — 16. Использование IP-ID не определено для какой-либо другой версии IP. Выбор IPAddress в расширении сертификата subjectAltName не включает явного указания версии IP, поэтому адреса различаются по размеру (см. параграф 4.2.1.6 в [RFC5280]).

Ссылочное отождествление типа IP-ID соответствует, если адрес идентичен значению iPAddress в расширении сертификата subjectAltName.

5. Поля

В HTTP используются поля (field) для предоставления данных в форме расширяемых пар «имя-значение» из зарегистрированного пространства имён ключей. Поля передаются и принимаются в разделах заголовков и трейлеров сообщений ().

5.1. Имена полей

Имя поля помечает соответствующее значение поля, как имеющее семантику, заданную этим именем. Например, поле заголовка Date определено в параграфе 6.6.1 как содержащее временную метку создания сообщения, куда поле включено.

     field-name     = token

Имена полей указываются без учёта регистра символов и должны быть зарегистрированы в реестре Hypertext Transfer Protocol (HTTP) Field Name Registry (см. параграф 16.3.1).

Интерпретация поля не меняется в разных младших версий одной старшей версии HTTP, хотя принятое по умолчанию поведение получателя при отсутствии поля может изменяться. Если не задано иное, поля определяются для всех версий HTTP. В частности, поля Host и Connection должны распознавать все реализации HTTP независимо от того, анонсируют ли они поддержку HTTP/1.1.

Новые поля могут вводиться без смены версии протокола, если заданная для поля семантика позволяет безопасно игнорировать поле не понимающим его получателем (см. параграф 16.3).

Прокси должны пересылать непонятные поля заголовка, если только это поле не указано в заголовке Connection (параграф 7.6.1) или прокси не настроен специально на блокировку или преобразование таких полей. Остальным получателям следует игнорировать непонятные поля заголовка и трейлера. Соблюдение этих требований позволяет расширять функциональность HTTP без добавления и удаления развёрнутых посредников.

5.2. Строки и совокупное значение поля

Разделы поля могут содержать произвольное число строк (field line), каждая со именем (field name, параграф 5.1), указывающим поле, и значением (field line value), указывающим данные для этого экземпляра поля.

Когда имя поля указано в разделе лишь однократно, совокупным значением поля (field value) будет соответствующее значение строки поля. Если имя встречается в разделе неоднократно, совокупным значением поля будет конкатенация списка значений строк поля в этом разделе (в порядке их следования) через запятую. Например, раздел

   Example-Field: Foo, Bar
   Example-Field: Baz

содержит две строки поля Example-Field — Foo, Bar и Baz. Совокупным значением поля будет Foo, Bar, Baz.

5.3. Порядок полей

Получатель может объединить несколько строк поля с одним именем в одну строку поля без изменения семантики сообщения, добавляя каждое следующее значение строки поля к прежней строке через запятую (,) и (необязательный) пробельный символ (OWS, параграф 5.6.3). Для согласованности следует использовать запятую и пробел ( SP).

Порядок строк с одним именем поля важен для интерпретации значения поля и прокси недопустимо менять этот порядок при пересылке сообщения. Это означает, что за описанным ниже общеизвестным исключением отправителю недопустимо генерировать сообщения с одним именем в нескольких строках (в заголовке или трейлере) или добавлять строки с уже имеющимся в сообщении именем, если только определение этого поля не позволяет объединять несколько строк поля в список через запятые (т. е. хотя бы один из вариантов определения поля разрешает объединять строки в список через запятые, например, правила ABNF #(values) из параграфа 5.6.1).

Примечание. На практике поле заголовка Set-Cookie [COOKIE] часто встречается в нескольких строках и не использует синтаксис списков в нарушение приведённых выше требований для строк полей с одним именем. Поскольку эти поля нельзя объединять в одно значение, получатели должны обрабатывать Set-Cookie как особый случай (см. Приложение A.2.3 к [Kri2001]).

Порядок размещения строк полей с разными именами значения не имеет. Однако хорошим тоном является передача сначала полей заголовков, содержащих дополнительные данные управления, такие как Host в запросах и Date в откликах, чтобы реализация могла как можно раньше решить вопрос о возможности обработки сообщения.

Серверу недопустимо применять запрос к целевому ресурсу, пока раздел заголовков запроса не принят целиком, поскольку последующие строки полей заголовка могут включать условия, свидетельства для аутентификации или намеренно ложные дубликаты полей, которые могут влиять на обработку запроса.

5.4. Ограничения для полей

HTTP не задаёт предопределённых ограничений для размера каждой строки поля, значения поля, а также размера заголовка или трейлера в целом, как описано в разделе 2. На практике встречаются специальные ограничения отдельных размеров, зачастую связанные с семантикой конкретных полей.

Сервер, получивший строку поля заголовка запроса, значение поля или набор полей, размер которых превышает желаемый для обработки, должен ответить подходящим кодом статуса 4xx (ошибка клиента). Игнорирование таких полей заголовка повышает уязвимость сервера к атакам с недопустимыми запросами (параграф 11.2 в [HTTP/1.1]).

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

5.5. Значения полей

Значение поля HTTP состоит из последовательности символов, определяемых грамматикой поля, обычно определяемой с использованием ABNF ([RFC5234]).

     field-value    = *field-content
     field-content  = field-vchar
                      [ 1*( SP / HTAB / field-vchar ) field-vchar ]
     field-vchar    = VCHAR / obs-text
     obs-text       = %x80-FF

Значение поля не пробельных символов в начале и в конце. Конда конкретная версия HTTP разрешает такие символы в сообщении, реализация анализатора должна исключать их до оценки значения поля.

В значениях полей обычно используется лишь диапазон символов US-ASCII [USASCII]. Для полей, требующих более широкого диапазона символов можно применять кодирование, вроде того, которае определена в [RFC8187]. Исторически в HTTP допускается содержимое полей в кодировке ISO-8859-1 [ISO-8859-1] и поддержка других наборов символов обеспечивается лишь за счёт применения кодирования [RFC2047]. Спецификациям недавно определённых полей следует ограничивать значения печатаемыми (visible) октетами US-ASCII (VCHAR), SP и HTAB. Получателю следует считать иные разрешённые октеты в содержимом поля (т. е., obs-text) необрабатываемыми (opaque) данными.

Поля, с символами CR, LF, NUL, недействительны и опасны, поскольку разные реализации могут по-своему анализировать и интерпретировать эти символы. Получатель поля с такими символами должен отклонить сообщение или заменить каждый из них символом SP перед обработкой или пересылкой этого сообщения. Поля с другими символами управления (CTL) тоже недействительны, однако получатель может сохранять эти символы ради отказоустойчивости, если символы появляются в безопасном контексте (например, в специфической для приложения строке с кавычками, которая не будет обрабатываться ни одним нисходящим синтаксическим анализатором HTTP).

Поля, допускающие в качестве значения поля лишь один элемент, называют одноэлементными (singleton field). Поля, разрешающие несколько элементов в своём значении, называют списочными (list-based field). Расширение оператора списка из параграфа 5.6.1 применяется как общая нотация для определения значений полей, которые могут включать несколько элементов.

Поскольку запятые (,) служат разделителем элементов, к ним нужно относиться с осторожностью, если они разрешены внутри элемента данных. Это верно как для одноэлементных, так и для списочных полей, поскольку одноэлементное поле может быть ошибочно передано с несколькими элементами и обнаружение таких ошибок повышает функциональную совместимость. Поля, в которых ожидаются запятые внутри элемента, такие как HTTP-date и URI-reference, должны определяться с разделителями вокруг такого элемента, чтобы отличить запятую в данных от разделителя списка. Например, текстовая дата и URI (оба могут включать запятую) можно безопасно передавать в значениях списочного поля, как показано ниже.

   Example-URIs: "http://example.com/a.html,foo",
                 "http://without-a-comma.example.com/"
   Example-Dates: "Sat, 04 May 1996", "Wed, 14 Sep 2005"

Отметим, что разделители в форме двойных кавычек почти всегда применяются при создании строк в кавычках (quoted-string, параграф 5.6.4) и применение иного синтаксиса внутри двойных кавычек приведёт, скорей всего, к ненужной путанице.

Многие поля (такие как Content-Type из параграфа 8.3) используют для параметров базовый синтаксис (параграф 5.6.6), допускающий указывать значения параметра как без кавычек (token), так и в кавычках (quoted-string). Это позволяет получателям использовать имеющиеся компоненты синтаксического анализатора. Если разрешены обе формы, смысл значения параметра должен быть одинаковым при его получении в виде маркера или в кавычках.

Примечание. Для определения синтаксиса значения полей в этой спецификации применяется правило ABNF, называемое по имени поля, для задания разрешённой грамматики в значении поля (после того, как значение поля извлечено из базового синтаксиса сообщения и экземпляры объединены в список).

5.6. Общие правила определения значений полей

5.6.1. Списки (расширение #rule в ABNF)

Расширение #rule для правил ABNF [RFC5234] служит для улучшения читаемости в некоторых определениях значений полей на основе списков. Определена конструкция #, похожая на *, для задания списков элементов, разделённых запятыми. Полная форма <n>#<m>element указывает наличие от <n> до <m> элементов, разделённых запятой (,) и необязательными пробельными символами (OWS, параграф 5.6.3).

5.6.1.1. Требования к отправителю

В любом результате, использующем список, отправителю недопустимо генерировать пустые элементы списка. Иными словами, при генерации списка отправитель должен следовать синтаксису

     1#element => element *( OWS "," OWS element )

и

     #element => [ 1#element ]

а также для n >= 1 и m > 1 должно выполняться условие

     <n>#<m>element => element <n-1>*<m-1>( OWS "," OWS element )

В приложении A дана сводка ABNF для отправителей после преобразования конструкций со списком.

5.6.1.2. Требования к получателю

Пустые элементы не учитываются при подсчёте. Получатель должен анализировать и игнорировать разумное число пустых элементов списка, достаточное, чтобы справиться с обычными ошибками отправителей, но не так много, чтобы это можно было использовать для Dos-атак. Иными словами, получатель должен воспринимать списки, удовлетворяющий приведённому ниже синтаксису.

     #element => [ element ] *( OWS "," OWS [ element ] )

Отметим, что из-за возможного присутствия пустых элементов RFC 5234 ABNF не может потребовать определённое число элементов списка и поэтому все варианты отображаются, как будто это число не указано. Например,

     example-list      = 1#example-list-elmt
     example-list-elmt = token ; см. параграф 5.6.2

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

     "foo,bar"
     "foo ,bar,"
     "foo , ,bar,charlie"

Ниже приведены значения, которые недействительны, поскольку в example-list нужен хотя бы один непустой элемент.

     ""
     ","
     ",   ,"

5.6.2. Маркеры

Маркер (token) — короткий текстовый идентификатор без пробелов и разграничителей.

     token          = 1*tchar

     tchar          = "!" / "#" / "$" / "%" / "&" / "'" / "*"
                    / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
                    / DIGIT / ALPHA
                    ; any VCHAR, except delimiters

Многие значения полей HTTP определяются с использованием компонентов базового синтаксиса, разделённых пробельными символами или конкретными ограничителями. Ограничители выбираются из числа видимых символов US-ASCII, не разрешённых в маркерах (DQUOTE и (),/:;<=>?@[\]{}).

5.6.3. Пробельные символы

В этой спецификации применяется 3 правила для обозначения пробельных символов — OWS (необязательные), RWS (обязательные), BWS («плохие»).

Правило OWS используется в случаях, когда может присутствовать последовательность пробельных октетов. Для элементов протокола, где необязательные пробелы улучшают читаемость, отправителю следует генерировать необязательные пробельные символы в форме одного символа SP, в иных случаях отправителю не следует генерировать такие символы за исключением случаев переопределения непригодных или нежелательных элементов протокола при фильтрации сообщения на месте (in-place).

Правило RWS применяется, когда нужен хотя бы один пробельный октет для разделения маркеров поля. Отправителю следует генерировать RWS в форме одного символа SP.

OWS и RWS имеют такую же семантику, как один символ SP. Любое содержимое, заданное как OWS или RWS можно заменить одним символом SP перед интерпретацией или пересылкой сообщения в нисходящем направлении.

Правило BWS применяется там, где грамматика допускает дополнительные пробельные символы лишь по историческим причинам. Отправителю недопустимо генерировать BWS в сообщениях. Получатель должен анализировать такие пробельные символы и удалять их перед интерпретацией протокольного элемента. BWS не имеет семантики и любое содержимое, заданное как BWS можно удалять перед интерпретацией или пересылкой сообщения в нисходящем направлении.

     OWS            = *( SP / HTAB )
                    ; необязательные пробельные символы
     RWS            = 1*( SP / HTAB )
                    ; обязательные пробельные символы
     BWS            = OWS
                    ; «плохие» пробельные символы

5.6.4. Строки в кавычках

Строка текста считается одним значением, если она заключена в двойные кавычки.

     quoted-string  = DQUOTE *( qdtext / quoted-pair ) DQUOTE
     qdtext         = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text

Октет обратной дробной черты (backslash octet, \) может служить служить в качестве однооктетного символа «кавычек» внутри конструкции с кавычками и комментариев. Получатель, обрабатывающий значение строки в кавычках, должен обрабатывать пару кавычек, как будто она заменена октетом, следующим за символом \.

     quoted-pair    = "\" ( HTAB / SP / VCHAR / obs-text )

Отправителям не следует генерировать пары кавычек в строке с кавычками за исключением случаев необходимости поместить в кавычки DQUOTE и октеты \, встречающиеся в строке. Отправителю не следует генерировать пары кавычек в комментариях за исключением случаев необходимости поместить в кавычки символы круглых скобок () и октеты \ внутри комментария.

5.6.5. Комментарии

Комментарии можно помещать в некоторые поля HTTP, заключая текст комментария в круглые скобки. Комментарии разрешены лишь в полях, включающих comment как часть определения поля.

     comment        = "(" *( ctext / quoted-pair / comment ) ")"
     ctext          = HTAB / SP / %x21-27 / %x2A-5B / %x5D-7E / obs-text

5.6.6. Параметры

Параметры — это экземпляры пар «имя-значение». Параметры часто используются в значениях полей как базовый синтаксис добавления вспомогательной информации к элементу. Каждый параметр обычно ограничивается непосредственно предшествующим символом точки с запятой (;).

     parameters      = *( OWS ";" OWS [ parameter ] )
     parameter       = parameter-name "=" parameter-value
     parameter-name  = token
     parameter-value = ( token / quoted-string )

Регистр символов в именах параметров не учитывается, а в значениях регистр может играть роль в зависимости от семантики имени параметра. Примеры параметров и некоторые эквивалентные формы представлены в описании типов носителей (параграф 8.3.1) и поля заголовка Accept (параграф 12.5.1). Значение параметра, соответствующее маркеру, может быть представлено маркером или строкой в кавычках (эти представления эквивалентны).

Примечание. В параметрах не разрешены пробельные символы (даже BWS) вокруг символа равенства (=).

5.6.7. Форматы дат и времени

До 1995 г. серверы обычно использовали три разных формата для передачи меток времени. Для совместимости со старыми реализациями эти форматы определены ниже. Предпочтительным форматом является подмножество спецификации даны и времени с фиксированным размером и одним часовым поясом, используемый в сообщениях Internet (Internet Message Format) [RFC5322].

     HTTP-date    = IMF-fixdate / obs-date

Пример этого формата приведён ниже.

     Sun, 06 Nov 1994 08:49:37 GMT    ; IMF-fixdate

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

     Sunday, 06-Nov-94 08:49:37 GMT   ; формат RFC 850
     Sun Nov  6 08:49:37 1994         ; формат asctime() из ANSI C

Получатель, анализирующий значение метки времени в поле HTTP, должен воспринимать все 3 формата HTTP-date. Когда отправитель генерирует поле с одной или несколькими метками времени, определёнными как HTTP-date, он должен использовать формат IMF-fixdate.

Значение HTTP-date указывает время как экземпляр всемирного координированного времени (Coordinated Universal Time или UTC). В двух первых форматах UTC обозначается трехсимвольной аббревиатурой GMT (Greenwich Mean Time), которая является предшественницей UTC. Значения в формате asctime предполагают время в UTC.

Часы (clock) — это реализация, способная обеспечить разумное приближение текущего момента в UTC. Реализация часов должна использовать NTP ([RFC5905]) или похожий протокол для синхронизации с UTC.

Ниже представлен предпочтительный формат.

     IMF-fixdate  = day-name "," SP date1 SP time-of-day SP GMT
     ; fixed length/zone/capitalization subset of the format
     ; see Section 3.3 of [RFC5322]

     day-name     = %s"Mon" / %s"Tue" / %s"Wed"
                  / %s"Thu" / %s"Fri" / %s"Sat" / %s"Sun"

     date1        = day SP month SP year
                  ; например, 02 Jun 1982

     day          = 2DIGIT
     month        = %s"Jan" / %s"Feb" / %s"Mar" / %s"Apr"
                  / %s"May" / %s"Jun" / %s"Jul" / %s"Aug"
                  / %s"Sep" / %s"Oct" / %s"Nov" / %s"Dec"
     year         = 4DIGIT

     GMT          = %s"GMT"

     time-of-day  = hour ":" minute ":" second
                  ; 00:00:00 - 23:59:60 (високосная секунда)

     hour         = 2DIGIT
     minute       = 2DIGIT
     second       = 2DIGIT

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

     obs-date     = rfc850-date / asctime-date

     rfc850-date  = day-name-l "," SP date2 SP time-of-day SP GMT
     date2        = day "-" month "-" 2DIGIT
                  ; например, 02-Jun-82

     day-name-l   = %s"Monday" / %s"Tuesday" / %s"Wednesday"
                  / %s"Thursday" / %s"Friday" / %s"Saturday"
                  / %s"Sunday"

     asctime-date = day-name SP date3 SP time-of-day SP year
     date3        = month SP ( 2DIGIT / ( SP 1DIGIT ))
                  ; например, Jun  2

Регистр символов в HTTP-date имеет значение. Отметим, что в параграфе 4.2 [CACHING] это требование смягчено для получателей кэшированных данных.

Отправителю недопустимо включать в HTTP-date пробельные символы сверх указанных в грамматике как SP. Семантика day-name, day, month, year, time-of-day может быть такой же, как определено для конструкций Internet Message Format с соответствующими именами ([RFC5322], параграф 3.3).

Получатели меток в формате rfc850-date, где используется 2 цифры года, должны интерпретировать метки, указывающие более чем на 50 лет в будущее, как представляющие последний год в прошлом, имеющий те же 2 последних цифры. Получателям меток времени рекомендуется быть отказоустойчивыми при анализе меток, если иное не задано определением поля. Например, сообщения иногда передаются по HTTP от иного (не HTTP) источника, который может генерировать дату и время в соответствии с любой спецификацией, заданной Internet Message Format.

Примечание. Требования HTTP к форматам меток времени применяются лишь при их использовании в потоке протокола. Реализации не обязаны использовать их в представлении пользователю, при записи в журнал и т. п.

6. Абстракция сообщения

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

Сообщение (message) включает:

  • данные управления для описания и маршрутизации сообщения;

  • таблицу заголовков с парами «имя-значение» для расширения данных управления и передачи дополнительных сведений об отправителе, сообщении, содержимом и контексте;

  • потенциально неограниченный поток содержимого;

  • таблицу трейлеров с парами «имя-значение» для передачи сведений, полученных при отправке содержимого.

Данные обрамления (framing) и управления передаются первыми, затем следует раздел заголовков с полями для таблицы заголовков. Если в сообщении имеется содержимое (content), оно передаётся после раздела заголовков, а за ним может следовать раздел трейлеров с полями для таблицы трейлеров.

Предполагается, что сообщения будут обрабатываться как поток, причём назначение этого потока и его дальнейшая обработка раскрываются в процессе чтения. Данные управления описывают, что получателю нужно узнать незамедлительно, поля заголовка, — что нужно знать до получения содержимого, а оно (при наличии) предположительно состоит из того, что получатель хочет или что нужно для выполнения семантики сообщения. Поля трейлера могут включать необязательные метаданные, которые не были известны до отправки содержимого.

Сообщения должны быть «самоописывающими» — всё, что получателю нужно знать о сообщении, можно определить просмотром самого сообщения после декодирования и восстановления частей, которые были сжаты или пропущены при передаче, без необходимости понимать текущее состояние приложения-отправителя (установленное через предшествующие сообщения). Однако клиент должен сохранять сведения о запросе при анализе, интерпретации или кэшировании соответствующего отклика. Например, отклики для метода HEAD выглядят как начало ответа на GET, но анализируются иначе.

Отметим, что эта абстракция сообщений является обобщением для многих версий HTTP, включая свойства, которые могут отсутствовать в некоторых версиях. Например, трейлеры были введены в версии HTTP/1.1 в форме раздела после содержимого. Эквивалент ACK присутствует в HTTP/2 и HTTP/3 в блоке заголовка, завершающего поток.

6.1. Обрамление и полнота

Обрамление показывает начало и конец сообщения, чтобы можно было отличить одно сообщение от других и шума в том же соединении. В каждой старшей версии HTTP определён свой механизм обрамления. В HTTP/0.9 и ранних внедрениях HTTP/1.0 использовался разрыв соединения в качестве завершения отклика. Для совместимости с прежними версиями такое неявное обрамление разрешено и в HTTP/1.1. Однако при неявном обрамлении может не различаться неполный отклик, если соединение разорвано рано. По этой причине в большинстве современных реализаций применяется явное обрамление в форме указания размера последовательности данных сообщения.

Сообщение считается полным (complete), когда доступны все октеты, указанные его обрамлением. Отметим, что при отсутствии явного обрамления сообщение, завершённое разрывом базового соединения считается полным, даже если его невозможно отличить от неполного отклика, пока ошибка транспортного уровня не указывает эту неполноту.

6.2. Данные управления

Сообщения начинаются с данных управления, описывающих основное назначение сообщения. Данные управления в запросе включают метод (раздел 9), и цель (параграф 7.1) запроса, версию протокола (параграф 2.5). Данные управления в отклике включают код статуса (раздел 15), необязательное описание причины и версию протокола.

В HTTP/1.1 ([HTTP/1.1]) и ранее данные управления передавались как первая строка сообщения, HTTP/2 ([HTTP/2]) и HTTP/3 ([HTTP/3]) — в полях псевдозаголовка, с зарезервированными префиксами имён (например, :authority).

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

Клиенту следует передавать запрос с номером версии, совпадающим с наибольшей поддерживаемой им версией, но не выше наибольшей версии, поддерживаемой сервером, если та известна. Клиенту недопустимо указывать версию, которой он не соответствует. Клиент может указать меньшую версию, если он знает, что сервер некорректно реализует спецификацию HTTP, но только после хотя бы однократной попытки обычного запроса и определения по коду отклика и полям заголовка (например, Server), что сервер не обрабатывает корректно запросы с большей версией.

Серверу следует передавать отклик с наибольшей поддерживаемой им версией, где старший номер не превышает номер версии в запросе. Серверу недопустимо указывать версию, которой он не соответствует. Сервер может передать отклик с кодом 505 (HTTP Version Not Supported), если он хочет отказать в обслуживании указанного клиентом старшего номера версии протокола.

Получателю сообщения со старшим номером версии, который он реализует, и младшим номером выше реализуемого им следует обработать сообщение, как будто оно соответствует наибольшему младшему номеру версии, реализуемому клиентом для данного старшего номера. Получатель может считать, что сообщение с большим младшим номером версии, отправленное получателю, ещё не указавшему поддержку этой версии, достаточно совместимо с прежними версиями и может быть безопасно обработано любой реализацией той же старшей версии.

6.3. Поля заголовков

Поля (раздел 5), передаваемые или принимаемые перед содержимым, называют полями заголовка (header field) или просто заголовками. Раздел заголовков (header section) сообщения состоит из последовательности строк полей заголовков. Каждое поле заголовка может изменять или расширять семантику сообщения, описывать отправителя, задавать содержимое или обеспечивать дополнительный контекст.

Примечание. Именуемые поля называются здесь header field, когда из разрешено передавать только с заголовке.

6.4. Содержимое

В сообщениях HTTP часто передаётся полное или частичное представление в форме содержимого (content) — потока октетов, передаваемого после заголовка, как это обозначено обрамлением сообщения. Это абстрактное определение содержимого отражает данные после их извлечения из рамок сообщения. Например, тело сообщения HTTP/1.1 (раздел 6 в [HTTP/1.1]) может состоять из потока данных, закодированного в форме блоков (chunk) — последовательности блоков данных, одного блока нулевого размера и раздела трейлеров, тогда как содержимое того же сообщения включает только поток данных после декодирования транспортного формата и не содержит размеров блоков, синтаксиса обрамления, поля трейлера (параграф 6.5).

Примечание. Имена некоторых полей имеют префикс Content-. Это неформальное соглашение — часть таких полей относится к содержимому сообщения, определённому выше, а другие — к выбранному представлению (параграф 3.2). Неоднозначность устраняется определениями конкретных полей.

6.4.1. Семантика содержимого

Назначение содержимого запроса задаёт семантика метода (раздел 9). Например, представление в содержимом запроса PUT (параграф 9.3.4) показывает желаемое состояние целевого ресурса после успешного применения запроса, а представление в содержимом POST (параграф 9.3.3) — информацию для обработки целевым ресурсом.

Назначение содержимого отклика определяется методом запроса, кодом статуса (раздел 15) и полями отклика, описывающими это содержимое. Например, содержимое отклика 200 (OK) на запрос GET (параграф 9.3.1) представляет текущее состояние целевого ресурса на момент создания сообщения (параграф 6.6.1), а содержимое отклика на POST с тем же кодом может представлять результат или новое состояние целевого ресурса после применения обработки. Содержимым отклика 206 (Partial Content) на запрос GET будут одна часть выбранного представления или многокомпонентное сообщение, содержащее части этого представления (параграф 15.3.7). Содержимым откликов с кодом ошибки обычно является представление условий ошибки, такое как состояние ошибки и предлагаемые шаги по её устранению.

Отклики на запрос HEAD (параграф 9.3.2) не включают содержимого и поля заголовка указывают лишь значения, которые были бы при использовании для запроса метода GET (параграф 9.3.1).

Отклики 2xx (Successful) на запрос CONNECT (параграф 9.3.6) переключают соединение в туннельный режим и не включают содержимого. Отклики с кодами 1xx (Informational), 204 (No Content), 304 (Not Modified) не имеют содержимого. Все прочие отклики включают содержимое, но оно может быть пустым (размера 0).

6.4.2. Идентификация содержимого

При передаче в качестве содержимого полного или частичного представления часто бывает желательно, чтобы отправитель предоставил, а получатель определил идентификатор для ресурса, соответствующий этому представлению. Например, клиент передающий запрос GET для ресурса с текущей сводкой погоды, может захотеть получить идентификатор для возвращаемого содержимого (например, сводка погоды в Laguna Beach в момент 20210720T1711). Это может быть полезно при совместном использовании или создании закладок для ресурсов, представление которых будет меняться с течением времени.

Для сообщений с запросами применяются указанные ниже правила.

  • Запрос с полем заголовка Content-Location означает утверждение отправителя, что содержимое является представлением ресурса, указанного значением поля Content-Location. Однако такому утверждению нельзя доверять, пока оно не может быть проверено иными средствами (не заданы в этой спецификации). Информация все равно может быть полезной для просмотра истории.

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

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

  1. Для запроса HEAD или отклик с кодом 204 (No Content) или 304 (Not Modified), в отклике нет содержимого.

  2. Для запроса GET и отклика с 200 (OK) содержимым является представление целевого ресурса (параграф 7.1).

  3. Для запроса GET и отклика с 203 (Non-Authoritative Information) содержимым является возможно изменённое или расширенное представление целевого ресурса от посредника.

  4. Для запроса GET и отклика с 206 (Partial Content) содержимое включает одну или несколько частей представления целевого ресурса.

  5. Если в отклике есть поле заголовка Content-Location, значением которого является та же ссылка URI, что и URI цели, содержимым является представление целевого ресурса.

  6. Если в отклике есть поле заголовка Content-Location, значением которого является ссылка URI, отличающаяся от URI цели, это означает утверждение отправителя, что содержимым является представление ресурса, указанного значением поля Content-Location. Однако такому утверждению нельзя доверять, пока оно не может быть проверено иными средствами (не заданы в этой спецификации).

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

6.5. Поля трейлера

Поля (раздел 5), размещаемые в разделе трейлера (trailer section), называют полями трейлера (trailer field) или просто трейлерами. Эти поля могут быть полезны для проверки целостности сообщения, цифровых подписей, параметров доставки и сведение о статусе пост-обработки. Поля трейлера должны обрабатываться и сохраняться отдельно от полей заголовка, чтобы не противоречить семантике сообщения, заданной на момент завершения заголовочной части. Наличие или отсутствие некоторых полей заголовка может влиять на выбор маршрутизации или обработки сообщения в целом до приёма трейлера. Этот выбор не может быть отменен последующими полями трейлера.

6.5.1. Ограничения на использование трейлеров

Раздел трейлера возможен лишь в случае поддержки применяемой версией HTTP и разрешения явным механизмом обрамления. Например блочное (chunk) транспортное кодирование в HTTP/1.1 разрешает передавать трейлерный раздел после содержимого (параграф 7.1.2 в [HTTP/1.1]).

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

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

Наличие ключевого слова trailers в поле заголовка TE (параграф 10.1.4) в запросе указывает, что клиент желает воспринимать поля трейлеров от своего имени и от имени всех нисходящих клиентов. Для запросов от посредника это означает, что все клиенты нисходящего направления желают воспринимать поля трейлеров в пересылаемых сообщениях. Отметим, что наличие trailers не означает, что клиенты будут обрабатывать какое-либо конкретное поле трейлера и говорит лишь о том, что разделы трейлеров не будут отбрасываться каким-либо из клиентов.

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

6.5.2. Обработка полей трейлера

Поле заголовка Trailer (параграф 6.6.2) может передаваться для указания полей, которые, вероятно, будут передаваться в разделе трейлера, что позволит получателям подготовиться к их приёму до обработки содержимого. Например, это может быть полезно, если имя поля указывает, что следует рассчитывать динамическую контрольную сумму по мере получения содержимого, а затем сразу же проверять её после получения значения в поле трейлера.

Как и поля заголовков, трейлерные поля с одинаковыми именами обрабатываются в порядке приёма. Семантика полей с одним именем в нескольких строках эквивалентна добавлению в конец множества значения в форме списка. Поля трейлера, которые могут генерироваться неоднократно в сообщении, должны определяться как списочные даже если значение каждого элемента обрабатывается лишь один раз на принятую строку поля.

В конце сообщения получатель может рассматривать набор принятых полей трейлера как структуру данных «имя-значение», аналогичную (но отдельную) полям заголовка. Дополнительные ожидания в части обработки могут задаваться в спецификации поля, предназначенного для использования в трейлерах.

6.6. Метаданные сообщения

Поля, описывающие само сообщение, например, момент и способ генерации, разрешены в запросах и откликах.

6.6.1. Date

Поле заголовка Date указывает дату и время создания сообщения, используя семантику поля Origination Date (orig-date), заданную в параграфе 3.6.1 [RFC5322]. Значение поля имеет тип HTTP-date, как указано в параграфе 5.6.7.

     Date = HTTP-date

Ниже приведён пример строки поля.

   Date: Tue, 15 Nov 1994 08:12:31 GMT

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

Сервер-источник с часами (как указано в параграфе 5.6.7) должен генерировать поле Date во всех откликах с кодом 2xx (Successful), 3xx (Redirection), 4xx (Client Error) и может генерировать его в откликах 1xx (Informational) и 5xx (Server Error). Серверу-источнику без часов недопустимо генерировать поле заголовка Date.

Получатель с часами, принявший отклик без поля заголовка Date, должен записать время получения и добавить соответствующее поле заголовка Date в конец раздела заголовков сообщения, если он кэширует или пересылает сообщения в нисходящем направлении. Получатель с часами, принявший отклик с полем заголовка Date, может заменить значение этого поля моментом, соответствующим приёму отклика.

Пользовательский агент может передавать поле заголовка Date в запросе, но обычно это не делается, если он не считает, что сведения будут полезны серверу. Например, пользовательские приложения HTTP могут передавать Date, если предполагается, что сервер будет подстраивать интерпретаций пользовательского запроса с учётом разницы часов пользовательского агента и сервера.

6.6.2. Trailer

Поле заголовка Trailer обеспечивает список имён полей, которые отправитель предполагает передать в трейлере данного сообщения. Это позволяет получателю приготовиться в приёму указанных метаданных до начала обработки содержимого.

     Trailer = #field-name

Отправитель может указать, например, что подпись рассчитывается в процессе передачи потока и предоставить окончательную подпись в поле трейлера. Это позволит получателю выполнить ту же проверку «на лету» по мере приёма содержимого.

Отправителю, намеренному передать 1 или несколько полей трейлера, следует создать поле Trailer в разделе заголовков сообщения для указания полей, которые могут быть помещены в трейлер.

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

7. Маршрутизация сообщений HTTP

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

7.1. Определение целевого ресурса

Хотя HTTP применяется в самых разных приложениях, большинство клиентов полагается на тот же механизм и методы настройки конфигурации, что и Web-браузеры общего назначения. Даже при жёстком задании опций настройки в конфигурации клиента их можно рассматривать в совокупности как ссылку URI (параграф 4.1). Ссылка URI для получения URI цели преобразуется в абсолютную форму. В URI исключён компонент фрагмента (если он был), поскольку идентификаторы фрагменты зарезервированы для обработки на стороне клиента ([URI], параграф 3.5).

Для выполнения действий над целевым ресурсом клиент передаёт сообщение с запросом, содержащее достаточное число компонентов разобранного URI цели, чтобы получатели могли идентифицировать этот ресурс. По историческим причинам разобранные компоненты URI цели, совместно называемые целью запроса (request target), передаются в управляющих данных сообщения и поле заголовка Host (параграф 7.2).

Имеется 2 необычных случая, когда компоненты цели запроса имеют зависящую от метода форму:

  • для CONNECT (параграф 9.3.6) целью запроса является имя хоста и номер порта у адресата туннеля, разделённые двоеточием;

  • для OPTIONS (параграф 9.3.7) целью запроса может быть один символ звёздочки (*).

Детали приведены в описаниях указанных методов. В других методах эти формы недопустимы.

При получении запроса от клиента сервер восстанавливает URI цели из принятых компонентов в соответствии со своей локальной конфигурацией и контекстом входящего соединения. Эта реконструкция зависит от старшей версии протокола. Например, в параграфе 3.3 [HTTP/1.1] сказано, как сервер определяет URI цели в запросе HTTP/1.1.

Примечание. Предыдущие спецификации определяли восстановленный URI цели как отдельное понятие эффективного URI запроса (effective request URI).

7.2. Host и :authority

Поле заголовка Host в запросе предоставляет сведения о хосте и номере порта из URI цели, позволяя серверу-источнику различать ресурсы при обслуживании запросов для разных имён хостов. В HTTP/2 [HTTP/2] и HTTP/3 [HTTP/3] поле Host в некоторых случаях подменяется полем псевдозаголовка :authority в данных управления запроса.

     Host = uri-host [ ":" port ] ; Section 4

Сведения о полномочиях URI цели критически важны для обработки запроса. Агент пользователя должен генерировать поле Host в запросах, если он не передаёт эти сведения в поле псевдозаголовка :authority. Пользовательскому агенту, передающему Host следует размещать его первым в разделе заголовков запроса. Например, запрос GET к серверу-источнику <http://www.example.org/pub/WWW/> следует начинать с

   GET /pub/WWW/ HTTP/1.1
   Host: www.example.org

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

7.3. Маршрутизация входящих запросов

После определения URI цели и источника клиент решает, нужен ли сетевой запрос для реализации желаемой семантики и куда его следует направлять (если запрос нужен).

7.3.1. В кэш

Если у клиента имеется кэш [CACHING], способный выполнить запрос, тогда запрос обычно сначала передаётся в кэш.

7.3.2. В прокси

Если запрос не выполнен кэшем, клиент обычно определяет из своей конфигурации наличие прокси, куда можно отправить запрос. Настройка прокси зависит от реализации, но зачастую базируется на сопоставлении префиксов URI, выбранных полномочных органов или того и другого, а сам прокси обычно указывается URI http или https. Если прокси http или https применим, клиент организует (или использует имеющееся) входящее с этим прокси и передаёт ему запросное сообщение HTTP с целью запроса, соответствующей клиентскому URI цели.

7.3.3. Источнику

Если прокси не применим, типичный клиент вызывает для доступа к указанному ресурсу процедуру-обработчик (в зависимости от схемы URI цели), заданную соответствующей спецификацией.

В параграфе 4.3.2 указано, как получить доступ к ресурсу http путём организации (или использования имеющегося) входящего соединения с указанным сервером-источником и последующей отправки ему запросного сообщения HTTP с целью запроса, соответствующей клиентскому URI цели.

В параграфе 4.3.3 указано, как получить доступ к ресурсу https путём организации (или использования имеющегося) защищённого входящего соединения с сервером-источником, полномочным для указанной цели, и последующей отправки ему запросного сообщения HTTP с целью запроса, соответствующей клиентскому URI цели.

7.4. Отклонение ошибочно направленных запросов

Когда запрос получен сервером и проанализирован достаточно для определения URI цели, сервер решает, обработать ли запрос самостоятельно, перенаправить клиента на другой ресурс, ответить кодом ошибки или сбросить соединение. На это решение могут влиять любые сведения о запросе и контексте соединения, но в первую очередь влияет настроенность сервера на обработку запросов для URI цели и пригодность контекста соединения для этого запроса. Например, запрос может быть направлен по ошибке (намеренной или случайной), такой как несоответствие сведений в полученном поле заголовка Host порту или хосту в соединении. Если соединение осуществляется с доверенного шлюза, такое несоответствие может быть ожидаемым, в ином случае оно может говорить о попытке обойти защитные фильтры, обмануть сервер для получения непубличного содержимого или отравить кэш. Вопросы безопасности, связанные с маршрутизацией сообщений, рассматриваются в разделе 17.

Когда соединение установлено не с доверенным шлюзом, сервер-источник должен отклонять запрос, если тот не соответствует какому-либо требованию к URI цели, определяемому схемой. В частности, запрос https должен отвергаться, если он не получен через соединение, защищённое с сертификатом, который действителен для источника URI цели, как указано в параграфе 4.2.2.

Код 421 (Misdirected Request) в отклике указывает, что сервер-источник отклонил запрос, по-видимому, сочтя его направленным ошибочно ().

7.5. Сопоставление запросов и откликов

Соединение может быть использовано для множества обменов «запрос-отклик». Механизм сопоставления сообщений с запросами и откликами зависит от версии HTTP и может использовать явное или неявное упорядочение.

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

Клиенту, получившему отклик во время передачи связанного с ним запроса, следует продолжать передачу запроса, если он не получил явного указания на обратное (см., например, параграф 9.5 в [HTTP/1.1] и параграф 6.4 в [HTTP/2]).

7.6. Пересылка сообщений

Как описано в параграфе 3.7, посредники могут играть разные роли в обработке запросов и откликов HTTP. Некоторые посредники служат для повышения производительности и доступности, другие — для контроля доступа или фильтрации содержимого. Поскольку характеристики потока HTTP похожи на архитектуру «труба и фильтр» (pipe-and-filter), не возникает каких-либо ограничений степени улучшения (или помех) от посредников для любого направления потока. Предполагается, что посредники пересылают сообщения даже с непонятными элементами протокола (например, с новыми методами, кодами статуса или именами полей), поскольку это сохранит расширяемость для нисходящих получателей.

Посредник, не являющийся туннелем, должен реализовать поле заголовка Connection, как описано в параграфе 7.6.1, и исключать из пересылки поля, предназначенные лишь для входящего соединения. Посреднику недопустимо пересылать сообщение самому себе, если он не защищён от бесконечных циклов запросов. В общем случае посредник должен распознавать свои имена серверов, включая псевдонимы, локальные варианты и адреса IP, отвечая на такие запросы напрямую.

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

7.6.1. Connection

Поле заголовка Connection позволяет отправителю задать список желаемых опций управления для текущего соединения. Регистр символов в опциях не принимается во внимание.

     Connection        = #connection-option
     connection-option = token

Если отличное от Connection поле применяется для передачи управляющих сведений для текущего соединения или о нем, отправитель должен указать имя соответствующего поля в поле заголовка Connection. Отметим, что некоторые версии HTTP запрещают использование полей для таких сведений и, следовательно, не разрешают Connection.

Посредники должны анализировать поле заголовка Connection до пересылки сообщения и для каждой опции соединения (connection-option) в этом поле удалять из сообщения любые поля заголовка или трейлера с тем же именем как у опции соединения, а затем удалять само поле заголовка Connection или заменять его своими опциями управления для пересылаемого сообщения).

Поле заголовка Connection обеспечивает декларативный способ отличать поля, предназначенные лишь для непосредственного получателя (hop-by-hop), от полей для всех получателей в цепочке (end-to-end), позволяя сообщению быть самоописывающим и обеспечивая возможность внедрения будущих расширений, связанных с соединением, без опасений их пересылки вслепую старыми посредниками. Кроме того, посредникам следует удалять или заменять поля, для которых это требуется перед пересылкой, независимо от их присутствия в качестве опций соединения, после применения семантики этих полей. Это включает перечисленные ниже поля (возможно, и другие):

  • Proxy-Connection (Приложение C.2.2 к [HTTP/1.1]);

  • Keep-Alive (параграф 19.7.1 в [RFC2068]);

  • TE (параграф 10.1.4);

  • Transfer-Encoding (параграф 6.1 в [HTTP/1.1]);

  • Upgrade (параграф 7.8).

Отправителю недопустимо передавать опцию соединения, соответствующую полю, которое предназначено для всех получателей содержимого. Например, Cache-Control не подходит как опция соединения (параграф 5.2 в [CACHING]).

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

При определении новой опции соединения, не соответствующей полю, авторы спецификации должны зарезервировать соответствующее имя поля, чтобы впредь не возникало конфликтов. Такие имена полей регистрируются в реестре Hypertext Transfer Protocol (HTTP) Field Name Registry ().

7.6.2. Max-Forwards

Поле заголовка Max-Forwards позволяет ограничить число пересылок запроса между прокси с помощью методов TRACE (параграф 9.3.8) и OPTIONS (параграф 9.3.7). Это может быть полезно, когда клиент пытается отследить запрос, который, вероятно, вызвал отказ или попал в петлю пересылки.

     Max-Forwards = 1*DIGIT

Значение Max-Forwards задаётся десятичным целым числом, указывающим оставшееся число возможных пересылок.

Каждый посредник, получивший запрос TRACE или OPTIONS с полем заголовка Max-Forwards, должен проверить и обновить значение до пересылки запроса. Если получено значение 0, посреднику недопустимо пересылать сообщение и он должен ответить как конечный получатель. Если Max-Forwards больше 0, посредник должен обновить поле Max-Forwards в пересылаемом сообщении значением a) меньше принятого на 1 или b) максимальным значением Max-Forwards, установленным у посредника.

Получатель может игнорировать полученное в заголовке поле Max-Forwards для любого другого метода запроса.

7.6.3. Via

Поле заголовка Via указывает наличие промежуточных протоколов и получателей между агентом пользователя и сервером (для запросов) или между сервером-источником и клиентом (для откликов), подобно полю Received в заголовках электронной почты (параграф 3.6.7 в [RFC5322]). Поле Via может служить для отслеживания пересылок сообщения, предотвращения петель для запросов и указания протокольных возможностей отправителей по цепочке запросов и откликов.

     Via = #( received-protocol RWS received-by [ RWS comment ] )

     received-protocol = [ protocol-name "/" ] protocol-version
                       ; см. параграф 7.8
     received-by       = pseudonym [ ":" port ]
     pseudonym         = token

Каждый элемент поля Via представляет прокси или шлюз, пересылающий сообщение. Каждый посредник добавляет в конец свои сведения о приёме сообщения и конечный результат упорядочен в соответствии с последовательностью получателей при пересылке. Прокси должны передавать соответствующее поле заголовка Via, как описано ниже, в каждом пересылаемом сообщении. Шлюз HTTP-HTTP должен передавать соответствующее поле заголовка Via в каждом входящем запросе и может передавать Via в пересылаемых откликах.

Для каждого посредника received-protocol указывает протокол и его версию, используемые восходящим отправителем сообщения. В результате значение поля Via фиксирует анонсированные возможности протокола в цепочке запросов и откликов так, что они остаются видимыми для нисходящих получателей. Это может быть полезно для обнаружения возможности безопасного использования несовместимых с прежними версиями свойств в отклике или последующем запросе, как описано в параграфе 2.5. Для краткости protocol-name не указывается, если received-protocol — это HTTP.

Элемент received-by обычно указывает хост и необязательный номер порта сервера-получателя или клиента, который переслал сообщение. Однако если сведения о реальных хостах считаются конфиденциальными, отправитель может заменить их псевдонимом. Если порт не указан, получатель может считать его принятым по умолчанию, если такой порт задан для received-protocol.

Отправитель может вносить комментарии для идентификации программ каждого получателя (как в полях User-Agent и Server). Однако комментарии в Via не обязательны и получатель может удалить их до пересылки сообщения.

Например, запрос может передать агент пользователя HTTP/1.0 внутреннему прокси с именем fred, где применяется HTTP/1.1, для пересылки публичному прокси p.example.net, который завершает запрос пересылкой серверу-источнику www.example.com. В полученном сервером запросе будет поле заголовка

   Via: 1.0 fred, 1.1 p.example.net

Посреднику, служащему порталом через межсетевой экран, не следует пересылать имена и порты из защищённой области, если это не разрешено явно. При отсутствии такого разрешения посреднику следует заменять каждый в received-by хоста из защищённой области подходящим псевдонимом.

Посредник может объединять элементы упорядоченного списка поля заголовка Via в один элемент, если эти записи имеют идентичные значения received-protocol. Например,

   Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy

можно сжать до

   Via: 1.0 ricky, 1.1 mertz, 1.0 lucy

Отправителю недопустимо объединять элементы списка, если они не находятся под управлением одной организации, а хосты уже заменены псевдонимами. Отправителю недопустимо объединять записи с разными received-protocol.

7.7. Преобразование сообщения

У некоторых посредников имеются средства преобразования сообщений и их содержимого. Например, прокси может преобразовывать формат изображений для экономии пространства в кэше и сокращения трафика в медленных каналах. Однако применение таких преобразований к содержимому, предназначенному для критически важных приложений (например, медицинские изображения или анализ научных данных), могут вызывать проблемы при работе, особенно в случаях применения контроля целостности или цифровых подписей для обеспечения доставки содержимого без изменений.

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

Если прокси получает URI с именем хоста, не являющимся полным доменным именем, он может добавить имя своего домена к имени хоста при пересылке запроса. Прокси недопустимо менять имя хоста, если в URI цели указано полное доменное имя.

Прокси недопустимо менять absolute-path и query в полученном URI цели при пересылке следующему принимающему серверу, если этого не требует протокол пересылки. Например, прокси, пересылающий запрос серверу-источнику по протоколу HTTP/1.1, будет заменять пустой путь символом / (параграф 3.2.1 в [HTTP/1.1]) или * (параграф 3.2.4 в [HTTP/1.1]) в зависимости от метода запроса.

Прокси недопустимо преобразовывать содержимое (параграф 6.4) отклика с директивой кэширования no-transform (параграф 5.2.2.6 в [CACHING]). Отметим, что это не относится к преобразованию сообщений, не меняющему содержимого, такому как добавление или удаление транспортного кодирования (раздел 7 в [HTTP/1.1]). Прокси может преобразовывать содержимое сообщения без директивы кэширования no-transform. Прокси, преобразующий содержимое отклика 200 (OK), может информировать нисходящих получателей о применении преобразования заменой пода отклика на 203 (Non-Authoritative Information) (параграф 15.3.4).

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

7.8. Upgrade

Поле заголовка Upgrade предназначено для обеспечения простого механизма перехода от HTTP/1.1 к другому протоколу в том же соединении. Клиент может передать список имён протоколов в поле заголовка Upgrade в запросе, чтобы предложить серверу переключиться на один или несколько из указанных протоколов до отправки окончательного отклика. Сервер может игнорировать полученное поле заголовка Upgrade, если он хочет продолжить использование в соединении текущего протокола. Поле Upgrade не может применяться для настаивания на смене протокола.

     Upgrade          = #protocol

     protocol         = protocol-name ["/" protocol-version]
     protocol-name    = token
     protocol-version = token

Хотя имена протоколов регистрируются в предпочтительном регистре, получателям следует использовать сравнение без учёта регистра при сопоставлении protocol-name с поддерживаемыми протоколами.

Сервер, передающий отклик 101 (Switching Protocols), должен включить поле заголовка Upgrade для указания новых протоколов, на которые переключено соединение. Если переключаются протоколы нескольких уровней, отправитель должен указать список протоколов в порядке роста уровней. Серверу недопустимо переключаться на протокол, не указанный клиентом в поле заголовка Upgrade соответствующего запроса. Сервер может игнорировать указанный клиентом порядок предпочтения и выбирать новые протоколы на основе других факторов, например, характера запроса или текущей загрузки сервера. Сервер, передающий отклик 426 (Upgrade Required), должен включить в него поле заголовка Upgrade для указания приемлемых протоколов в порядке снижения предпочтений.

Сервер может передавать поле заголовка Upgrade в любом другом отклике для анонсирования поддержки перехода на указанные в списке протоколы (в порядке снижения предпочтений) в будущих запросах. Ниже приведён пример гипотетического запроса от клиента.

   GET /hello HTTP/1.1
   Host: www.example.com
   Connection: upgrade
   Upgrade: websocket, IRC/6.9, RTA/x11

Возможности и характер взаимодействия на прикладном уровне после смены протокола полностью зависят от выбранных протоколов. Однако предполагается, что сразу после передачи отклика 101 (Switching Protocols) сервер продолжит отвечать на исходный запрос, как будто принят его аналог по новому протоколу (после смены протокола сервер все равно должен выполнить запрос и предполагается, что запрос не потребуется повторять). Например, при получении поля Upgrade в запросе GET сервер, решивший поменять протокол, сначала передаёт сообщение 101 (Switching Protocols) в HTTP/1.1, а сразу после этого отвечает по новым протоколам на запрос GET для целевого ресурса. Это позволяет перевести соединение на протоколы с идентичной HTTP семантикой без издержек в виде дополнительного кругового обхода. Серверу недопустимо переключать протоколы, если семантика полученного сообщения не реализуется с новыми протоколами. Запрос OPTIONS может быть выполнен любым протоколом.

Ниже представлен пример отклика, на приведённый выше запрос.

   HTTP/1.1 101 Switching Protocols
   Connection: upgrade
   Upgrade: websocket

   [...поток данных переключён на websocket с соответствующим откликом
    (определяется новым протоколом) на запрос GET /hello...]

Отправитель Upgrade должен также передать опцию соединения Upgrade в поле заголовка Connection (параграф 7.6.1) для информирования посредников о том, что это поле не следует пересылать. Сервер, получивший поле заголовка Upgrade в запросе HTTP/1.0, должен игнорировать это поле.

Клиент не может начать использование в соединении обновлённого протокола, пока он не передаст полностью запросное сообщение (т. е. клиент не может поменять протокол, если передача сообщения ещё не завершена). Если сервер получает сразу поля заголовка Upgrade и Expect с ожиданием 100-continue (параграф 10.1.1), он должен передать отклик 100 (Continue) до отправки отклика 101 (Switching Protocols).

Поле заголовка Upgrade применяется только для переключения протоколов, работающий через имеющееся соединение и не позволяет переключить базовый (транспортный) протокол или поменять имеющееся соединение на другое. Для этих целей можно использовать отклики 3xx (Redirection) (параграф 15.4).

Данная спецификация задаёт лишь имя протокола HTTP только для семейства протоколов передачи гипертекста (Hypertext Transfer Protocols), как задано правилами для версии HTTP в параграфе 2.5 и будущими обновлениями этой спецификации. Другие имена протоколов должны регистрироваться по процедуре, заданной с параграфе 16.7.

8. Представление данных и метаданных

8.1. Представление данных

Данные представления, связанного с сообщением HTTP, обеспечиваются содержимым сообщения или ссылкой семантики сообщения и URI цели. Формат и кодировку данных представления задают поля метаданных в заголовке. Тип данных представления определяется в полях заголовка Content-Type и Content-Encoding. Это задаёт двухуровневую упорядоченную модель кодирования.

     representation-data := Content-Encoding( Content-Type( data ) )

8.2. Представление метаданных

Метаданные представления содержатся в полях заголовка этого представления. Если в сообщении имеется содержимое, поля заголовка представления описывают способы интерпретации данных. В отклике на запрос HEAD поля заголовка представления описывают данные представления, которые мыли бы вложен в отклик на такой же запрос GET.

8.3. Content-Type

Поле заголовка Content-Type указывает тип носителя в связанном представлении — это представление, вложенное в содержимое сообщения или выбранное представление, заданное семантикой сообщения. Указанный тип носителя определяет формат данных и способ их обработки получателем в рамках семантики принятого сообщения после декодирования содержимого в соответствии с Content-Encoding.

     Content-Type = media-type

Типы носителей определены в параграфе 8.3.1. Пример поля приведён ниже.

   Content-Type: text/html; charset=ISO-8859-4

Отправителю, генерирующему сообщение с содержимым, следует включать в сообщение поле заголовка Content-Type, если отправитель не знает тип содержимого для вложенного представления. Если поле Content-Type не включено, получатель может предположить тип application/octet-stream ([RFC2046], Section 4.5.1) или проверить данные для определения типа.

На практике владельцы ресурсов не всегда настраивают свой сервер-источник на указание корректного Content-Type для данного представления. Некоторые пользовательские агенты проверяют содержимое и, в некоторых случаях, переопределяют полученный тип (см., например, [Sniffing]). В результате такого «вынюхивания» (MIME sniffing) могут быть сделаны ложные выводы о данных, которые могут вызывать для пользователя дополнительный риск в части защиты (например, повышение привилегий). Кроме того, в различных типах носителей часто применяется один формат данных и типы различаются лишь способом обработки данных, которые не определить простым изучением данных. При реализации «обнюхивания» разработчикам рекомендуется давать пользователю возможность отключить его.

Хотя поле Content-Type определено как одноэлементное, иногда его некорректно указывают несколько раз, что ведёт к возникновению списка значений. Получатели часто пытаются обработать такую ошибку используя из списка последний синтаксически верный элемент, что может вести к проблемам совместимости и рискам безопасности, если разные реализации по-своему обрабатывают ошибку.

8.3.1. Тип носителя

HTTP использует тип носителя [RFC2046] в полях заголовка Content-Type (параграф 8.3) и Accept (параграф 12.5.1) для обеспечения открытой, расширяемой типизации данных и согласования типов. Тип носителя задаёт формат данных и способ их обработки в соответствии с контекстом сообщения.

     media-type = type "/" subtype parameters
     type       = token
     subtype    = token

Регистр символов в маркерах типов и субтипов не принимается во внимание.

За типом (субтипом) могут через точку с запятой следовать параметры (параграф 5.6.6) в виде пар «имя-значение». Наличие или отсутствие параметра может быть значимым для обработки типа носителя в зависимости от его определения в реестре типов. Регистр символов в параметрах может иметь значение в зависимости от семантики имени параметра. Ниже в качестве примера приведены эквивалентные записи, описывающие текстовые данные HTML в кодировке UTF-8, среди которых первая строка является предпочтительной с плане согласованности (значение параметра charset определено как независимое от регистра символов в параграфе 4.1.2 [RFC2046]).

     text/html;charset=utf-8
     Text/HTML;Charset="utf-8"
     text/html; charset="utf-8"
     text/html;charset=UTF-8

Типы носителей должны регистрироваться в реестре IANA по процедурам, заданным в [BCP13].

8.3.2. Charset

В HTTP применяются имена charset для указания кодировки символов ([RFC6365], раздел 2) в текстовом представлении. В полях, определяемых этим документом, имена charset указываются в параметрах (Content-Type) или (для Accept-Charset7) в форме обычного маркера (token). В обоих случаях имена сопоставляются без учёта регистра.

Имена charset должны регистрироваться в реестре IANA Character Sets (https://www.iana.org/assignments/character-sets) по процедурам, заданным в разделе 2 [RFC2978].

Примечание. В теории имена charset определяет правило ABNF mime-charset, определённое в параграфе 2.3 [RFC2978] (с учётом [Err1912]). Это правило допускает использование двух символов, не входящих в token ({ и }), однако ни в одном из зарегистрированных на момент написания документа имён этих символов нет (см. [Err5433]).

8.3.3. Составные типы

MIME применяется для большого числа многокомпонентных (multipart) типов, где инкапсулируется одно или несколько представлений в теле одного сообщения. Для всех составных типов применяется общий синтаксис, заданный в параграфе 5.1.1 [RFC2046], и параметр границы как часть значения media-type. Само тело сообщения является элементом протокола. Отправитель должен лишь генерировать символы CRLF для разделения частей тела.

В обрамлении сообщения HTTP не применяются границы между частями для указания размера тела сообщения, хотя их могут использовать реализации, генерирующие и обрабатывающие содержимое. Например, тип multipart/form-data часто применяется для переноса данных форм в запросе, как задано в [RFC7578], а тип multipart/byteranges задан этой спецификацией (параграф 15.3.7) для применения в некоторых откликах 206 (Partial Content).

8.4. Content-Encoding

Поле Content-Encoding указывает, какие кодировки содержимого применялись к представлению, помимо присущих типу носителя, м, соответственно, какое нужно использовать декодирование для получения данных с типом носителя, указанным полем Content-Type. Поле Content-Encoding применяется в основном для обеспечения возможности сжатия данных представления без потери идентичности базового типа носителя.

     Content-Encoding = #content-coding

Ниже приведён пример использования поля.

   Content-Encoding: gzip

Если для представления использовано одно или несколько кодирований, применивший их отправитель должен создать поле заголовка Content-Encoding, в котором указаны все использованные варианты кодирования в порядке их применения. Отметим, что имя кодирования identity зарезервировано для особой роли в Accept-Encoding и включать его не следует. Дополнительные сведения о кодировании могут указываться в других полях заголовка, не заданных этой спецификацией.

В отличие от Transfer-Encoding (параграф 6.1 в [HTTP/1.1]), кодирование в Content-Encoding является характеристикой представления, которое задаётся в терминах кодированной формы и все прочие метаданные о представлении относятся к кодированной форме, если иное не указано в определении метаданных. Обычно представление декодируется только перед визуализацией (rendering) или аналогичным применением.

Если тип носителя имеет встроенное кодирование, такое как сжатие, это кодирование не указывается в Content-Encoding, даже если в нем применяется тот же алгоритм, что и в одном из кодирований содержимого. Такое кодирование указывается лишь в странных и редких случаях повторного применения для формирования представления. Сервер-источник может публиковать одни и те же данные в нескольких представлениях, отличающихся лишь кодированием, указанным в Content-Type или Content-Encoding, поскольку некоторые пользовательские агенты могут по-разному вести себя при обработке каждого отклика (например, открывать диалог Save as … вместо автоматической декомпрессии и отображения содержимого). Сервер-источник может отвечать кодом (Unsupported Media Type), если представление в содержимом запроса имеет неприемлемое кодирование.

8.4.1. Кодирование содержимого

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

     content-coding   = token

Регистр символов в content-coding не принимается во внимание, а имена должны регистрироваться в реестре HTTP Content Coding Registry, как описано в параграфе 16.6. Значения content-coding применяются в полях заголовка Accept-Encoding (параграф 12.5.3) и Content-Encoding (параграф 8.4).

8.4.1.1. Кодирование Compress

Кодирование compress — это адаптивное кодирование Lempel-Ziv-Welch (LZW) [Welch], которое обычно создаёт UNIX- программа compress для сжатия файлов. Получателю следует считать x-compress эквивалентом compress.

8.4.1.2. Кодирование Deflate

Кодирование deflate — это формат данных zlib [RFC1950], содержащий сжатый с помощью deflate поток данных [RFC1951], где применяется комбинация алгоритма сжатия Lempel-Ziv (LZ77) и кодирования Huffman.

Примечание. Некоторые реализации, не соответствующие спецификации, передают сжатые данные deflate без оборачивания в формат zlib.

8.4.1.3. Кодирование gzip

Кодирование gzip — это LZ77 с 32-битовой контрольной суммой (Cyclic Redundancy Check или CRC), которое обычно обеспечивается программой сжатия [RFC1952]. Получателю следует считать x-gzip эквивалентом gzip.

8.5. Content-Language

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

     Content-Language = #language-tag

Теги языков определены в параграфе 8.5.1. Основное назначение Content-Language состоит в том, чтобы позволить пользователю указывать и различать представления в соответствии с предпочитаемым им языком. Например, содержимое, предназначенное для владеющих датским языком может быть указано как

   Content-Language: da

При отсутствии Content-Language предполагается, что содержимое предназначено для аудитории с любым языком. Это может означать, что отправитель не считает представление специфичным для какого-либо языка или не знает, для какого языка оно предназначено.

Для содержимого можно указать несколько языков, если оно предназначено для разноязычных аудиторий. Например, текст Договора Вайтанги (Treaty of Waitangi), представленный одновременно на английском и языке Maori, может включать

Content-Language: mi, en

Однако наличие в представлении нескольких языков не означает, что оно предназначено для разноязычной аудитории. Примером может служить учебник языка для начинающих, такой как A First Lesson in Latin, который явно предназначен для англоязычной аудитории, и в этом случае разумно указывать для Content-Language только значение en.

Поле Content-Language может применяться для носителей любого типа, а не только для текста.

8.5.1. Теги языков

Тег языка, как определено в [RFC5646], указывает естественный язык, на котором говорят, пишут или иным способом люди передают информацию между собой. Компьютерные языки здесь явно исключены.

HTTP использует теги языка в полях заголовка Accept-Language и Content-Language. В Accept-Language применяется более широкий диапазон языков, как указано в параграфе 12.5.4, а в Content-Language language-tag имеет форму

     language-tag = <Language-Tag, see [RFC5646], Section 2.1>

Тег языка включает один или несколько субтегов (без учёта регистра символов), разделённых символом дефиса (-, %x2D). В большинстве случаев тег состоит из основного субтега языка, указывающего семью языков (например, en = English), за которым могут следовать субтеги, уточняющие или сужающие языковой диапазон (например, en-CA для канадской разновидности английского языка). Пробелы в тегах языка не разрешаются. Примеры тегов приведены ниже.

     fr, en-US, es-419, az-Arab, x-pig-latin, man-Nkoo-GN

Дополнительные сведения можно найти в [RFC5646].

8.6. Content-Length

Поле заголовка Content-Length указывает размер данных соответствующего представления десятичным неотрицательным целым числом октетов. При передаче представления как содержимого Content-Length относится именно к объёму данных, заключённых в нем, поэтому может служить для указания границы обрамления (см. например, параграф 6.2 в [HTTP/1.1]). В иных случаях Content-Length указывает текущий размер выбранного представления, который получатель могут использовать для оценки времени передачи или сравнения с сохраненным ранее представлением.

     Content-Length = 1*DIGIT

Пример приведён ниже.

   Content-Length: 3495

Агенту пользователя следует передавать Content-Length в запросе, если метод задаёт значение для вложенного содержимого и не передаётся Transfer-Encoding. Например, агент пользователя обычно передаёт Content-Length в запросе POST даже при значении 0 (пустое содержимое). Агенту пользователя не следует передавать поле Content-Length, если в запросе нет содержимого и семантика метода не предполагает таких данных.

Сервер может передавать поле Content-Length в отклике на запрос HEAD (параграф 9.3.2), но это недопустимо, если значение поля не указывает десятичное значение числа октетов, которые будут переданы в содержимом отклика на такой же запрос с методом GET.

Сервер может передавать поле Content-Length в отклике 304 (Not Modified) на условный запрос GET (параграф 15.4.5), но это недопустимо, если значение поля не указывает десятичное значение числа октетов, которые будут переданы в содержимом отклика 200 (OK) на тот же запрос.

Серверу недопустимо передавать поле Content-Length в откликах с кодом 1xx (Informational) или 204 (No Content), а также в откликах 2xx (Successful) на запрос CONNECT (параграф 9.3.6).

Помимо указанных выше случаев, серверу-источнику следует передавать поле Content-Length при отсутствии Transfer-Encoding, когда размер содержимого известен до завершения передачи раздела заголовков. Это позволит нисходящим получателям оценивать ход передачи, знать о полноте принятого сообщения и, возможно, использовать то же соединение для дополнительных запросов.

В поле Content-Length действительны любые положительные значения. Поскольку нет предопределённого ограничения на размер содержимого, получатель должен предвидеть возможность больших десятичных чисел и предотвращать ошибки разбора в результате переполнения или потери точности при преобразовании в целое число (параграф 17.5).

Поскольку Content-Length служит для определения границ сообщений в HTTP/1.1, значение поля может влиять на разбор сообщения нисходящими получателями даже при отсутствии на промежуточных соединениях HTTP/1.1. Если сообщение пересылается посредником нисходящего направления, значение поля Content-Length, не соответствующее обрамлению полученного им сообщения, может вызывать проблемы безопасности из-за нелегитимных запросов или разделения откликов. Поэтому отправителю недопустимо передавать сообщения с заведомо некорректным значением поля Content-Length. Точно так же отправителю недопустимо пересылать сообщения с полем Content-Length, не соответствующим ABNF (см. выше) с единственным исключением — получатель поля Content-Length с одним и тем же десятичным значением, повторяющимся в списке через запятую (например, Content-Length: 42, 42), может отвергнуть сообщение как непригодное или заменить недействительное значение поля одним десятичным значением, поскольку дубликат, вероятно, был создан при обработке восходящим процессором сообщений.

8.7. Content-Location

Поле заголовка Content-Location указывает URI для возможного применения в качестве идентификатора конкретного ресурса, соответствующего представлению в содержимом этого сообщения. Иными словами, если выполнить запрос GET с этим URI в момент генерации данного сообщения, отклик 200 (OK) будет содержать то же представление, которое включено в содержимое этого сообщения.

     Content-Location = absolute-URI / partial-URI

Значением поля является absolute-URI или partial-URI. В последнем случае (раздел 4) URI указывается относительно URI цели ([URI], раздел 5).

Значение Content-Location не является заменой URI цели (параграф 7.1) и служит представлением метаданных. В нем применяется тот же синтаксис и семантика, что и в одноимённом поле заголовка, определённом для частей тела MIME в разделе 4 [RFC2557]. Однако наличие этого поля в сообщении HTTP оказывает некоторое особое влияние на получателей HTTP.

Если поле Content-Location включено в сообщение с откликом 2xx (Successful) и значение поля указывает (после преобразования в абсолютную форму) URI, соответствующий URI цели, получатель может считать содержимое текущим представлением этого ресурса в момент, указанный датой создания сообщения. Для запросов GET (параграф 9.3.1) и HEAD (параграф 9.3.2) это соответствует принятой по умолчанию семантике, когда сервер не предоставляет Content-Location. Для запросов со сменой состояния, таких как PUT (параграф 9.3.4) или POST (параграф 9.3.3) это означает, что отклик сервера содержит новое представление данного ресурса, что отличает его от представлений, которые могут лишь сообщать о действии (например, It worked!). Это позволяет разработчикам приложений обновлять локальные копии без необходимости дополнительного запроса GET.

Поле Content-Location в сообщении с откликом 2xx (Successful) и значением поля, указывающим URI, отличающийся от URI цели, указывает заявление сервера-источника о том, что этот URI является идентификатором другого ресурса, соответствующего вложенному представлению. Такому утверждению можно доверять лишь в том случае, когда у обоих идентификаторов один владелец, что невозможно проверить программным путем через HTTP.

  • Для откликов на запрос GET или HEAD это говорит, что URI цели указывает ресурс, для которого требуется согласование содержимого, а значение поля Content-Location является более конкретным идентификатором для выбранного представления.

  • Для отклика 201 (Created) на метод, меняющий состояние, значение поля Content-Location, совпадающее со значением Location, указывает, что содержимое является текущим представлением вновь созданного ресурса.

  • В иных случаях Content-Location указывает, что содержимое является представлением, указывающим статус запрошенного действия и доступность (для будущего запроса GET) отчёта о статусе по данному URI. Например, операция покупки через запрос POST может включать чек в форме содержимого отклика 200 (OK) и поле Content-Location будет указывать идентификатор для извлечения копии этого чека в будущем.

Передавая Content-Location в запросном сообщении, агент пользователя указывает, что значение поля соответствует местоположению, откуда этот агент изначально получил содержимое (до того, как он внёс какие-либо изменения). Иными словами, агент пользователя указывает обратную ссылку на источник исходного представления.

Сервер-источник, передающий поле Content-Location в отклике, должен считать эти сведения временным контекстом запроса, а не метаданными, сохраняемыми без изменений как часть представления. Сервер-источник может использовать этот контекст как руководство по обработке запроса или сохранить его для иных целей, например, в ссылках на источник или метаданных о версии. Однако ему недопустимо использовать данные контекста для смены семантики запроса. Например, если клиент подаёт запрос PUT для согласованного ресурса и сервер-источник воспринимает PUT (без перенаправления), предполагается, что новое состояние этого ресурса будет соответствовать одному из представлений в этом PUT. Поле Content-Location нельзя применять как форму обратного идентификатора выбора содержимого для обновления лишь одного из согласованных представлений. Если пользовательскому агенту нужна такая семантика, он будет применять PUT непосредственно для Content-Location URI.

8.8. Поля валидатора

Метаданные ресурса называют валидатором, если их можно использовать в предварительных условиях (параграф 13.1) для запроса (раздел 13). Поля передают текущий валидатор для выбранного представления (параграф 3.2).

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

В отклике об успехе меняющего состояние запроса поля валидатора описывают новое представление, которое в результате обработки заменило выбранное ранее представление. Например, поле ETag в отклике 201 (Created) передаёт тег сущности недавно созданного представления ресурса так, что этот тег можно использовать в качестве валидатора в последующих условных запросах для предотвращения проблемы потери обновления (lost update).

Эта спецификация задаёт две формы метаданных, которые обычно применяются для наблюдения за состоянием ресурса и проверки предварительных условий — даты изменений (параграф 8.8.2) и необрабатываемые (opaque) теги сущностей (параграф 8.8.3). Дополнительные метаданные, определяющие состояние ресурса, могут определяться расширениями HTTP, такими как Web Distributed Authoring and Versioning [WEBDAV], выходящими за рамки документа.

8.8.1. Строгие и мягкие валидаторы

Валидаторы могут быть строгими (strong) или мягкими (weak). Мягкие валидаторы проще создавать, но они менее полезны при сравнении. Строгие валидаторы идеальны для сравнения, но их генерация может быть очень сложной (иногда невозможно). Вместо навязывания одной формы валидаторов для всех ресурсов HTTP раскрывает тип применяемых валидаторов и вносит ограничения на использование мягких валидаторов при сравнении.

Строгий валидатор — это метаданные представления, меняющие значение при любом изменении данных представления, которое можно видеть в содержимом отклика 200 (OK) на запрос GET. Строгий валидатор может менять значение не только в результате изменения данных представления, такого как изменение семантически значимой части метаданных (например, Content-Type), но сервер-источник заинтересован в смене значения лишь при необходимости аннулировать сохранённые отклики, размещённые в удалённых кэшах и средствах разработки.

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

На практике применяются различные строгие валидаторы. Лучшие из них основаны на строгом контроле выпусков (ревизий), когда при каждой смене представления ему назначается уникальное имя узла и идентификатор выпуска до того, как представление станет доступным для GET. Устойчивая к конфликтам хэш-функция, применяемая к представлению данных, подходит и для случаев, когда данные доступны до отправки полей заголовка и дайджест не нужно обновлять при каждом получении запроса на проверку. Однако при наличии у ресурса представлений, отличающихся лишь метаданными, например, как при согласовании содержимого по типам носителей с одинаковым форматом данных, серверу-источнику нужно включать в валидатор дополнительные сведения, различающие эти представления.

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

Серверу-источнику следует менять мягкий тег сущности всякий раз, когда он считает прежние представления неприемлемыми в качестве замены текущего представления. Иными словами, мягкий тег сущности должен меняться всякий раз, когда сервер-источник хочет аннулировать старые отклики в кэшах. Например, представления прогноза погоды, содержимое которого меняется каждую секунду на основе динамических измерений, можно сгруппировать в наборы эквивалентных (с точки зрения сервера-источника) представлений с одним мягким валидатором, чтобы кэшированные представления были действительны с течение разумного интервала времени (возможно, динамически корректируемого в зависимости от нагрузки на сервер или качества измерений). Аналогично, время смены представления, указанное с разрешением в 1 секунду, может быть мягким валидатором, если существует возможность неоднократной смены представления в течение 1 секунды и извлечения между такими сменами представлений.

Валидатор будет мягким, если он применяется одновременно для нескольких представлений данного ресурса, если у них не совпадают данные представления. Например, если сервер-источник передаёт один валидатор для представления с кодированием содержимого gzip и представления без кодирования, этот валидатор будет мягким. Однако два одновременных представления могут иметь один строгий валидатор, если они отличаются лишь метаданными, например, при использовании для одних данных представления разных типов носителя.

Строгие валидаторы подходят для всех условных запросов, включая проверку кэша, частичные диапазоны содержимого и предотвращение потери обновлений. Мягкие валидаторы пригодны лишь в случаях, когда клиент не требует точного совпадения с полученными ранее данными представления, например, при проверке записи в кэше или выборе лишь последних изменений при просмотре web.

8.8.2. Last-Modified

Поле Last-Modified в отклике содержит временную метку, указывающую дату и время последнего изменения выбранного представления с точки зрения сервера-источника, которые были определены при завершении обработки запроса.

     Last-Modified = HTTP-date

Пример поля представлен ниже.

   Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT
8.8.2.1. Генерация

Серверу-источнику следует передавать Last-Modified для любого выбранного представления, когда можно обоснованно и согласованно определить дату последнего изменения, поскольку использование поля в условных запросах и при оценке свежести кэша ([CACHING]) может существенно сократить ненужные передачи, а также значительно улучшить доступность и расширяемость сервиса.

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

Серверу-источнику следует получать значение Last-Modified для представления как можно ближе к моменту генерации им значения Date для своего отклика. Это позволит получателю точно оценить время изменения представления, особенно вблизи времени генерации отклика.

Серверу-источнику с часами (см. параграф 5.6.7) недопустимо генерировать время Last-Modified позднее момента создания сервером сообщения с откликом (Date, параграф 6.6.1). Если время последнего изменения выводится из зависящих от реализации метаданных, которые относятся к будущему моменту по часам сервера-источника, сервер должен заменить это значением временем создания сообщения. Это предотвратит негативное влияние дат из будущего при проверке кэша. Серверу-источнику без часов недопустимо генерировать время Last-Modified, если только это значение не было присвоено ресурсу какой-либо другой системой (предположительно имеющей часы).

8.8.2.2. Сравнение

Поле Last-Modified в качестве валидатора неявно является мягким, если иное нельзя принять на основании любого приведённых ниже правил.

  • Валидатор сравнивается сервером-источником с фактическим текущим валидатором для представления и сервер-источник точно знает, что связанное представление не изменялось дважды в течение секунды, охватываемой представленным валидатором;

  • Валидатор будет применяться клиентом в поле заголовка If-Modified-Since, If-Unmodified-Since или If-Range, поскольку клиент имеет кэшированную запись для соответствующего представления и эта запись включает значение Date, которое по меньшей мере на 1 секунду позже времени Last-Modified, а у клиента есть основания полагать, что метки исходят от одних часом или разница между Last-Modified и Date достаточно велика, чтобы считать проблемы синхронизации часов малозначимыми.

  • Валидатор сравнивается промежуточным кэшем с валидатором, сохраненным в записи этого кэша для данного представления, и запись в кэше включает значение Date, которое по меньшей мере на 1 секунду позже времени Last-Modified, а у клиента есть основания полагать, что метки исходят от одних часом или разница между Last-Modified и Date достаточно велика, чтобы считать проблемы синхронизации часов малозначимыми.

Этот метод основан на том, что в случае отправки сервером-источником двух разных откликов в течение 1 секунды с одинаковым значением Last-Modified, хотя бы в одном из них значения Date и Last-Modified будут совпадать.

8.8.3. ETag

Поле Etag в отклике представляет текущий тег сущности для выбранного представления, определённый по завершении обработки запроса. Тег сущности — это неанализируемый (opaque) валидатор для различения разных представлений одного ресурса, независимо смены состояния ресурса со временем, согласования содержимого, ведущего к действительности сразу нескольких представлений или обоих причин. Тег сущности состоит из неанализируемой строки, которая может включать префикс индикатора «слабости» (weakness ).

     ETag       = entity-tag

     entity-tag = [ weak ] opaque-tag
     weak       = %s"W/"
     opaque-tag = DQUOTE *etagc DQUOTE
     etagc      = %x21 / %x23-7E / obs-text
                ; VCHAR, за исключением двойных кавычек, плюс obs-text

Примечание. Ранее элемент opaque-tag был определён как строка в (quoted-string) кавычках (параграф 3.11 в [RFC2616]) и некоторые получатели могли снимать экранирование (unescape) символа \. Поэтому серверам следует избегать включения данного символа в теги сущности.

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

Ниже показаны примеры тегов сущности.

   ETag: "xyzzy"
   ETag: W/"xyzzy"
   ETag: ""

Тег сущности может быть мягким или строгим валидатором, по умолчанию он является строгим. Если сервер-источник указывает тег сущности для представления, а генерация этого тега не соответствует всем требованиям к строгому валидатору (параграф 8.8.1), сервер-источник должен пометить тег как слабый, добавив к нему префикс W/ (с учётом регистра).

Отправитель может передавать поле ETag в разделе трейлеров (параграф 6.5). Однако трейлеры часто игнорируются, поэтому предпочтительно передавать ETag как поле заголовка, если он не создаётся в процесс отправки содержимого.

8.8.3.1. Генерация

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

Серверу-источнику следует передавать ETag для любого выбранного представления, когда можно обоснованно и согласованно определить дату последнего изменения, поскольку использование поля в условных запросах и при оценке свежести кэша ([CACHING]) может существенно сократить ненужные передачи, а также значительно улучшить доступность, надёжность и расширяемость сервиса.

8.8.3.2. Сравнение

Имеется две функции сравнения тегов сущностей в зависимости от возможности применять мягкое сравнение.

Строгое сравнение

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

Мягкое сравнение

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

В таблице 3 приведены примеры результатов сравнения пар тегов сущностей для строго и мягкого сопоставления.

Таблица .

 

ETag1

ETag2

Строгое сравнение

Мягкое сравнение

W/»1″

W/»1″

не соответствует

соответствует

W/»1″

W/»2″

не соответствует

не соответствует

W/»1″

«1»

не соответствует

соответствует

«1»

«1»

соответствует

соответствует

 

8.8.3.3. Пример со сменой ETag при согласовании содержимого

Рассмотрим ресурс, к которому применяется согласование содержимого (раздел 12), а представления, передаваемые в откликах на GET, отличаются полем заголовка Accept-Encoding (параграф 12.5.3).

>> Запрос

   GET /index HTTP/1.1
   Host: www.example.com
   Accept-Encoding: gzip

В этом случае отклик может (но не обязан) использовать кодирование содержимого gzip. Несжатый отклик имеет вид

>> Отклик

   HTTP/1.1 200 OK
   Date: Fri, 26 Mar 2010 00:05:00 GMT
   ETag: "123-a"
   Content-Length: 70
   Vary: Accept-Encoding
   Content-Type: text/plain

   Hello World!
   Hello World!
   Hello World!
   Hello World!
   Hello World!

Представление с кодированием gzip будет иметь вид

>> Отклик

   HTTP/1.1 200 OK
   Date: Fri, 26 Mar 2010 00:05:00 GMT
   ETag: "123-b"
   Content-Length: 43
   Vary: Accept-Encoding
   Content-Type: text/plain
   Content-Encoding: gzip

   ...двоичные данные...

Примечание. Кодирование содержимого является свойством данных представления, поэтому строгий тег сущности для представления с кодированием содержимого отличается от тега сущности некодированного представления, чтобы предотвратить возможные конфликты при обновлениях кэша и запросах диапазона. Транспортное кодирование (раздел 7 в [HTTP/1.1]), напротив, применяется лишь при передаче сообщения и не ведёт к разным тегам сущности.

9. Методы

9.1. Обзор

Маркер метода запроса является основным индикатором семантики запроса, указывая цель, с которой клиент обратился с данным запросом и что он ожидает в качестве успешного результата. Семантика метода запроса может быть уточнена семантикой полей заголовков, если та не противоречит методу. Например, клиент может включить в запрос поля условий (параграф 13.1), чтобы действия определялись текущим состоянием целевого ресурса.

Протокол HTTP предназначен служить интерфейсом к системам распределенных объектов. Метод запроса вызывает действие, применяемое к целевому ресурсу так же, как удалённый вызов метода можно передать указанному объекту.

     method = token

Регистр символов в маркере метода принимается во внимание, поскольку маркер может служить шлюзом в объектно-ориентированные системы с учётом регистра в именах методов. По соглашению в именах стандартизованных методов применяются только заглавные буквы US-ASCII.

В отличие от распределенных объектов, стандартизованные методы запросов HTTP не привязаны к ресурсам, поскольку унифицированные интерфейсы обеспечивают лучшую наглядность и многократное использованием в сетевых системах [REST]. После определения стандартизованного метода он должен сохранять свою семантику применительно к любому ресурсу, хотя каждый из них сам определяет возможность применения этой семантики. Данная спецификация задаёт ряд стандартизованных методов, широко применяемых в HTTP (таблица 4).

Таблица .

 

Имя метода

Описание

Параграф

GET

Запрос передачи текущего представления целевого ресурса.

9.3.1

HEAD

Аналогично GET, но без передачи содержимого отклика.

9.3.2

POST

Выполнение специфичной для ресурса обработки содержимого запроса.

9.3.3

PUT

Замена всех текущих представлений целевого ресурса содержимым запроса.

9.3.4

DELETE

Удаление всех текущих представлений целевого ресурса.

9.3.5

CONNECT

Организация туннеля с сервером, указанным целевым ресурсом.

9.3.6

OPTIONS

Описание коммуникационных опций для целевого ресурса.

9.3.7

TRACE

Отслеживание прохождения сообщения по пути к целевому ресурсу.

9.3.8

 

Все серверы общего назначения должны поддерживать методы GET и HEAD, поддержка остальных необязательна.

Набор разрешаемых целевым ресурсом методов может быть указан в поле заголовка Allow (параграф 10.2.1), однако этот набор может меняться динамически. Серверу-источнику, получившему запрос с непонятным или не реализованным методом, следует отвечать кодом статуса 501 (Not Implemented). При получении сервером-источником запроса с понятным и реализованным, но не разрешённым методом следует отвечать кодом 405 (Method Not Allowed).

Для применения в HTTP могут определяться методы, не включённые в эту спецификацию. Такие методы должны регистрироваться в реестре Hypertext Transfer Protocol (HTTP) Method Registry, как описано в параграфе 16.1.

9.2. Общие свойства методов

9.2.1. Безопасные методы

Метод запроса считается безопасным (safe), если заданная для него семантика по существу предусматривает лишь чтение (read-only), т. е. клиент не запрашивает и не ожидает какой-либо смены состояния сервера-источника в результате применения безопасного метода к целевому ресурсу. Предполагается, что разумное применение безопасного метода не будет наносить серверу-источнику какого-либо ущерба, потерь или необычной нагрузки.

Это определение безопасных методов не препятствует реализации поведения, которое может быть опасным, предусматривать не только чтение или приводить к побочным эффектам при вызове безопасного метода. Важно отметить, что клиент не запрашивает такого поведения и не может нести за него ответственность. Например, большинство серверов добавляет сведения о запросах в системный журнал доступа по завершении каждого запроса, независимо от метода, и это считается безопасным даже с учётом возможного переполнения хранилища системных журналов и отказа сервера. Аналогично, безопасный запрос, инициированный выбором рекламы на Web-странице, может приводить к побочным эффектам, таким как списание средств с рекламного счета..

Определённые в этой спецификации методы GET, HEAD, OPTIONS и TRACE считаются безопасными.

Методы делятся на безопасные и небезопасные для того, чтобы автоматизированные процессы поиска (spider) и оптимизации производительности кэширования (pre-fetching) могли работать без опасения причинить ущерб. Кроме того, это позволяет применить подходящие ограничения на автоматизированное применение небезопасных методов при обработке потенциально недоверенного содержимого.

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

Если ресурс устроен так, что параметры в URI цели влияют на выбор действия, владелец ресурса должен убедиться, что действие соответствует семантике метода запроса. Программы редактирования содержимого Web часто указывают действия в параметрах запроса, например, page?do=delete. Если ресурс предполагает выполнение небезопасных действий, его владелец должен отключать или запрещать такие действия при использовании безопасных методов запроса. Отказ от этого может приводить к неприятным побочным эффектам, когда автоматизированные процессы используют GET в каждой ссылке URI для обслуживания ссылок (link), предварительной выборки, создания поисковых индексов и т. п.

9.2.2. Идемпотентные методы

Метод запроса считается идемпотентным, если повторное или многократное применение этого метода на сервере не даёт дополнительного эффекта по сравнению с первым использованием. Определённые в этой спецификации методы PUT, DELETE, а также безопасные методы запросов являются идемпотентными.

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

Идемпотентные методы отличаются тем, что запрос можно автоматически повторить при коммуникационном отказе, возникшем до того, как клиент смог прочитать отклик сервера. Например, если клиент передал запрос PUT, а базовое соединение было разорвано до получения какого-либо отклика, клиент может организовать новое соединение и повторить идемпотентный запрос. Клиент знает, что повторный запрос будет давать тот же предусмотренный эффект, даже если исходный запрос уже был выполнен, хотя отклики могут различаться. Клиенту не следует автоматически повторять запрос с неидемпотентным методом, пока у него нет возможности знать, что семантика запроса на деле идемпотентна независимо от метода или исходный запрос не был применён. Например, агент пользователя может автоматически повторить запрос POST, если ему известно (из устройства или конфигурации), что запрос безопасен для этого ресурса. Аналогично, пользовательский агент, созданный специально для работы с репозиторием контроля версий, может восстанавливаться после частичных отказов, проверяя целевые ресурсы после отказа соединения, восстанавливая или исправляя частично внесённые изменения, а затем повторяя неудавшийся ранее запрос. Некоторые клиенты используют более рискованный подход и пытаются угадать, когда возможно автоматически повторить запрос. Например, клиент может автоматически повторить запрос POST, если базовое транспортное соединение было закрыто до приёма какой-либо части отклика, особенно если использовалось бездействовавшее сохраняемое соединение.

Прокси недопустимо автоматически повторять неидемпотентные запросы. Клиентам не следует автоматически повторять запрос после отказа автоматического повтора.

9.2.3. Методы и кэширование

Чтобы кэш мог сохранить и использовать отклик, связанный метод должен явно разрешать кэширование и подробно описывать, при каких условиях отклик можно использовать для выполнения последующих запросов. Если определение метода не включает этого, кэширование невозможно. Дополнительные требования приведены в [CACHING].

Эта спецификация задаёт семантику кэширования для методов GET, HEAD и POST, но большинство реализаций поддерживают лишь GET и HEAD.

9.3. Определения методов

9.3.1. GET

Метод GET запрашивает передачу текущего выбранного представления целевого ресурса. Успешный отклик отражает «одинаковость» URI цели (параграф 1.2.2 of [URI]). Таким образом, извлечение идентифицируемой цели по протоколу HTTP обычно выполняется с помощью запроса GET по идентификатору, связанному с потенциальной возможностью предоставить информацию в отклике 200 (OK).

GET является основным механизмом извлечения информации и объектом почти всех оптимизаций производительности. Приложения, создающие URI для каждого важного ресурса, могут пользоваться результатами такой оптимизации, обеспечивая возможность многократного её использования, что создаёт в сети эффект, способствующий дальнейшему расширению Web.

Заманчиво рассматривать идентификаторы ресурсов как имена путей в удалённой файловой системе, а представления — как копии содержимого этих файлов. В действительности многие ресурсы реализованы именно так (см. вопросы безопасности, связанные с этим, в параграфе 17.3), однако это не всегда так.

Интерфейс HTTP для ресурса может быть реализован как дерево объектов содержимого, программное представление записей баз данных или шлюз в другие информационные системы. Даже в случае привязки механизма сопоставления URI к файловой системе сервер-источник можно настроить для исполнения файлов с запросами на входе и передачи вывода в качестве представления взамен передачи файлов напрямую. В любом случае только серверу-источнику нужно знать, как каждый идентификатор ресурса соответствует реализации и как это реализация выбирает и передаёт текущее представление целевого ресурса.

Клиент может изменить семантику GET, чтобы это стало запросом диапазона (range request) для передачи лишь некоторых частей выбранного представления, передав в запросе поле заголовка Range (параграф 14.2).

Хотя структура запросного сообщения не зависит от применяемого метода, содержимое принятого запроса GET не имеет общепринятой семантики, не может менять смысл (значение) или цель запроса, а некоторые реализации могут отвергать запрос и закрывать соединение из-за возможности атак с контрабандой (smuggling) запросов (параграф 11.2 в [HTTP/1.1]). Клиенту не следует создавать содержимое в запросе GET, если запрос не направлен непосредственно серверу-источнику, который ранее указал (по основному каналу или иначе), что такой запрос имеет смысл и будет адекватно поддерживаться. Серверу-источнику не следует полагаться на частные соглашения о получении содержимого, поскольку при взаимодействиях HTTP часто неизвестны посредники в цепочке запросов.

Отклик на запрос GET может кэшироваться и кэш может служить для выполнения последующих запросов GET и HEAD, если поле заголовка Cache-Control (параграф 5.2 в [CACHING]) не задаёт иное.

При извлечении информации с помощью механизма, создающего URI цели из предоставленных пользователем сведений, таких как поля запроса формы с применением GET, возможно предоставление конфиденциальных (sensitive) данных, которые не следует раскрывать в URI (см. параграф 17.9). В некоторых случаях данные можно отфильтровать или преобразовать так, чтобы сведения не раскрывались. В иных случаях, особенно, когда кэширование откликов не приносит пользы, применение метода POST (параграф 9.3.3) вместо GET позволяет передать такие данные в содержимом запроса, а не в URI цели.

9.3.2. HEAD

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

Серверу следует передавать в отклике на запрос HEAD те же поля заголовков, которые он передал бы в отклике на GET. Однако сервер может не создавать поля заголовков, которые имеют смысл только при генерации содержимого. Например, некоторые серверы буферизуют динамический отклик на запрос GET, пока не создан минимальный объем данных, чтобы более эффективно разграничивать небольшие отклики или принимать поздние решения по выбору содержимого. Такой отклик для GET может включать, например, поля Content-Length и Vary, которые не нужны в отклике HEAD. Такие незначительные несоответствия считаются более предпочтительными, нежели генерация и отбрасывание содержимого для HEAD, поскольку запросы HEAD обычно служат для повышения эффективноси.

Хотя структура запросных сообщений не зависит от применяемого метода, содержимое принятого запроса HEAD не имеет общепринятой семантики, не может менять смысл (значение) или цель запроса, а некоторые реализации могут отвергать запрос и закрывать соединение из-за возможности атак с контрабандой (smuggling) запросов (параграф 11.2 в [HTTP/1.1]). Клиенту не следует создавать содержимое в запросе HEAD, если запрос не направлен непосредственно серверу-источнику, который ранее указал (по основному каналу или иначе), что такой запрос имеет смысл и будет адекватно поддерживаться. Серверу-источнику не следует полагаться на частные соглашения о получении содержимого, поскольку при взаимодействиях HTTP часто неизвестны посредники в цепочке запросов.

Отклик на запрос HEAD может кэшироваться и кэш может служить для выполнения последующих запросов HEAD, если поле заголовка Cache-Control (параграф 5.2 в [CACHING]) не задаёт иное. На отклик HEAD могут влиять кэшированные ранее отклики на GET (см. параграф 4.3.5 в [CACHING]).

9.3.3. POST

Метод POST запрашивает у целевого ресурса обработку вложенного в запрос представления в соответствии с семантикой этого ресурса. Например, POST можно использовать для

  • предоставления блока данных, таких как значения полей HTML-формы, для процесса обработки данных;

  • отправки сообщения на «доску объявлений», в группу новостей, список рассылки, блог или иную группу статей;

  • создания нового ресурса, который ещё не идентифицирован сервером-источником;

  • добавления данных в имеющиеся представления ресурса.

Сервер-источник указывает семантику отклика подходящим кодом статуса в зависимости от результата обработки POST. Для этого подходят почти все коды, заданные в этой спецификации, за исключением 206 (Partial Content), 304 (Not Modified), 416 (Range Not Satisfiable).

Если на сервере-источнике создаётся один или несколько ресурсов в результате обработки запроса POST, серверу следует передавать отклик 201 (Created) с полем заголовка Location, указывающим идентификатор созданного первичного ресурса (параграф 10.2.2), и представлением, описывающим статус запроса со ссылкой на новые ресурсы.

Отклики на запросы POST можно кэшировать лишь при наличии в них явных сведений о свежести (см. параграф 4.2.1 в [CACHING]) и совпадении поля заголовка Content-Location со значением, указанным в URI цели запроса POST (параграф 8.7). Кэшированный отклик POST может применяться для выполнения последующих запросов GET или HEAD. Запрос POST не может быть выполнен с использованием кэшированного отклика POST, поскольку метод POST может быть небезопасным (см. раздел 4 в [CACHING]).

Если результат обработки POST эквивалентен представлению имеющегося ресурса, сервер-источник может перенаправить агент пользователя, передавая отклик 303 (See Other) с идентификатором имеющегося ресурса в поле Location. Преимуществом такого подхода является предоставление пользовательскому агенту идентификатора ресурса и передача представления с использованием метода, более подходящего для общего кэша, хотя это и связано с дополнительным запросом, если у агента пользователя ещё нет кэшированного представления.

9.3.4. PUT

Метод PUT запрашивает создание или замену состояния целевого ресурса состоянием, заданным представлением из содержимого сообщения с запросом. Успешное выполнение запроса PUT с данным представлением предполагает, что последующий запрос GET к тому же целевому ресурсу приведёт к отправке эквивалентного представления в отклике 200 (OK). Однако нет гарантий наблюдаемости такой смены состояния, поскольку целевой ресурс может параллельно обрабатываться другими пользовательскими агентами или подвергаться динамической обработке сервером-источником до получения последующего запроса GET. Отклик об успехе означает лишь, что намерения пользовательского агента были реализованы в процессе обработки запроса сервером-источником.

Если у целевого ресурса нет текущего представления и PUT создаёт его, сервер-источник должен передать агенту пользователя отклик 201 (Created). Если у целевого ресурса есть текущее представления и оно было изменено св соответствии с состоянием вложенного в запрос представления, сервер-источник должен передать отклик 200 (OK) или 204 (No Content) для индикации успешного выполнения запроса.

Серверу-источнику следует проверить, что представление PUT соответствует заданным для целевого ресурса ограничениям. Например, если сервер-источник определяет метаданные представления ресурса на основе URI, он должен убедиться, что содержимое полученного запроса PUT соответствует этим метаданным. Если представление PUT не соответствует целевому ресурсу, серверу-источнику следует привести их в соответствие, путём преобразования представления или ответить подходящим сообщением об ошибке с достаточными сведениями для разъяснения причины непригодности преставления. Предлагается использовать код 409 (Conflict) или 415 (Unsupported Media Type), причём последний относится к ограничениям для значений Content-Type. Например, если целевой ресурс настроен всегда иметь Content-Type со значением text/html, а в представлении PUT задано Content-Type image/jpeg, сервер-источник должен выполнить одно из указанных ниже действий.

  1. Перенастроить целевой ресурс в соответствии с новым типом носителя.

  2. преобразовать представление PUT в формат, соответствующий ресурсу до сохранения нового состояния.

  3. отклонить запрос с кодом 415 (Unsupported Media Type), показывающим, что для целевого ресурса подходит лишь text/html, возможно включив ссылку на другой ресурс, который может подойти для нового представления.

HTTP не задаёт точного влияния метода PUT на состояние сервера-источника помимо того, что может быть выражено намерениями запроса от агента пользователя и семантикой отклика сервера-источника. Протокол не указывает, чем должен быть ресурс (в любом смысле этого слова) за интерфейсом, обеспечиваемым HTTP. Не задаётся способ «хранения» состояния ресурса, изменения этого хранилища в результате смены состояния ресурса, трансляции сервером-источником состояния ресурса в представления. Детали реализации, находящиеся за интерфейсом ресурса, намеренно скрываются сервером. Это относится и к хранению полей заголовков и трейлеров — хотя базовые поля заголовков, такие как Content-Type, обычно сохраняются при последующих запросах GET, обработка полей заголовка и трейлера зависит от принявшего запрос ресурса. Поэтому серверу-источнику следует игнорировать непонятные поля заголовка и трейлера в запросе PUT (т. е. не сохранять их как часть состояния ресурса).

Серверу-источнику недопустимо передавать поля валидатора (параграф 8.8), такие как ETag или Last-Modified, в отклике на успешно выполненный запрос PUT, пока данные представления из запроса не были сохранены без преобразований содержимого (т. е. новые данные представления ресурса идентичны содержимому запроса PUT), а значение поля валидатора не отражает новое представление. Это требование позволяет агенту пользователя знать, когда переданное им (и сохранённое в памяти) представление является результатом PUT и его не нужно снова извлекать с сервера-источника. Новые валидаторы, полученные в отклике, можно применять в будущих условных запросах, чтобы предотвратить случайную перезапись (параграф 13.1).

Принципиальным различием методов POST и PUT является назначение вложенного представления. Для метода POST целевой ресурс должен обрабатывать вложенное представление в соответствии с семантикой самого ресурса, а вложенное представление запроса PUT определено как замена состояния целевого ресурса. Поэтому назначение PUT является идемпотентным и видимым для посредников, хотя его точное влияние известно лишь серверу-источнику.

Корректная реализация PUT предполагает, что агент пользователя знает, какой целевой ресурс нужен ему. Службу, выбирающую URI от имени клиента после получения меняющего состояние запроса, следует реализовать на основе метода POST, а не PUT. Если сервер-источник не выполняет запрошенную PUT смену состояния целевого ресурса и вместо этого хочет применить запрос к другому ресурсу, например, перенесённому на другой URI, этот сервер должен передать подходящий отклик 3xx (Redirection), а пользовательский агент может сам принять решение о перенаправлении запроса.

Применение PUT к целевому ресурсу может оказывать побочное влияние на другие ресурсы. Например, статья может иметь URI для идентификации «текущей версии» (ресурса), отдельный от URI, указывающих каждую отдельную версию (другие ресурсы, которые в какой-то момент имели такое же состояние, что и текущая версия ресурса. Успешное применение PUT по URI «текущей версии» может создавать новый ресурс в дополнение к смене состояния целевого ресурса, а также приводить к созданию новых ссылок между связанными ресурсами.

Некоторые серверы-источники могут применять поле заголовка Content-Range (параграф 14.4) в качестве модификатора запроса для частичного выполнения PUT, как описано в параграфе 14.5.

Отклики на PUT не являются кэшируемыми. Если успешный запрос PUT проходит через кэш, где имеется один или несколько сохранённых откликов для URI цели, эти отклики аннулируются (см. параграф 4.4 в [CACHING]).

9.3.5. DELETE

Метод DELETE просит сервер-источник удалить связь между целевым ресурсом и его текущей функциональностью. Фактически это эквивалент команды rm в UNIX, он выражает операцию удаления сопоставления URI сервера-источника, а не ожидание удаления ранее ассоциированной информации.

Если у целевого ресурса есть одно или несколько текущих представлений, они могут быть уничтожены сервером-источником, а связанное с ними хранилище может быть использовано снова, что полностью зависит от природы ресурса и его реализации сервером-источником (это выходит за рамки данной спецификации). В результате запроса DELETE может потребоваться деактивация или архивирование других аспектов реализации ресурса, таких как соединения с базой данных или шлюзом. В общем случае предполагается, что сервер-источник разрешает применять DELETE лишь к ресурсам, для которых он имеет предписанный механизм удаления. Использование метода DELETE разрешается для сравнительно небольшого числа ресурсов, он применяется в основном в средах удалённой разработки (authoring), где пользователь имеет некоторое представление о результате применения запроса. Например, для ресурса, созданного ранее с помощью запроса PUT, или идентифицированного по полю заголовка Location после отклика 201 (Created) на запрос POST, может быть разрешён соответствующий запрос DELETE для отмены упомянутого действия. Аналогично, пользовательские агенты реализующие функции публикации (authoring), такие как клиенты контроля версий, использующие HTTP для удалённых операций, могут использовать DELETE на основе допущения, что создано пространство URI сервера для соответствия репозиторию версий.

Если метод DELETE применён, серверу-источнику следует передать

  • отклик с кодом 202 (Accepted), если действие вероятно будет успешно, но ещё не было выполнено;

  • отклик с кодом 204 (No Content), если действие выполнено и дополнительные сведения не требуются;

  • отклик с кодом 200 (OK), если действие выполнено и сообщение с откликом включает представление с описанием статуса.

Хотя обрамление запросного сообщения зависит от метода, содержимое в запросе DELETE не имеет общепринятой семантики, не может изменить смысл или цель запроса и может заставить некоторые реализации отвергнуть запрос и закрыть соединение из-за возможности атаки с контрабандой запросов (smuggling, параграф 11.2 в [HTTP/1.1]). Клиенту не следует генерировать содержимое для запроса DELETE, если тот не адресован напрямую серверу-источнику, которые ранее не указал (по основному каналу или вне его), что такой запрос имеет смысл и будет адекватно поддержан. Серверу-источнику не следует полагаться на частные соглашения о получении содержимого, поскольку участники взаимодействия HTTP зачастую не знают о посредниках в цепочке запроса.

Отклики на DELETE не являются кэшируемыми. Если успешный запрос DELETE проходит через кэш, где имеется один или несколько сохранённых откликов для URI цели, эти отклики аннулируются (см. параграф 4.4 в [CACHING]).

9.3.6. CONNECT

Метод CONNECT запрашивает у получателя организацию туннеля с сервером-источником, указанным целью запроса и при успешной организации ограничивает поведение туннеля пересылкой данных «вслепую» в обоих направлениях пока туннель не будет закрыт. Туннели обычно применяются для создания сквозного виртуального соединения через 1 или несколько прокси, которое можно дополнительно защитить с помощью TLS (Transport Layer Security, [TLS13]).

В CONNECT применяется особая (уникальная для него) форма цели запроса, включающая только хост и номер порта на целевой стороне туннеля, разделённые двоеточием (:). Принятый по умолчанию порт не задан и клиент должен указать номер порта, даже если запрос CONNECT основан на ссылке URI с компонентом authority с известным портом (параграф 4.1). Например,

   CONNECT server.example.com:80 HTTP/1.1
   Host: server.example.com

Сервер должен отвергать запросы CONNECT с отсутствующим или недействительным номером порта, возвращая обычно код статуса 400 (Bad Request).

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

Метод CONNECT предназначен для запросов к прокси. Получатель может организовать туннель, соединившись напрямую с сервером, указанным как цель запроса, или пересылая CONNECT следующему входящему прокси при настройке на работу через другого посредника. Сервер-источник может воспринять запрос CONNECT, но на большинстве серверов-источников метод CONNECT не реализован.

Любой отклик 2xx (Successful) указывает, что отправитель (и все входящие прокси) переключились в туннельный режим сразу после раздела заголовков отклика и переданные затем данные будут поступать от сервера, указанного целью запроса. Все прочие отклики указывают, что туннель ещё не создан. Туннель разрывается при обнаружении его посредником закрытия соединения любой из сторон и посредник должен попытаться передать все остающиеся данные от закрывшей соединение стороны на другую сторону, закрыть оба своих соединения и затем отбросить все недоставленные данные.

Для установки полномочий на создание туннелей может применяться аутентификация прокси, например,

   CONNECT server.example.com:443 HTTP/1.1
   Host: server.example.com:443
   Proxy-Authorization: basic aGVsbG86d29ybGQ=

Создание туннелей с произвольными серверами сопряжено со значительным риском, особенно при соединении с общеизвестным или зарезервированным портом TCP, не предназначенным для трафика Web. Например, CONNECT с example.com:25 предлагает прокси соединиться с портом, зарезервированным для трафика SMTP и если его разрешить, прокси можно использовать для ретрансляции спама. Прокси, поддерживающим CONNECT, следует разрешать использование метода лишь с ограниченным набором известных портов или настраиваемым списком безопасных целей запросов.

Серверу недопустимо передавать поля заголовка Transfer-Encoding или Content-Length в откликах 2xx (Successful) на CONNECT. Клиент должен игнорировать поля Content-Length и Transfer-Encoding в откликах об успехе CONNECT.

Сообщения с запросом CONNECT не имеют содержимого. Интерпретация данных после раздела заголовков сообщения с запросом CONNECT зависит от применяемой версии HTTP.

Отклики на CONNECT не кэшируются.

9.3.7. OPTIONS

Метод OPTIONS запрашивает сведения о коммуникационных опциях, доступных для целевого ресурса на сервере-источнике или посреднике. Это позволяет клиенту определить опции и/или требования, связанные с ресурсом, или возможности сервера, не предполагая действий с ресурсом. Запрос OPTIONS с символом * в качестве цели запроса (параграф 7.1) относится к серверу в целом, а не к конкретному его ресурсу. Поскольку коммуникационные опции сервера обычно зависят от ресурса, запрос с * полезен лишь в качестве ping или no-op и не даёт клиенту ничего, кроме проверки возможностей сервера. Например, этом можно использовать для проверки прокси на соответствие HTTP/1.1. Если указана иная цель, запрос OPTIONS применяется к опциям, доступным при взаимодействии с целевым ресурсом.

Серверу, генерирующему отклик об успехе OPTIONS, следует передавать любой заголовок, который может указать реализуемые сервером дополнительные возможности, которые применимы к целевому ресурсу (например, Allow), включая расширения, не заданные этой спецификацией. При наличии в отклике содержимого оно также может описывать коммуникационные опции в представлении для машины или человека. Спецификация не задаёт стандартный формат для такого представления, но он может быть определён в будущих расширениях HTTP.

Клиент запросе может передать поле заголовка Max-Forwards в запросе OPTIONS, чтобы указать конкретного получателя в цепочке запроса (см. параграф 7.6.2). Прокси недопустимо генерировать поле Max-Forwards при пересылке запроса, если запрос не содержал поля Max-Forwards. Клиент, создающий запрос OPTIONS с содержимым, должен включить в него действительное поле заголовка Content-Type с описанием типа носителя для представления. Отметим, что данная спецификация не задаёт такого содержимого.

Отклики на OPTIONS не кэшируются.

9.3.8. TRACE

Метод TRACE запрашивает удалённый возврат запроса на прикладном уровне. Конечному получателю запроса следует «отражать» клиенту принятое сообщение, исключая описанные ниже поля, как содержимое отклика 200 (OK). Одним из вариантов является применение формата message/http (параграф 10.1 в [HTTP/1.1]). Конечным получателем является сервер-источник или первый сервер, получивший запрос с Max-Forwards 0 (параграф 7.6.2).

Клиенту недопустимо включать в запрос TRACE поля с конфиденциальными сведениями, которые могут раскрываться в отклике. Например, агенту пользователя неразумно передавать в запросе сохранённые свидетельства пользователя (раздел 11) или cookie [COOKIE]. Конечному получателю запроса следует при формировании содержимого отклика исключать поля, которые могут содержать конфиденциальные данные.

Метод TRACE позволяет клиенту увидеть, что было получено на другой стороне, и использовать эти сведения для тестирования и диагностики. Особый интерес представляют значения поля заголовка Via (параграф 7.6.3), позволяющие отследить цепочку запросов. Использование поля заголовка Max-Forwards позволяет клиенту ограничить длину цепочки запросов, что полезно при тестировании цепочки серверов, пересылающих сообщения по петле.

Клиенту недопустимо включать содержимое в запрос TRACE.

Отклики на TRACE не кэшируются.

10. Содержимое сообщения

10.1. Поля контекста запроса

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

10.1.1. Expect

Поле заголовка Expect в запросе указывает некий набор моделей поведения (ожидания), который должен поддерживаться сервером для корректной обработки этого запроса.

     Expect =      #expectation
     expectation = token [ "=" ( token / quoted-string ) parameters ]

Регистр символов в значении поля Expect не принимается во внимание.

Эта спецификация определяет единственное ожидание 100-continue, не задавая для него параметров. Сервер, получивший поле Expect с иным значением, может вернуть отклик 417 (Expectation Failed) для указания невозможности выполнить ожидание.

Ожидание 100-continue информирует получателей, что клиент собирается отправить (предположительно крупное) содержимое в данном запросе и хочет получить промежуточный отклик 100 (Continue), если метода, URI цели и полей заголовка недостаточно для немедленного ответа об успехе, перенаправлении или ошибке. Это позволяет клиенту дождаться сигнала о целесообразности отправки содержимого до его реальной передачи, что может повысить эффективность в случае большого объёма данных или ожидания ошибки клиентом (например, при передаче метода, изменяющего состояние в первый раз без уже проверенных свидетельств для аутентификации). Например, запрос, начинающийся с

   PUT /somewhere/fun HTTP/1.1
   Host: origin.example.com
   Content-Type: video/h264
   Content-Length: 1234567890987
   Expect: 100-continue

позволяет серверу-источнику ответить сообщением об ошибке, таким как 401 (Unauthorized) или 405 (Method Not Allowed) до того, как клиент начнёт загружать канал ненужной передачей данных.

Ниже приведены требования к клиенту.

  • Недопустимо помещать ожидание 100-continue в запрос без содержимого.

  • Клиент, ожидающий отклика 100 (Continue) перед отправкой следующего запроса, должен передать поле заголовка Expect с ожиданием 100-continue.

  • Клиент, передавший ожидание 100-continue, не обязан ждать в течение какого-либо определённого времени и может продолжить отправку содержимого до получения отклика. Поскольку отклики 100 (Continue) не могут передаваться через посредников HTTP/1.0, такому клиенту не следует выжидать неопределённое время перед отправкой содержимого.

  • Клиенту, получившему код статуса 417 (Expectation Failed) в отклике на запрос с ожиданием 100-continue, следует повторить этот запрос без 100-continue, поскольку код 417 указывает лишь отсутствие поддержки ожиданий в цепочке запросов (например, прохождение через сервер HTTP/1.0).

Ниже приведены требования к серверу.

  • Сервер, получивший ожидание 100-continue в запросе HTTP/1.0, должен игнорировать это ожидание.

  • Сервер может не передавать отклик 100 (Continue), если он уже получил часть или все содержимое для соответствующего запроса или обрамление говорит об отсутствии содержимого.

  • Сервер, передавший отклик 100 (Continue), должен в конечном итоге отправить финальный код статуса после получения и обработки содержимого запроса, если соединение не было закрыто преждевременно.

  • Серверу, ответившему финальным кодом статуса до прочтения всего содержимого запроса, следует указать, намерен ли он закрыть соединение (см., например, параграф 9.6 в [HTTP/1.1]) или продолжить чтение содержимого запроса.

Получив запрос HTTP/1.1 (или выше) с методом, URI цели и полным разделом заголовков, содержащим ожидание 100-continue и указание наличия содержимого, сервер-источник должен передать один из откликов:

  • незамедлительный отклик с финальным кодом статуса, если этот статус можно определить по номеру, URI цели и полям заголовка;

  • незамедлительный отклик 100 (Continue), чтобы побудить клиента передать содержимое запроса.

Серверу-источнику недопустимо дожидаться содержимого перед отправкой отклика 100 (Continue).

Получив запрос HTTP/1.1 (или выше) с методом, URI цели и полным разделом заголовков, содержащим ожидание 100-continue и указание наличия содержимого, прокси должен выполнить одно из действий:

  • незамедлительно передать отклик с финальным кодом статуса, если этот статус можно определить по номеру, URI цели и полям заголовка;

  • переслать запрос в направлении сервера-источника, отправив соответствующую строку запроса (request-line) и раздел заголовков следующему входящему серверу.

Если сервер полагает (из конфигурации или прошлого взаимодействия), что следующий входящий сервер поддерживает лишь HTTP/1.0, он может незамедлительно передать отклик 100 (Continue), чтобы побудить клиента передать содержимое запроса.

10.1.2. From

В поле заголовка From указывается адрес электронной почты Internet человека, контролирующего пользовательский агент, передающий запрос. Адрес должен быть пригодным для машины в соответствии с определением mailbox в » in Section 3.4 of [RFC5322]:

     From    = mailbox

     mailbox = <mailbox, см. [RFC5322], параграф 3.4>

Пример поля приведён ниже.

   From: spider-admin@example.org

Поле From редко передают нероботизированные пользовательские агенты. Агенту пользователя не следует отправлять поле From без явного указания (настройки) пользователем, поскольку это может противоречить интересам приватности пользователя или политики безопасности сайта. Роботизированным пользовательским агентам следует передавать действительное поле From, чтобы можно было связаться с человеком, управляющим роботом, при возникновении проблем на сервере, например, при отправке роботом излишних, нежелательных или непригодных запросов

Серверам не следует использовать поле From для контроля доступа или аутентификации, поскольку это значение, по-видимому, будет доступно всем, кто получает или отслеживает запрос, и часто записывается в системные журналы (log) и отчёты об ошибках без какой-либо надежды на сохранение приватности.

10.1.3. Referer

Поле заголовка Referer [sic] позволяет агенту пользователя указать для ресурса ссылку URI, из которой был выведен URI цели (т. е. referrer — ссылающийся, если игнорировать ошибку в имени поля). Агенту пользователя недопустимо включать компоненты fragment и userinfo в ссылку URI[URI], если таковые имеются при создании поля Referer.

     Referer = absolute-URI / partial-URI

Значением поля является absolute-URI или partial-URI. В последнем случае (раздел 4), указанный URI задаётся относительно URI цели ([URI], раздел 5).

Поле заголовка Referer позволяет серверам генерировать обратные ссылки на другие ресурсы для простой аналитики, протоколирования, оптимизации кэширования и т. п. Оно также позволяет находить устаревшие и ошибочные ссылки для поддержки. Некоторые серверы используют поле Referer как средство отклонения ссылок с других сайтов (deep linking) или ограничения поддельных кросс-сайтовые запросов (cross-site request forgery или CSRF), хотя поле содержится не во всех запросах.

Пример поля представлен ниже.

   Referer: http://www.example.org/hypertext/Overview.html

Если URI цели получен из источника, не имеющего своего URI (например, с клавиатуры пользователя или из записи в закладках), агент пользователя должен исключить значение поля Referer или указать в нем значение about:blank. В значении поля Referer не обязательно передавать полный URI ссылающегося ресурса и агент пользователя может отсекать части, отличные от ссылающегося источника.

Поле заголовка Referer может раскрывать сведения о контексте запроса и истории просмотров, что создаёт проблему приватности, если идентификатор ссылающегося ресурса раскрывает персональные данные (такие как имя учётной записи) или ресурс, который должен быть конфиденциальным (например, находится за межсетевым экраном или внутри защищённой службы). Большинство пользовательских агентов общего назначения не передаёт поле Referer, когда ссылающимся ресурсом является локальный URI типа file или data. Агенту пользователя не следует передавать поле Referer, если доступ к ссылающемуся ресурсу происходил по защищённому протоколу и цель запроса имеет иной источник, нежели ссылающийся ресурс, если этот ресурс не разрешает явно отправку Referer. Агенту пользователя недопустимо передавать поле Referer в незащищённом запросе HTTP, если доступ к ссылающемуся ресурсу происходил по защищённому протоколу (соображения безопасности рассмотрены в параграфе 17.9).

Известно, что некоторые посредники без разбора удаляют поля Referer в исходящих запросах. Это имеет неприятный побочный эффект снижения защиты от атак CSRF, которые могут быть гораздо более опасными для пользователей. Посредники и расширения пользовательских агентов, желающие ограничить раскрытие информации в полях Referer, должны ограничиваться конкретными изменениями вроде замены внутренних доменных имён псевдонимами или отсечки компонентов запроса и/или пути. Посредникам ACK не следует изменять или удалять поля заголовка Referer, использующие ту же схему и хост, что и URI цели.

10.1.4. TE

Поле заголовка TE описывает возможности клиента в части транспортного кодирования и трейлера. Как указано в параграфе 6.5, поле TE с элементом trailers в запросе указывает, что клиент не будет отбрасывать поля трейлера. TE также применяется в HTTP/1.1 для информирования серверов о транспортном кодировании, которое клиент способен воспринять в отклике. На момент публикации документа транспортные кодировки применялись только в HTTP/1.1 (см. раздел 7 в [HTTP/1.1]).

Значением поля TE служит список элементов, каждый из которых (кроме trailers) включает маркер имени транспортного кодирования с необязательным весом, указывающим относительную предпочтительность этого кодирования для клиента (параграф 12.4.2), и необязательные параметры транспортного кодирования.

     TE                 = #t-codings
     t-codings          = "trailers" / ( transfer-coding [ weight ] )
     transfer-coding    = token *( OWS ";" OWS transfer-parameter )
     transfer-parameter = token BWS "=" BWS ( token / quoted-string )

Отправитель TE должен также передать опцию соединения TE в поле заголовка Connection (параграф 7.6.1), чтобы посредники не пересылали это поле.

10.1.5. User-Agent

Поле заголовка User-Agent содержит сведения о создавшем запрос агенте пользователя, которые часто используются серверами для определения масштаба проблем совместимости, обхода или адаптации к ограничениям конкретных пользовательских агентов в откликах, а также для аналитики, связанной с используемыми браузерами и операционными системами. Агенту пользователя следует включать поле заголовка User-Agent в каждый запрос, если явно не задано иное поведение.

     User-Agent = product *( RWS ( product / comment ) )

Значением поля User-Agent служит один или несколько идентификаторов продукции, за каждым из которых могут следовать комментарии (параграф 5.6.5), что в совокупности указывает программу пользовательского агента и её значимые варианты. По традиции идентификаторы продукции указываются в порядке снижения их значимости для идентификации программы пользовательского агента. Каждый идентификатор включает имя и может включать версию.

     product         = token ["/" product-version]
     product-version = token

Отправителю следует ограничиваться сведениями, требуемыми для идентификации продукции и недопустимо включать в идентификатор рекламу и иные несущественные сведения. Отправителю не следует указывать в версии продукции сведения, не являющиеся идентификатором версии (т. е. разные версии продукции с одним именем должны различаться лишь элементами product-version). Например,

   User-Agent: CERN-LineMode/2.15 libwww/2.17b3

Агенту пользователя не следует создавать поле заголовка User-Agent с излишними подробностями и следует ограничивать добавление вариантов другими сторонами. Слишком длинные и подробные значения User-Agent увеличивают задержку для запросов и создают риск нежелательной идентификации пользователя (fingerprinting).

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

10.2. Поля контекста отклика

Ниже рассмотрены поля заголовка отклика, содержащие сведения об отклике в дополнение к коду статуса, включая информацию о сервере, целевом ресурсе и связанных ресурсах.

10.2.1. Allow

Поле заголовка Allow содержит список методов, анонсируемых как поддерживаемые целевым ресурсом. Назначением этого поля является исключительно информирование получателя о доступных для целевого ресурса методах запроса.

     Allow = #method

Пример поля приведён ниже.

   Allow: GET, HEAD, PUT

Фактический набор разрешённых методов определяется сервером-источником в момент каждого запроса. Сервер-источник должен генерировать поле заголовка Allow в откликах 405 (Method Not Allowed) и может включать поле в любой другой отклик. Пустое значение поля Allow указывает, что ресурс не поддерживает никаких методов, и может передаваться в откликах 405, если ресурс временно отключён его конфигурацией.

Прокси недопустимо менять поле заголовка Allow и ему не нужно понимать все указанные в поле методы для обработки сообщения в соответствии с базовыми правилами.

10.2.2. Location

Поле заголовка Location применяется в некоторых откликах для указания определённого ресурса по отношению к отклику. Тип взаимоотношений определяется сочетанием семантики метода запроса и кода статуса.

     Location = URI-reference

Значением поля является одна ссылка URI. Когда ссылка имеет относительную форму ([URI], параграф 4.2), окончательное значение определяется её распознаванием относительно URI цели ([URI], раздел 5).

Для откликов 201 (Created) значение Location указывает на основной ресурс, созданный запросом, для откликов 3xx (Redirection) — на предпочтительный ресурс для автоматического перенаправления запроса.

Если значение Location, приведённое в отклике 3xx (Redirection), не имеет фрагментного компонента, агент пользователя должен обработать перенаправление, как будто значение наследует фрагментный компонент ссылки URI, использованной для генерации URI цели (перенаправление наследует фрагмент исходной ссылки, если он есть). Например, запрос GET, созданный для ссылки URI http://www.example.org/~tim, может приводить к отклику 303 (See Other) с полем заголовка

   Location: /People.html#tim

которое предлагает пользовательскому агенту перенаправление на http://www.example.org/People.html#tim.

Запрос GET для ссылки URI http://www.example.org/index.html#larry может возвращать отклик 301 (Moved Permanently) с полем заголовка

   Location: http://www.example.net/index.html

которое предлагает агенту пользователя перенаправление на http://www.example.net/index.html#larry с сохранением исходного идентификатора фрагмента.

В некоторых случаях идентификатор фрагмента в поле Location будет неуместен. Например, поле заголовка Location в отклике 201 (Created) предполагается содержащим URI для созданного ресурса.

Примечание. Некоторые получатели пытаются выполнять восстановление по полю Location, которое не является действительной ссылкой URI. Данная спецификация не требует и не задаёт такой обработки, но разрешает её в целях отказоустойчивости. Значение поля заголовка Location не может содержать список элементов, поскольку запятая в качестве разделителя элементов списка является допустимым символом данных с ссылке URI. При отправке недействительного сообщения с несколькими строками Location его получатель на пути доставки может объединить такие строки в одно значение. Восстановление действительного значения поля Location в таких ситуациях затруднено и может не быть совместимым в разных реализациях.

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

10.2.3. Retry-After

Серверы передают поле заголовка Retry-After для указания пользовательскому агенту времени, которое он должен выждать перед отправкой следующего (follow-up) запроса. В отклике 503 (Service Unavailable) поле Retry-After указывает ожидаемый срок недоступности услуг для клиента, в откликах 3xx (Redirection) — минимальное время, которое клиенту следует выждать перед отправкой перенаправленного запроса. Значением поля Retry-After может быть HTTP-date или величина задержки (в секундах) после приёма сообщения.

     Retry-After = HTTP-date / delay-seconds

Значение delay-seconds является неотрицательным целым числом, представляющим время в секундах.

     delay-seconds  = 1*DIGIT

Ниже представлены два примера использования.

   Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
   Retry-After: 120

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

10.2.4. Server

Поле заголовка Server содержит сведения о программах, используемых сервером-источником для обработки запроса, которые часто применяются клиентами для идентификации масштаба указанных проблем совместимости, обхода или адаптации к ограничениям конкретного сервера, а также для анализа распространённости серверов и операционных систем. Сервер-источник может включать поле Server в свои отклики.

     Server = product *( RWS ( product / comment ) )

Поле заголовка Server содержит один или несколько идентификаторов продукции, каждый из которых может сопровождаться комментариями (параграф 5.6.5), что в совокупности указывает программы сервера-источника и их значимые варианты. По традиции идентификаторы продукции указываются в порядке снижения их значимости для идентификации программы пользовательского агента. Каждый идентификатор включает имя и может включать версию, как описано в параграфе 10.1.5. Пример поля представлен ниже.

   Server: CERN/3.0 libwww/2.17

Серверу-источнику не следует создавать поля заголовка с излишними подробностями и следует ограничивать добавление вариантов другими сторонами. Слишком длинные и подробные значения Server увеличивают задержку для откликов и создают риск утечки деталей реализации, что может (слегка) упростить злоумышленникам поиск и использование известных брешей в защите.

11. Аутентификация HTTP

11.1. Схема проверки подлинности

HTTP обеспечивает общую модель контроля доступа и проверки подлинности на основе расширяемого набора схем аутентификации «вызов-отклик» (challenge-response), которые клиент и сервер могут применять для запроса аутентификационных данных у другой стороны. Для указания схемы служит не зависящий от регистра маркер (token)

     auth-scheme    = token

Этот документ не задаёт схем аутентификации помимо общей модели. Имеющиеся и новые схемы задаются независимо и должны регистрироваться в реестре Hypertext Transfer Protocol (HTTP) Authentication Scheme Registry. Например, схемы аутентификации basic и digest определены в [RFC7617] и [RFC7616], соответственно.

11.2. Параметры аутентификации

За схемой аутентификации следует дополнительная информация, требуемая для проверки подлинности по этой схеме, в форме разделённых запятыми параметров или одной последовательности символов, способной содержать сведения в представлении base64.

     token68        = 1*( ALPHA / DIGIT /
                          "-" / "." / "_" / "~" / "+" / "/" ) *"="

Синтаксис token68 разрешает 66 незарезервированных символов URI ([URI]) и несколько других, что позволяет помещать представление base64, base64url (безопасный алфавит для URL и имён файлов), base32, base16 (hex) с заполнением или без него, но без включения пробельных символов ([RFC4648]).

Параметры аутентификации задаются парами имя-значение и маркеры имён сравниваются без учёта регистра символов, а каждое имя параметра должно присутствовать в вызове лишь один раз.

     auth-param     = token BWS "=" BWS ( token / quoted-string )

Значение параметра указывается маркером (token) или строкой в кавычках (quoted-string, параграф 5.6). Определениям схем аутентификации нужно разрешать оба варианта, чтобы получатели могли применять компоненты разбора независимо от схемы аутентификации. Для совместимости с прежними версиями определения схем аутентификации могут ограничиваться поддержкой у отправителя лишь одного варианта. Это может быть важно, если известно, что в развёрнутых реализациях могут возникать отказы для одного из двух форматов.

11.3. Вызов и отклик

Отклик 401 (Unauthorized) может применяться серверами-источниками для запросов (challenge) аутентификации пользовательских агентов, включая поле заголовка WWW-Authenticate, содержащее хотя бы один вызов, применимый к запрашиваемому ресурсу. Отклик 407 (Proxy Authentication Required) применяется прокси для запросов аутентификации клиента, включая поле заголовка Proxy-Authenticate, содержащее хотя бы один вызов, применимый к прокси для запрошенного ресурса.

     challenge   = auth-scheme [ 1*SP ( token68 / #auth-param ) ]

Примечание. Многие клиенты сталкиваются с отказами при разборе вызовов с неизвестной схемой. Для обхода этой проблемы следует сначала указывать наиболее широко поддерживаемые схемы (например, basic).

Агент пользователя, желающий аутентифицироваться на сервере-источнике после получения отклика 401 (Unauthorized) обычно (но не всегда) может сделать это, включив в запрос поле заголовка Authorization. Агент пользователя, желающий аутентифицироваться на прокси после получения отклика 407 (Proxy Authentication Required) обычно обычно (но не всегда) может сделать это, включив в запрос поле заголовка Proxy-Authorization.

11.4. Свидетельства

Значения полей Authorization и Proxy-Authorization содержат свидетельства (credentials) клиента для области действия запрашиваемого ресурса, основанные на вызове (challenge), полученном в отклике (возможно, когда-то раньше). При формировании значений полей агент пользователя должен выбрать вызов с понятной ему и наиболее безопасной по его мнению схемой аутентификации (auth-scheme) для получения свидетельств от пользователя. Передача свидетельств в полях заголовка предполагает существенные требования к конфиденциальности базового соединения, как описано в параграфе 17.16.1.

     credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ]

При получении запроса для защищённого ресурса без свидетельств, с непригодными (например, неверный пароль) или неполными (например, когда схема аутентификации требует более одного кругового обхода) свидетельствами серверу-источнику следует передать отклик 401 (Unauthorized) с полем заголовка WWW-Authenticate, включающим хотя бы один (возможно, новый) вызов, пригодный для запрошенного ресурса. При получении запроса без свидетельств для прокси, с непригодными или неполными свидетельствами прокси следует передавать отклик 407 (Proxy Authentication Required) с полем Proxy-Authenticate, включающим хотя бы один (возможно, новый) вызов, пригодный для запрошенного ресурса. Сервер, получивший действительные свидетельства, которых недостаточно для получения доступа, должен отвечать кодом 403 (Forbidden, параграф 15.5.4).

HTTP не ограничивает приложения использованием простой схемы «вызов-отклик» для проверки подлинности. Можно применять дополнительные механизмы, такие как аутентификация на транспортном уровне или инкапсуляция сообщений, а также дополнительные поля заголовка со сведениями для аутентификации. Однако спецификация не задаёт таких механизмов. Отметим, что различные механизмы аутентификации пользователей применяют для передачи связанных с аутентификацией маркеров поля заголовка Set-Cookie и Cookie, определённые в [COOKIE].

11.5. Организация защищённого пространства

Параметр аутентификации realm зарезервирован для использования схемами аутентификации, которые хотят указать область действия защиты.

Пространство защиты определяется источником (origin, параграф 4.3.1) на сервере, к которому происходит доступ с использованием realm. Это позволяет разделить защищаемые ресурсы на сервере по нескольким пространствам защиты, каждое из которых использует свою схему аутентификации и/или базу данных о полномочиях. Значением realm является строка, обычно назначаемая сервером-источником, которая может иметь дополнительную семантику в зависимости от схемы проверки подлинности. Отметим, что отзыв может включать несколько вызовов с одинаковым значением auth-scheme, но разными realm.

Пространство защиты определяет область, к которой могут быть автоматически применены свидетельства. Если предыдущему запросу были предоставлены полномочий, агент пользователя может воспользоваться теми же свидетельствами для всех прочих запросов в том же пространстве защиты в течение периода, определяемого схемой аутентификации, параметров и/или пользовательских предпочтений (например, настраиваемым периодом бездействия). Область защиты и, следовательно, запросы, к которым автоматически применяются свидетельства, может быть неведома клиентам без дополнительной информации. Схема аутентификации может задавать параметры, описывающие область защиты. Если схема аутентификации не задаёт это специально, область действия пространства защиты не может выходить за пределы сервера.

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

11.6. Аутентификация пользователей на сервере-источнике

11.6.1. WWW-Authenticate

Поле WWW-Authenticate в заголовке отклика указывает схемы и параметры аутентификации, применимые для целевого ресурса.

     WWW-Authenticate = #challenge

Сервер, генерирующий отклик 401 (Unauthorized), должен передавать поле заголовка WWW-Authenticate, содержащее хотя бы один вызов. Сервер может генерировать поле заголовка WWW-Authenticate в других откликах для указания того, что предоставление этих (или иных) свидетельств может влиять на отклик.

Пересылающим отклик прокси недопустимо изменять в откликах поля заголовка WWW-Authenticate.

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

   WWW-Authenticate: Basic realm="simple", Newauth realm="apps",
                    type=1, title="Login to \"apps\""

В этом заголовке указано два вызова — схема Basic с realm = simple и схема Newauth с realm = apps, а также два дополнительных параметра type и title. Некоторые пользовательские агенты могут не понимать такие формы, поэтому отправка полей WWW-Authenticate с несколькими элементами в одной строке может препятствовать совместимости.

Примечание. Грамматика вызовов также использует списки, поэтому последовательность из разделённых пробелами запятых может считаться относящейся к предыдущему вызову или пустым элементом списка вызовов. На практике эта неоднозначность не меняет семантики значения поля заголовка и не представляет опасности.

11.6.2. Проверка и предоставление полномочий

Поле заголовка Authorization позволяет агенту пользователя подтвердить свою подлинность серверу-источнику, обычно (но необязательно) это происходит после получения отклика 401 (Unauthorized). Значение поля состоит из свидетельств с аутентификационными данными пользовательского агента для realm запрашиваемого ресурса.

     Authorization = credentials

Если запрос аутентифицирован и область действия (realm) указана, те же свидетельства считаются действительными для всех запросов в этой области realm (при условии, что схема аутентификации не задаёт иное, например, смену свидетельств в зависимости от вызова или использование синхронизированных часов).

Прокси, пересылающему запрос, недопустимо менять поле Authorization в этом запросе. Детали и требования к обработке поля заголовка Authorization в кэшах HTTP приведены в параграфе 3.5 [CACHING].

11.6.3. Authentication-Info

Схемы аутентификации HTTP могут использовать поле отклика Authentication-Info для передачи сведений после восприятия свидетельств аутентификации клиента. Эти сведения могут включать завершающее сообщение от сервера (например, аутентификацию сервера). Значением поля является список параметров (пар имя-значение) с синтаксисом auth-param, заданным в параграфе 11.3. Эта спецификация описывает лишь базовый формат и применяющие Authentication-Info схемы аутентификации будут задавать отдельные параметры. Например, схема аутентификации Digest задаёт множество параметров в параграфе 3.5 [RFC7616].

     Authentication-Info = #auth-param

Поле Authentication-Info может применяться в любом отклике HTTP, независимо от метода запроса и кода отклика. Семантика поля определяется схемой аутентификации, указанной полем заголовка Authorization (параграф 11.6.2) в соответствующем запросе.

Пересылающим прокси не разрешается вносить в это поле какие-либо изменения.

Authentication-Info можно передавать в трейлере (параграф 6.5), если схема аутентификации явно разрешает это.

11.7. Аутентификация клиентов на прокси

11.7.1. Proxy-Authenticate

Поле заголовка Proxy-Authenticate включает хотя бы один вызов (challenge) для указания схем аутентификации и параметров, применяемых к прокси для этого запроса. Прокси должен передавать хотя бы одно поле заголовка Proxy-Authenticate в каждом создаваемом отклике 407 (Proxy Authentication Required).

     Proxy-Authenticate = #challenge

В отличие от WWW-Authenticate, поле заголовка Proxy-Authenticate применяется только к следующему исходящему клиенту в цепочке запроса. Это обусловлено тем, что свидетельства для аутентификации имеются, скорей всего, лишь у клиента, выбравшего данный прокси. При использовании нескольких прокси в одном административном домене, например, офисных или региональных кэширующих прокси, свидетельства обычно генерируются агентом пользователя и передаются по иерархии, пока не будут восприняты. Поэтому в такой конфигурации будет создаваться впечатление пересылки Proxy-Authenticate, поскольку каждый прокси будет передавать тот же набор вызовов.

При разборе поля используются такие же правила, как для WWW-Authenticate (параграф 11.6.1).

11.7.2. Proxy-Authorization

Поле заголовка Proxy-Authorization позволяет клиенту идентифицировать себя (или своего пользователя) на прокси, требующем аутентификации. Значением поля служат свидетельства с данными аутентификации клиента на прокси и/или область действия (realm) для запрашиваемого ресурса.

     Proxy-Authorization = credentials

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

11.7.3. Proxy-Authentication-Info

Поле заголовка отклика Proxy-Authentication-Info аналогично Authentication-Info, но применяется к аутентификации на прокси (параграф 11.3) и его семантика определяется схемой аутентификации, указанной полем заголовка Proxy-Authorization (параграф 11.7.2) в соответствующем запросе.

     Proxy-Authentication-Info = #auth-param

Однако, в отличие от Authentication-Info, поле заголовка Proxy-Authentication-Info применяется только к следующему исходящему клиенту в цепочке отклика. Это обусловлено тем, что, скорее всего, требуемые для аутентификации свидетельства имеются лишь у клиента, выбравшего данный прокси. Однако при использовании в административном домене (офисные или региональные кэширующие прокси большой корпоративной сети) свидетельства обычно генерируются агентом пользователя и передаются по иерархии, пока не будут восприняты. Поэтому создаётся впечатление о пересылке Proxy-Authentication-Info, поскольку каждый прокси передаёт одно значение.

Proxy-Authentication-Info можно передавать как поле трейлера (параграф 6.5), когда схема аутентификации явно разрешает это.

12. Согласование содержимого

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

Эта спецификация задаёт три модели согласования содержимого, которые могут быть в протоколе, — упреждающее (proactive) согласование, где сервер выбирает представление на основе заявленных агентом пользователя предпочтений, реактивное согласование, где сервер предоставляет агенту пользователя список представлений для выбора, и согласование содержимого запроса (request content), где агент пользователя выбирает представление для будущих запросов на основе предпочтений сервера, заявленных в прошлых откликах.

Другие модели согласования содержимого включают условное содержимое (conditional content), где представление состоит из нескольких частей, которые выборочно отображаются на основе предпочтений пользовательского агента, активное содержимое (active content), где представление включает сценарий, выдающий дополнительные (более конкретные) запросы на основе характеристик агента пользователя, и прозрачное согласование содержимого (Transparent Content Negotiation [RFC2295]), где представление выбирается посредниками. Эти схемы не являются взаимоисключающими и у каждой имеются свои плюсы и минусы в плане применимости и практичности.

Отметим, что во всех случаях HTTP не знает о семантике ресурса. Согласованность откликов сервера-источника на запросы с учётом времени и вариантов согласования содержимого, а значит и «одинаковость» наблюдаемых представлений ресурса, полностью определяется тем, какая сущность или алгоритм выбирает или генерирует отклики.

12.1. Упреждающее согласование

Передача агентом пользователя предпочтений по согласованию содержимого в запросе называется упреждающим (proactive) согласованием (согласование, управляемое сервером). Выбор основывается на доступных представлениях отклика (например, язык, кодировка и т. п.) с учётом сведений из запроса, включая явное согласование указанных ниже полей заголовка и неявные характеристики, такие как сетевой адрес клиента или части поля User-Agent.

Предварительное согласование полезно в тех случаях, когда агенту пользователя сложно описать алгоритм выбора из числа доступных представлений или сервер желает отправить своё «лучшее представление» в первом отклике агенту пользователя (если «лучшее представление» подойдёт пользователю, это позволит избежать одного кругового обхода для последующего запроса). Для лучшего «угадывания» агент пользователя может передать в запросе поля заголовка, описывающие его предпочтения.

Ниже указаны серьёзные недостатки упреждающего согласования.

  • Серверу невозможно точно определить «лучший» отклик для пользователя, поскольку для этого нужно знать все возможности агента пользователя и предполагаемое использование отклика (например, просмотр на экране или вывод на печать).

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

  • Усложняется реализация сервера-источника и алгоритмов генерации откликов на запросы.

  • Ограничиваются возможности неоднократного использования откликов из общего кэша.

Агент пользователя не может полагаться на постоянный учёт предпочтений упреждающего согласования, поскольку сервер-источник может не поддерживать такое согласование для запрошенного ресурса или решить, что отправка отклика, не соответствующего предпочтениям пользовательского агента, лучше, чем передача 406 (Not Acceptable).

Для указания частей, использованных в алгоритме выбора, в откликах, являющихся предметом упреждающего согласования, часто передаётся поле заголовка Vary (параграф 12.5.5). Описанные ниже поля заголовка Accept, Accept-Charset, Accept-Encoding, Accept-Language позволяют агенту пользователя участвовать в упреждающем согласовании содержимого. Переданные в этих полях предпочтения применяются к любому содержимому отклика, включая представления целевого ресурса, ошибок или статуса обработки, а также могут применяться к текстовым строкам, появляющимся в протоколе.

12.2. Реактивное согласование

При реактивном согласовании (управляется агентом) выбор содержимого (независимо от кода статуса) выполняется пользовательским агентом после приёма исходного отклика. Механизм реактивного согласования может быть простым как список ссылок на варианты представления.

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

Сервер может не передавать исходное представление, отличное от списка вариантов и тем самым указать предпочтительность реактивного согласования с агентом пользователя. Например, варианты, указанные в откликах с кодом статуса 300 (Multiple Choices) и 406 (Not Acceptable), включают сведения о доступных представлениях, чтобы пользователь или его агент мог реагировать сделанным выбором.

Реактивное согласование подходит в случаях, если отклики различаются по часто используемым параметрам (например, тип, язык, кодировка), когда сервер не способен определить возможности пользовательского агента по запросу, а при использовании общего кэша для распределения нагрузки на сервер и снижения загрузки сети.

Недостатком реактивного согласования является необходимость передачи агенту пользователя списка вариантов, ведущей к росту воспринимаемой пользователем задержки при передаче списка в полях заголовка, и необходимость передачи повторного запроса для получения выбранного представления. Кроме того, эта спецификация не задаёт механизм для поддержки автоматического выбора, хотя и не препятствует разработке таких механизмов.

12.3. Согласование содержимого запроса

Когда предпочтения по согласованию содержимого передаются в отклике сервера, указанные в списке предпочтения называют согласованием содержимого запроса (request content negotiation), поскольку они влияют на выбор содержимого последующих запросов к данному ресурсу. Например, в отклике могут передаваться поля заголовка Accept (параграф 12.5.1) и Accept-Encoding (параграф 12.5.3) для указания предпочтительных типов носителя в последующих запросах к этому ресурсу. Поле Accept-Patch, определённое в параграфе 3.1 [RFC5789], позволяет обнаружить, какие типы содержимого воспринимаются в запросах PATCH.

12.4. Свойства полей согласования содержимого

12.4.1. Отсутствие полей

Для каждого из полей согласования содержимого запрос без такого поля означает отсутствие у отправителя предпочтений по данному аспекту согласования. Если поле согласования содержимого присутствует в запросе, но ни одно из доступных для отклика представлений не может считаться приемлемым для него, сервер-источник может принять поле запроса, возвращая отклик 406 (Not Acceptable), или игнорировать его, как будто это поле не является предметом согласования содержимого. Однако это не означает, что клиент сможет воспользоваться представлением.

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

12.4.2. Значения качества

Поля согласования содержимого, заданные этой спецификацией, используют общий параметр с именем q (без учёта регистра) для назначения относительного веса соответствующего вида содержимого. Этот вес называют значением качества (quality value или qvalue), поскольку параметр с таким же именем часто применяется в конфигурации серверов для указания веса относительному качеству различных представлений, которые могут быть выбраны для ресурса.

Вес нормализуется к действительному числу от 0 до 1, где 0,001 является наименее, 1 — наиболее предпочтительным, а 0 указывает неприемлемое качество. При отсутствии параметра q применяется вес 1.

     weight = OWS ";" OWS "q=" qvalue
     qvalue = ( "0" [ "." 0*3DIGIT ] )
            / ( "1" [ "." 0*3("0") ] )

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

12.4.3. Шаблонные значения

Для большинства этих полей заголовка задано использование шаблона * для выбора неуказанных значений. При отсутствии такого шаблона не указанные явно значения считаются неприемлемыми. В поле Vary шаблон означает неограниченный разброс.

Примечание. На практике использование шаблонов в полях согласования содержимого имеет ограниченное применение, поскольку редко бывает полезно сказать: «Я предпочитаю image/* больше или меньше некого конкретного значения». Передавая Accept: */*;q=0, клиент может явно запросить отклик 406 (Not Acceptable), если более предпочтительного формата не существует, но при этом он должен быть готов воспринять иной отклик, поскольку сервер волен игнорировать это предпочтение.

12.5. Поля согласования содержимого

12.5.1. Accept

Поле заголовка Accept пользовательские агенты могут использовать для указания своих предпочтений в части типов носителей. Например, можно использовать это поле для указания того, что запрос ограничен восприятием небольшого набора желаемых типов, как в случае запроса встроенного изображения. При передаче отклика сервером в поле Accept содержатся сведения о предпочтительных типах содержимого в последующих запросах к тому же ресурсу.

     Accept = #( media-range [ weight ] )

     media-range    = ( "*/*"
                        / ( type "/" "*" )
                        / ( type "/" subtype )
                      ) parameters

Символ * служит для группировки типов носителя в диапазоны, */* указывает все типы, а type/* — все субтипы указанного типа (type). Элемент media-range может включать параметры типа носителя, применимые к диапазону. За каждым media-range могут следовать применимые параметры типа носителя (например, charset), а затем — необязательный параметр q, указывающий относительный вес (параграф 12.4.2).

Предыдущие спецификации разрешали включать дополнительные параметры расширения после параметра weight. Грамматика расширения accept (accept-params, accept-ext) была исключена про причине сложности определения, отсутствия реального использования и большей простоты развёртывания с новыми полями заголовка. Отправителям, использующим weight, следует передавать параметр q последним (после всех параметров media-range). Получателям следует обрабатывать любые параметры с именем q как вес, независимо от местоположения параметра.

Примечание. Использование параметра q для управления согласованием содержимого будет конфликтовать с одноимённым параметром типа носителя, поэтому регистр типов носителя запретил параметров с именем q.

Пример расширения представлен ниже.

   Accept: audio/*; q=0.2, audio/basic

Это интерпретируеся как: «Я предпочитаю audio/basic, но можно передать иной тип звука, являющийся лучшим после снижения качества на 80%».

Ниже представлен более сложный пример.

   Accept: text/plain; q=0.5, text/html,
           text/x-dvi; q=0.8, text/x-c

Это можно описать как одинаковую предпочтительность text/html и text/x-c с передачей при их отсутствии представления text/x-dvi, а при отсутствии и его — text/plain.

Диапазоны носителей могут переопределяться более узкими диапазонами или конкретными типами. Если к данному типу применимо более одного диапазона носителей, предпочтение отдаётся более конкретному. Например,

   Accept: text/*, text/plain, text/plain;format=flowed, */*

задаёт показанный ниже порядок предпочтений.

  1. text/plain;format=flowed
  2. text/plain
  3. text/*
  4. */*

Фактор качества, связанный с данным типом носителя, определяется путём нахождения наиболее предпочтительного диапазона, соответствующего типу. Например,

   Accept: text/*;q=0.3, text/plain;q=0.7, text/plain;format=flowed,
          text/plain;format=fixed;q=0.4, */*;q=0.5

приведёт к привязке указанных в таблице 5 значений.

Таблица .

 

Тип носителя

Значение Quality

text/plain;format=flowed

1

text/plain

0,7

text/html

0,3

image/jpeg

0,5

text/plain;format=fixed

0,4

text/html;level=3

0,38

 

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

12.5.2. Accept-Charset

Агент пользователя может передать поле заголовка Accept-Charset для указания своих предпочтений в части кодировки символов в текстовом содержимом отклика. Например, это поле позволяет пользовательским агентам, способным понимать более полные и специальные наборы символов, сообщить об этом серверу-источнику, чтобы тот мог представлять информацию с таких кодировках.

     Accept-Charset = #( ( token / "*" ) [ weight ] )

Имена кодировок определены в параграфе 8.3.2. Агент пользователя может связать с каждым набором символов параметр качества для ранжирования предпочтений пользователя, как описано в параграфе 12.4.2. Например,

   Accept-Charset: iso-8859-5, unicode-1-1;q=0.8

Специальный символ * в поле Accept-Charset соответствует каждой кодировке, не указанной в других местах поля.

Примечание. Поле Accept-Charset признано устаревшим, поскольку кодировка UTF-8 стала практически повсеместно и передача подробного списка предпочитаемых пользователем кодировок ведёт к ненужному расходу пропускной способности и способствует упрощению пассивного снятия отпечатков (параграф 17.13). Большинство пользовательских агентов общего назначения не передаёт Accept-Charset без специальной настройки.

12.5.3. Accept-Encoding

Поле заголовка Accept-Encoding может служить для указания предпочтений при кодировании содержимого (параграф 8.4.1). При отправке агентом пользователя в запросе Accept-Encoding указывает приемлемое в отклике кодирование содержимого, при отправке сервером в отклике — сведения о предпочтительном кодировании в последующих запросах к тому же ресурсу. Маркер identity применяется как псевдоним отсутствия кодирования (no encoding) для взаимодействия при отсутствии предпочтений для кодировки.

     Accept-Encoding  = #( codings [ weight ] )
     codings          = content-coding / "identity" / "*"

Каждому кодированию может быть назначено значение качества (вес — weight), представляющее уровень предпочтительности для этого кодирования (параграф 12.4.2). Символ * в поле Accept-Encoding соответствует любому доступному типу кодирования, не указанному явно в этом поле. Примеры значений поля приведены ниже.

   Accept-Encoding: compress, gzip
   Accept-Encoding:
   Accept-Encoding: *
   Accept-Encoding: compress;q=0.5, gzip;q=1.0
   Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0

Сервер проверяет пригодность кодирования для данного кодирования с помощью указанных ниже правил.

  1. При отсутствии в запросе поля заголовка Accept-Encoding любое кодирование считается приемлемым для пользовательского агента.

  2. Представление без кодирования содержимого, оно считается приемлемым, если явно не исключено полем заголовка Accept-Encoding, содержащим identity;q=0 или *;q=0 без указания более конкретного identity.

  3. Кодирование представления, совпадающее с одним из указанных в поле Accept-Encoding, считается приемлемым, если оно не сопровождается qvalue = 0 (в параграфе 12.4.2 указано, что qvalue = 0 означает неприемлемость — not acceptable.)

В представлении может использоваться несколько вариантов кодирования, однако большинство способов кодирования просто являются разными способами достижения одной цели (например, сжатия данных). При выборе между вариантами кодирования, имеющими общую цель, предпочтение отдаётся варианту с большим значением qvalue.

Пустое поле Accept-Encoding указывает, что не хочет получать в отклике какое-либо кодирование содержимого. Если в запросе имеется непустое поле Accept-Encoding и ни один из вариантов кодирования представления не указан в числе приемлемых, серверу-источнику следует передавать отклик без какого-либо кодирования содержимого, если только кодирование сущности (identity) не указано как неприемлемое.

Поле Accept-Encoding в отклике указывает кодирование содержимого, которое ресурс готов воспринять в связанном запросе. Значение поля оценивается так же, как в запросе.

Отметим, что эта информация относится только к конкретному запросу и набор поддерживаемых вариантов кодирования может меняться с течением времени или зависеть от других аспектов запроса (например, от метода).

Сервер, отклоняющий запрос из-за неподдерживаемого кодирования, должен передавать отклик с кодом статуса 415 (Unsupported Media Type) и полем заголовка Accept-Encoding, позволяющим клиенту различать проблемы, связанные с кодированием и типами носителей. Во избежание путаницы с проблемами из-за типа носителя серверам, отклоняющим запрос с кодом 415 по причинам, не связанным с кодированием содержимого, недопустимо включать в отклик поле заголовка Accept-Encoding.

Наиболее часто поле Accept-Encoding применяется в откликах с кодом статуса 415 (Unsupported Media Type) в ответ на оптимистическое использование клиентами вариантов кодирования содержимого. Однако это поле может служить для указания клиента поддерживаемых вариантов кодирования содержимого с целью оптимизации будущих взаимодействий. Например, ресурс может включить это поле в отклик 2xx (Successful), если содержимое запроса было достаточно велико, чтобы использовать сжатие, но клиент не сделал этого.

12.5.4. Accept-Language

Поле заголовка Accept-Language агент пользователя может применять для указания набора естественных языков, предпочитаемых в отклике. Теги языков определены в параграфе 8.5.1.

     Accept-Language = #( language-range [ weight ] )
     language-range  = <language-range, см. [RFC4647], параграф 2.1>

Для каждого language-range можно задать значение качества, указывающее оценку предпочтений пользователя для языков диапазона, как указано в параграфе 12.4.2. Например,

   Accept-Language: da, en-gb;q=0.8, en;q=0.7

будет означать: «я предпочитаю датский язык, но буду воспринимать британский английский и другие варианты английского языка».

Отметим, что некоторые получатели трактуют порядок тегов языка, как признак снижения приоритета, особенно для тегов с одинаковым значением качества (отсутствие значения эквивалентно q=1). Однако полагаться на такое поведение нельзя. Для согласованности и максимальной совместимости многие пользовательские агенты назначают каждому тегу языка уникальное значение качества, размещая теги в порядке снижения качества. Дополнительное обсуждение приоритетов в списках языков приведено в параграфе 2.3 [RFC4647].

Раздел 3 в [RFC4647] задаёт различные схемы сопоставления. Реализации могут предложить наиболее подходящую для них схему. Схема Basic Filtering ([RFC4647], параграф 3.3.1) идентична схеме сопоставления, заданной ранее для HTTP в параграфе 14.4 [RFC2616].

Передача поля заголовка Accept-Language с полными языковыми предпочтениями в каждом запросе может противоречить ожиданиям пользователя в части приватности (параграф 17.13).

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

Примечание. Пользовательские агенты должны предоставлять пользователю рекомендации по установке предпочтений, поскольку пользователи редко знакомы с описанными выше деталями сопоставления языков. Например, пользователь может предполагать, что при выборе en-gb ему будут предоставляться любой английский документ, если British English не доступен. В таком случае агент пользователя может предложить добавить в список тег en для более подходящего поведения.

12.5.5. Vary

Поле заголовка Vary в отклике описывает, какие части запросного сообщения, помимо метода и URI цели, могли повлиять на процесс выбора содержимого этого отклика сервером-источником.

     Vary = #( "*" / field-name )

Поле Vary представляет собой шаблон * или список имён полей запроса, известных как выбирающие поля заголовка, которые могли играть роль при выборе представления для данного отклика. Выбирающими полями могут быть не только указанные в этой спецификации поля.

Список, содержащий шаблон *, указывает, что при выборе представления могли сыграть роль другие аспекты запроса, возможно не относящиеся к синтаксису (например, сетевой адрес клиента). Получатель не сможет определить, подходит ли этот отклик для последующего запроса, не переслав запрос серверу-источнику. Прокси недопустимо генерировать * в значении поля Vary. Например, отклик с полем заголовка

   Vary: accept-encoding, accept-language

показывает, что сервер-источник мог использовать поля заголовка Accept-Encoding и Accept-Language (или их отсутствие) в качестве факторов, определивших содержимое отклика.

Поле Vary со списком имён полей служит двум целям.

  1. Информировать получателей кэша, что им недопустимо использовать этот отклик для выполнения последующих запросов, пока в тех не содержатся те же значения указанных в списке полей заголовка, что и в исходном запросе (параграф 4.1 в [CACHING]), или повторное не было подтверждено сервером-источником. Иными словами, поле Vary раскрывает ключ кэша для сопоставления нового запроса с кэшированной записью.

  2. Информировать пользовательские агенты-получатели о том, что этот отклик был предметом согласования содержимого (раздел 12) и при последующем запросе может быть передано другое представление, если в перечисленных полях его заголовка будут указаны другие значения (упреждающее согласование).

Серверу-источнику следует генерировать поле Vary в кэшируемом отклике, если он хочет, чтобы этот отклик можно было селективно использовать для последующих запросов. Обычно это происходит в случаях, когда содержимое отклика было адаптировано для лучшего соответствия предпочтениям, указанным в выбирающих полях заголовка, например, при выборе сервером-источником языка отклика по полю Accept-Language в заголовке отклика.

Поле Vary может не применяться, если сервер-источник считает варианты выбора содержимого менее значимыми, нежели влияние Vary на работу кэширования, особенно в случаях, когда повторное использование уже ограничено директивами кэширования откликов (параграф 5.2 в [CACHING]).

В Vary не требуется передавать поле Authorization, поскольку использование этого отклика другими пользователями запрещено определением поля (параграф 11.6.2). Если содержимое отклика выбирается с учётом области сети, а сервер-источник хочет, чтобы кэшированный отклик можно было повторно использовать даже при перемещении получателя в другую область сети, серверу-источнику не требуется указывать это в поле Vary.

13. Условные запросы

Условными называют запросы HTTP с одним или несколькими полями заголовка, указывающими предварительные условия, выполнение которых можно проверить до применения метода запроса к целевому ресурсу. В параграфе 13.2 описана проверка выполнения предварительных условий и порядок применения при наличии нескольких условий.

Условные запросы GET являются наиболее эффективным механизмом обновления кэша HTTP [CACHING]. Условия могут также применяться к методам, меняющим состояние, таким как PUT и DELETE, для предотвращения потери обновлений, когда один клиент случайно переписывает работу другого клиента, действующего параллельно.

13.1. Предварительные условия

Предварительные условия обычно задаются применительно к состоянию всего целевого ресурса (его текущего набора значений) или его состоянию в полученном ранее представлении (одно из значений в наборе). Если у ресурса несколько текущих представлений, каждое из которых имеет своё наблюдаемое состояние, предварительное условие будет предполагать, что сопоставление каждого запроса с выбранным представлением (параграф 3.2) согласовано во времени. Независимо от этого при несогласованности сопоставления или невозможности сервера выбрать подходящее представление не будет никакого вреда в результате невыполнения (false) предварительных условий.

Каждое из определённых ниже предварительных условий включает сравнение набора валидаторов из предыдущих представлений целевого ресурса с текущим состоянием набора валидаторов для выбранного представления (параграф 8.8). Таким образом, предварительные условия позволяют понять, изменилось ли состояние целевого ресурса относительно данного состояния, известного клиенту. Влияние такой оценки зависит от семантики метода и выбора условий, как описано в параграфе 13.2.

Предварительные условия, задаваемые в других спецификациях как поля расширения, могут ставить условия для всех получателей, состояния всего целевого ресурса или группы ресурсов. Например, поле заголовка If в WebDAV может делать запрос зависимым от различных аспектов нескольких ресурсов, таких как блокировки, если получатель понимает и реализует поле ([WEBDAV], параграф 10.4).

Расширяемость предварительных условий возможна лишь в тех случаях, когда неизвестное условие можно безопасно игнорировать (как If-Modified-Since), внедрение можно предположить в данной среде или его реализацию можно указать каким-либо свойством целевого ресурса. Это позволяет сосредоточиться на согласовании общих стандартов.

13.1.1. If-Match

Поле заголовка If-Match делает метод запроса условным в зависимости от наличия у принявшего запрос сервера-источника хотя бы одного текущего представления целевого ресурса. Условие считается выполненным, если в поле указано значение * или имеется текущее представление целевого ресурса, у которого тег сущности совпадает с одним из элементов списка тегов в значении поля.

Сервер-источник должен применять строгое сопоставление для тегов If-Match (параграф 8.8.3.2), поскольку намерение клиента состоит в предотвращении применения метода, если данные представления были изменены.

     If-Match = "*" / #entity-tag

Примеры поля представлены ниже.

   If-Match: "xyzzy"
   If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
   If-Match: *

If-Match чаще всего применяется с методами, меняющими состояние (например, POST, PUT, DELETE), для предотвращения случайной перезаписи при параллельной работе нескольких пользовательских агентов с одним ресурсом (проблема потери обновлений). В общем случае поле может применяться с любым методом, предполагающим выбор или изменение представления, для прерывания запроса при отсутствии текущего тега сущности выбранного представления в списке поля If-Match.

При получении сервером-источником выбирающего представление запроса с полем заголовка If-Match сервер должен до применения метода проверить выполнение условия If-Match в соответствии с параграфом 13.2.

  1. При значении поля * условие будет выполняться при наличии у сервера-источника текущего представления для целевого ресурса.

  2. Если поле содержит список тегов сущностей, условие считается выполненным при соответствии хотя бы одного тега из списка тегу сущности выбранного представления.

  3. В иных случаях условия считаются не выполненными.

Серверу-источнику, оценивающему условие If-Match, недопустимо выполнять запрошенный метод, если условие не выполняется. Вместо этого сервер может указать невыполнение условия откликом с кодом 412 (Precondition Failed). Как вариант, сервер может передать отклик 2xx (Successful), если запрос был меняющей статус операцией, которая, по-видимому, уже применена (запрошенное пользовательским агентом изменение, уже внесено, но агент может не знать об этом, возможно, по причине потери предыдущего отклика или внесения эквивалентных изменений другим пользовательским агентом). Разрешение серверу-источнику передавать отклик об успехе, когда представляется, что запрос на изменение уже был применён, является более эффективным для многих случаев использования инструментов публикации, но связано с некоторым риском, если несколько пользовательских агентов делают очень похожие, но не согласованные запросы. Например, несколько пользовательских агентов пишущих в общий ресурс (например, неатомарное добавление) могут вступить в конфликт, влекущий возможность потери важных изменений состояния. Для таких ресурсов серверу-источнику лучше быть строгим и передавать отклик 412 для каждого запроса с небезопасным методом, где условие не было выполнено. В иных случаях исключение поля ETag из отклика об успехе может побудить пользовательский агент к отправке GET в качестве следующего запроса для устранения путаницы с текущим состоянием ресурса.

Клиент может передать поле заголовка If-Match в запросе GET для указания того, что он предпочитает получить отклик 412 (Precondition Failed), если выбранное представление не соответствует. Однако это полезно лишь в запросах с диапазоном (раздел 14) для завершения полученного ранее частичного представления, когда новое представление нежелательно. Поле If-Range (параграф 13.1.5) лучше подходит для запросов диапазона, если клиент предпочитает получит новое представление.

Кэш или посредник может игнорировать If-Match, поскольку его функциональная совместимость нужна лишь серверу-источнику.

Отметим, что поле заголовка If-Match со списком, содержащим * и другие значения (включая другие экземпляры *), синтаксически некорректно (и не разрешено для генерации) и вряд ли будет функционально совместимым.

13.1.2. If-None-Match

Поле заголовка If-None-Match делает метод запроса условным по отсутствию в кэше получателя или на сервере-источнике соответствующего значению поля текущего представления целевого ресурса. Для поля со значением * условие считается выполненным, если нет никакого текущего представления целевого ресурса. При указании в поле списка тегов сущностей условие считается выполненным, когда имеется тег сущности, не указанный в списке поля.

Получатель должен применять функцию мягкого сравнения тегов сущностей (параграф 8.8.3.2) при сравнении с полем If-None-Match, поскольку мягкие теги сущностей можно применять для проверки кэша даже при внесении изменений в данные представления.

     If-None-Match = "*" / #entity-tag

Примеры заголовков приведены ниже.

   If-None-Match: "xyzzy"
   If-None-Match: W/"xyzzy"
   If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
   If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
   If-None-Match: *

If-None-Match применяется в основном в условных запросах GET для эффективного обновления кэшированных данных с минимальными издержками на транзакции. Когда клиент хочет обновить один или несколько сохранённых откликов, имеющих теги сущности, ему следует генерировать поле заголовка If-None-Match со списком этих тегов при создании запроса GET. Это позволяет получившему запрос серверу отправлять отклик 304 (Not Modified) в случаях, когда один из сохранённых откликов совпадает с выбранным представлением.

If-None-Match можно использовать со значением * для предотвращения непреднамеренного изменения небезопасным методом (например, PUT) имеющегося представления целевого ресурса, когда клиент считает, что у этого ресурса нет текущего представления (параграф 9.2.1). Этот один из вариантов потери обновлений, возможный при попытке нескольких клиентов создать исходное представление целевого ресурса.

При получении сервером-источником запроса, выбирающего представление, с полем заголовка If-None-Match этот сервер должен оценить выполнение условий If-None-Match в соответствии с параграфом 13.2 до применения метода.

  1. При значении поля * условие не будет выполняться при наличии у сервера-источника текущего представления для целевого ресурса.

  2. Если поле содержит список тегов сущностей, условие считается не выполненным при соответствии хотя бы одного тега из списка тегу сущности выбранного представления.

  3. В иных случаях условия считаются выполненными.

Серверу-источнику, оценивающему условие If-None-Match, недопустимо выполнять запрошенный метод, если условие не выполняется. Вместо этого сервер должен передать отклик с кодом a) 304 (Not Modified) для запросов с методом GET или HEAD или b) 412 (Precondition Failed) в иных случаях.

Требования к обработке кэшем полученного поля заголовка If-None-Match заданы в параграфе 4.3.2 [CACHING].

Отметим, что поле заголовка If-None-Match со списком, содержащим * и другие значения (включая другие экземпляры *), синтаксически некорректно (и не разрешено для генерации) и вряд ли будет функционально совместимым.

13.1.3. If-Modified-Since

Поле заголовка If-Modified-Since делает метод запроса GET или HEAD условным по дате изменения выбранного представления Передача данных выбранного представления не происходит, если они не изменились с момента, указанного значением поля.

     If-Modified-Since = HTTP-date

Пример поля приведён ниже.

   If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT

Получатель должен игнорировать If-Modified-Since, если запрос включает поле If-None-Match, поскольку условие If-None-Match считается более точной заменой If-Modified-Since, а комбинация условий применяется лишь для совместимости со старыми посредниками, не реализующими If-None-Match. Получатель должен игнорировать If-Modified-Since, если поле не содержит действительного значения HTTP-date, имеет несколько элементов или метод запроса отличается от GET и HEAD. Получатель должен игнорировать If-Modified-Since, если ресурс не имеет доступной даты изменения. Получатель должен интерпретировать значение временной мети в поле If-Modified-Since по часам сервера-источника.

If-Modified-Since обычно применяется для двух целей: 1) эффективное обновление кэшированного представления без тега сущности и 2) ограничение области обхода web ресурсами, которые недавно были изменены.

При использовании для обновления кэша для генерации If-Modified-Since обычно берётся значение поля заголовка Last-Modified. Это обеспечивает функциональную совместимость в случаях когда часы не синхронизированы точно или сервер предпочитает учитывать лишь точное совпадение меток времени (из-за проблемы дат в Last-Modified, представляющихся прошлым, когда часы сервера корректируются или представление восстанавливается из резервной копии). Однако кэш иногда создаёт значение поля на основе других данных, таких как поле заголовка Date в кэшированном сообщении или момент приёма сообщения, особенно при отсутствии в кэшируемом сообщении поля Last-Modified.

При использовании для ограничения области извлечения данных недавним интервалом времён пользовательский агент создаёт значение поля If-Modified-Since на основе своих часов или поля Date в предыдущем отклике от сервера. Серверы-источники, проверяющие точное совпадение меток времени выбранного сопоставления с полем заголовка Last-Modified, не смогут помочь пользовательскому агенту ограничиться получением лишь данных, изменившихся в заданном интервале времени.

При получении сервером-источником запроса, выбирающего представление, с полем заголовка If-Modified-Since, но без If-None-Match этому серверу следует проверить выполнение условия If-Modified-Since в соответствии с параграфом 13.2 до применения метода.

  1. Если выбранное представление изменено не позже указанного полем момента, условие считается не выполненным.

  2. В иных случаях условие считается выполненным.

Серверу-источнику, проверяющему условие If-Modified-Since, не следует применять запрошенный метод, если условие не выполняется. Вместо этого следует создать отклик 304 (Not Modified), включающий лишь метаданные, которые полезны для идентификации или обновления кэшированного ранее отклика.

Требования к обработке кэшем полученного поля заголовка If-Modified-Since заданы в параграфе 4.3.2 [CACHING].

13.1.4. If-Unmodified-Since

Поле заголовка If-Unmodified-Since делает запрос условным по дате последнего изменения выбранного представления — условие считается выполненным, если эта дата не позже указанной в значении поля. Поле служит для той же задачи, что и If-Match, в случае отсутствия у агента пользователя тега сущности для представления.

     If-Unmodified-Since = HTTP-date

Пример поля приведён ниже.

   If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT

Получатель должен игнорировать поле If-Unmodified-Since, если в запросе имеется поле If-Match — условие If-Match является более точным, чем If-Unmodified-Since, и они применяются вместе лишь для совместимости со старыми посредниками, которые могут не реализовать If-Match. Получатель должен игнорировать поле If-Unmodified-Since, если в нем содержится значение, не являющееся действительным HTTP-date (включая значения в списке). Получатель должен игнорировать If-Unmodified-Since, если ресурс не имеет доступной даты изменения. Получатель должен интерпретировать значение временной мети в поле If-Unmodified-Since по часам сервера-источника.

If-Unmodified-Since чаще всего применяется в методах, меняющих состояние (например, POST, PUT, DELETE), для предотвращения случайной перезаписи при параллельной работе нескольких пользовательских агентов с одним ресурсом без тега сущности в представлениях (проблема потери обновлений). В общем случае поле может применяться с любым методом, предполагающим выбор или изменение представления, для прерывания запроса, если дата последнего изменения выбранного представления позже даты в поле If-Unmodified-Since.

При получении сервером-источником запроса, выбирающего представление, с полем заголовка If-Unmodified-Since, но без If-Match, сервер должен проверить выполнение условия If-Unmodified-Since в соответствии с параграфом 13.2.

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

  2. В иных случаях условие считается не выполненным.

Серверу-источнику, проверяющему условие If-Unmodified-Since, недопустимо применять запрошенный метод, если условие не выполняется. Вместо этого сервер может указать невыполнение условия для запроса откликом с кодом статуса 412 (Precondition Failed). Как вариант, сервер может передать отклик 2xx (Successful), если запрос был меняющей статус операцией, которая, по-видимому, уже применена к выбранному представлению (запрошенное пользовательским агентом изменение, уже внесено, но агент может не знать об этом, возможно, по причине потери предыдущего отклика или внесения эквивалентных изменений другим пользовательским агентом). Разрешение серверу-источнику передавать отклик об успехе, когда представляется, что запрос уже был применён, является более эффективным для многих случаев использования инструментов публикации, но связано с некоторым риском, если несколько пользовательских агентов делают очень похожие, но не согласованные запросы. В таких случаях серверу-источнику лучше быть строгим и передавать отклик 412 для каждого запроса с небезопасным методом, где условие не было выполнено.

Клиент может передать поле заголовка If-Unmodified-Since в запросе GET для указания того, что он предпочитает получить отклик 412 (Precondition Failed), если выбранное представление было изменено. Однако это полезно лишь в запросах с диапазоном (раздел 14) для завершения полученного ранее частичного представления, когда новое представление нежелательно. Поле If-Range (параграф 13.1.5) лучше подходит для запросов диапазона, если клиент предпочитает получит новое представление.

Кэш или посредник может игнорировать If-Unmodified-Since, поскольку его функциональная совместимость нужна лишь серверу-источнику.

13.1.5. If-Range

Поле заголовка If-Range обеспечивает специальный механизм условных запросов, подобный If-Match и If-Unmodified-Since, но предписывающий получателю игнорировать поле заголовка Range при несоответствии валидатора, что ведёт к отправке нового выбранного представления вместо отклика 412 (Precondition Failed).

Если клиент имеет частичную копию представления и хочет получить актуальную копию всего представления, он может использовать поле заголовка Range в условном запросе GET (с If-Unmodified-Since и/или If-Match). Однако, если условие не выполняется из-за изменения представления, клиенту придётся сделать второй запрос для получения текущего представления целиком.

Поле заголовка If-Range позволяет клиенту «сократить» второй запрос. Неформально оно говорит: «Если представление не изменилось, отправьте мне части, указанные в Range, в ином случае — представление целиком».

     If-Range = entity-tag / HTTP-date

Действительный тег entity-tag можно отличить от действительной даты HTTP-date по DQUOTE в первых 3 символах.

Клиенту недопустимо генерировать поле заголовка If-Range в запросе без поля Range в заголовке. Сервер должен игнорировать поле If-Range в запросах без поля заголовка Range. Сервер-источник должен игнорировать поле If-Range в запросе к ресурсу, не поддерживающему запросы Range. Клиенту недопустимо генерировать поле заголовка If-Range, содержащее тег сущности, который помечен как слабый. Клиенту недопустимо генерировать поле заголовка If-Range, содержащее HTTP-date, если у него нет тега сущности для соответствующего представления и дата не является строгим валидатором в смысле, указанном в параграфе 8.8.2.2.

При получении сервером-источником поля заголовка If-Range header в запросе Range он должен проверить выполнение условий в соответствии с параграфом 13.2 до применения метода. Проверка поля If-Range с HTTP-date описана ниже.

  1. Если предоставленный валидатор HTTP-date не является строгим в смысле, указанном в параграфе 8.8.2.2, условия считаются не выполненными.

  2. Если предоставленный валидатор HTTP-date точно совпадает со значением поля Last-Modified для выбранного представления, условия считаются выполненными.

  3. В иных случаях условия считаются не выполненными.

Проверка поля If-Range с тегом сущности описана ниже.

  1. Если предоставленный валидатор entity-tag точно совпадает со значением поля Etag для выбранного представления при строгом сравнении (параграф 8.8.3.2), условия считаются выполненными.

  2. В иных случаях условия считаются не выполненными.

Получатель If-Range должен игнорировать поле заголовка Range, если условие If-Range не выполняется. В ином случае получателю следует обрабатывать поле Range в соответствии с запросом. Отметим, что для If-Range проверяется точное совпадение, включая случай с указанием HTTP-date, что отличается от условия «не позже» в If-Unmodified-Since.

13.2. Оценка предварительных условий

13.2.1. Когда выполнять оценку

За исключением указанных ниже случаев кэш-получатель или сервер-источник должен оценивать предварительные условия в полученном запросе после успешного завершения обычных проверок запроса и непосредственно перед обработкой содержимого запроса (при его наличии) или выполнением действий, связанных с методом запроса. Сервер должен игнорировать все полученные предварительные условия, если его отклик на тот же запрос без этих условий имел бы код статуса, отличный от 2xx (Successful) и 412 (Precondition Failed), до обработки содержимого запроса. Иными словами, перенаправления и отказы, которые можно обнаружить до выполнения значительной обработки имеют приоритет перед оценкой предварительных условий.

Серверу, который не является источником для целевого ресурса и не может выступать в роли кэша для запросов к целевому ресурсу, недопустимо оценивать поля условий в заголовке запроса, заданные этой спецификацией, и он должен переслать их, если запрос пересылается, поскольку создающий запрос клиент предполагает, что условия оцениваются сервером, который может обеспечить текущее представление. Сервер должен игнорировать поля заголовка с условиями, определённые этой спецификацией, при получении запроса с методом, не предполагающим выбор или изменение текущего представления (например, CONNECT, OPTIONS, TRACE).

Отметим, что расширения протокола могут изменять обстоятельства оценки предварительных условий или последствия такой оценки. Например, директива кэширования immutable ([RFC8246]) предписывает кэшам не пересылать условные запросы при наличии в кэше свежего отклика.

Хотя поля заголовка запроса с условиями определены как пригодные для использования с методом HEAD (для сохранения в HEAD семантики метода GET), нет смысла передавать условные запросы HEAD, поскольку отклик об успехе имеет примерно такой же размер, как 304 (Not Modified), и более полезен, чем 412 (Precondition Failed).

13.2.2. Порядок применения предварительных условий

Когда в запросе имеется более одного поля заголовка с запросом, важен порядок оценки этих полей. На практике поля, заданные в этом документе, применяются последовательно в логическом порядке, поскольку условия, связанные с потерей обновлений, задают более строгие требования, нежели проверка кэша, проверенный кэш важнее частичного отклика, а теги сущности важнее валидаторов дат. Кэш-получатель или сервер-источник должен оценивать в запросе заданные этой спецификацией условия в приведённом ниже порядке.

  1. Сервер-источник, получивший запрос с условием If-Match:

    • переходит к п. 3, если условие выполнено;

    • при невыполненном условии сервер передаёт отклик 412 (Precondition Failed), если не установлено, что меняющий состояние запрос уже был выполнен (см. параграф 13.1.1).

  1. Сервер-источник, получивший запрос без If-Match, но с условием If-Unmodified-Since:

    • переходит к п. 3, если условие выполнено;

    • при невыполненном условии сервер передаёт отклик 412 (Precondition Failed), если не установлено, что меняющий состояние запрос уже был выполнен (см. параграф 13.1.4).

  1. Для запросов с условием If-None-Match получатель:

    • переходит к п. 5, если условие выполнено;

    • при невыполненном условии передаёт отклик 304 (Not Modified) для методов GET и HEAD, 412 (Precondition Failed) — для других методов.

  1. Для запросов GET или HEAD без If-None-Match, но с условием If-Modified-Since получатель:

    • переходит к п. 5, если условие выполнено;

    • при невыполненном условии передаёт отклик 304 (Not Modified).

  1. Для запросов GET с полем Range и условием If-Range получатель:

    • передаёт отклик 206 (Partial Content), если условие выполнено значение Range применимо в выбранному представлению;

    • в иных случаях получатель игнорирует Range и передаёт отклик 200 (OK).

  1. В остальных случаях получатель выполняет запрошенный метод и передаётся соответствующий отклик.

Любое расширение HTTP, задающее дополнительные поля заголовка с условием, должно определять порядок оценки этих полей по отношению к определённому здесь порядку и другим условиям, которые могут возникать на практике.

14. Запросы диапазонов

Клиенты часто сталкиваются с прерыванием передачи данных в результате отмены запросов или разрыва соединений. Если клиент сохранил частичное представление, желательно запросить оставшуюся часть вместо передачи всего представления. Устройства с ограниченным локальным хранилищем могут выиграть за счёт возможности запрашивать лишь часть крупного содержимого, например, одну страницу очень большого документа или фрагмент изображения.

Диапазоны запросов являются необязательной функцией HTTP, созданной так, что получатели, не поддерживающие её (совсем или для целевого ресурса) могут ответить как на обычный запрос GET без потери функциональной совместимости. Частичные отклики обозначаются отдельным кодом статуса, чтобы кэш без поддержки этой функции не принимал их за полные отклики.

14.1. Единицы диапазона

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

Такое базовое обозначение единицы диапазона (range unit) применяется в полях заголовка Accept-Ranges (параграф 14.3) для анонсирования поддержки запросов диапазона, Range (параграф 14.2) для разграничения запрашиваемых частей представления и Content-Range (параграф 14.4) для описания передаваемой части.

     range-unit       = token

Регистр символов в именах единиц диапазона не принимается во внимание, а имена должны регистрироваться в реестре HTTP Range Unit Registry, как указано в параграфе 16.5.1. Предполагается, что единицы диапазона являются расширяемыми, как описано в параграфе 16.5.

14.1.1. Задание диапазона

Диапазоны указываются в единицах, соответствующих спецификатору диапазона. Имя единицы диапазона указывает тип range-spec, разрешённый для спецификаторов. Базовая грамматика приведена ниже и предполагается, что каждая единица диапазона указывает, когда разрешено применять int-range, suffix-range и other-range. Запрос может указывать один или несколько диапазонов в рамках одного представления.

     ranges-specifier = range-unit "=" OWS9 range-set
     range-set        = 1#range-spec
     range-spec       = int-range
                      / suffix-range
                      / other-range

Форма int-range задаёт диапазон одним (начало диапазона) или двумя неотрицательными целыми числами. Единица диапазона определяет смысл спецификаторов (например, они могут указывать смещение от начала, пронумерованные части и т. п.). Форма int-range недействительна, если значение last-pos меньше first-pos.

     int-range     = first-pos "-" [ last-pos ]
     first-pos     = 1*DIGIT
     last-pos      = 1*DIGIT

Форма suffix-range указывает диапазон суффиксом данных представления с неотрицательным значением максимального размера (в единицах диапазона). Иными словами, указывается N последних блоков представления.

     suffix-range  = "-" suffix-length
     suffix-length = 1*DIGIT

Для обеспечения расширяемости правило other-range предоставляет почти не ограниченную грамматику, позволяющую задавать спецификаторы для конкретных приложений или будущих единиц диапазонов.

     other-range   = 1*( %x21-2B / %x2D-7E )
                   ; 1*(VCHAR за исключением запятой)

Спецификатор ranges-specifier является недействительным при наличии в нем какого-либо недействительного или непонятного range-unit. Действительный ranges-specifier является «удовлетворительным» при наличии хотя бы одного удовлетворительного range-spec, как это определено указанным элементом range-unit. В остальных случаях ranges-specifier будет «неудовлетворительным».

14.1.2. Диапазоны байтов

Единица диапазона bytes служит для указания поддиапазонов последовательностей октетов содержимого представления. Каждый диапазон байтов указывается целыми числами смещения от начала (int-range) или конца (suffix-range) данных представления. В диапазонах байтов не применяется спецификатор other-range.

Значение first-pos в байтовом int-range указывает смещение первого байта диапазона, last-pos — смещение последнего (оба байта включаются в диапазон). Отсчёт смещений начинается с 0.

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

Примеры указания диапазонов приведены ниже.

  • Первые 500 байтов (смещение от 0 до 499, включительно)

    bytes=0-499
  • вторые 500 байтов (смещение от 500 до 999, включительно)

    bytes=500-999

Клиент может ограничивать число байтов, запрашиваемых при неизвестном размере выбранного представления. Если значение last-pos не задано или выходит за размер данных представления, диапазон байтов рассматривается как остаток представления (т. е. сервер использует в качестве last-pos значение на 1 меньше текущего размера выбранного представления). Клиент может указать последние N байтов (N > 0) выбранного представления, используя suffix-range. Если выбранное представление меньше указанного suffix-length, используется все представление.

Ниже приведены другие примеры для представления размером 10000.

  • последние 500 байтов ( смещение от 9500 до 9999, включительно)

    bytes=-500

    или

    bytes=9500-
  • Только первый и последний байт (байты 0 и 9999)

    bytes=0-0,-1
  • По 1000 байтов из начала, середины и конца

    bytes= 0-999, 4500-5499, -1000
  • Другие действительные (но не канонические) спецификации вторых 500 байтов (500 — 999, включительно)

    bytes=500-600,601-999
    bytes=500-700,601-999

Для запроса GET байтовая спецификация range-spec удовлетворительна при выполнении одного из условий:

  • указан int-range со значением first-pos меньше текущего размера выбранного представления;

  • указан suffix-range с ненулевым значением suffix-length.

Для выбранного представления с нулевым размером единственной удовлетворительной формой range-spec в запросе GET является suffix-range с ненулевым значением suffix-length.

В синтаксисе byte-range значения first-pos, last-pos, suffix-length указываются десятичными числами (в октетах). Поскольку нет предопределённых ограничений на размер содержимого, получатели должны быть готовы принимать большие целые числа и предотвращать ошибки разбора из-за переполнения при целочисленных преобразованиях.

14.2. Range

Поле заголовка Range в запросе GET меняет семантику метода для запроса передачи лишь одного или нескольких субдиапазонов выбранного представления данных (параграф 8.1) вместо отправки всего представления.

     Range = ranges-specifier

Сервер может игнорировать поле заголовка Range, однако серверы-источники и посредники должны поддерживать диапазоны байтов, когда это возможно, поскольку это позволяет поддерживать эффективное восстановление при частичных сбоях передачи и частичном извлечении больших представлений.

Сервер должен игнорировать поле заголовка Range, полученное с методом запроса, который непонятен или не предусматривает обработку диапазонов. Эта спецификация задаёт обработку диапазонов лишь для метода GET. Сервер должен игнорировать поле заголовка Range, содержащее непонятные единицы диапазона. Прокси может отбрасывать поле заголовка Range с непонятными единицами диапазона.

Сервер, поддерживающий запросы диапазонов, может игнорировать или отклонять поле заголовка Range с недействительным спецификатором диапазона (параграф 14.1.1), спецификатором, с двумя или более перекрывающимися диапазонами или набором из множества мелких диапазонов, указанных не в порядке возрастания, поскольку это указывает на взломанного (broken) клиента или преднамеренную DoS-атаку (параграф 17.15). Клиенту не следует запрашивать несколько диапазонов, поскольку это по сути менее эффективно, чем обработка и передача одного диапазона, охватывающего те же данные. Сервер, поддерживающий запросы диапазонов, может игнорировать поле заголовка Range, если в выбранном представлении нет содержимого (т. е. оно имеет размер 0).

Клиенту, запрашивающему несколько диапазонов, следует указывать их в порядке роста (как они были бы получены в полном представлении), если нет необходимости специально изменить порядок. Например, агенту пользователя, обрабатывающему большое представление с внутренним каталогом частей может потребоваться сначала запросить более поздние части, особенно если представление состоит из размещённых в обратном порядке страниц, которые агент хочет получать по одной.

Поле заголовка Range оценивается после проверки полей предварительных условий, определённых в параграфе 13.1, и лишь в том случае, когда при отсутствии поля заголовка Range был бы передан отклик 200 (OK). Иными словами, Range игнорируется, если условный запрос GET будет приводить к отклику 304 (Not Modified). Поле заголовка If-Range (параграф 13.1.5) может применяться как предварительное условие для применения поля Range.

Если все предварительные условия выполнены, сервер поддерживает поле заголовка Range для этого ресурса, полученное в поле Range значение имеет действительный спецификатор ranges-specifier с элементом range-unit, поддерживаемым для целевого ресурса, и ranges-specifier подходит для выбранного представления, серверу следует передать отклик 206 (Partial Content) с одним или несколькими частичными представлениями, соответствующими range-spec из запроса. Это не означает, что сервер передаст все запрошенные диапазоны. В некоторых случаях может быть возможна (или эффективна) передача начала лишь части запрошенных диапазонов с ожиданием от клиента повторного запроса для оставшихся частей, если они ещё нужны (см. параграф 15.3.7).

Если все предварительные условия выполнены, сервер поддерживает поле заголовка Range для этого ресурса, полученное в поле Range значение имеет действительный спецификатор ranges-specifier, но range-unit не поддерживается для целевого ресурса или ranges-specifier не подходит для выбранного представления, серверу следует передать отклик 416 (Range Not Satisfiable).

14.3. Accept-Ranges

Поле Accept-Ranges в отклике указывает, поддерживает и сервер восходящего направления запросы диапазонов для целевого ресурса.

     Accept-Ranges     = acceptable-ranges
     acceptable-ranges = 1#range-unit

Например, сервер, поддерживающий диапазоны байтов (параграф 14.1.2) может передать

   Accept-Ranges: bytes

для индикации поддержки запросов с диапазонами байтов для целевого ресурса, чтобы клиент могут указывать их в будущих частичных запросах с тем же путём к ресурсу. Единицы диапазонов определены в параграфе 14.1.

Клиент может генерировать запросы диапазонов независимо от получения поля Accept-Ranges, которое служит лишь рекомендацией для повышения производительности и сокращения ненужных передач через сеть. Клиенту недопустимо предполагать, что полученное поле Accept-Ranges означает, что будущие запросы диапазона будут возвращать частичные отклики. Может измениться содержимое, сервер может поддерживать диапазоны лишь в течение некоторого времени или следующий запрос может быть обработан другим посредником.

Сервер, не поддерживающий запросы диапазонов для целевого ресурса, может передать

   Accept-Ranges: none

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

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

14.4. Content-Range

Поле заголовка Content-Range передаётся в отклике 206 (Partial Content) с одной частью для указания частичного диапазона, вложенного в сообщение содержимого представления, в каждой части многокомпонентного отклика 206 для указания частичного диапазона, вложенного в каждую часть (параграф 14.6), и в отклике 416 (Range Not Satisfiable) для предоставления сведений о выбранном представлении.

     Content-Range       = range-unit SP
                           ( range-resp / unsatisfied-range )

     range-resp          = incl-range "/" ( complete-length / "*" )
     incl-range          = first-pos "-" last-pos
     unsatisfied-range   = "*/" complete-length

     complete-length     = 1*DIGIT

Если отклик 206 (Partial Content) содержит поле заголовка Content-Range с единицей диапазона (параграф 14.1), которую получатель не понимает, получателю недопустимо пытаться рекомбинировать отклик с сохраненным представлением. Прокси, получающему такое сообщение, следует переслать его в нисходящем направлении.

Поле Content-Range может передаваться как модификатор запроса для частичного PUT (см. параграф 14.5) на основе частных соглашений между клиентом и сервером-источником. Сервер должен игнорировать поле заголовка Content-Range, полученное в запросе с методом, для которого поддержка Content-Range не задана.

Для байтовых диапазонов отправителю следует указывать полный размер (complete-length) представления, из которого извлечён диапазон, за исключением случаев, когда определить полный размер трудно или невозможно. Символ * вместо complete-length указывает, что размер представления не был известен в момент создания поля. Ниже приведён пример пример, где полный размер представления известен отправителю и составляет 1234 байта.

   Content-Range: bytes 42-1233/1234

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

   Content-Range: bytes 42-1233/*

Значение поля Content-Range считается недействительным, если оно содержит range-resp с last-pos меньше first-pos или complete-length меньше или совпадает с last-pos. Получателю недействительного Content-Range недопустимо пытаться рекомбинировать полученное содержимое с сохраненным представлением. .

Серверу, генерирующему отклик 416 (Range Not Satisfiable) для запроса byte-range, следует передавать поле заголовка Content-Range со значением unsatisfied-range, как показано ниже.

   Content-Range: bytes */1234

Элемент complete-length в отклике 416 указывает текущий размер выбранного представления.

Поле заголовка Content-Range не имеет смысла для кодов статуса, не описывающих его семантику явно. В данной спецификации Content-Range имеет смысл только в откликах 206 (Partial Content) и 416 (Range Not Satisfiable).

Ниже приведены примеры значений Content-Range при полном размере выбранного содержимого 1234 байта.

  • Первые 500 байтов

    Content-Range: bytes 0-499/1234
  • Вторые 500 байтов

    Content-Range: bytes 500-999/1234
  • Все, кроме первых 500 байтов

    Content-Range: bytes 500-1233/1234
  • Последние 500 байтов

    Content-Range: bytes 734-1233/1234

14.5. Частичный запрос PUT

Некоторые серверы-источники поддерживают PUT для частичного представления, когда пользователь передаёт в запросе поле заголовка Content-Range (параграф 14.4), хотя такая поддержка противоречива и зависит от частного соглашения с агентом пользователя. В общем случае запрашивается замена части целевого ресурса содержимым запроса по смещению и размеру, указанным в поле Content-Range, где смещение указано относительно текущего выбранного представления.

Серверу-источнику следует отвечать кодом 400 (Bad Request) при получении Content-Range в запросе PUT для целевого ресурса, который не поддерживает частичные запросы PUT. Частичные запросы PUT не совместимы с исходным определением PUT и могут приводить к полной замене текущего представления содержимым запроса.

Частичные обновления ресурса возможны также при нацеливании на отдельно идентифицированный ресурс с состоянием, которое имеет пересечение или расширяет часть большего ресурса, или при использовании другого метода, который специально определён для частичных обновлений (например, метод PATCH из [RFC5789]).

14.6. Тип носителя multipart/byteranges

Когда сообщение с откликом 206 (Partial Content) включает содержимое из нескольких диапазонов, оно передаётся как части тела многокомпонентного сообщения ([RFC2046], параграф 5.1) с типом носителя multipart/byteranges, который включает одну или несколько частей тела сообщения, каждая из которых имеет свои поля Content-Type и Content-Range. Обязательный параметр границы задаёт строку, отделяющую одну часть от другой.

  1. Перед первой граничной строкой в теле сообщения могут указываться дополнительные символы CRLF.

  2. [RFC2046] разрешает заключать граничную строку в кавычки, однако некоторые реализации некорректно обрабатывают такие строки.

  3. Многие клиенты и серверы разработаны на основе предварительной спецификации byteranges, использовавшей тип носителя multipart/x-byteranges, который почти (но не совсем) совместим с byteranges.

Несмотря на имя, тип носителя multipart/byteranges предназначен не только для байтовых диапазонов. Ниже приведён пример с использованием единицы диапазона exampleunit.

   HTTP/1.1 206 Partial Content
   Date: Tue, 14 Nov 1995 06:25:24 GMT
   Last-Modified: Tue, 14 July 04:58:08 GMT
   Content-Length: 2331785
   Content-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATES

   --THIS_STRING_SEPARATES
   Content-Type: video/example
   Content-Range: exampleunit 1.2-4.3/25

   ...первый диапазон...
   --THIS_STRING_SEPARATES
   Content-Type: video/example
   Content-Range: exampleunit 11.2-14.3/25

   ...второй диапазон
   --THIS_STRING_SEPARATES--

Приведённые ниже сведения служат регистрационной формой типа носителя multipart/byteranges.

   Type name:  multipart
   Subtype name:  byteranges
   Required parameters:  boundary
   Optional parameters:  N/A
   Encoding considerations:  only "7bit", "8bit", or "binary" are permitted
   Security considerations:  see Section 17
   Interoperability considerations:  N/A
   Published specification:  RFC 9110 (see Section 14.6)
   Applications that use this media type:  HTTP components supporting
      multiple ranges in a single request
   Fragment identifier considerations:  N/A
   Additional information:  Deprecated alias names for this type:  N/A
                            Magic number(s):  N/A
                            File extension(s):  N/A
                            Macintosh file type code(s):  N/A
   Person and email address to contact for further information:  See Aut
      hors' Addresses section.
   Intended usage:  COMMON
   Restrictions on usage:  N/A
   Author:  See Authors' Addresses section.
   Change controller:  IESG

15. Коды статуса

Код статуса в отклике является 3-значным десятичным числом, описывающим результат запроса и семантику отклика, включая сведения об успешности запроса и характере вложенного содержимого (при наличии). Действительные коды статуса имеют значения от 100 до 599, включительно.

Первая цифра кода статуса указывает класс отклика, две оставшиеся не задают категории.

  • 1xx (Informational) — запрос получен, процесс продолжается.

  • 2xx (Successful) — запрос получен, понят и воспринят.

  • 3xx (Redirection) — нужны дополнительные действия для завершения запроса.

  • 4xx (Client Error) — запрос имеет некорректный синтаксис и не может быть выполнен.

  • 5xx (Server Error) — отказ сервера при выполнении запроса, представляющегося действительным.

Коды статуса HTTP могут расширяться. Клиент не обязан понимать смысл всех зарегистрированных кодов статуса, хотя такое понимание желательно. Однако клиент должен понимать класс любого кода, указанный первой цифрой и считать нераспознанные коды эквивалентом кода x00 для этого класса. Например, если клиент получает непонятный код 471, по первой цифре он может понять, что в запросе была какая-то ошибка и считать этот код эквивалентом кода 400 (Bad Request). Отклик обычно включает представление, разъясняющее статус.

Значения за пределами диапазона 100 — 599 недействительны. Реализации часто используют такие значения (600- 999) для внутренней передачи статуса, не связанного с HTTP (например, ошибки библиотеки). Клиенту, получившему отклик с таким кодом следует обрабатывать его как отклик с кодом 5xx (Server Error).

На запрос может возвращаться несколько связанных откликов — промежуточные (interim, не окончательный) отклики с кодами 1xx, за которыми следует один окончательный (final) отклик с кодом статуса из другого диапазона.

15.1. Обзор кодов статуса

Ниже описаны коды статуса, определённые этой спецификацией. Приведённые здесь фразы причин в кодах являются лишь рекомендациями и могут быть заменены локальными эквивалентами и даже опущены без ущерба для протокола.

Отклики с кодами, которые определены как эвристически кэшируемые (например, 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501 в данной спецификации) могут повторно применяться кэшем с эвристическим сроком действия, если иное не задано в определении метода или в элементах явного управления кэшем [CACHING]. Остальные коды статуса не являются эвристически кэшируемыми.

Для использования в HTTP могут быть заданы дополнительные коды статуса, выходящие за рамки этой спецификации. Все коды статуса должны регистрироваться в реестре Hypertext Transfer Protocol (HTTP) Status Code Registry, как описано в параграфе 16.2.

15.2. Информационные коды (1xx)

Коды статуса 1xx (Informational) указывают промежуточный отклик для передачи сведений о состоянии соединения или обработки запроса до завершения запрошенного действия и передачи окончательного отклика. Поскольку в HTTP/1.0 коды статуса 1xx не определены, серверу недопустимо передавать отклики 1xx клиенту HTTP/1.0.

Отклик 1xx завершается концом раздела заголовков и не может включать содержимого или трейлеров.

Клиент должен быть способен обработать один или несколько откликов 1xx до получения финального отклика. Агент пользователя может игнорировать неожиданные отклики 1xx.

Прокси должен пересылать отклики 1xx, если только он сам не запросил его генерацию. Например, если прокси добавляет поле заголовка Expect: 100-continue при пересылке запроса, ему не следует пересылать соответствующие отклики 100 (Continue).

15.2.1. 100 Continue

Код статуса 100 (Continue) указывает, что начальная часть запроса получена и ещё не отвергнута сервером. Сервер намерен передать финальный отклик после приёма и обработки запроса полностью.

Если запрос включает поле заголовка Expect с ожиданием 100-continue, код отклика 100 указывает, что сервер желает получить содержимое запроса, как указано в параграфе 10.1.1. Клиент должен продолжить отправку запроса и отбросить отклик 100. Если в запросе нет поля Expect с ожиданием 100-continue, клиент может просто отбросить этот промежуточный отклик.

15.2.2. 101 Switching Protocols

Код 101 (Switching Protocols) указывает, что сервер понимает и готов выполнить запрос клиента через поле заголовка Upgrade (параграф 7.8) для смены прикладного протокола, используемого в этом соединении. Сервер должен генерировать в отклике поле заголовка Upgrade, указывающие протокол(ы), который будет действовать после этого отклика. Предполагается, что сервер будет соглашаться на смену протокола лишь в том случае получения выигрыша. Например, переход на более новую версию HTTP может давать выигрыш, а переход на синхронный протокол, работающий в реальном масштабе времени, может быть выгоден при доставке ресурсов, имеющих такие свойства.

15.3. Успешное выполнение (2xx)

Класс кодов 2xx (Successful) показывает, что запрос клиента успешно получен, понят и воспринят.

15.3.1. 200 OK

Код статуса 200 (OK) указывает, что запрос был успешно выполнен. Содержимое отклика 200 зависит от метода запроса. Для заданных этой спецификацией методов предполагаемый смысл содержимого указан в таблице 6.

Таблица .

 

Метод запроса

Представление содержимого отклика

GET

Целевой ресурс

HEAD

Целевой ресурс, как для GET, но без передачи данных представления

POST

Статус или результаты действия

PUT, DELETE

Статус действия

OPTIONS

Коммуникационные опции для целевого ресурса

TRACE

Запросное сообщение, полученное сервером, возвращающим трассировку

 

Кроме случая CONNECT, предполагается, что отклик 200 будет включать содержимое сообщения, если в обрамлении того не указан явно нулевой размер содержимого. Если тот или иной аспект запроса указывает предпочтительность отсутствия содержимого при успехе, сервер-источник должен передавать взамен отклик 204 (No Content). Для CONNECT отклик не имеет содержимого, поскольку успешным результатом является туннель, который начинается сразу после раздела заголовков отклика 200.

Отклик 200 является эвристически кэшируемым, т. е. кэшируется, если иное не указано определением метода или явным элементом управления кэшем (см. параграф 4.2.2 в [CACHING]).

В откликах 200 на GET или HEAD серверу-источнику следует передавать любые доступные поля валидаторов (параграф 8.8) для выбранного представления, но предпочтительны строгий тег сущности и дата Last-Modified. В откликах 200 для методов, меняющих состояние, любые поля валидаторов (параграф 8.8) в отклике передают текущие валидаторы для нового представления, созданного в результате успешного применения семантики запроса. С методом PUT (параграф 9.3.4) связаны дополнительные требования, которые могут исключать отправку валидаторов.

15.3.2. 201 Created

Код 201 (Created) указывает, что запрос был выполнен и в результате создан один или несколько новых ресурсов. Основной ресурс, созданный запросом, указывается полем Location в отклике или URI цели, если Location не получено.

Отклик с кодом 201 обычно содержит описание и ссылки на созданные ресурсы. Любые поля валидаторов (параграф 8.8) в отклике содержат текущие валидаторы нового представления, созданного запросом. Отметим, что с методом PUT (параграф 9.3.4) связаны дополнительные требования, которые могут исключать отправку таких валидаторов.

15.3.3. 202 Accepted

Код 202 (Accepted) указывает, что запрос был принят для обработки, но та не была завершена. Запрос может быть выполнен или не выполнен, поскольку при обработке в любой момент возможен запрет. В HTTP нет возможности повторно передать код статуса при асинхронной операции.

Отклик 202 намеренно неполон и его цель заключается в том, чтобы позволить серверу воспринять запрос на выполнение какого-либо иного процесса (возможно, пакетной обработки, выполняемой 1 раз в день) не требуя сохранять соединение с агентом пользователя до момента завершения этого процесса. Передаваемое с этим откликом представление должно описывать текущий статус запроса и указывать (или включать в себя) средство отслеживания состояния, которое может предоставить пользователю оценку времени завершения выполнения запроса.

15.3.4. 203 Non-Authoritative Information

Код 203 (Non-Authoritative Information) указывает, что запрос был успешным, но вложенное содержимое изменено по сравнению с исходным откликом 200 (OK) от сервера-источника преобразующим прокси (параграф 7.7). Этот код позволяет прокси уведомить получателей при выполнении преобразований, поскольку это может влиять на последующие решения, связанные с содержимым. Например, будущие запросы проверки кэша для содержимого могут быть применимы лишь для того же пути запроса (через те же прокси).

Отклик 203 является эвристически кэшируемым, т. е. кэшируется, если иное не указано определением метода или явным элементом управления кэшем (см. параграф 4.2.2 в [CACHING]).

15.3.5. 204 No Content

Код 204 (No Content) указывает, что сервер выполнил запрос и для передачи в отклике нет дополнительного содержимого. Метаданные в полях заголовка отклика относятся к целевому ресурсу и выбранному представлению после применения запрошенного действия. Например, код статуса 204 в отклике с полем ETag на запрос PUT говорит о выполнении метода PUT и указании в поле ETag тега сущности для нового представления этого целевого ресурса.

Отклик 204 позволяет серверу сообщить об успешном применении действия к целевому ресурсу. При этом подразумевается, что агенту пользователя не требуется выходить из текущего просмотра документа (если он есть). Сервер предполагает, что пользовательский агент обеспечит пользователю индикацию успеха в соответствии со своим интерфейсом и применит новые или обновлённые метаданные из отклика к активному представлению. Например, код 204 широко применяется с действием сохранения (save), в результате чего сохранённый документ остаётся доступным пользователю для редактирования. Этот код также часто применяется в интерфейсах, предполагающих преобладание автоматической передачи данных, таких как распределенные системы контроля версий.

Отклик 204 завершается в конце раздела заголовков и не включает содержимого и трейлеров.

Отклик 204 является эвристически кэшируемым, т. е. кэшируется, если иное не указано определением метода или явным элементом управления кэшем (см. параграф 4.2.2 в [CACHING]).

15.3.6. 205 Reset Content

Код 205 (Reset Content) указывает, что сервер выполнил запрос и хочет, чтобы агент пользователя сбросил «представление документа», вызвавшее передачу запроса, в исходное состояние, полученное от сервера-источника. Этот код предназначен для поддержки распространённого случая ввода данных, где пользователь получает содержимое, поддерживающее ввод данных (форма, блокнот, холст и т. п.), вводит или изменяет данные в этом пространстве, отправляет введённые данные в запросе, а затем механизм ввода данных сбрасывается для ввода следующей записи, чтобы пользователь мог продолжить работу по вводу. Поскольку отклик 205 подразумевает отсутствие дополнительного содержимого, серверу недопустимо генерировать содержимое для откликов 205.

15.3.7. 206 Partial Content

Код статуса 206 (Partial Content) указывает, что сервер успешно выполнил запрос диапазона для целевого ресурса, передавая одну или несколько частей выбранного представления. Сервер, поддерживающий запросы диапазона (раздел 14), обычно будет пытаться удовлетворить всем запрошенным диапазонам, поскольку отправка меньшего объёма данных, скорей всего, приведёт к другому запросу клиента на оставшуюся часть. Однако сервер может отправить лишь часть запрошенных данных по своим внутренним причинам, таким как временная недоступность, эффективность кэша, распределение нагрузки и т. п. Поскольку отклик 206 описывает себя, клиент все равно способен понять, что выполнена лишь часть запроса диапазона.

Клиент должен проверить в отклике 206 поля Content-Type и Content-Range для определения вложенных частей и необходимости дополнительных запросов.

Сервер, генерирующий отклик 206, должен в дополнение к полям, указанным в последующих параграфах, создавать поля Date, Cache-Control, ETag, Expires, Content-Location, Vary, если бы они были в отклике 200 (OK) на тот же запрос.

Поле заголовка Content-Length в отклике 206 указывает число октетов содержимого в сообщении, которое обычно отличается от полного размера выбранного представления. Каждое поле Content-Range включает сведения о полном размере выбранного представления.

Отправителю, создающему отклик 206 на запрос с полем заголовка If-Range, не следует генерировать поля заголовка сверх требуемых, поскольку у клиента уже есть предыдущий отклик с этими полями. В иных случаях отправитель должен генерировать все поля заголовка представления, которые были бы в отклике 200 (OK) на тот же запрос.

Отклик 206 является эвристически кэшируемым, т. е. кэшируется, если иное не указано явным элементом управления кэшем (см. параграф 4.2.2 в [CACHING]).

15.3.7.1. Одна часть

Если передаётся одна часть, сервер, создающий отклик 206, должен генерировать поле заголовка Content-Range, описывающее, в каком диапазоне заключено выбранное представление, и содержимое этого диапазона. Например,

   HTTP/1.1 206 Partial Content
   Date: Wed, 15 Nov 1995 06:25:24 GMT
   Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
   Content-Range: bytes 21010-47021/47022
   Content-Length: 26012
   Content-Type: image/gif

   ... 26012 байтов данных части изображения ...
15.3.7.2. Несколько частей

При передаче нескольких частей сервер, создающий отклик 206, должен генерировать содержимое типа multipart/byteranges, как указано в параграфе 14.6, и поле заголовка Content-Type, указывающее тип носителя multipart/byteranges и требуемый параметр границы. Для предотвращения путаницы с откликами с одной частью серверу недопустимо генерировать поле заголовка Content-Range в разделе заголовков HTTP отклика с несколькими частями (это поле передаётся в каждой части).

В области заголовка каждой части тела сервер должен создать поле Content-Range, соответствующее диапазону, включённому в эту часть тела. Если выбранное представление имело бы поле заголовка Content-Type в отклике 200 (OK), серверу следует использовать то же поле заголовка Content-Type в области заголовка каждой части. Например,

   HTTP/1.1 206 Partial Content
   Date: Wed, 15 Nov 1995 06:25:24 GMT
   Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
   Content-Length: 1741
   Content-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATES

   --THIS_STRING_SEPARATES
   Content-Type: application/pdf
   Content-Range: bytes 500-999/8000

   ... первый диапазон ...
   --THIS_STRING_SEPARATES
   Content-Type: application/pdf
   Content-Range: bytes 7000-7999/8000

   ... второй диапазон
   --THIS_STRING_SEPARATES--

При запросе нескольких диапазонов сервер может объединить диапазоны, которые перекрываются или разделены зазором меньшим, чем издержки на передачу нескольких частей, независимо от порядка указания соответствующих range-spec в поле заголовка Range. Поскольку типичные издержки на разделение частей в multipart/byteranges составляют около 80 байтов, в зависимости от типа носителя для выбранного представления и выбранного граничного параметра передача множества мелких разделённых частей может оказаться менее эффективной, нежели передача всего выбранного представления.

Серверу недопустимо создавать многокомпонентный отклик на запрос одного диапазона, поскольку клиент, не запрашивающий несколько частей, может не поддерживать многокомпонентные отклики. Однако сервер может генерировать отклик multipart/byteranges с единственной частью в теле, если запрошено несколько диапазонов и лишь один был сочтён удовлетворительным или лишь один остался после слияния. Клиенту, не способному обрабатывать отклик multipart/byteranges, недопустимо генерировать запросы с несколькими диапазонами.

Серверу, создающему многокомпонентный отклик, следует передавать его части в том же порядке, в каком соответствующие range-spec указаны в принятом поле заголовка Range, исключая диапазоны, сочтённые неудовлетворительными или включённые в другие диапазоны. Получивший многокомпонентный отклик клиент должен проверить поле заголовка Content-Range в каждой части тела сообщения для определения содержащейся в нем части представления, не полагаясь на то, что они переданы для тех же диапазонов и в том же порядке, как было в запросе.

15.3.7.3. Объединение частей

Отклик может передавать лишь поддиапазон представления, если соединение закрылось преждевременно или в запросе была спецификация Range. После нескольких таких передач у клиента может быть несколько принятых диапазонов одного представления. Эти диапазоны можно безопасно объединить лишь в случае наличия у каждого из них одного и того же строгого валидатора (параграф 8.8.1). Клиент, получивший несколько частичных откликов на запросы GET для целевого ресурса, может объединить отклики в один непрерывный диапазон, если они имеют общий строгий валидатор. Если последним получен неполный отклик 200 (OK), поля заголовка из него применяются для объединённого отклика, заменяя соответствующие значения сохранённых частичных откликов. Если последним получен отклик 206 (Partial Content) и хотя бы один из соответствующих сохранённых откликов имеет код 200 (OK), поля заголовка комбинированного отклика являются полями последнего отклика 200. Если все соответствующие сохранённые отклики имеют код 206, в комбинированном отклике используются последние поля заголовка, но клиент должен использовать другие поля заголовка (помимо взятых из Content-Range), предоставленные в новом отклике, для замены всех экземпляров соответствующих полей в сохранённом отклике.

Содержимым комбинированного отклика является объединение частичных диапазонов содержимого из нового отклика и всех соответствующих сохранённых откликов. Если объединение образует весь диапазон представления, клиент должен обработать комбинированный отклик, как будто он является полным откликом 200 (OK), включая поле заголовка Content-Length, отражающее полный размер. В ином случае клиент должен обработать набор непрерывных диапазонов как неполный отклик 200 (OK), если комбинированный отклик является префиксом представления, один отклик 206 (Partial Content) с содержимым multipart/byteranges или несколько откликов 206 (Partial Content), каждый из которых содержит непрерывный диапазон, указанный поле заголовка Content-Range.

15.4. Перенаправление (3xx)

Класс кодов статуса 3xx (Redirection) указывает необходимость дополнительных действий со стороны пользовательского агента для выполнения запроса. Имеется несколько типов перенаправления.

  1. Указание на доступность ресурса по другому URI, указанному в поле заголовка Location с кодом статуса 301 (Moved Permanently), 302 (Found), 307 (Temporary Redirect) или 308 (Permanent Redirect).

  2. Предложение выбрать из числа подходящих ресурсов, обеспечивающих представление данного ресурса в отклике с кодом 300 (Multiple Choices).

  3. Перенаправление на ресурс, указанный полем заголовка Location, который может предоставить непрямой отклик на запрос, в отклике с кодом 303 (See Other).

  4. Перенаправление на сохранённый ранее результат с отклике с кодом 304 (Not Modified).

Примечание. В HTTP/1.0 коды статуса 301 (Moved Permanently) и 302 (Found) исходно были определены как сохраняющие метод ([HTTP/1.0], параграф 9.3) для соответствия их реализации в CERN. Отклик 303 (See Other) был определён для перенаправления со сменой метода на GET. Однако ранние пользовательские агенты разошлись в части перенаправления запросов POST как POST (соответствует данной спецификации) или GET (более безопасный вариант при перенаправлении на другой сайт). В конце концов практика свелась к смене метода на GET. Отклики 307 (Temporary Redirect) и 308 (Permanent Redirect) [RFC7538] были добавлены позднее для однозначного указания перенаправлений с сохранением метода, а коды 301 и 302 были скорректированы, чтобы разрешить перенаправление запросов POST на GET.

Если представлено поле заголовка Location (параграф 10.2.2), агент пользователя может автоматически перенаправить запрос на URI из значения поля Location даже в случаях, когда конкретный код статуса не понятен. Автоматическое перенаправление должно выполняться осторожно для методов, о безопасности которых не известно, как указано в параграфе 9.2.1, поскольку пользователь может не захотеть перенаправлять небезопасный запрос.

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

  1. URI цели заменяется на URI из поля Location в отклике о перенаправлении после его преобразования по отношению к URI цели в исходном запросе.

  2. Удаляются поля заголовка, автоматически созданные реализацией, с заменой обновлёнными значениями, подходящими для нового запроса:

    1. специфичные для соединения поля заголовка (см. параграф 7.6.1);

    2. поля заголовка, специфичные для настройки прокси у клиента, включая Proxy-Authorization и др.;

    3. специфичные для источника поля заголовка (при наличии), включая Host и др.;

    4. проверка полей заголовка, добавленных кэшем реализации (например, If-None-Match, If-Modified-Since);

    5. специфичные для ресурса поля заголовка, включая Referer, Origin, Authorization, Cookie и др.

  3. Рассматривается удаление полей заголовка, которые не были автоматически созданы реализацией (т. е добавлены в запрос вызывающим контекстом), если это связано с безопасностью. Это включает поля Authorization, Cookie и др.

  4. Изменяется метод запроса в соответствии с семантикой кода перенаправления, если это уместно.

  5. При замене метода на GET или HEAD удаляются специфичные для содержимого поля заголовка, включая Content-Encoding, Content-Language, Content-Location, Content-Type, Content-Length, Digest, Last-Modified и др.

Клиенту следует детектировать циклическое перенаправления (петля) и вмешиваться при их обнаружении.

Примечание. Ранняя версия этой спецификации рекомендовала не более 5 перенаправлений ([RFC2068], параграф 10.3). Разработчики содержимого должны учитывать, что некоторые клиенты могут реализовать такое ограничение.

15.4.1. 300 Multiple Choices

Код 300 (Multiple Choices) говорит, что целевой ресурс имеет более одного представления и у каждого из них есть свой более конкретный идентификатор, а сведения о вариантах предоставляются так, чтобы пользователь (или его агент) мог выбрать предпочтительное представление, перенаправляя свой запрос на один или несколько таких идентификаторов. Иными словами, сервер желает, чтобы агент пользователя начал реактивное согласование для выбора наиболее подходящих представлений с учётом своих потребностей (раздел 12).

Если у сервера есть предпочтительный выбор, ему следует генерировать поле Location с URI предпочтительного выбора. Агент пользователя может использовать значение поля Location для автоматического перенаправления.

Для запросов, отличных от HEAD, серверу следует создавать отклик 300 со списком метаданных представления и ссылками URI, из которых пользователь или его агент выбирает наиболее предпочтительный. Пользовательский агент может сделать выбор из этого списка автоматически, если он понимает представленный тип носителя. Конкретный формат для автоматического выбора эта спецификация не задаёт, поскольку HTTP пытается сохранить ортогональность к определению содержимого. На практике представление обеспечивается в каком-либо легко разбираемом формате, который считается приемлемым для агента пользователя, как определено общим решением, согласованием содержимого или неком общепринятым форматом гипертекста.

Отклик 300 является эвристически кэшируемым, т. е. кэшируется, если иное не указано определением метода или явным элементом управления кэшем (см. параграф 4.2.2 в [CACHING]).

Примечание. В исходом предложении для кода 300 поле заголовка URI определялось как предоставляющее список вариантов представления, что делало его применимым для откликов 200, 300, 406 и передавать в откликах для метода HEAD. Однако малый объем внедрения и разногласия в части синтаксиса привели к тому, что URI и Alternates (последующее предложение) были исключены из спецификации. Можно передать список как значение поля заголовка Link [RFC8288], элементы которого имеют отношение alternate, однако внедрение этого списка порождает проблему «курицы и яйца» (chicken-and-egg).

15.4.2. 301 Moved Permanently

Код 301 (Moved Permanently) показывает, что целевому ресурсу назначено новое постоянное значение URI и во всех будущих ссылках на этот ресурс должен применяться один из вложенных URI. Сервер предполагает, что агент пользователя с возможностью редактирования ссылок может на постоянной основе заменить ссылки на URI цели одной из новых ссылок, переданных сервером. Однако это предложение обычно игнорируется, за исключением случая, когда агент пользователя активно занимается редактированием ссылок (например, при создании содержимого), соединение защищено и сервер-источник является доверенным для редактируемого содержимого.

Серверу следует создавать в отклике поле заголовка Location с предпочтительной ссылкой URI для нового постоянного URI. Агент пользователя может применять значение поля Location для автоматического перенаправления. Содержимое отклика сервера обычно включает короткое гипертекстовое примечание с гиперссылкой на новые URI.

Примечание. По историческим причинам агент пользователя может поменять метод POST на GET для последующего запроса. Если это нежелательно, можно использовать отклик с кодом 308 (Permanent Redirect).

Отклик 301 является эвристически кэшируемым, т. е. кэшируется, если иное не указано определением метода или явным элементом управления кэшем (см. параграф 4.2.2 в [CACHING]).

15.4.3. 302 Found

Код 302 (Found) указывает, что целевой ресурс временно размещён по другому URI. Поскольку перенаправление может быть изменено, клиент должен продолжать использование URI в будущих запросах.

Серверу следует создавать в отклике поле заголовка Location с другой ссылкой URI. Агент пользователя может применять значение поля Location для автоматического перенаправления. Содержимое отклика сервера обычно включает короткое гипертекстовое примечание с гиперссылкой на новые URI.

Примечание. По историческим причинам агент пользователя может поменять метод POST на GET для последующего запроса. Если это нежелательно, можно использовать отклик с кодом 307 (Temporary Redirect).

15.4.4. 303 See Other

Код 303 (See Other) говорит, что сервер перенаправляет агент пользователя на другой ресурс, указанный URI в поле заголовка Location, который должен дать непрямой отклик на исходный запрос. Агент пользователя может выполнить запрос на извлечение по этому URI (GET или HEAD для HTTP), который тоже может быть перенаправлен, и представить конечный результат как ответ на исходный запрос. Отметим, что URI в поле Location не считается эквивалентом URI цели.

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

Отклик 303 на запрос GET указывает, что у сервера-источника нет представления, которое он мог бы передать по протоколу HTTP. Однако значение поля Location указывает ресурс, описывающий целевой ресурс, и запрос извлечения для этого ресурса может дать представление, которое будет полезно получателям, не подразумевая, что оно является представлением исходного целевого ресурса. Отметим, что ответы на вопросы, что может быть представлено, какие представления будут адекватными и что может быть полезным описанием, выходят за рамки HTTP.

За исключением откликов на запросы HEAD, представление отклика 303 должно включать краткое гипертекстовое замечание с гиперссылкой на URI, представленный в поле заголовка Location.

15.4.5. 304 Not Modified

Код статуса 304 (нет изменений) указывает, что был получен условный запрос GET или HEAD, который привёл бы к отклику 200 (OK), если бы проверка условия запроса не давала значение false. Иными словами, серверу нет необходимости передавать представление целевого ресурса, поскольку запрос указывает, что у клиента, сделавшего запрос, уже есть действительное представление. Поэтому сервер перенаправляет клиента на использование сохранённого представления, как будто это содержимое отклика с кодом 200 (OK).

Сервер, создающий отклик 304, должен генерировать какие-либо из указанных ниже полей, как при отправке отклика 200 (OK) на тот же запрос.

  • Content-Location, Date, ETag, Vary.

  • Cache-Control и Expires (см. [CACHING])

Поскольку целью отклика 304 является минимизация передачи информации при наличии у клиента одного или нескольких кэшированных представлений, отправителю не следует генерировать метаданные представления сверх указанных выше, если только эти метаданные не служат для управления обновлением кэша (например, может быть полезно поле Last-Modified, если в отклике нет поля ETag).

Требования к кэшу, получившему отклик 304, определены в параграфе 4.3.4 [CACHING]. Если условный запрос был создан исходящим клиентом, таким как агент пользователя со своим кэшем, передающий условный запрос GET общему прокси, этому прокси следует переслать отклик 304 клиенту.

Отклик 304 завершается концом раздела заголовков и не может включать содержимое или трейлеры.

15.4.6. 305 Use Proxy

Код 305 (Use Proxy) был задан в предыдущей версии спецификации и сейчас отменен (Приложение B к [RFC7231]).

15.4.7. 306 (Unused)

Код 306 был задан в предыдущей версии спецификации, больше не используется и сейчас переведён в резерв.

15.4.8. 307 Temporary Redirect

Код 307 (Temporary Redirect) указывает, что целевой ресурс временно находится на другом URI и агенту пользователя недопустимо менять метод запроса при автоматическом перенаправлении на этот URI. Поскольку перенаправление может измениться со временем, клиент должен продолжать использовать в будущих запросах исходный URI цели.

Серверу следует генерировать в отклике поле заголовка Location со ссылкой для другого URI. Агент пользователя может применять значение поля Location для автоматического перенаправления. Содержимое отклика сервера обычно включает краткое гипертекстовое замечание с гиперссылкой на URI.

15.4.9. 308 Permanent Redirect

Код 308 (Permanent Redirect) говорит, что целевому ресурсу назначен новый постоянный URI и в будущих ссылках на этот ресурс должен применяться один из вложенных URI. Агенту пользователя недопустимо менять метод запроса при автоматическом перенаправлении на этот URI10. Сервер предполагает, что агент пользователя с возможностью редактирования ссылок может на постоянной основе заменить URI цели новыми ссылками, переданными сервером. Однако это предложение обычно игнорируется, за исключением случая, когда агент пользователя активно занимается редактированием ссылок (например, при создании содержимого), соединение защищено и сервер-источник является доверенным для редактируемого содержимого.

Серверу следует создавать в отклике поле заголовка Location с предпочтительной ссылкой URI для нового постоянного URI. Агент пользователя может применять значение поля Location для автоматического перенаправления. Содержимое отклика сервера обычно включает короткое гипертекстовое примечание с гиперссылкой на новые URI.

Отклик 308 является эвристически кэшируемым, т. е. кэшируется, если иное не указано определением метода или явным элементом управления кэшем (см. параграф 4.2.2 в [CACHING]).

Примечание. Этот код значительно моложе (июнь 2014 г.) своих собратьев и его могут распознавать не все. Вопросы внедрения кода рассмотрены в разделе 4 [RFC7538].

15.5. Ошибки клиента (4xx)

Класс кодов статуса 4xx (Client Error) указывает на то, что клиент, по-видимому, допустил ошибку. За исключением откликов на запрос HEAD серверу следует передавать представление, содержащее объяснение ошибочной ситуации и указание её временного или постоянного характера. Эти коды применимы к любому методу запроса. Пользовательским агентам следует выводить содержимое отклика для пользователя.

15.5.1. 400 Bad Request

Код 400 (Bad Request) говорит, что сервер не может или не будет обрабатывать запрос из-за чего-то, представляющегося ошибкой клиента (например, синтаксическая ошибка в запросе, непригодное обрамление сообщения, обманная маршрутизация запроса).

15.5.2. 401 Unauthorized

Код 401 (Unauthorized) указывает, что запрос не был применён из-за отсутствия действительных аутентификационных свидетельств для целевого ресурса. Сервер, генерирующий отклик 401, должен передавать поле заголовка WWW-Authenticate (параграф 11.6.1), содержащее хотя бы один вызов (challenge), применимый к целевому ресурсу.

Если запрос включал аутентификационные свидетельства, отклик 401 говорит, что предоставление полномочий на основании представленных свидетельств отклонено. Агент пользователя может повторить запрос с новым или измененным полем заголовка Authorization (параграф 11.6.2). Если отклик 401 содержит тот же вызов, что и предыдущий отклик, а агент пользователя уже предпринял хотя бы одну попытку аутентификации, агенту следует вывести вложенное представление для пользователя, поскольку обычно оно содержит диагностические сведения.

15.5.3. 402 Payment Required

Код 402 (Payment Required) зарезервирован на будущее.

15.5.4. 403 Forbidden

Код 403 (Forbidden) показывает, что сервер понял запрос, но отказался выполнять его. Сервер, желающий сообщить причину отказа, может указать её в содержимом отклика (если оно имеется).

Если в запросе были указаны свидетельства для аутентификации, это означает, что сервер счёл их недостаточными для предоставления доступа. Клиенту не следует автоматически повторять запрос с теми же свидетельствами, но он может повторить запрос с другими или новыми свидетельствами. Однако запрос может быть отклонён по причинам, не связанным со свидетельствами. Сервер-источник, желающий «скрыть» наличие данного защищённого целевого ресурса, может передать отклик с кодом 404 (Not Found).

15.5.5. 404 Not Found

Код 404 (Not Found) указывает, что сервер-источник не нашёл текущего представления целевого ресурса или не желает раскрывать его наличие. Код 404 не говорит, является отсутствие постоянным или временным. Если у сервера-источника есть основания предполагать постоянное отсутствие (например, с помощью настраиваемых средств) следует передавать код 410 (Gone) вместо 404.

Отклик 404 является эвристически кэшируемым, т. е. кэшируется, если иное не указано определением метода или явным элементом управления кэшем (см. параграф 4.2.2 в [CACHING]).

15.5.6. 405 Method Not Allowed

Код 405 (Method Not Allowed) указывает, что полученный в строке запроса метод известен серверу-источнику, но не поддерживается целевым ресурсом. Сервер-источник должен помещать в отклик 405 поле заголовка Allow со списком методов, поддерживаемых в настоящее время целевым ресурсом.

Отклик 405 является эвристически кэшируемым, т. е. кэшируется, если иное не указано определением метода или явным элементом управления кэшем (см. параграф 4.2.2 в [CACHING]).

15.5.7. 406 Not Acceptable

Код 406 (Not Acceptable) показывает, что у целевого ресурса нет текущего представления, приемлемого для агента пользователя в соответствии с полями упреждающего согласования в заголовке запроса (параграф 12.1), а сервер не желает возвращать принятое по умолчанию представление.

Серверу следует генерировать содержимое, включающее список доступных характеристик представления и соответствующие идентификаторы ресурсов, из которых пользователь или его агент могут наиболее подходящее представление. Агент пользователя может автоматически выбрать наиболее подходящий вариант из списка, однако эта спецификация не задаёт стандарта для такого автоматического выбора, как указано в параграфе 15.4.1.

15.5.8. 407 Proxy Authentication Required

Код 407 (Proxy Authentication Required) похож на 401 (Unauthorized), но указывает, что клиенту необходимо аутентифицироваться для использования прокси с этим запросом. Прокси должен передавать поле заголовка Proxy-Authenticate (параграф 11.7.1) с вызовом (challenge) применимым к этому прокси для запроса. Клиент может повторить запрос с новым или измененным полем заголовка Proxy-Authorization (параграф 11.7.2).

15.5.9. 408 Request Timeout

Код 408 (Request Timeout) указывает, что сервер не получил полного сообщения с запросом в течение времени ожидания. Если у клиента имеется незавершённый запрос, он может повторить его. Если текущее соединение непригодно (например, из-за потери разграничения запросов в HTTP/1.1), будет использовано новое соединение.

15.5.10. 409 Conflict

Код 409 (Conflict) указывает, что запрос не может быть выполнен из-за конфликта с текущим состоянием целевого ресурса. Этот код применяется в ситуациях, когда пользователь может устранить конфликт и подать запрос снова. Серверу следует генерировать содержимое, включающее сведение, достаточные для определения причин конфликта.

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

15.5.11. 410 Gone

Код 410 (Gone) говорит, что доступ к целевому ресурсу на сервере-источнике больше не предоставляется и это состояние, скорей всего, является постоянным. Если сервер-источник не знает или не имеет возможности определить, является ли это состояние постоянным, должен использоваться код 404 (Not Found).

Код 410 предназначен, прежде всего, для помощи в поддержке web уведомляя получателя о том, что ресурс осознанно сделан недоступным и владельцы сервера хотят избавиться от удалённых ссылок на этот ресурс. Такие события обычны для рекламных услуг с ограниченным сроком действия и ресурсов, принадлежащих лицам, больше не связанным с сайтом сервера-источника. Не требуется помечать все постоянно недоступные ресурсы как «ушедшие» или сохранять такую маркировку определённое время — это отдаётся на откуп владельцу сервера.

Отклик 410 является эвристически кэшируемым, т. е. кэшируется, если иное не указано определением метода или явным элементом управления кэшем (см. параграф 4.2.2 в [CACHING]).

15.5.12. 411 Length Required

Код 411 (Length Required) указывает, что сервер отклонил запрос без Content-Length (параграф 8.6). Клиент может повторить запрос, добавив поле заголовка Content-Length, указывающее размер содержимого запроса.

15.5.13. 412 Precondition Failed

Код 412 (Precondition Failed) говорит о невыполнении одного или нескольких условий, заданных в полях заголовка запроса, при проверке на сервере (раздел 13). Этот код в отклике позволяет клиенту задать предварительные условия с учётом текущего состояния ресурса (текущее представление и метаданные) и предотвратить применение метода, когда целевой ресурс находится в неожиданном состоянии.

15.5.14. 413 Content Too Large

Код 413 (Content Too Large) указывает, что сервер отклонил запрос из-за того, что размер его содержимого больше, чем сервер хочет или может обработать. Сервер может прервать запрос, если версия протокола позволяет это. В ином случае сервер может разорвать соединение.

Если условие является временным, серверу следует создать поле заголовка Retry-After, указывающее клиенту, когда можно повторить запрос.

15.5.15. 414 URI Too Long

Код 414 (URI Too Long) говорит об отказе сервера обрабатывать запрос из-за размера URI цели, превышающего поддерживаемый. Это редкое состояние может возникать лишь в случае, когда клиент неправильно преобразовал запрос POST в GET со слишком длинной информацией, клиент попал в петлю перенаправления (например, префикс URI указывает свой суффикс) или сервер подвергается атаке со стороны клиента, пытающегося воспользоваться уязвимостями.

Отклик 414 является эвристически кэшируемым, т. е. кэшируется, если иное не указано определением метода или явным элементом управления кэшем (см. параграф 4.2.2 в [CACHING]).

15.5.16. 415 Unsupported Media Type

Код 415 (Unsupported Media Type) указывает, что сервер-источник отказывается обслуживать запрос из-за того, что формат его содержимого не поддерживается на целевом ресурсе для этого метода. Проблема с форматом может быть связана с указанным в запросе Content-Type или Content-Encoding, либо возникать при прямом просмотре данных. Если проблема вызвана неподдерживаемым кодированием содержимого, в заголовке отклика должно использоваться поле Accept-Encoding (параграф 12.5.3) для указания воспринятых в запросе вариантов кодирования содержимого (при наличии). Если причиной является неподдерживаемый тип носителя, можно использовать в отклике поле заголовка Accept (параграф 12.5.1) для указания воспринятых типов носителя в запросе.

15.5.17. 416 Range Not Satisfiable

Код 416 (Range Not Satisfiable) указывает, что набор диапазонов в поле заголовка Range (параграф 14.2) был отвергнут из-за того, что ни один из них не является удовлетворительным или клиент указал слишком много мелких или перекрывающихся диапазонов (возможная атака на отказ а обслуживании).

Каждая единица диапазона указывает, что требуется для того, чтобы её диапазоны были удовлетворительны. Например, в параграфе 14.1.2 указано, что делает диапазоны байтов удовлетворительными.

Серверу, генерирующему отклик 416 на запрос byte-range, следует создавать поле Content-Range, задающее текущий размер выбранного представления (параграф 14.4). Например,

   HTTP/1.1 416 Range Not Satisfiable
   Date: Fri, 20 Jan 2012 15:41:54 GMT
   Content-Range: bytes */47022

Примечание. Поскольку серверы могут игнорировать Range, многие реализации будут отвечать полным выбранным представлением в отклике 200 (OK). Отчасти это связано с тем, что большинство клиентов готовы получить отклик 200 (OK) для завершения задачи (менее эффективно), отчасти с тем, что клиенты не могут остановить создание запроса с недопустимым диапазоном, пока не получат полное представление. Таким образом, клиенты не могут рассчитывать на получение отклика 416 (Range Not Satisfiable), даже ели это наиболее целесообразно.

15.5.18. 417 Expectation Failed

Код 417 (Expectation Failed) указывает, что ожиданию, заданному полем Expect в заголовке запроса (параграф 10.1.1), не соответствует хотя бы один из входных (inbound) серверов.

15.5.19. 418 (Unused)

В первоапрельском [RFC2324] высмеиваются различные способы злоупотребления HTTP, одним из которых является определение специфичного для приложения кода статуса 418, который применялся в качестве шутки достаточно часто, чтобы стать непригодным для использования в будущем. Поэтому код 418 указан как резервный в реестре IANA HTTP Status Code Registry. Это означает, что в настоящее время код не может быть присвоен какому-либо приложению. Если в будущем возникнут обстоятельства, требующие выделить этот код (например, исчерпание кодов 4NN), он может быть назначен снова.

15.5.20. 421 Misdirected Request

Код 421 (ошибочно направленный запрос) указывает, что запрос был направлен серверу, который не может или не хочет создавать полномочный отклик для URI цели. Сервер-источник (или действующий от его имени шлюз) передаёт код 421 для отклонения целевого URI, не соответствующего источнику, для которого сервер настроен (параграф 4.3.1), или контексту соединения, через которое был получен запрос (параграф 7.4).

Клиент, получивший отклик 421 (Misdirected Request), может повторить запрос, независимо от идемпотентости метода, через другое соединение, например, через свежее соединение с источником целевого ресурса или через альтернативную службу [ALTSVC].

Прокси недопустимо генерировать отклик 421.

15.5.21. 422 Unprocessable Content

Код 422 (Unprocessable Content) указывает, что сервер понимает тип содержимого в запросе (поэтому код 415 (Unsupported Media Type) неуместен) и синтаксис содержимого, но не способен обработать инструкции из запроса. Например, этот код может передаваться, если содержимое XML в запросе содержит корректно сформированные (синтаксически верные), но семантически ошибочные инструкции XML.

15.5.22. 426 Upgrade Required

Код 426 (Upgrade Required) указывает, что сервер отказывается выполнять запрос с использованием текущего протокола, но может сделать это после обновления протокола клиентом. Сервер должен передавать поле Upgrade в отклике 426 для указания требуемого протокола или протоколов (параграф 7.8). Например,

   HTTP/1.1 426 Upgrade Required
   Upgrade: HTTP/3.0
   Connection: Upgrade
   Content-Length: 53
   Content-Type: text/plain

Эта служба требует использования протокола HTTP/3.0.

15.6. Ошибки сервера (5xx)

Класс кодов 5xx (Server Error) указывает, что сервер знает о своей ошибке или неспособности выполнить запрошенный метод. За исключением откликов на запрос HEAD, серверу следует передавать представление с разъяснением ошибки и временный или постоянный характер связанной с ней ситуации. Агенту пользователя следует выводить пользователю любое включённое в отклик содержимое. Коды этого класса применимы к любому методу запроса.

15.6.1. 500 Internal Server Error

Код 500 (Internal Server Error) указывает, что сервер столкнулся с неожиданными условиями, помешавшими выполнить запрос.

15.6.2. 501 Not Implemented

Код 501 (Not Implemented) указывает, что сервер не поддерживает функциональность, требуемую для выполнения запроса. Такой отклик подходит для случаев, когда сервер не распознал метод запроса и не способен поддерживать его для какого-либо ресурса.

Отклик 501 является эвристически кэшируемым, т. е. кэшируется, если иное не указано определением метода или явным элементом управления кэшем (см. параграф 4.2.2 в [CACHING]).

15.6.3. 502 Bad Gateway

Код 502 (Bad Gateway) указывает, что сервер, выступая в качестве шлюза или прокси, получил непригодный отклик от входного (inbound) сервера, к которому он обратился для выполнения запроса.

15.6.4. 503 Service Unavailable

Код 503 (Service Unavailable) говорит, что в данный момент сервер не способен обработать запрос из-за временной перегрузки или планового обслуживания, что будет, вероятно, устранено по истечении некоторого времени. Сервер может передать поле Retry-After (параграф 10.2.3), указывающее клиенту время ожидания до повтора запроса.

Примечание. Наличие кода 503 не означает, что сервер обязан использовать его при перегрузке. Некоторые серверы могут просто отвергать соединение.

15.6.5. 504 Gateway Timeout

Код 504 (Gateway Timeout) указывает, что сервер, выступая в качестве шлюза или прокси, не получил своевременного отклика от сервера восходящего направления, к которому должен был обратиться для выполнения запроса.

15.6.6. 505 HTTP Version Not Supported

Код 505 (HTTP Version Not Supported) говорит, что сервер не поддерживает или отвергает старшую (major) версию HTTP, использованную в запросном сообщении. Сервер указывает невозможность или нежелание завершить запрос, используя ту же старшую версию, которую указал клиент, как описано в параграфе 2.5, иначе, нежели отправкой этого сообщения об ошибке. Серверу следует генерировать для отклика 505 представление, описывающее причину отклика и протоколы, поддерживаемые этим сервером.

16. Расширения HTTP

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

Для независимых от версии расширений рекомендуется избегать зависимости от конкретной версии протокола или интеграции с таковой. При неизбежности этого нужно тщательно продумать функциональную совместимость расширения с разными версиями. Кроме того, в конкретных версиях HTTP могут быть свои точки расширения, такие как транспортное кодирование в HTTP/1.1 (параграф 6.1 в [HTTP/1.1]) и HTTP/2 SETTINGS или типы кадров ([HTTP/2]). Эти точки расширения специфичны для соответствующей версии протокола. Зависящие от версии расширения не могут переопределять или изменять семантику независимых от версии механизмов и точек расширения (например, метода или поля заголовка) без явного разрешения со стороны элемента протокола. Например, такие изменения разрешает метод CONNECT (параграф 9.3.6).

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

16.1. Расширяемость методов

16.1.1. Реестр методов

В реестр IANA Hypertext Transfer Protocol (HTTP) Method Registry (https://www.iana.org/assignments/http-methods) вносятся имена методов. Регистрация метода HTTP должна включать указанные ниже поля.

     Имя метода (раздел 9)
     Безопасный (yes или no, параграф 9.2.1)
     Идемпотентный (yes или no, параграф 9.2.2)
     Указатель на текст спецификации.

Значения выделяются по процедуре IETF Review (параграф 4.8 в [RFC8126]).

16.1.2. Рассмотрение новых методов

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

Синтаксический анализ сообщения (раздел 6) должен быть независимым от семантики методов (за исключением откликов на HEAD), поэтому определения новых методов не могут менять алгоритм синтаксического анализа или запрещать наличие содержимого в запросе или отклике. Определения новых методов могут указывать, что разрешено лишь пустое (размером 0) содержимое, требуя наличия поля заголовка Content-Length со значением 0.

Новые методы не могут использовать специальные формы цели запроса host:port и *, которые разрешены для CONNECT и OPTIONS, соответственно (параграф 7.1). Для URI цели требуется полная форма абсолютного URI, т. е. цель запроса должна передаваться в абсолютной форме или URI будет восстанавливаться из контекста запроса как в других методах.

Определение нового метода должно указывать, является ли метод безопасным (параграф 9.2.1), идемпотентным (параграф 9.2.2), кэшируемым (параграф 9.2.3), какая семантика связана с содержимым запроса (при его наличии) и какие уточнения метод вносит в семантику поля заголовка или кода статуса. Если новый метод является кэшируемым, определение должно указывать, как и при каких условиях в кэше может сохраняться отклик и как такой отклик может использоваться для выполнения последующих запросов. Новый метод должен указывать, является ли он условным (параграф 13.1) и задавать поведение сервера при невыполнении условий (для условных методов). Если новый метод может применяться с семантикой частичных откликов (параграф 14.2), документ должен описывать это.

Примечание. Следует избегать определения методов, имена которых начинаются с M-, поскольку такой префикс может быть неверно истолкован, как имеющий семантику, заданную в [RFC2774].

16.2. Расширяемость кодов статуса

16.2.1. Реестр кодов статуса

В реестр IANA Hypertext Transfer Protocol (HTTP) Status Code Registry (https://www.iana.org/assignments/http-status-codes) вносятся коды статуса для откликов. При регистрации должны указываться приведённые ниже поля.

Код статуса (3 цифры)
Краткое описание
Указатель на текст спецификации.

Значения выделяются по процедуре IETF Review (параграф 4.8 в [RFC8126]).

16.2.2. Рассмотрение новых кодов статуса

Когда требуется выразить семантику отклика, не определяемую имеющимися кодами статуса, могут регистрироваться новые коды. Коды статуса являются базовыми, т. е. потенциально применимыми для любого ресурса, а не просто для отдельного типа носителя, вида ресурса или приложения HTTP. Поэтому предпочтительно регистрировать новые методы в документах, не привязанных к отдельному приложению.

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

В предложениях по новым кодам статуса, ещё не получившим широкого распространения, следует избегать указания конкретных числовых значений кодов, пока не будет чёткого согласия о возможности регистрации кода. Вместо этого в ранних версиях можно использовать обозначение вида 4NN, 3N0 .. 3N9, указывающие класс предлагаемых кодов статуса без преждевременного назначения номера.

Определение нового кода статуса должно разъяснять условия, при которых запрос будет вызвать отклик с таким кодом статуса (например, комбинация полей заголовка и/или методов, а также любые зависимости полей заголовка отклика, такие как обязательные или меняющие семантику поля, уточнение семантики при использовании нового кода).

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

В определении кода финального статуса должно быть указано, является ли отклик эвристически кэшируемым. Следует отметить, что любой отклик с кодом финального статуса может кэшироваться, если он содержит явные сведения о свежести информации. Код статуса, заданный как эвристически кэшируемый, можно кэшировать без явно указанной свежести информации. Определение кода статуса может вносить ограничения для поведения кэша при использовании директивы must-understand (см. [CACHING]).

Определение нового кода статуса должно указывать, имеет ли содержимое какую-либо подразумеваемую связь с идентифицированным ресурсом (параграф 6.4.2).

16.3. Расширяемость полей

Наиболее частым расширениям подвергается набор определений полей заголовков и трейлеров. Новые поля могут определяться так, что, будучи понятыми получателем, они переопределяют или расширяют интерпретацию определённых ранее полей, задают предварительные условия для оценки запроса или уточняют значение откликов.

Однако определение поля не гарантирует его внедрения и распознавания получателями. Большинство полей создаётся с расчётом на возможность безопасного игнорирования (но с пересылкой в нисходящем направлении) не понимающим поле получателем. В иных случаях способность отправителя понять данное поле может указываться предшествующим взаимодействие, возможно, версией протокола или полями, переданными в предшествующих сообщениях, а также использованием конкретного типа носителя. Непосредственная проверка поддержки может быть выполнена с помощью запроса OPTIONS или путём взаимодействия с определенным общеизвестным URI [RFC8615], если такая проверка определена вместе с новым полем.

16.3.1. Реестр имён полей

Реестр Hypertext Transfer Protocol (HTTP) Field Name Registry определяет пространство имён для полей HTTP. Регистрацию поля HTTP может запросить любая сторона. Аспекты добавления полей HTTP рассматриваются в параграфе 16.3.2. Реестр Hypertext Transfer Protocol (HTTP) Field Name Registry доступен по ссылке <https://www.iana.org/assignments/http-fields/>. Запросы на регистрацию выполняются в соответствии с приведёнными ниже инструкциями или путём отправки сообщения в список рассылки ietf-http-wg@w3.org.

Имена полей регистрируются по рекомендации эксперта, назначенного IESG или уполномоченным IESG органом. Поля с постоянным статусом (permanent) регистрируются по процедуре Specification Required ([RFC8126], параграф 4.6).

Запрос на регистрацию должен включать указанные ниже поля.

Field name — имя поля

Имя регистрируемого поля. Имя должно соответствовать синтаксису, заданному в параграфе 5.1, и следует использовать имена, начинающиеся с буквы и включающие только буквы, цифры и символ дефиса (-).

Status — статус

Постоянное (permanent), временное (provisional), отменённое (deprecated), устаревшее (obsoleted).

Specification document(s) — документы со спецификацией

Ссылка на документы, определяющие данное поле, желательно с указанием URI для получения копии. Это поле не требуется, но приветствуется для временных регистраций. Можно также включать указание на раздел документа.

Кроме того, можно включать дополнительное поле.

Comments — комментарии

Дополнительные сведения, например, о зарезервированных записях.

Эксперты, проконсультировавшись с сообществом, могут добавить поля для включения в реестр.

Определённые в стандартах имена полей имеют статус permanent. Другие имена также получают такой статус, если эксперт установит, что они применяются, проконсультировавшись с сообществом. Для других имён следует задавать статус provisional. Эксперты могут удалять временные (provisional) записи после консультации с сообществом, если установлено, что они не применяются. Эксперт может в любой момент сменить временный статус на permanent.

Отметим, что имена могут регистрировать третьи лица (включая экспертов), если эксперт сочтёт, что незарегистрированное имя широко применяется и вряд ли будет зарегистрировано иным путём.

16.3.2. Рассмотрение новых полей

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

  • Условия, при которых может применяться поле, например, только в запросах или откликах, во всех сообщениях, в откликах для определённого метода запроса и т. п.

  • Зависимость семантики поля от контекста, например, использование с определёнными методами запроса или кодами статуса.

  • Область применимости передаваемых сведений. По умолчанию поля применяются только к сообщению, с которым они связаны, но некоторые поля откликов предназначены для применения ко всем представлениям ресурса, самому ресурсу или более широкой области. В спецификациях, расширяющих область действия поля, требуется тщательно учитывать такие аспекты, как согласование содержимого, временной интервал применимости и (в некоторых случаях) работу серверов для нескольких арендаторов (multi-tenant).

  • Условия, при которых посредникам разрешено вставлять, удалять или изменять значение поля.

  • Возможность размещения поля в трейлере (по умолчанию запрещено, см. параграф 6.5.1).

  • Уместность или необходимость указывать имя поля в поле заголовка Connection (параграф 7.6.1).

  • Связанные с полем вопросы безопасности, например, раскрытие связанных с приватностью сведений.

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

  • Уместность включения имени поля в поле заголовка отклика Vary (например, при использовании поля заголовка запроса сервером-источником в алгоритме выбора содержимого, см. параграф 12.5.5).

  • Сохранение поля при его получении в запросе PUT (параграф 9.3.4).

  • Удаление поля при автоматическом перенаправлении запроса в целях безопасности (параграф 15.4).

16.3.2.1. Рассмотрение новых имён полей

Авторам спецификаций, определяющих новые поля, рекомендуется выбирать для полей короткие и описательные имена. Краткость позволяет сократить расход пропускной способности, описательность избавляет от путаницы и захвата (squatting) имён, которые могут иметь широкое применение. С учётом этого рекомендуется выбирать для полей ограниченного применения (например, для одного приложения или варианта использования) имена, включающие такое применение (или сокращение для него) в качестве префикса. Например, если для приложения Foo требуется поле Description, можно использовать имя Foo-Desc. Имя Description было бы слишком общим, а Foo-Description — избыточно длинным.

Хотя синтаксис имён полей определён с возможностью включения любых символов (token), на практике некоторые реализации вносят ограничения на символы в именах полей. Для совместимости в именах новых полей следует ограничиваться буквами, цифрами, а также символами «-» и «.», а начинать имя следует с буквы. Например, символ подчёркивания (_) может вызывать проблемы при передаче через интерфейсы шлюзов, не относящихся к HTTP (параграф 17.10). Имена полей должны избегать префикса X- (см. [BCP178]). Другие префиксы иногда применяются в именах полей HTTP. Например, префикс Accept- используется во многих полях согласования содержимого, а применение префикса Content- описано в параграфе 6.4. Такие префиксы помогают распознать назначение поля и не вызывают автоматической обработки.

16.3.2.2. Рассмотрение новых значений полей

При определении нового поля HTTP важной задачей является задание синтаксиса значений — что следует генерировать отправителю и как получателям следует понимать семантику полученного значения. Авторам рекомендуется (но не требуется) применять для задания синтаксиса значений новых полей правила ABNF из данной спецификации или правила [RFC8941]. Авторам рекомендуется тщательно продумать влияние присутствия нескольких строк поля (параграф 5.3). Поскольку отправители могут по ошибке передавать несколько значений, а посредники и библиотеки HTTP могут автоматически объединять их, этот относится ко всем (даже одиночным) значениям поля. Поэтому авторам рекомендуется разграничивать или кодировать значения с запятыми (например, с помощью правила quoted-string из параграфа 5.6.4, типа данных String из [RFC8941] или специального кодирования поля). Это гарантирует, что запятые в значении поля не будут спутаны с запятыми, разделяющими значения в списке. Например, для поля Content-Type запятые можно размещать лишь внутри кавычек, что обеспечивает надёжный разбор даже при наличии нескольких значений. Значения поля Location являются контр-примером, которому лучше не следовать — поскольку URI могут содержать запятые, невозможно надёжно отличить одно значение с запятой от двух значений через запятую. Авторам полей с единственным (singleton) значением (параграф 5.5) дополнительно рекомендуется документировать поведение при получении сообщения с несколькими элементами (разумным поведением по умолчанию является игнорирование поля, но в некоторых случаях это может оказаться неверным решением).

16.4. Расширяемость схем аутентификации

16.4.1. Реестр схем аутентификации

Реестр Hypertext Transfer Protocol (HTTP) Authentication Scheme Registry (https://www.iana.org/assignments/http-authschemes) указывает пространство имён для схем аутентификации в вызовах и свидетельствах. Регистрация должна включать указанные ниже поля.

Имя схемы аутентификации
Указатель на текст спецификации
Примечания (необязательно)

Значения добавляются в реестр по процедуре IETF Review ([RFC8126], параграф 4.8).

16.4.2. Рассмотрение новых схем аутентификации

Ниже указаны аспекты модели аутентификации HTTP, ограничивающие работу новых схем проверки подлинности.

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

  • Параметр аутентификации realm зарезервирован для задания пространств защиты, как описано в параграфе 11.5. В новых схемах недопустимо использовать параметр не совместимым с этим определением способом.

  • Нотация token68 была введена для совместимости с имеющимися схемами аутентификации и может применяться в вызове или свидетельстве лишь однократно. Поэтому в новых схемах вместо этого должен применяться синтаксис auth-param, поскольку иначе будущие расширения станут невозможными.

  • Синтаксический анализ вызовов и свидетельств задаётся этой спецификацией и не может быть изменён новыми схемами аутентификации. При использовании синтаксиса auth-param все параметры должны поддерживать маркеры (token) и строки в кавычках, а синтаксические ограничения должны задаваться для значений полей после разбора (обработки строк с кавычками). Это требуется для того, чтобы получатель могли использовать базовый синтаксический анализатор, применимый ко всем схемам аутентификации.

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

  • В определениях новых схем должно обращение с неизвестными параметрами расширения. В общем случае правило must-ignore (игнорировать) предпочтительней правила must-understand (нужно понимать), поскольку иначе будут сложно вводить новые параметры при наличии унаследованных получателей. Кроме того, полезно описать правила определения новых параметров (такие как обновление спецификации или использование реестра).

  • В документации к схемам аутентификации должно быть указано, пригодны ли они для аутентификации на сервере-источнике (с использованием WWW-Authenticate) и/или прокси (с использованием Proxy-Authenticate).

  • Свидетельства, передаваемые в поле заголовка Authorization, специфичны для пользовательского агента, поэтому оказывают на кэши HTTP такое же влияние, как директива private для кэш-откликов (параграф 5.2.2.7 в [CACHING]), в рамках запроса, где они появляются. Таким образом, новые схемы, отказавшиеся от передачи свидетельство в поле Authorization (например, за счёт передачи в новом поле заголовка), должны явно запретить кэширование, требуя использовать директивы для откликов из кэша (например, private).

  • Схемы, использующие Authentication-Info, Proxy-Authentication-Info или какое-либо иное поле заголовка, связанное с аутентификацией, должны рассматривать и документировать связанные с этим вопросы безопасности (см. параграф 17.16.4).

16.5. Расширяемость единиц диапазонов

16.5.1. Реестр единиц диапазонов

Реестр IANA HTTP Range Unit Registry (https://www.iana.org/assignments/http-parameters) содержит пространства имён для блоков диапазонов с указанием соответствующих спецификаций. Каждая запись HTTP Range Unit должна включать указанные ниже поля.

Имя
Описание
Указатель на текст спецификации.

Значения добавляются в реестр по процедуре IETF Review ([RFC8126], параграф 4.8).

16.5.2. Рассмотрение новых единиц диапазонов

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

16.6. Расширяемость кодирования содержимого

16.6.1. Реестр кодирования содержимого

Реестр IANA HTTP Content Coding Registry (https://www.iana.org/assignments/http-parameters/) содержит имена кодирования содержимого. Каждая запись реестра должна включать указанные ниже поля.

Имя
Описание
Указатель на текст спецификации.

Именам кодирования содержимого недопустимо пересекаться с именами транспортного кодирования (HTTP Transfer Coding Registry, https://www.iana.org/assignments/http-parameters/), если только эти преобразования не являются идентичными (как в случае кодирования со сжатием, рассмотренного в параграфе 8.4.1).

Значения добавляются в реестр по процедуре IETF Review ([RFC8126], параграф 4.8) и должны соответствовать цели кодирования содержимого, заданной в параграфе 8.4.1.

16.6.2. Рассмотрение новых вариантов кодирования содержимого

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

16.7. Обновление реестра маркеров

Реест Hypertext Transfer Protocol (HTTP) Upgrade Token Registry (https://www.iana.org/assignments/http-upgrade-tokens) содержит пространства имён для маркеров имён протоколов, служащих для идентификации протокола а поле заголовка Upgrade. С каждым зарегистрированным именем протокола связаны контактные данные и может быть связан набор спецификаций, указывающих, как будет обрабатываться соединение после его обновления. Регистрация выполняется по процедуре First Come First Served (параграф 4.4 в [RFC8126]) и указанным ниже правилам.

  1. Однажды зарегистрированный маркер protocol-name сохраняется навсегда.

  2. Регистр символов в protocol-name не учитывается, а имя включается в реестр в соответствии с предпочтениями отправителей.

  3. При регистрации должна быть указана ответственная за регистрацию сторона.

  4. При регистрации должны быть указаны контактные данные.

  5. Регистрация может включать связанные с маркером спецификаций, которые должны быть общедоступными.

  6. В регистрацию следует включать набор ожидаемых пар «протокол-версия», связанных с маркером на момент регистрации.

  7. Ответственная сторона может изменить регистрацию в любой момент. IANA будет вести реестр таких изменений и предоставлять его по запросу.

  8. IESG может поменять ответственную за регистрацию маркера сторону (обычно это происходит лишь при отсутствии возможности связаться с текущим ответственным).

17. Вопросы безопасности

Этот раздел содержит сведения для разработчиков, поставщиков информации и пользователей об известных проблемах безопасности, связанных с семантикой HTTP и использованием протокола для передачи информации через Internet. Связанные с кэшированием вопросы рассмотрены в разделе 7 [CACHING], а вопросы, относящиеся к синтаксису и анализу сообщений HTTP/1.1 — в разделе 11 [HTTP/1.1].

Набор рассмотренных вопросов не является исчерпывающим. Большинство вопросов безопасности, связанных с семантикой HTTP, касается проблем безопасности приложений на стороне сервера (код за интерфейсом HTTP), пользовательских агентов, обрабатывающих полученное по HTTP содержимое или безопасной работы в Internet в целом, а не безопасности самого протокола. Соображения безопасности для URI, являющихся основой работы HTTP, рассмотрены в разделе 7 [URI]. Различные организации поддерживают тематическую информацию и ссылки на современные исследования в сфере безопасности приложений Web (например, [OWASP]).

17.1. Установление полномочий

HTTP полагается на полномочный отклик (authoritative response), который определяется сервером источником (или от его имени), указанным в URI цели, как наиболее приемлемый для запроса с учётом состояния целевого ресурса в момент создания отклика.

При использовании зарегистрированного имени в компоненте authority схема URI http (параграф 4.2.1) полагается на локальную службу распознавания имён, чтобы определить, где можно получить полномочный отклик. Это означает, что атака на таблицу хостов в сети пользователя, кэшированные имена или библиотеки распознавания имён превращается в атаку на установление полномочий URI http. Аналогично, выбор пользователем сервера системы доменных имён (Domain Name Service или DNS) и иерархии серверов, от которых приходят результаты распознавания, может влиять на аутентичность сопоставления с адресами. Защитные расширения DNS (DNS Security Extensions или DNSSEC, [RFC4033]) являются одним из способом повышения достоверности, как и другие механизмы передачи запросов DNS через более защищённые транспортные протоколы.

После получения адреса IP установление полномочности для URI http уязвимо к атакам на маршрутизацию IP.

Схема https (параграф 4.2.2) предназначена для предотвращения (или хотя бы раскрытия) множества возможных атак на установление полномочности, если согласованное соединение защищено, а клиент должным образом проверяет соответствие отождествления сервера компоненту authority в URI цели (параграф 4.3.4). Корректная реализация такой проверки может быть достаточно сложной (см. [Georgiev]).

Полномочия для данного сервера-источника могут быть переданы с помощью расширений протокола, например, [ALTSVC]. Набор серверов, для которых соединение считается полномочным, также может быть изменён с помощью расширений, таких как [RFC8336].

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

К сожалению довести до пользователей сведения о полномочности может быть непросто. Например, фишинг (phishing) представляет собой атаку на восприятие пользователем полномочий, искажённых путём представления похожего имени (brand) в гипертексте, возможно с помощью userinfo, маскирующего компонент authority (см. параграф 4.2.1). Пользовательские агенты могут смягчить влияние фишинговых атак, позволяя пользователю легко проверить URI цели до выполнения действий, заметно выделяя (или отвергая) userinfo (при наличии) и передавая сохранённые свидетельства и cookie, когда ссылающийся документ получен из неизвестного или недоверенного источника.

17.2. Риск, связанный с посредниками

С посредниками HTTP непосредственно связаны атаки в пути (on-path). Компрометация систем, где работают посредники, может вызывать серьёзные проблемы безопасности и приватности. У посредников может быть доступ к связанным с безопасностью сведениям, персональным данным пользователей и организаций, а также к служебной (proprietary) информации, принадлежащей пользователям или поставщикам содержимого. Скомпрометированный посредник, а также посредник, настроенный без учёта соображений безопасности и приватности, может служить для широкого спектра возможных атак. Посредники с общим кэшем особенно уязвимы для атак с отравлением кэша, как описано в разделе 7 [CACHING].

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

Посредники не заслуживают доверия больше, чем люди и правила, в рамках которых они работают. Протокол HTTP не может решить эту проблему.

17.3. Атаки на основе имён путей и файлов

Серверы-источники часто используют свою локальную файловую систему для управления сопоставлениями целевых URI с представлениями ресурсов. Большинство файловых систем не защищены от вредоносных имён путей и файлов, поэтому серверу нужно избегать обращения по именам, имеющим специальное значение в системе, при сопоставлении целевого ресурса с файлами и каталогами. Например, в UNIX, Microsoft Windows и других операционных системах используются две точки (..) в качестве компонента пути, указывающего каталог на один уровень выше текущего, а также применяются имена путей и файлов для передачи данных системным устройствам. Похожие соглашения об именовании могут применяться и в других типах систем хранения. В локальных системах хранения имеется неприятная тенденция отдавать предпочтение удобству пользователя в ущерб безопасности при обработке недопустимых и неожиданных символов, перекомпоновке разложенных символов и нормализации регистра в именах, не принимающих регистр во внимание. Атаки, основанные на специальных именах, обычно нацелены на отказ в обслуживании (например, запросить у сервера чтение из порта COM) или раскрытие файлов конфигурации или исходных кодов, доступ к которым не предусмотрен.

17.4. Атаки путём внедрения команд, кода или запросов

Серверы-источники часто используют URI для идентификации системных служб, выбора записей базы данных или источника данных. Однако данным, полученным в запросе, нельзя доверять. Атакующий может создать любой из элементов данных запроса (метод, URI цели, поля заголовков, содержимое), поместив в него сведения, которые могут быть ошибочно истолкованы как команда, код или запрос при передаче через вызов команды, интерпретатор языка или интерфейс базы данных. Например, внедрение SQL является распространённой атакой, где часть URI цели или полей заголовка (например, Host, Referer и т. п) содержит язык запросов. Если полученные данные напрямую используются в операторе SELECT, язык запроса может быть интерпретирован как команда базы данных, а не просто строка. Такие уязвимости реализаций встречаются очень часто, несмотря на простоту их предотвращения.

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

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

17.5. Атаки через размер элементов протокола

Поскольку в HTTP используются в основном текстовые поля, ограниченные символами, синтаксические анализаторы часто подвержены атакам, основанным на передаче очень длинных (или очень медленных) потоков данных, особенно в случаях, когда реализация ожидает элемент протокола без предопределённого размера (параграф 2.3).

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

Сервер может отвергнуть сообщение со слишком длинным URI цели (параграф 15.5.15) или слишком большим содержимым запроса (параграф 15.5.14). Для связанных с размерами ограничений расширениями HTTP [RFC6585] были заданы дополнительные коды статуса.

Получатель должны чётко ограничивать процессы обработки других элементов протокола, включая методы запросов, текст откликов со статусом, имена полей, численные значения, размер блоков (chunk) и пр. Отказ от ограничений на обработку может приводить к исполнению произвольного кода в результате переполнения буферов или разрядности и росту уязвимости к DoS-атакам.

17.6. Атаки со сжатием по общему словарю

В некоторых атаках на защищённые протоколы используется различие в размерах при динамическом сжатии для раскрытия конфиденциальных сведений (см., например, [BREACH]). Такие атаки основаны на создании избыточности контролируемого злоумышленником содержимого по сравнению с конфиденциальными данными, при этом алгоритм динамического сжатия, использующий один словарь в обоих случаях, будет давать более эффективное сжатие при совпадении контролируемого атакующим содержимого с частью конфиденциальных данных.

Сообщения HTTP сжимаются разными способами, включая компрессию TLS, кодирование содержимого, транспортное кодирование и другие механизмы, зависящие от расширений или версии.

Наиболее эффективным способом снижения риска является запрет сжатия конфиденциальных данных или строгая изоляция контролируемых атакующим данных от конфиденциальных сведений, чтобы злоумышленники не могли воспользоваться для сжатия тем же словарём. При осторожном проектировании схема сжатия может быть устроена так, что она не будет уязвимой в некоторых вариантах применения, таких как HPACK ([HPACK]).

17.7. Раскрытие персональных сведений

Клиентам часто доступны большие объёмы персональных данных, включая сведения, предоставляемые им для взаимодействия с ресурсами (например, имя пользователя, местоположение, почтовый адрес, пароль, ключи шифрования и т. п.), и данные о просмотре за определённое время (например, история, закладки и т. п.). Реализации должны предотвращать непреднамеренное раскрытие персональных данных.

17.8. Приватность сведений из системного журнала сервера

Сервер может сохранять персональные данные из запросов пользователей в течение некоторого времени, что позволяет выявить характер запросов или интересующие пользователя темы. В частности, сведения из системного журнала посредника часто содержит историю взаимодействий пользовательских агентов с множеством сайтов и из неё можно извлечь сведения об отдельных пользователях.

Журнальная информация HTTP конфиденциальна по своей природе и её обработка зачастую регулируется законами и нормативными актами. Данные журналов нужно хранить в защищённом месте, а при их анализе нужно соблюдать соответствующие правила. Анонимизация персональных данных в отдельных записях помогает, но обычно её недостаточно для предотвращения трассировки файлов для повторной идентификации на основе сопоставления с другими характеристиками доступа. Поэтому трассировки доступа с привязкой к конкретным клиентам небезопасно публиковать даже при использовании псевдонимов.

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

17.9. Раскрытие данных в URI

URI предназначены для совместного использования без защиты, даже если они указывают защищённые ресурсы. URI часто отображаются на экранах, добавляются в шаблоны при печати страниц, сохраняются в закладках без защиты. Многие серверы, прокси и пользовательские агенты записывают в системный журнал или отображают URI без защиты от доступа посторонних. Поэтому не следует включать в URI сведения, которые могут быть конфиденциальными, приватными или опасными для раскрытия.

При использовании приложением на стороне клиента механизмов создания URI цели по предоставленным пользователем данным, таким как поля запроса из формы с методом GET, возможно включение в URI сведений, раскрывать которые не следует. В таких случаях часто предпочтительней использовать POST, поскольку для него URI обычно не создаётся, а данные передаются в содержимом запроса. Однако это мешает кэшированию и использует небезопасный метод для запроса, который иначе был бы безопасным. Другой вариант включает преобразование данных от пользователя до создания URI или фильтрация таких данных с сохранением лишь сведений, не являющихся конфиденциальными. Аналогичным образом перенаправление результата запроса на другой URI (созданный сервером) может удалить конфиденциальные сведения из последующих передач и обеспечить кэшируемость данных.

Поскольку поле Referer говорит целевому сайту о контексте, в котором сделан запрос, оно может раскрывать сведения о ближайшей истории просмотров пользователя, а также персональные данные из URI ссылающегося ресурса. Ограничения для поля заголовка Referer, указанные в параграфе 10.1.3, учитывают некоторые аспекты безопасности.

17.10. Обработка имён полей приложениями

Для обработки полученных запросов и формирования содержимого откликов серверы часто используют интерфейсы и схемы шлюзов, не относящихся к HTTP. По историческим причинам такие интерфейсы часто перелают полученные имена полей как имена внешних переменных, используя подходящее для среды сопоставление имён. Например, отображение общего интерфейса шлюзов (Common Gateway Interface или CGI) для связанных с протоколом метапеременных, описанное в параграфе 4.1.18 [RFC3875], применяется к полученным именам полей, которые не соответствуют ни одной из стандартных переменных CGI — к каждому такому имени поля добавляется префикс HTTP_, а все символы дефиса (-) заменяются символами подчёркивания (_). Такое сопоставление было унаследовано многими другими прикладными схемами для упрощения переноса приложений с одной платформы на другую. В CGI полученное поле Content-Length передаётся как метапеременная CONTENT_LENGTH со строковым значением, соответствующим значению принятого поля. Полученное поле Content_Length будет передаваться как связанная с протоколом метапеременная HTTP_CONTENT_LENGTH, что может приводить к путанице, если приложение ошибочно прочитает связанную с протоколом метапеременную вместо стандартной переменной (именно поэтому в параграфе 16.3.2.1 рекомендуется не создавать новых полей с символом подчёркивания).

К сожалению сопоставление имён полей с именами другого интерфейса может приводить к серьёзным уязвимостям, если это сопоставление неполно или неоднозначно. Например, если злоумышленник передаёт поле с именем Transfer_Encoding, наивный интерфейс может отобразить его в ту же переменную, что и поле с именем Transfer-Encoding, что приведёт к возможности контрабанды запросов (параграф 11.2 в [HTTP/1.1]). Для снижения связанных с этим рисков реализациям, выполняющим отображения рекомендуется делать их однозначными и полными для всего диапазона октетов, возможных в имени (включая нерекомендуемые и запрещённые в грамматике HTTP). Например, поле с необычным символом в имени может приводить к блокированию запроса, удалению соответствующего поля или передаче имени с другим суффиксом, чтобы отличить его от остальных полей.

17.11. Раскрытие фрагмента после перенаправления

Хотя идентификаторы фрагментов в ссылках URI не передаются в запросах, разработчики должны понимать, что их будет видеть агент пользователя и любые расширения и сценарии, запускаемыми в результате отклика. В частности, при перенаправлении с наследованием идентификатора фрагмента из исходного запроса в новой ссылке в Location (параграф 10.2.2) фрагмент одного сайта может раскрываться другому сайту. Если первый сайт использует во фрагментах персональные данные, он должен гарантировать включение в перенаправления на другие сайты идентификатора фрагмента (возможно, пустого) для блокировки такого наследования.

17.12. Раскрытие сведений о продукции

Поля заголовка User-Agent (параграф 10.1.5), Via (параграф 7.6.3) и Server (параграф 10.2.4) часто раскрывают сведения о соответствующих программных системах отправителя. В теории это может упростить злоумышленникам использование известных уязвимостей, но на практике атакующие обычно пытаются воспользоваться всеми уязвимостями независимо от фактически используемых версий.

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

17.13. Отпечатки браузеров

Отпечатки (fingerprint) браузера — это набор методов для идентификации с течением времени конкретного пользовательского агента по его уникальному набору характеристик. Эти характеристики могут включать сведения об использовании базового транспортного протокола, функциональных возможностях и среде сценариев, но особый интерес представляют уникальные характеристики, которые могут передаваться по протоколу HTTP. Отпечатки связаны с приватностью, поскольку они позволяют отслеживать поведение агента пользователя в течение определённого времени ([Bujlow]) без соответствующего контроля, который может быть у пользователя для других форм сбора данных (например, cookie). Многие пользовательские агенты общего назначения (Web-браузеры) имеют средства сокращения своих отпечатков.

Имеется ряд полей заголовков запроса, которые могут передавать серверам достаточно уникальные сведения, позволяющие отслеживать отпечатки. Поле заголовка From наиболее очевидно, хотя его передача предполагается лишь при желании пользователя указать себя. Поля заголовка Cookie намеренно предназначены для возможности повторной идентификации, поэтому проблемы с отпечатками возникают лишь в ситуациях, когда cookie отключены или ограничены конфигурацией агента пользователя. Поле User-Agent может включать сведения, достаточные для однозначной идентификации конкретного устройства, обычно в сочетании с другими характеристиками, особенно при передаче пользовательским агентом избыточных сведений о системе пользователя или расширениях. Однако упреждающее согласование (параграф 12.1) является источником уникальных сведений, которые меньше всего ожидает пользователь, включая поля заголовка Accept, Accept-Charset, Accept-Encoding, Accept-Language.

Помимо отпечатка, детали поля Accept-Language могут раскрывать сведения, которые пользователь считает приватными. Например, понимание данного языка может быть строго сопоставлено с принадлежностью к определённой этнической группе. Подход к ограничению такого раскрытия состоит в отказе агента пользователя от передачи поля Accept-Language за исключением сайтов, для которых это явно разрешено, возможно, через взаимодействие после обнаружения поля Vary, указывающего, что согласование языка может быть полезным.

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

17.14. Сохранение валидатора

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

Тег сущности может злонамеренно применяться для создания рисков приватности. Например, сайт может намеренно создать семантически непригодный тег сущности, уникальный для пользователя или пользовательского агента, передать его в кэшируемом отклике с продолжительным сроком пригодности (freshness), а затем считывать этот тег в последующих условных запросах как средство повторной идентификации пользователя или пользовательского агента. Такой тег идентификации станет постоянным на время, пока агент пользователя сохраняет исходное кэшированное представление. Пользовательские агенты, кэширующие представления, должны обеспечивать очистку или замену кэша при действиях пользователя по сохранению приватности, таких как очистка сохранённых cookie или переход в приватный режим просмотра.

17.15. DoS-атаки с использованием диапазона

Неограниченные запросы с множеством диапазонов создают риск DoS-атак, поскольку усилия для запроса множества перекрывающихся диапазонов одних данных очень малы по сравнению с затратами времени, памяти и пропускной способности при попытке обслуживания запрошенных данных по частям. Серверы должны игнорировать, объединять или отвергать вопиющие запросы диапазонов, такие как запрос больше двух перекрывающихся диапазонов или множества мелких диапазонов в одном наборе, особенно при запросе диапазонов с нарушением порядка без видимых причин. Запросы с несколькими диапазонами не предназначены для предоставления произвольного доступа.

17.16. Вопросы проверки подлинности

Все, что связано с аутентификацией HTTP, относится к вопросам безопасности, поэтому приведённый ниже список не является исчерпывающим. Кроме того, в него включены лишь вопросы безопасности, связанные с аутентификацией в целом без рассмотрения всех возможных соображений для конкретных схем (они должны быть рассмотрены в спецификациях таких схем). Различные организации поддерживают тематические сведения и ссылки на текущие исследования безопасности Web-приложений (например, [OWASP]), включая основные ошибки при реализации и применении схем проверки подлинности, найденные на практике.

17.16.1. Конфиденциальность свидетельств

Схема аутентификации HTTP не задаёт единого механизма для поддержки конфиденциальности свидетельств и в каждой схеме аутентификации задаётся свой способ кодирования свидетельств перед их отправкой. Это обеспечивает гибкость при разработке схем аутентификации, но недостаточно для защиты имеющихся схем, которые сами не имеют защиты конфиденциальности или недостаточно защищены от атак с воспроизведением (replay). Кроме того при ожидании сервером специфичных для каждого пользователя свидетельств обмен такими свидетельствами приведёт к идентификации пользователей даже без раскрытия содержимого самих свидетельств.

В HTTP конфиденциальность значений передаваемых полей зависит от защитных свойств базового транспортного или сеансового соединения. Для служб, зависящих от аутентификации отдельных пользователей требуется организация защищённого соединения до обмена свидетельствами (параграф 4.2.2).

17.16.2. Свидетельства и бездействующие клиенты

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

  • После длительного бездействия клиента сервер может снова запросить свидетельства для аутентификации.

  • Приложения с индикацией прерывания сессии (например, кнопка logout или commit на странице), после которого серверная сторона узнаёт, что у клиента больше нет причин сохранять свидетельства.

Агентам пользователя, кэширующим свидетельства, настоятельно рекомендуется предоставлять легкодоступный механизм для отбрасывания кэшированных свидетельств под управлением пользователя.

17.16.3. Пространства защиты

Схемы аутентификации, основанные исключительно на механизме realm для создания защищённого пространства, будут раскрывать свидетельства всем ресурсам на сервере-источнике. Клиенты, успешно выполнившие аутентификационные запросы к ресурсу, могут использовать те же аутентификационные свидетельства для других ресурсов сервера-источника. Это позволяет одному ресурсу воспринимать аутентификационные свидетельства других ресурсов. Это особенно важно при размещении на сервере-источнике ресурсов разных сторон (организаций) с одним источником (origin, параграф 11.5). Возможные схемы смягчения проблемы включают ограничение прямого доступа к аутентификационным свидетельствам (недоступность содержимого поля заголовка Authorization в запросе) и разделение пространства защиты путём использования разных имён хостов (или номеров портоа) для каждой стороны.

17.16.4. Дополнительные поля отклика

Добавление сведений в отклики, передаваемые по незащищённому каналу, может влиять на приватность и безопасность. Наличие полей заголовка Authentication-Info и Proxy-Authentication-Info само по себе указывает на применение аутентификации HTTP. Дополнительные сведения могут раскрывать параметры конкретной схемы аутентификации и это должно учитываться при создании таких схем.

18. Взаимодействие с IANA

Контролёр изменений для описанных ниже регистраций является IETF (iesg@ietf.org) — Internet Engineering Task Force.

18.1. Регистрация схем URI

Агентство IANA обновило реестр Uniform Resource Identifier (URI) Schemes [BCP35] (https://www.iana.org/assignments/uri-schemes/) включив в него постоянные (permanent) схемы из таблицы 2 в параграфе 4.2.

18.2. Регистрация методов

Агентство IANA обновило реестр Hypertext Transfer Protocol (HTTP) Method Registry (https://www.iana.org/assignments/http-methods) с процедурой регистрации, указанной в параграфе 16.1.1, и именами методов, указанными в таблице 7.

Таблица .

 

Метод

Безопасный

Идемпотентный

Параграф

CONNECT

нет

нет

9.3.6

DELETE

нет

да

9.3.5

GET

да

да

9.3.1

HEAD

да

да

9.3.2

OPTIONS

да

да

9.3.7

POST

нет

нет

9.3.3

PUT

нет

да

9.3.4

TRACE

да

да

9.3.8

*

нет

нет

18.2

 

Имя метода * является зарезервированным, поскольку применение метода с именем * будет конфликтовать с использованием этого символа как шаблона для некоторых методов (например, Access-Control-Request-Method).

18.3. Регистрация кодов статуса

Агентство IANA обновило реестр Hypertext Transfer Protocol (HTTP) Status Code Registry (https://www.iana.org/assignments/http-status-codes) с процедурой регистрации, указанной в параграфе 16.2.1, и именами методов, указанными в таблице 8.

Таблица .

 

Значение

Описание

Параграф

100

Continue

15.2.1

101

Switching Protocols

15.2.2

200

OK

15.3.1

201

Created

15.3.2

202

Accepted

15.3.3

203

Non-Authoritative Information

15.3.4

204

No Content

15.3.5

205

Reset Content

15.3.6

206

Partial Content

15.3.7

300

Multiple Choices

15.4.1

301

Moved Permanently

15.4.2

302

Found

15.4.3

303

See Other

15.4.4

304

Not Modified

15.4.5

305

Use Proxy

15.4.6

306

(Unused)

15.4.7

307

Temporary Redirect

15.4.8

308

Permanent Redirect

15.4.9

400

Bad Request

15.5.1

401

Unauthorized

15.5.2

402

Payment Required

15.5.3

403

Forbidden

15.5.4

404

Not Found

15.5.5

405

Method Not Allowed

15.5.6

406

Not Acceptable

15.5.7

407

Proxy Authentication Required

15.5.8

408

Request Timeout

15.5.9

409

Conflict

15.5.10

410

Gone

15.5.11

411

Length Required

15.5.12

412

Precondition Failed

15.5.13

413

Content Too Large

15.5.14

414

URI Too Long

15.5.15

415

Unsupported Media Type

15.5.16

416

Range Not Satisfiable

15.5.17

417

Expectation Failed

15.5.18

418

(Unused)

15.5.19

421

Misdirected Request

15.5.20

422

Unprocessable Content

15.5.21

426

Upgrade Required

15.5.22

500

Internal Server Error

15.6.1

501

Not Implemented

15.6.2

502

Bad Gateway

15.6.3

503

Service Unavailable

15.6.4

504

Gateway Timeout

15.6.5

505

HTTP Version Not Supported

15.6.6

 

18.4. Регистрация имён полей

Эта спецификация обновляет связанные с HTTP аспекты имеющихся процедур регистрации для полей заголовков сообщения, определённых в [RFC3864]. Старые процедуры заменены новыми и определения полей HTTP перенесены в отдельный реестр IANA Hypertext Transfer Protocol (HTTP) Field Name Registry, как указано в параграфе 16.3.1. Агентство IANA перенесло все записи из реестров Permanent Message Header Field Names и Provisional Message Header Field Names (https://www.iana.org/assignments/message-headers/) с протоколом http в новый реестр с внесением указанных ниже изменений.

  1. Поле Applicable Protocol исключено.

  2. Записи со статусом standard, experimental, reserved, informational получили статус permanent.

  3. Временные записи без назначенного статуса получили статус provisional.

  4. Постоянные записи без назначенного статуса (после подтверждения его отсутствия в регистрационном документе) получили статус provisional. Эксперты могут принять решение об обновлении таких записей, если есть основания для установки иного статуса.

Агентство IANA анонсировало реестры Permanent Message Header Field Names и Provisional Message Header Field Names с указанным ниже примечанием для указания переноса регистрации имён полей HTTP.

Примечание. Регистрации имён полей HTTP перенесены в https://www.iana.org/assignments/http-fields в соответствии с [RFC9110].

Агентство IANA обновило Hypertext Transfer Protocol (HTTP) Field Name Registry, включив имена полей из таблицы 9.

Таблица .

 

Имя поля

Статус

Параграф

Комментарии

Accept

permanent

12.5.1

Accept-Charset

deprecated

12.5.2

Accept-Encoding

permanent

12.5.3

Accept-Language

permanent

12.5.4

Accept-Ranges

permanent

14.3

Allow

permanent

10.2.1

Authentication-Info

permanent

11.6.3

Authorization

permanent

11.6.2

Connection

permanent

7.6.1

Content-Encoding

permanent

8.4

Content-Language

permanent

8.5

Content-Length

permanent

8.6

Content-Location

permanent

8.7

Content-Range

permanent

14.4

Content-Type

permanent

8.3

Date

permanent

6.6.1

ETag

permanent

8.8.3

Expect

permanent

10.1.1

From

permanent

10.1.2

Host

permanent

7.2

If-Match

permanent

13.1.1

If-Modified-Since

permanent

13.1.3

If-None-Match

permanent

13.1.2

If-Range

permanent

13.1.5

If-Unmodified-Since

permanent

13.1.4

Last-Modified

permanent

8.8.2

Location

permanent

10.2.2

Max-Forwards

permanent

7.6.2

Proxy-Authenticate

permanent

11.7.1

Proxy-Authentication-Info

permanent

11.7.3

Proxy-Authorization

permanent

11.7.2

Range

permanent

14.2

Referer

permanent

10.1.3

Retry-After

permanent

10.2.3

Server

permanent

10.2.4

TE

permanent

10.1.4

Trailer

permanent

6.6.2

Upgrade

permanent

7.8

User-Agent

permanent

10.1.5

Vary

permanent

12.5.5

Via

permanent

7.6.3

WWW-Authenticate

permanent

11.6.1

*

permanent

12.5.5

(резерв)

 

Имя поля * зарезервировано, поскольку использование такого имени для полей заголовков HTTP может вызывать конфликты с особой семантикой поля заголовка Vary (параграф 12.5.5).

Агентство IANA указало запись Content-MD5 в новом реестре как устаревшую (obsoleted) со ссылкой на параграф 14.15 в [RFC2616] (определение поля заголовка) и Приложение B к [RFC7231] (исключение поля из новой спецификации).

18.5. Регистрация схем аутентификации

Агентство IANA обновило реестр Hypertext Transfer Protocol (HTTP) Authentication Scheme Registry (https://www.iana.org/assignments/http-authschemes), указав процедуру регистрации из параграфа 16.4.1. Этот документ не определяет схем аутентификации.

18.6. Регистрация кодирования содержимого

Агентство IANA обновило реестр HTTP Content Coding Registry (https://www.iana.org/assignments/http-parameters/) с указанием процедуры регистрации из параграфа 16.6.1 и именами кодировок, указанными в таблице 10.

Таблица .

 

Имя

Описание

Параграф

compress

Формат данных UNIX compress [Welch]

8.4.1.1

deflate

Сжатые данные deflate ([RFC1951]) внутри формата zlib ([RFC1950])

8.4.1.2

gzip

Формат файлов GZIP [RFC1952]

8.4.1.3

identity

Резерв

12.5.3

x-compress

Отменено (псевдоним для compress)

8.4.1.1

x-gzip

Отменено (псевдоним для gzip)

8.4.1.3

 

18.7. Регистрация Range Unit

Агентство IANA обновило реестр HTTP Range Unit Registry (https://www.iana.org/assignments/http-parameters/) с указанием процедуры регистрации из параграфа 16.5.1 и именами единиц диапазона, указанными в таблице 11.

Таблица .

 

Имя

Описание

Параграф

bytes

Диапазон октетов

14.1.2

none

Зарезервировано как ключевое слово для указания отсутствия поддержки запросов диапазона

14.3

 

18.8. Регистрация типов носителей

Агентство IANA обновило реестр Media Types (https://www.iana.org/assignments/media-types) с указанием сведений о регистрации из параграфа 14.6 для типа носителя multipart/byteranges. Обновлено также примечание о параметрах q с включением ссылки на параграф 12.5.1 этого документа.

18.9. Регистрация портов

Агентство IANA обновило реестр Service Name and Transport Protocol Port Number Registry (https://www.iana.org/assignments/service-names-port-numbers/) для служб на портах 80 и 443 протоколов UDP или TCP

  1. этот документ указан в качестве ссылки (Reference);

  2. для не ещё заданного поля Assignee установлено значение IESG, для Contact — IETF_Chair.

18.10. Регистрация маркера обновления

Агентство IANA обновило реестр Hypertext Transfer Protocol (HTTP) Upgrade Token Registry (https://www.iana.org/assignments/http-upgrade-tokens) с указанием процедуры регистрации из параграфа 16.7 и имени маркера из таблицы 12.

Таблица .

 

Имя

Описание

Ожидаемые маркеры версии

Параграф

HTTP

Hypertext Transfer Protocol

Любое значение DIGIT.DIGIT (например, 2.0)

2.5

 

19. Литература

19.1. Нормативные документы

[CACHING] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «HTTP Caching», STD 98, RFC 9111, DOI 10.17487/RFC9111, June 2022, <https://www.rfc-editor.org/info/rfc9111>.

[RFC1950] Deutsch, P. and J-L. Gailly, «ZLIB Compressed Data Format Specification version 3.3», RFC 1950, DOI 10.17487/RFC1950, May 1996, <https://www.rfc-editor.org/info/rfc1950>.

[RFC1951] Deutsch, P., «DEFLATE Compressed Data Format Specification version 1.3», RFC 1951, DOI 10.17487/RFC1951, May 1996, <https://www.rfc-editor.org/info/rfc1951>.

[RFC1952] Deutsch, P., «GZIP file format specification version 4.3», RFC 1952, DOI 10.17487/RFC1952, May 1996, <https://www.rfc-editor.org/info/rfc1952>.

[RFC2046] Freed, N. and N. Borenstein, «Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types», RFC 2046, DOI 10.17487/RFC2046, November 1996, <https://www.rfc-editor.org/info/rfc2046>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC4647] Phillips, A., Ed. and M. Davis, Ed., «Matching of Language Tags», BCP 47, RFC 4647, DOI 10.17487/RFC4647, September 2006, <https://www.rfc-editor.org/info/rfc4647>.

[RFC4648] Josefsson, S., «The Base16, Base32, and Base64 Data Encodings», RFC 4648, DOI 10.17487/RFC4648, October 2006, <https://www.rfc-editor.org/info/rfc4648>.

[RFC5234] Crocker, D., Ed. and P. Overell, «Augmented BNF for Syntax Specifications: ABNF», STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, <https://www.rfc-editor.org/info/rfc5234>.

[RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, «Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile», RFC 5280, DOI 10.17487/RFC5280, May 2008, <https://www.rfc-editor.org/info/rfc5280>.

[RFC5322] Resnick, P., Ed., «Internet Message Format», RFC 5322, DOI 10.17487/RFC5322, October 2008, <https://www.rfc-editor.org/info/rfc5322>.

[RFC5646] Phillips, A., Ed. and M. Davis, Ed., «Tags for Identifying Languages», BCP 47, RFC 5646, DOI 10.17487/RFC5646, September 2009, <https://www.rfc-editor.org/info/rfc5646>.

[RFC6125] Saint-Andre, P. and J. Hodges, «Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS)», RFC 6125, DOI 10.17487/RFC6125, March 2011, <https://www.rfc-editor.org/info/rfc6125>.

[RFC6365] Hoffman, P. and J. Klensin, «Terminology Used in Internationalization in the IETF», BCP 166, RFC 6365, DOI 10.17487/RFC6365, September 2011, <https://www.rfc-editor.org/info/rfc6365>.

[RFC7405] Kyzivat, P., «Case-Sensitive String Support in ABNF», RFC 7405, DOI 10.17487/RFC7405, December 2014, <https://www.rfc-editor.org/info/rfc7405>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[TCP] Postel, J., «Transmission Control Protocol», STD 7, RFC 793, DOI 10.17487/RFC0793, September 1981, <https://www.rfc-editor.org/info/rfc793>.

[TLS13] Rescorla, E., «The Transport Layer Security (TLS) Protocol Version 1.3», RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.

[URI] Berners-Lee, T., Fielding, R., and L. Masinter, «Uniform Resource Identifier (URI): Generic Syntax», STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, <https://www.rfc-editor.org/info/rfc3986>.

[USASCII] American National Standards Institute, «Coded Character Set — 7-bit American Standard Code for Information Interchange», ANSI X3.4, 1986.

[Welch] Welch, T., «A Technique for High-Performance Data Compression», IEEE Computer 17(6), DOI 10.1109/MC.1984.1659158, June 1984, <https://ieeexplore.ieee.org/document/1659158/>.

19.2. Дополнительная литература

[ALTSVC] Nottingham, M., McManus, P., and J. Reschke, «HTTP Alternative Services», RFC 7838, DOI 10.17487/RFC7838, April 2016, <https://www.rfc-editor.org/info/rfc7838>.

[BCP13] Freed, N. and J. Klensin, «Multipurpose Internet Mail Extensions (MIME) Part Four: Registration Procedures», BCP 13, RFC 4289, December 2005.
Freed, N., Klensin, J., and T. Hansen, «Media Type Specifications and Registration Procedures», BCP 13, RFC 6838, January 2013. <https://www.rfc-editor.org/info/bcp13>

[BCP178] Saint-Andre, P., Crocker, D., and M. Nottingham, «Deprecating the «X-» Prefix and Similar Constructs in Application Protocols», BCP 178, RFC 6648, June 2012. <https://www.rfc-editor.org/info/bcp178>

[BCP35] Thaler, D., Ed., Hansen, T., and T. Hardie, «Guidelines and Registration Procedures for URI Schemes», BCP 35, RFC 7595, June 2015. <https://www.rfc-editor.org/info/bcp35>

[BREACH] Gluck, Y., Harris, N., and A. Prado, «BREACH: Reviving the CRIME Attack», July 2013, <http://breachattack.com/resources/BREACH%20-%20SSL,%20gone%20in%2030%20seconds.pdf>.

[Bujlow] Bujlow, T., Carela-Español, V., Solé-Pareta, J., and P. Barlet-Ros, «A Survey on Web Tracking: Mechanisms, Implications, and Defenses», In Proceedings of the IEEE 105(8), DOI 10.1109/JPROC.2016.2637878, August 2017, <https://doi.org/10.1109/JPROC.2016.2637878>.

[COOKIE] Barth, A., «HTTP State Management Mechanism», RFC 6265, DOI 10.17487/RFC6265, April 2011, <https://www.rfc-editor.org/info/rfc6265>.

[Err1912] RFC Errata, Erratum ID 1912, RFC 2978, <https://www.rfc-editor.org/errata/eid1912>.

[Err5433] RFC Errata, Erratum ID 5433, RFC 2978, <https://www.rfc-editor.org/errata/eid5433>.

[Georgiev] Georgiev, M., Iyengar, S., Jana, S., Anubhai, R., Boneh, D., and V. Shmatikov, «The Most Dangerous Code in the World: Validating SSL Certificates in Non-Browser Software», In Proceedings of the 2012 ACM Conference on Computer and Communications Security (CCS ’12), pp. 38-49, DOI 10.1145/2382196.2382204, October 2012, <https://doi.org/10.1145/2382196.2382204>.

[HPACK] Peon, R. and H. Ruellan, «HPACK: Header Compression for HTTP/2», RFC 7541, DOI 10.17487/RFC7541, May 2015, <https://www.rfc-editor.org/info/rfc7541>.

[HTTP/1.0] Berners-Lee, T., Fielding, R., and H. Frystyk, «Hypertext Transfer Protocol — HTTP/1.0», RFC 1945, DOI 10.17487/RFC1945, May 1996, <https://www.rfc-editor.org/info/rfc1945>.

[HTTP/1.1] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «HTTP/1.1», STD 99, RFC 9112, DOI 10.17487/RFC9112, June 2022, <https://www.rfc-editor.org/info/rfc9112>.

[HTTP/2] Thomson, M., Ed. and C. Benfield, Ed., «HTTP/2», RFC 9113, DOI 10.17487/RFC9113, June 2022, <https://www.rfc-editor.org/info/rfc9113>.

[HTTP/3] Bishop, M., Ed., «HTTP/3», RFC 9114, DOI 10.17487/RFC9114, June 2022, <https://www.rfc-editor.org/info/rfc9114>.

[ISO-8859-1] International Organization for Standardization, «Information technology — 8-bit single-byte coded graphic character sets — Part 1: Latin alphabet No. 1», ISO/IEC 8859-1:1998, 1998.

[Kri2001] Kristol, D., «HTTP Cookies: Standards, Privacy, and Politics», ACM Transactions on Internet Technology 1(2), November 2001, <http://arxiv.org/abs/cs.SE/0105018>.

[OWASP] The Open Web Application Security Project, <https://www.owasp.org/>.

[REST] Fielding, R.T., «Architectural Styles and the Design of Network-based Software Architectures», Doctoral Dissertation, University of California, Irvine, September 2000, <https://roy.gbiv.com/pubs/dissertation/top.htm>.

[RFC1919] Chatel, M., «Classical versus Transparent IP Proxies», RFC 1919, DOI 10.17487/RFC1919, March 1996, <https://www.rfc-editor.org/info/rfc1919>.

[RFC2047] Moore, K., «MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text», RFC 2047, DOI 10.17487/RFC2047, November 1996, <https://www.rfc-editor.org/info/rfc2047>.

[RFC2068] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., and T. Berners-Lee, «Hypertext Transfer Protocol — HTTP/1.1», RFC 2068, DOI 10.17487/RFC2068, January 1997, <https://www.rfc-editor.org/info/rfc2068>.

[RFC2145] Mogul, J. C., Fielding, R., Gettys, J., and H. Frystyk, «Use and Interpretation of HTTP Version Numbers», RFC 2145, DOI 10.17487/RFC2145, May 1997, <https://www.rfc-editor.org/info/rfc2145>.

[RFC2295] Holtman, K. and A. Mutz, «Transparent Content Negotiation in HTTP», RFC 2295, DOI 10.17487/RFC2295, March 1998, <https://www.rfc-editor.org/info/rfc2295>.

[RFC2324] Masinter, L., «Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0)», RFC 2324, DOI 10.17487/RFC2324, 1 April 1998, <https://www.rfc-editor.org/info/rfc2324>.

[RFC2557] Palme, J., Hopmann, A., and N. Shelness, «MIME Encapsulation of Aggregate Documents, such as HTML (MHTML)», RFC 2557, DOI 10.17487/RFC2557, March 1999, <https://www.rfc-editor.org/info/rfc2557>.

[RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, «Hypertext Transfer Protocol — HTTP/1.1», RFC 2616, DOI 10.17487/RFC2616, June 1999, <https://www.rfc-editor.org/info/rfc2616>.

[RFC2617] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S., Leach, P., Luotonen, A., and L. Stewart, «HTTP Authentication: Basic and Digest Access Authentication», RFC 2617, DOI 10.17487/RFC2617, June 1999, <https://www.rfc-editor.org/info/rfc2617>.

[RFC2774] Nielsen, H., Leach, P., and S. Lawrence, «An HTTP Extension Framework», RFC 2774, DOI 10.17487/RFC2774, February 2000, <https://www.rfc-editor.org/info/rfc2774>.

[RFC2818] Rescorla, E., «HTTP Over TLS», RFC 2818, DOI 10.17487/RFC2818, May 2000, <https://www.rfc-editor.org/info/rfc2818>.

[RFC2978] Freed, N. and J. Postel, «IANA Charset Registration Procedures», BCP 19, RFC 2978, DOI 10.17487/RFC2978, October 2000, <https://www.rfc-editor.org/info/rfc2978>.

[RFC3040] Cooper, I., Melve, I., and G. Tomlinson, «Internet Web Replication and Caching Taxonomy», RFC 3040, DOI 10.17487/RFC3040, January 2001, <https://www.rfc-editor.org/info/rfc3040>.

[RFC3864] Klyne, G., Nottingham, M., and J. Mogul, «Registration Procedures for Message Header Fields», BCP 90, RFC 3864, DOI 10.17487/RFC3864, September 2004, <https://www.rfc-editor.org/info/rfc3864>.

[RFC3875] Robinson, D. and K. Coar, «The Common Gateway Interface (CGI) Version 1.1», RFC 3875, DOI 10.17487/RFC3875, October 2004, <https://www.rfc-editor.org/info/rfc3875>.

[RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose, «DNS Security Introduction and Requirements», RFC 4033, DOI 10.17487/RFC4033, March 2005, <https://www.rfc-editor.org/info/rfc4033>.

[RFC4559] Jaganathan, K., Zhu, L., and J. Brezak, «SPNEGO-based Kerberos and NTLM HTTP Authentication in Microsoft Windows», RFC 4559, DOI 10.17487/RFC4559, June 2006, <https://www.rfc-editor.org/info/rfc4559>.

[RFC5789] Dusseault, L. and J. Snell, «PATCH Method for HTTP», RFC 5789, DOI 10.17487/RFC5789, March 2010, <https://www.rfc-editor.org/info/rfc5789>.

[RFC5905] Mills, D., Martin, J., Ed., Burbank, J., and W. Kasch, «Network Time Protocol Version 4: Protocol and Algorithms Specification», RFC 5905, DOI 10.17487/RFC5905, June 2010, <https://www.rfc-editor.org/info/rfc5905>.

[RFC6454] Barth, A., «The Web Origin Concept», RFC 6454, DOI 10.17487/RFC6454, December 2011, <https://www.rfc-editor.org/info/rfc6454>.

[RFC6585] Nottingham, M. and R. Fielding, «Additional HTTP Status Codes», RFC 6585, DOI 10.17487/RFC6585, April 2012, <https://www.rfc-editor.org/info/rfc6585>.

[RFC7230] Fielding, R., Ed. and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing», RFC 7230, DOI 10.17487/RFC7230, June 2014, <https://www.rfc-editor.org/info/rfc7230>.

[RFC7231] Fielding, R., Ed. and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content», RFC 7231, DOI 10.17487/RFC7231, June 2014, <https://www.rfc-editor.org/info/rfc7231>.

[RFC7232] Fielding, R., Ed. and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests», RFC 7232, DOI 10.17487/RFC7232, June 2014, <https://www.rfc-editor.org/info/rfc7232>.

[RFC7233] Fielding, R., Ed., Lafon, Y., Ed., and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Range Requests», RFC 7233, DOI 10.17487/RFC7233, June 2014, <https://www.rfc-editor.org/info/rfc7233>.

[RFC7234] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Caching», RFC 7234, DOI 10.17487/RFC7234, June 2014, <https://www.rfc-editor.org/info/rfc7234>.

[RFC7235] Fielding, R., Ed. and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Authentication», RFC 7235, DOI 10.17487/RFC7235, June 2014, <https://www.rfc-editor.org/info/rfc7235>.

[RFC7538] Reschke, J., «The Hypertext Transfer Protocol Status Code 308 (Permanent Redirect)», RFC 7538, DOI 10.17487/RFC7538, April 2015, <https://www.rfc-editor.org/info/rfc7538>.

[RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., «Hypertext Transfer Protocol Version 2 (HTTP/2)», RFC 7540, DOI 10.17487/RFC7540, May 2015, <https://www.rfc-editor.org/info/rfc7540>.

[RFC7578] Masinter, L., «Returning Values from Forms: multipart/form-data», RFC 7578, DOI 10.17487/RFC7578, July 2015, <https://www.rfc-editor.org/info/rfc7578>.

[RFC7615] Reschke, J., «HTTP Authentication-Info and Proxy-Authentication-Info Response Header Fields», RFC 7615, DOI 10.17487/RFC7615, September 2015, <https://www.rfc-editor.org/info/rfc7615>.

[RFC7616] Shekh-Yusef, R., Ed., Ahrens, D., and S. Bremer, «HTTP Digest Access Authentication», RFC 7616, DOI 10.17487/RFC7616, September 2015, <https://www.rfc-editor.org/info/rfc7616>.

[RFC7617] Reschke, J., «The ‘Basic’ HTTP Authentication Scheme», RFC 7617, DOI 10.17487/RFC7617, September 2015, <https://www.rfc-editor.org/info/rfc7617>.

[RFC7694] Reschke, J., «Hypertext Transfer Protocol (HTTP) Client-Initiated Content-Encoding», RFC 7694, DOI 10.17487/RFC7694, November 2015, <https://www.rfc-editor.org/info/rfc7694>.

[RFC8126] Cotton, M., Leiba, B., and T. Narten, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.

[RFC8187] Reschke, J., «Indicating Character Encoding and Language for HTTP Header Field Parameters», RFC 8187, DOI 10.17487/RFC8187, September 2017, <https://www.rfc-editor.org/info/rfc8187>.

[RFC8246] McManus, P., «HTTP Immutable Responses», RFC 8246, DOI 10.17487/RFC8246, September 2017, <https://www.rfc-editor.org/info/rfc8246>.

[RFC8288] Nottingham, M., «Web Linking», RFC 8288, DOI 10.17487/RFC8288, October 2017, <https://www.rfc-editor.org/info/rfc8288>.

[RFC8336] Nottingham, M. and E. Nygren, «The ORIGIN HTTP/2 Frame», RFC 8336, DOI 10.17487/RFC8336, March 2018, <https://www.rfc-editor.org/info/rfc8336>.

[RFC8615] Nottingham, M., «Well-Known Uniform Resource Identifiers (URIs)», RFC 8615, DOI 10.17487/RFC8615, May 2019, <https://www.rfc-editor.org/info/rfc8615>.

[RFC8941] Nottingham, M. and P-H. Kamp, «Structured Field Values for HTTP», RFC 8941, DOI 10.17487/RFC8941, February 2021, <https://www.rfc-editor.org/info/rfc8941>.

[Sniffing] WHATWG, «MIME Sniffing», <https://mimesniff.spec.whatwg.org>.

[WEBDAV] Dusseault, L., Ed., «HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)», RFC 4918, DOI 10.17487/RFC4918, June 2007, <https://www.rfc-editor.org/info/rfc4918>.

Приложение A. Сводка ABNF

Приведённая ниже сводка ABNF содержит правила, преобразованные в соответствии с параграфом 5.6.1.

   Accept = [ ( media-range [ weight ] ) *( OWS "," OWS ( media-range [
    weight ] ) ) ]
   Accept-Charset = [ ( ( token / "*" ) [ weight ] ) *( OWS "," OWS ( (
    token / "*" ) [ weight ] ) ) ]
   Accept-Encoding = [ ( codings [ weight ] ) *( OWS "," OWS ( codings [
    weight ] ) ) ]
   Accept-Language = [ ( language-range [ weight ] ) *( OWS "," OWS (
    language-range [ weight ] ) ) ]
   Accept-Ranges = acceptable-ranges
   Allow = [ method *( OWS "," OWS method ) ]
   Authentication-Info = [ auth-param *( OWS "," OWS auth-param ) ]
   Authorization = credentials

   BWS = OWS

   Connection = [ connection-option *( OWS "," OWS connection-option ) ]
   Content-Encoding = [ content-coding *( OWS "," OWS content-coding ) ]
   Content-Language = [ language-tag *( OWS "," OWS language-tag ) ]
   Content-Length = 1*DIGIT
   Content-Location = absolute-URI / partial-URI
   Content-Range = range-unit SP ( range-resp / unsatisfied-range )
   Content-Type = media-type

   Date = HTTP-date

   ETag = entity-tag
   Expect = [ expectation *( OWS "," OWS expectation ) ]

   From = mailbox

   GMT = %x47.4D.54 ; GMT

   HTTP-date = IMF-fixdate / obs-date
   Host = uri-host [ ":" port ]

   IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT
   If-Match = "*" / [ entity-tag *( OWS "," OWS entity-tag ) ]
   If-Modified-Since = HTTP-date
   If-None-Match = "*" / [ entity-tag *( OWS "," OWS entity-tag ) ]
   If-Range = entity-tag / HTTP-date
   If-Unmodified-Since = HTTP-date

   Last-Modified = HTTP-date
   Location = URI-reference

   Max-Forwards = 1*DIGIT

   OWS = *( SP / HTAB )

   Proxy-Authenticate = [ challenge *( OWS "," OWS challenge ) ]
   Proxy-Authentication-Info = [ auth-param *( OWS "," OWS auth-param )
    ]
   Proxy-Authorization = credentials

   RWS = 1*( SP / HTAB )
   Range = ranges-specifier
   Referer = absolute-URI / partial-URI
   Retry-After = HTTP-date / delay-seconds

   Server = product *( RWS ( product / comment ) )

   TE = [ t-codings *( OWS "," OWS t-codings ) ]
   Trailer = [ field-name *( OWS "," OWS field-name ) ]

   URI-reference = <URI-reference, см. [URI], параграф 4.1>
   Upgrade = [ protocol *( OWS "," OWS protocol ) ]
   User-Agent = product *( RWS ( product / comment ) )

   Vary = [ ( "*" / field-name ) *( OWS "," OWS ( "*" / field-name ) ) ]
   Via = [ ( received-protocol RWS received-by [ RWS comment ] ) *( OWS
    "," OWS ( received-protocol RWS received-by [ RWS comment ] ) ) ]

   WWW-Authenticate = [ challenge *( OWS "," OWS challenge ) ]

   absolute-URI = <absolute-URI, см. [URI], параграф 4.3>
   absolute-path = 1*( "/" segment )
   acceptable-ranges = range-unit *( OWS "," OWS range-unit )
   asctime-date = day-name SP date3 SP time-of-day SP year
   auth-param = token BWS "=" BWS ( token / quoted-string )
   auth-scheme = token
   authority = <authority, см. [URI], параграф 3.2>

   challenge = auth-scheme [ 1*SP ( token68 / [ auth-param *( OWS ","
    OWS auth-param ) ] ) ]
   codings = content-coding / "identity" / "*"
   comment = "(" *( ctext / quoted-pair / comment ) ")"
   complete-length = 1*DIGIT
   connection-option = token
   content-coding = token
   credentials = auth-scheme [ 1*SP ( token68 / [ auth-param *( OWS ","
    OWS auth-param ) ] ) ]
   ctext = HTAB / SP / %x21-27 ; '!'-'''
    / %x2A-5B ; '*'-'['
    / %x5D-7E ; ']'-'~'
    / obs-text

   date1 = day SP month SP year
   date2 = day "-" month "-" 2DIGIT
   date3 = month SP ( 2DIGIT / ( SP DIGIT ) )
   day = 2DIGIT
   day-name = %x4D.6F.6E ; Пнд
    / %x54.75.65 ; Втр
    / %x57.65.64 ; Срд
    / %x54.68.75 ; Чтв
    / %x46.72.69 ; Птн
    / %x53.61.74 ; Сбт
    / %x53.75.6E ; Вск
   day-name-l = %x4D.6F.6E.64.61.79 ; Понедельник
    / %x54.75.65.73.64.61.79 ; Вторник
    / %x57.65.64.6E.65.73.64.61.79 ; Среда
    / %x54.68.75.72.73.64.61.79 ; Четверг
    / %x46.72.69.64.61.79 ; Пятница
    / %x53.61.74.75.72.64.61.79 ; Суббота
    / %x53.75.6E.64.61.79 ; Воскресенье
   delay-seconds = 1*DIGIT

   entity-tag = [ weak ] opaque-tag
   etagc = "!" / %x23-7E ; '#'-'~'
    / obs-text
   expectation = token [ "=" ( token / quoted-string ) parameters ]

   field-content = field-vchar [ 1*( SP / HTAB / field-vchar )
    field-vchar ]
   field-name = token
   field-value = *field-content
   field-vchar = VCHAR / obs-text
   first-pos = 1*DIGIT

   hour = 2DIGIT
   http-URI = "http://" authority path-abempty [ "?" query ]
   https-URI = "https://" authority path-abempty [ "?" query ]

   incl-range = first-pos "-" last-pos
   int-range = first-pos "-" [ last-pos ]

   language-range = <language-range, см. [RFC4647], параграф 2.1>
   language-tag = <Language-Tag, см. [RFC5646], параграф 2.1>
   last-pos = 1*DIGIT

   mailbox = <mailbox, см. [RFC5322], Section 3.4>
   media-range = ( "*/*" / ( type "/*" ) / ( type "/" subtype ) )
    parameters
   media-type = type "/" subtype parameters
   method = token
   minute = 2DIGIT
   month = %x4A.61.6E ; Янв
    / %x46.65.62 ; Фев
    / %x4D.61.72 ; Мар
    / %x41.70.72 ; Апр
    / %x4D.61.79 ; Май
    / %x4A.75.6E ; Июн
    / %x4A.75.6C ; Июл
    / %x41.75.67 ; Авг
    / %x53.65.70 ; Сен
    / %x4F.63.74 ; Окт
    / %x4E.6F.76 ; Ноя
    / %x44.65.63 ; Дек

   obs-date = rfc850-date / asctime-date
   obs-text = %x80-FF
   opaque-tag = DQUOTE *etagc DQUOTE
   other-range = 1*( %x21-2B ; '!'-'+'
    / %x2D-7E ; '-'-'~' )

   parameter = parameter-name "=" parameter-value
   parameter-name = token
   parameter-value = ( token / quoted-string )
   parameters = *( OWS ";" OWS [ parameter ] )
   partial-URI = relative-part [ "?" query ]
   path-abempty = <path-abempty, см. [URI], параграф 3.3>
   port = <port, см. [URI], параграф 3.2.3>
   product = token [ "/" product-version ]
   product-version = token
   protocol = protocol-name [ "/" protocol-version ]
   protocol-name = token
   protocol-version = token
   pseudonym = token

   qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'['
    / %x5D-7E ; ']'-'~'
    / obs-text
   query = <query, см. [URI], параграф 3.4>
   quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
   quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
   qvalue = ( "0" [ "." *3DIGIT ] ) / ( "1" [ "." *3"0" ] )

   range-resp = incl-range "/" ( complete-length / "*" )
   range-set = range-spec *( OWS "," OWS range-spec )
   range-spec = int-range / suffix-range / other-range
   range-unit = token
   ranges-specifier = range-unit "=" range-set
   received-by = pseudonym [ ":" port ]
   received-protocol = [ protocol-name "/" ] protocol-version
   relative-part = <relative-part, см. [URI], параграф 4.2>
   rfc850-date = day-name-l "," SP date2 SP time-of-day SP GMT

   second = 2DIGIT
   segment = <segment, см. [URI], параграф 3.3>
   subtype = token
   suffix-length = 1*DIGIT
   suffix-range = "-" suffix-length

   t-codings = "trailers" / ( transfer-coding [ weight ] )
   tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
    "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
   time-of-day = hour ":" minute ":" second
   token = 1*tchar
   token68 = 1*( ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" )
    *"="
   transfer-coding = token *( OWS ";" OWS transfer-parameter )
   transfer-parameter = token BWS "=" BWS ( token / quoted-string )
   type = token

   unsatisfied-range = "*/" complete-length
   uri-host = <host, см. [URI], параграф 3.2.2>

   weak = %x57.2F ; W/
   weight = OWS ";" OWS "q=" qvalue

   year = 4DIGIT

Приложение B. Отличия от предшествующих RFC

B.1. Отличия от RFC 2818

Отменено использование CN-ID11.

B.2. Отличия от RFC 7230

Сюда перенесены разделы, описывающие цели разработки HTTP, историю, архитектуру, критерии соответствия, версии протокола, URI, маршрутизацию сообщений и поля заголовков.

Требование семантического соответствия заменено разрешением игнорировать или обходить характерные для реализаций отказы(параграф 2.2).

Описание источника и полномочного доступа к серверам-источникам расширено для URI http и https с учётом дополнительных служб и защищённых соединений, не обязательно основанных на TCP (параграфы 4.2.1, 4.2.2, 4.3.1, 7.3.3)

Добавлены явные требования для проверки семантики схемы URI цели и отклонения запросов, не соответствующих требованиям (параграф 7.4).

Параметры для типа и диапазона носителей, а также ожиданий могут быть пустыми с одним или несколькими символами точки с запятой в конце (параграф 5.6.6).

Под значением поля понимается значение после объединения нескольких строк поля через запятые (это наиболее распространённое использование). Для одной строки заголовка применяется термин «значение строки поля» (field line value, параграф 6.3).

Семантика полей трейлера выходит за рамки блочного (chunk) транспортного кодирования. Использование трейлерных полей ограничено дополнительно, чтобы разрешить генерацию в качестве таких полей лишь случаями, когда отправитель знает, что для поля определено такое использование, и слияние в раздел заголовка лишь случаями, когда получатель знает, что определение соответствующего поля описывает такое слияние. В остальных случаях реализации рекомендуется сохранять поля трейлеров отдельно или отбрасывать их вместо слияния (параграф 6.5.1).

Приоритет абсолютной формы URI запроса перед полем заголовка Host на сервере-источнике сделан явным для согласования с обработкой на прокси (параграф 7.2).

Определение грамматики поля Via received-by было расширено в RFC 7230 в связи с изменениями грамматики URI для хостов [URI], которые нежелательны для Via. Для простоты из received-by удалён элемент uri-host, поскольку он может быть охвачен имеющейся грамматикой для псевдонимов. В частности, это изменение удаляет запятую из разрешённых символов имени хоста в received-by (параграф 7.6.3).

B.3. Отличия от RFC 7231

Рекомендованы минимальные размеры URI для поддержки реализациями (параграф 4.1).

Добавлено разъяснение, что CR и NUL в значениях полей отвергаются или заменяются SP, а начальные или завершающие пробельные символы должны исключаться из значений полей перед их восприятием (параграф 5.5).

Параметры и ожидания типа или диапазона типов носителя могут быть пустыми с одним или несколькими символами точки с запятой в конце (параграф 5.6.6).

Введён абстрактный тип данных для сообщений HTTP, определяющий компоненты сообщения и их семантику как абстракцию для разных версий HTTP вместо конкретных форм HTTP/1.1 изи [HTTP/1.1] и отражающий содержимое после синтаксического анализа сообщения. Это упрощает отделение требований к содержимому (что передаётся) от требований к синтаксису (как передавать) и позволяет избежать ограничений ранних версий протокола в будущих HTTP (раздел 6).

Термины payload и payload body заменены на content, для согласования с их использованием в других местах (например, в именах полей) и предотвращения путаницы с содержимым кадров HTTP/2 и HTTP/3 (параграф 6.4).

Термин effective request URI заменён на target URI (параграф 7.1).

Смягчены ограничения для повторных попыток клиента в соответствии с поведением реализаций (параграф 9.2.2).

Уточнено, что тела запросов GET, HEAD, DELETE не являются совместимыми (параграфы 9.3.1, 9.3.2, 9.3.5).

Разрешено использовать поле Content-Range (параграф 14.4) как модификатор запроса PUT (параграф 9.3.4).

Из описания метода OPTIONS исключено лишнее требование об установке Content-Length (параграф 9.3.7).

Исключено нормативное требование об использовании носителя типа message/http в откликах TRACE (параграф 9.3.8).

Для совместимости RFC 2616 восстановлена списочная грамматика Expect (параграф 10.1.1).

Разрешены Accept и Accept-Encoding (добавлен [RFC7694]) в сообщениях с откликами (параграф 12.3).

Исключены параметры восприятия (ABNF accept-params и accept-ext) из определения поля Accept (параграф 12.5.1).

Поле Accept-Charset признано устаревшим (параграф 12.5.2).

Уточнена семантика * в поле заголовка Vary при наличии других значений (параграф 12.5.5).

При сравнении единиц диапазона регистр символов не учитывается (параграф 14.1).

Использование поля Accept-Ranges разрешено не только серверам-источникам (параграф 14.3).

Уточнён процесс создания перенаправленного запроса (параграф 15.4).

Добавлен код статуса 308 (определён в [RFC7538]), чтобы он был ближе к кодам 301, 302, 307 (параграф 15.4.9).

Добавлен код статуса 421 (определён в параграфе 9.1.2 [RFC7540]) по причине распространённости его применения. Этот код больше не считается эвристически кэшируемым, поскольку отклик специфичен для соединения, а не целевого ресурса (параграф 15.5.20).

Добавлен код статуса 422 (определён в параграфе 11.2 [WEBDAV]) по причине распространённости его применения (параграф 15.5.21).

B.4. Отличия от RFC 7232

Предыдущие версии HTTP вносили произвольное ограничение (60 секунд) на проверку, является ли Last-Modified строгим валидатором для обнаружения того, что значения Date и Last-Modified получены от разных часов или в разные моменты при подготовке отклика. Эта спецификация смягчает требование для обеспечения разумной свободы действий (параграф 8.8.2.2).

Исключено требование не передавать валидаторы If-Match и If-Unmodified-Since в откликах 2xx при отрицательном результате проверки, поскольку запрос уже был применён (параграфы 13.1.1 и 13.1.4)

Уточнено, что If-Unmodified-Since не применяется к ресурсу, не понимающему концепции времени изменения (параграф 13.1.4).

Предварительные условия разрешено проверять до обработки содержимого запроса без ожидания его успеха (параграф 13.2).

B.5. Отличия от RFC 7233

Переработана грамматика range-unit и ranges-specifier для упрощения и сокращения искусственных различий между батовыми и другими (расширения) единицами диапазонов. Удалено дублирование грамматики other-range-unit путём определения единиц диапазона как маркеров и размещения расширений в области действия range-spec (other-range). Это устраняет неоднозначность роли синтаксиса списков (запятые) во всех наборах диапазонов, включая расширенные единицы, для индикации range-set с множеством диапазонов. Перенос грамматики расширения в спецификатор диапазона позволяет также отдельно задавать протокол, специфичный для диапазона байтов.

Стало возможным определение обработки Range в методах расширения (параграф 14.2).

Описано применение поля заголовка Content-Range (параграф 14.4) как модификатора запроса для выполнения частичного PUT (параграф 14.5).

B.6. Отличия от RFC 7235

Нет.

B.7. Отличия от RFC 7538

Нет.

B.8. Отличия от RFC 7615

Нет.

B.9. Отличия от RFC 7694

Эта спецификация включает расширения из [RFC7694], но без примеров и рекомендаций по внедрению.

Благодарности

Помимо текущих редакторов, следует отметить вклад в ранние работы по HTTP и базовые спецификации протокола Marc Andreessen, Tim Berners-Lee, Robert Cailliau, Daniel W. Connolly, Bob Denny, John Franks, Jim Gettys, Jean-François Groff, Phillip M. Hallam-Baker, Koen Holtman, Jeffery L. Hostetler, Shel Kaphan, Dave Kristol, Yves Lafon, Scott D. Lawrence, Paul J. Leach, Håkon W. Lie, Ari Luotonen, Larry Masinter, Rob McCool, Jeffrey C. Mogul, Lou Montulli, David Morris, Henrik Frystyk Nielsen, Dave Raggett, Eric Rescorla, Tony Sanders, Lawrence C. Stewart, Marc VanHeyningen, Steve Zilles.

Этот документ основан на прошлых спецификациях HTTP, включая [HTTP/1.0], [RFC2068], [RFC2145], [RFC2616], [RFC2617], [RFC2818], [RFC7230], [RFC7231], [RFC7232], [RFC7233], [RFC7234], [RFC7235]. Включённые в эти документы благодарности сохраняют силу.

После 2014 г помогли улучшить эту спецификацию своими отчётами об ошибках, правильными вопросами, написанием или рецензированием текста и решением проблем Alan Egerton, Alex Rousskov, Amichai Rothman, Amos Jeffries, Anders Kaseorg, Andreas Gebhardt, Anne van Kesteren, Armin Abfalterer, Aron Duby, Asanka Herath, Asbjørn Ulsberg, Asta Olofsson, Attila Gulyas, Austin Wright, Barry Pollard, Ben Burkert, Benjamin Kaduk, Björn Höhrmann, Brad Fitzpatrick, Chris Pacejo, Colin Bendell, Cory Benfield, Cory Nelson, Daisuke Miyakawa, Dale Worley, Daniel Stenberg, Danil Suits, David Benjamin, David Matson, David Schinazi, Дилян Палаузов (Dilyan Palauzov), Eric Anderson, Eric Rescorla, Éric Vyncke, Erik Kline, Erwin Pe, Etan Kissling, Evert Pot, Evgeny Vrublevsky, Florian Best, Francesca Palombini, Igor Lubashev, James Callahan, James Peach, Jeffrey Yasskin, Kalin Gyokov, Kannan Goundan, 奥 一穂 (Kazuho Oku), Ken Murchison, Krzysztof Maczyński, Lars Eggert, Lucas Pardue, Martin Duke, Martin Dürst, Martin Thomson, Martynas Jusevičius, Matt Menke, Matthias Pigulla, Mattias Grenfeldt, Michael Osipov, Mike Bishop, Mike Pennisi, Mike Taylor, Mike West, Mohit Sethi, Murray Kucherawy, Nathaniel J. Smith, Nicholas Hurley, Nikita Prokhorov, Patrick McManus, Piotr Sikora, Poul-Henning Kamp, Rick van Rein, Robert Wilton, Roberto Polli, Roman Danyliw, Samuel Williams, Semyon Kholodnov, Simon Pieters, Simon Schüppel, Stefan Eissing, Taylor Hunt, Todd Greer, Tommy Pauly, Vasiliy Faronov, Vladimir Lashchev, Wenbo Zhu, William A. Rowe Jr., Willy Tarreau, Xingwei Liu, Yishuai Li, Zaheduzzaman Sarker.

Предметный указатель

Адреса авторов

Roy T. Fielding (editor)
Adobe
345 Park Ave
San Jose, CA 95110
United States of America
Email: fielding@gbiv.com
URI: https://roy.gbiv.com/
 
Mark Nottingham (editor)
Fastly
Prahran
Australia
Email: mnot@mnot.net
URI: https://www.mnot.net/
 
Julian Reschke (editor)
greenbytes GmbH
Hafenweg 16
48155 Münster
Germany
Email: julian.reschke@greenbytes.de
URI: https://greenbytes.de/tech/webdav/

Перевод на русский язык

nmalykh@protokols.ru


1Hypertext Transfer Protocol — протокол передачи гипертекста.

2Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

3Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

4В оригинале — IETF Contributions. Прим. перев.

5В оригинале — IETF Standards Process. Прим. перев.

6Этот документ отменяет лишь части RFC 7230, не зависящие от синтаксиса обмена сообщениями и управления соединениями HTTP/1.1, остальные части 7230 отменяет [HTTP/1.1].

7В оригинале ошибочно сказано Content-Encoding, см. https://www.rfc-editor.org/errata/eid7419. Прим. перев.

8В оригинале ошибочно указано значение 0,7. См. https://www.rfc-editor.org/errata/eid7138. Прим. перев.

9В оригинале элемент OWS пропущен, см. https://www.rfc-editor.org/errata/eid7306. Прим. перев.

10В оригинале это предложение отсутствует, см. https://www.rfc-editor.org/errata/eid7109. Прим. перев.

11В оригинале указано отсутствие изменений, см. https://www.rfc-editor.org/errata/eid7105. Прим. перев.

Рубрика: RFC | Оставить комментарий

RFC 9260 Stream Control Transmission Protocol

Internet Engineering Task Force (IETF)                        R. Stewart
Request for Comments: 9260                                 Netflix, Inc.
Obsoletes: 4460, 4960, 6096, 7053, 8540                         M. Tüxen
Category: Standards Track                Münster Univ. of Appl. Sciences
ISSN: 2070-1721                                               K. Nielsen
                                                            Kamstrup A/S
                                                               June 2022

Протокол SCTP

Stream Control Transmission Protocol

PDF

Аннотация

Этот документ описывает протокол управления потоковой передачей (Stream Control Transmission Protocol или SCTP) и отменяет RFC 4960. Он включает спецификацию реестра флагов блоков (chunk) из RFC 6096 и спецификацию бита I в блоках DATA из RFC 7053, поэтому отменяет также RFC 6096 и RFC 7053. Кроме того, документ отменяет RFC 4460 и RFC 8540, где указаны ошибки для SCTP.

Протокол SCTP изначально был предназначен для передачи сигнальных сообщений PSTN1 через сети IP, но может использоваться и для других приложений, например, WebRTC.

SCTP представляет собой протокол транспортного уровня с гарантированной доставкой, работающий в пакетных сетях без явной организации соединений таких, как IP. Протокол обеспечивает пользователям следующие типы сервиса:

  • передача пользовательских данных с корректировкой ошибок, подтверждением доставки и отсутствием дубликатов;
  • фрагментирование данных в соответствии с определенным для пути значением MTU2;
  • упорядоченная доставка пользовательских сообщений внутри множества потоков с возможностью управления порядком доставки отдельных пользовательских сообщений;
  • возможность группировки пользовательских сообщений в один пакет SCTP;
  • устойчивость к отказам на сетевом уровне за счёт поддержки многодомных хостов на обеих сторонах соединения.

Протокол SCTP включает механизмы предотвращения gthtuheprb и устойчивости к атакам с использованием лавины пакетов (flooding) или маскированием адресов (masquerade).

Статус документа

Документ относится к категории Internet Standards Track.

Документ является результатом работы IETF3 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG4. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке https://www.rfc-editor.org/info/rfc9260.

Авторские права

Авторские права (Copyright (c) 2022) принадлежат IETF Trust и лицам, указанным в качестве авторов документа. Все права защищены.

К документу применимы права и ограничения, перечисленные в BCP 78 и IETF Trust Legal Provisions и относящиеся к документам IETF (http://trustee.ietf.org/license-info), на момент публикации данного документа. Прочтите упомянутые документы внимательно. Фрагменты программного кода, включённые в этот документ, распространяются в соответствии с упрощённой лицензией BSD, как указано в параграфе 4.e документа Trust Legal Provisions, без каких-либо гарантий (как указано в Simplified BSD License).

Документ может содержать материалы из IETF Document или IETF Contribution, опубликованных или публично доступных до 10 ноября 2008 года. Лица, контролирующие авторские права на некоторые из таких документов, могли не предоставить IETF Trust права разрешать внесение изменений в такие документы за рамками процессов IETF Standards. Без получения соответствующего разрешения от лиц, контролирующих авторские права этот документ не может быть изменён вне рамок процесса IETF Standards, не могут также создаваться производные документы за рамками процесса IETF Standards за исключением форматирования документа для публикации или перевода с английского языка на другие языки.

1. Введение

В этом разделе рассматриваются причины, побудившие к разработке протокола SCTP, обеспечиваемые протоколом типы сервиса, а также базовые концепции, требуемые для детального описания протокола.

Этот документ заменяет собой [RFC4960]. Кроме того, он включает спецификацию реестра флагов блоков (chunk) из RFC 6096 и спецификацию бита I в блоках DATA из RFC 7053, поэтому отменяет также [RFC 6096] и [RFC 7053].

1.1. Мотивация

Протокол TCP [RFC0793] обеспечивает, прежде всего, гарантированную доставку данных в сетях IP. Однако многие современные приложения сталкиваются с ограниченными возможностями TCP и вынуждены реализовать свои средства обеспечения гарантированной доставки на основе транспорта UDP [RFC0768]. Ниже перечислены основные ограничения TCP, которые пользователи стремятся обойти.

  • Протокол TCP обеспечивает гарантию доставки данных с сохранением их порядка. Некоторым приложениям требуется лишь гарантированная доставка, независимо от порядка, а другим приложениям может быть достаточно частичного сохранения порядка доставки. Оба типа приложений не устраивают дополнительные задержки TCP, возникающие при нарушении порядка доставки пакетов в сети.
  • Потоковая природа протокола TCP зачастую не подходит для приложений, которым приходится вводить свои средства маркировки записей для делинеаризации передаваемых сообщений. Кроме того, приложениям приходиться явно использовать средства выталкивания данных (push) для того, чтобы сообщение было передано полностью за разумное время.
  • Ограниченные возможности сокетов TCP усложняют для приложений задачу обеспечения высокого уровня доступности при обмене данными за счёт использования многодомных5 хостов.
  • Протокол TCP достаточно слабо защищён от атак на службы6, в частности, от SYN-атак.

Передача сигнальных сообщений PSTN через сети IP является примером приложения, которое сталкивается со всеми ограничениями протокола TCP. Это послужило основным мотивом разработки протокола SCTP, но можно найти и другие приложения, для которых транспорт SCTP будет предпочтительным. Одним из примеров является использование каналов данных в инфраструктуре WebRTC.

1.2. Архитектура SCTP

Протокол SCTP размещается в многоуровневой модели между уровнем пользовательских приложений SCTP и сетевым сервисом без организации явных соединений (например, IP). В остальной части этого документа предполагается, что SCTP работает «поверх» протокола IP. Основным типом сервиса, обеспечиваемого протоколом SCTP, является гарантированная передача сообщений между пользователями SCTP. Этот сервис обеспечивается в контексте ассоциаций между парами конечных точек SCTP. В параграфе 10 данного документа приводится схематическое рассмотрение интерфейса API, который должен существовать на границе между протоколом SCTP и пользовательскими приложениями SCTP.

Протокол SCTP работает на основе явных соединений7, но ассоциация SCTP представляет собой более широкое понятие, нежели соединение TCP. Протокол SCTP обеспечивает для каждой конечной точки SCTP (см. параграф 1.4) способ обеспечения другой конечной точки (в процессе создания ассоциации) списком транспортных адресов (т. е. множеством адресов IP в комбинации с номером порта SCTP), которые конечная точка может использовать для связи и откуда она будет получать пакеты SCTP. Ассоциация может передавать данные с использованием всех возможных пар адресов отправителя и получателя, которые могут быть созданы на основе списков адресов конечных точек.

 _____________                                      _____________
| Приложения  |                                    | Приложения  |
|    SCTP     |                                    |    SCTP     |
|-------------|                                    |-------------|
|Транспортный |                                    |Транспортный |
| сервис SCTP |                                    | сервис SCTP |
|-------------|                                    |-------------|
|   Сетевой   |Один или       ----      Один или   |   Сетевой   |
|  сервис IP  |несколько       \/       несколько  |  сервис IP  |
|             |адресов IP      /\       адресов IP |             |
|_____________|               ----                 |_____________|

  SCTP-узел A |<-------- Сетевой транспорт ------->| SCTP-узел B

Рисунок 1. SCTP-ассоциация.

В дополнение к инкапсуляции пакетов SCTP в IPv4 и IPv6 возможна инкапсуляция в UDP, как указано в [RFC6951], или в DTLS, как указано в [RFC8261].

1.3. Основные термины

Некоторые термины, используемые в контексте SCTP, уже были упомянуты в предыдущих параграфах. Здесь даются определения основных терминов, связанных с протоколом.

Active destination transport address — активный транспортный адрес получателя

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

Association Maximum DATA Chunk Size (AMDCS) — максимальный размер блока DATA для ассоциации

Меньшее из значение PMDCS (Path Maximum DATA Chunk Size) среди всех адресов получателя.

Bundling of Chunks — группировка блоков

Дополнительная операция мультиплексирования, позволяющая передать в одном пакете несколько блоков SCTP.

Bundling of User messages — группировка пользовательских сообщений

Дополнительная операция мультиплексирования, позволяющая передать в одном пакете несколько сообщений SCTP. Каждое пользовательское сообщение помещается в отдельный блок DATA.

Chunk — блок

Единица информации в пакете SCTP, содержащая заголовок блока (chunk header) и данные.

Congestion window (cwnd) — окно насыщения (перегрузки)

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

Cumulative TSN Ack Point — указатель на кумулятивный номер Ack

Значение TSN для последнего блока DATA, подтверждённого с использованием поля Cumulative TSN Ack в SACK.

Flightsize — размер данных «в пути»

Число остающихся данных для конкретного транспортного адреса получателя в данный момент.

Idle destination address — неиспользуемый адрес получателя

Адрес, который не используется для передачи пользовательских сообщений в течение некоторого периода (обычно ≥ HB.interval).

Inactive destination transport address — неактивный транспортный адрес получателя

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

Message (user message) — (пользовательское) сообщение

Данные, полученные протоколом SCTP от протокола вышележащего уровня (Upper Layer Protocol или ULP).

Network Byte Order — сетевой порядок байтов

Порядок передачи байтов, при котором старший байт следует первым. Синоним Big Endian.

Ordered Message — упорядоченные сообщения

Пользовательские сообщения, доставленные в том же порядке, в котором они были помещены в поток.

Outstanding Data (Data Outstanding или Data In Flight) — остающиеся данные (данные «в пути»)

Общий размер блоков DATA связанных с остающимися TSN. Повторно передаваемый блок DATA учитывается в остающихся данных один раз. Блок DATA, сочтённый потерянным, но ещё не переданный повторно не относится к остающимся данным.

Outstanding TSN (в конечной точке SCTP)

Номер TSN (и связанный с ним блок DATA), который был передан конечной точкой, но его получение ещё не подтверждено.

«Out of the Blue» (OOTB) Packet

Пакет с корректным форматом, для которого получатель не может определить ассоциацию (см. параграф 8.4).

Path — путь

Маршрут, используемый пакетами SCTP, переданными одной конечной точкой SCTP по определённому транспортному адресу другой конечной точки SCTP. Передача пакетов по различным транспортным адресам удалённой точки не обязательно ведёт к изменению пути. В этой спецификации путь указывается транспортным адресом получателя, поскольку маршрутизация считается стабильной. Это включает, в частности, выбор адреса отправителя при отправке пакета получателю.

Path Maximum DATA Chunk Size (PMDCS) — максимальный размер блока DATA для пути

Максимальный размер блока DATA (включая заголовок блока), который помещается в пакет SCTP, не превышающий по размеру PMTU для конкретного адреса получателя.

Path Maximum Transmission Unit (PMTU)

Максимальный размер пакета SCTP (включая общий заголовок SCTP и все блоки вместе с их заполнением), который можно передать по конкретному адресу получателя без использования фрагментации на уровне IP.

Primary Path — основной путь

Комбинация адресов отправителя и получателя которая будет помещаться в исходящие пакеты SCTP по умолчанию. Адрес отправителя включён в определение потому, что реализации протокола могут указывать оба адреса (получателя и отправителя) для обеспечения контроля пути возврата блоков с откликами и выбора интерфейса для передачи пакетов многодомными хостами.

Receiver Window (rwnd) — окно получателя

Переменная SCTP, которую отправитель использует для хранения последнего рассчитанного значения размера окна приёма своего партнёра по ассоциации. Размер окна приёма задаётся количеством байтов. Значение размера позволяет отправителю определить величину свободного пространства в приёмном буфере получателя.

SCTP association — ассоциация SCTP

Протокольные отношения между конечными точками SCTP, включающие пару узлов SCTP и информацию о состоянии протокола (теги Verification, активные значения TSN и т. п.). Для уникальной идентификации ассоциаций SCTP могут использоваться пары транспортных адресов конечных точек ассоциации. Между любой парой конечных точек SCTP недопустимо одновременное существование нескольких ассоциаций.

SCTP endpoint — конечная точка SCTP

Логический приёмник/передатчик пакетов SCTP. Для многодомных хостов конечная точка SCTP представляется своему партнёру как комбинация набора допустимых транспортных адресов, по которым можно передавать пакеты SCTP и набора допустимых адресов транспортного уровня, с которых могут приниматься пакеты SCTP. Все транспортные адреса, используемые конечной точкой SCTP, должны быть связаны с одним номером порта, но могут иметь различные адреса IP. Транспортные адреса, используемые конечной точкой SCTP, недопустимо устанавливать для другой конечной точки SCTP (т. е. транспортный адрес каждой конечной точки SCTP уникален).

SCTP packet (packet) — пакет SCTP

Элемент данных, передаваемый через интерфейс между SCTP и пакетной сетью без организации соединений (например, IP). Пакет SCTP включает общий заголовок SCTP, блок пользовательских данных (DATA chunk) и может включать блок управления SCTP.

SCTP user application (SCTP user) — пользовательское приложение SCTP (пользователь SCTP)

Логический объект вышележащего уровня, который использует сервис SCTP. Используется также термин Upper-layer Protocol (ULP) — протокол вышележащего уровня.

Slow-Start Threshold (ssthresh) — порог замедленного старта

Переменная SCTP, определяющая пороговое значение, по которому конечная точка будет определять необходимость использования для конкретного транспортного адреса процедуры slow start или congestion avoidance. Значение ssthresh указывается в байтах.

State Cookie — куки состояния

Контейнер со всей информацией, требуемой для создания ассоциации.

Stream — поток

Однонаправленный логический канал между двумя участниками ассоциации SCTP, через который передаются все пользовательские сообщения. При доставке сообщений их порядок сохраняется, если не была задана неупорядоченная доставка8.

Stream Sequence Number — порядковый номер в потоке

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

Tie-Tags

Два 32-битовых случайных значений, которые вместе образуют 64-битовое одноразовое значение nonce. Эти теги используются в State Cookie и TCB для связывания недавно перезапущенной ассоциации с её предшественником на конечной станции, которая не была перезагружена, но, тем не менее, не может найти тегов Verification существующей ассоциации.

Transmission Control Block (TCB) — блок управления передачей

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

Transmission Sequence Number (TSN)- порядковый номер при передаче

32-битовый порядковый номер, используемый протоколом SCTP для нумерации передаваемых блоков. Значение TSN связывается с каждым блоком, который содержит пользовательские данные, чтобы дать возможность конечной точке SCTP на приёмной стороне подтвердить приём блока и обнаружить дубликаты.

Transport address — транспортный адрес

Адрес транспортного уровня обычно определяется комбинацией адреса сетевого уровня, транспортным протоколом и номером порта на транспортном уровне. При использовании SCTP в сетях IP транспортный адрес представляет собой комбинацию адреса IP и номера порта SCTP (транспортным протоколом является SCTP).

Unordered Message — неупорядоченное сообщение

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

User message — пользовательское сообщение

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

Verification Tag — тег верификации

32-битовое беззнаковое целое значение, которое обычно выбирается с использованием генератора случайных чисел. Verification Tag позволяет получателю проверить принадлежность полученного пакета SCTP к ассоциации и избавиться от старых пакетов из прежних ассоциаций.

1.4. Сокращения

MAC — Message Authentication Code [RFC2104] (код аутентификации сообщения).

RTO — Retransmission Timeout (тайм-аут повтора передачи).

RTT — Round-Trip Time (время кругового обхода).

RTTVAR — Round-Trip Time Variation (вариации времени кругового обхода).

SCTP — Stream Control Transmission Protocol (протокол управления потоковой передачей).

SRTT — Smoothed RTT (сглаженное значение RTT).

TCB — Transmission Control Block (блок управления передачей).

TLV — Type-Length-Value coding format (формат представления тип-размер-значение).

TSN — Transmission Sequence Number (порядковый номер при передаче).

ULP — Upper-Layer Protocol (протокол вышележащего уровня).

1.5. Функциональность SCTP

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

           Пользовательские приложения SCTP
-----------------------------------------------------
 _____________                  ____________________
|             |                |   Упорядоченная    |
|             |                | доставка в потоке  |
|  Создание   |                |____________________|
|     и       |         ____________________________
|   разрыв    |        | Фрагментация польз. данных |
| ассоциаций  |        |____________________________|
|             |         ____________________________
|             |        |      Подтверждения         |
|             |        |    и предотвращения        |
|             |        |        перегрузки          |
|             |        |____________________________|
|             |         ____________________________
|             |        |     Связывание блоков      |
|             |        |____________________________|
|             |     ________________________________
|             |    |      Проверка пакетов          |
|             |    |________________________________|
|             |     ________________________________
|             |    |     Управление путями          |
|_____________|    |________________________________|

Рисунок 2. Функциональное представление сервиса SCTP.

1.5.1. Создание и разрыв ассоциаций

Ассоциации создаются по запросам пользователей SCTP (см. описание примитива ASSOCIATE на стр. 49 или SEND на стр. 50).

В процессе создания ассоциаций используется механизм cookie, подобный предложенному Кэрном (Karn) и Симпсоном (Simpson) в [RFC2522], для обеспечения защиты от атак на синхронизацию. Этот механизм использует четырехэтапное согласование (four-way handshake), в котором два последних этапа могут использоваться для передачи пользовательских данных в целях ускорения процедуры соединения. Стартовые последовательности описаны в разделе 5. Создание ассоциации.

Протокол SCTP обеспечивает аккуратное завершение работы активных ассоциаций (shutdown) по запросу пользователя SCTP (см. описание примитива SHUTDOWN на стр. 50). Протокол SCTP позволяет также разрывать ассоциации (abort) по запросу пользователя (примитив ABORT) или в результате обнаружения ошибок на уровне SCTP. В разделе 9 описаны оба варианта завершения работы ассоциаций.

SCTP не поддерживает полуоткрытых состояний (как в TCP), когда одна сторона может передавать данные после того, как другая сторона уже закрыла соединение. Когда любая из конечных точек выполняет процедуру shutdown, на обеих сторонах ассоциации прекращается приём новых данных и доставляются лишь данные из очереди (см. раздел 9).

1.5.2. Упорядоченная доставка в потоках

Термин «поток» (stream) используется в протоколе SCTP для обозначения последовательности пользовательских сообщений, которые доставляются протоколам вышележащих уровней в том же порядке, который сообщения имели в самом потоке. Это отличается от значения термина в контексте TCP, где потоком называют последовательности байтов (в этом документе предполагается, что размер байта составляет 8 битов).

Пользователь SCTP может во время создания ассоциации задать число потоков, поддерживаемых этой ассоциацией. Это значение согласуется с удалённой стороной (см. 5.1.1. Обработка параметров потока). Пользовательские сообщения связываются с номерами потоков (см. примитивы SEND на стр. 50 и RECEIVE на стр. 51). SCTP присваивает порядковые номера в потоке каждому сообщению, полученному протоколом от пользователя SCTP. На приёмной стороне SCTP обеспечивает доставку сообщений пользователю с сохранением их последовательности в данном потоке. В силу того, что один поток может быть заблокирован ожиданием следующего по порядку пользовательского сообщения, в это время возможна доставка сообщений из других потоков.

Протокол SCTP обеспечивает механизм обхода упорядоченной доставки. Пользовательские сообщения, переданные с использованием такого механизма, доставляются пользователю по мере их приёма.

1.5.3. Фрагментация пользовательских данных

При необходимости SCTP фрагментирует пользовательские сообщения, чтобы пакеты SCTP, передаваемые нижележащему уровню, соответствовали значению MTU для пути. При получении фрагменты собираются протоколом SCTP до их доставки пользователю.

1.5.4. Подтверждения и предотвращение перегрузки

SCTP присваивает номер TSN каждому фрагменту и нефрагментированному пользовательскому сообщению. Нумерация TSN не зависит от Stream Sequence Number, присваиваемых на уровне потока. Принимающая сторона подтверждает все полученные TSN даже при обнаружении пропуска в номерах. Если нужно повторно передать фрагмент данных пользователя или нефрагментированное сообщение, используется выделенный номер TSN. Такой подход обеспечивает независимую функциональность для гарантии доставки и сохранения порядка сообщений.

Функция подтверждения и предотвращения перегрузки отвечает за повторную передачу пакетов, когда подтверждение о доставке не приходит от получателя вовремя. Повтор передачи связан с предотвращением перегрузки подобно тому, как это сделано для протокола TCP. В разделах 6 и 7 приводится подробное описание протокольных процедур, связанных с выполнением этой функции.

1.5.5. Группировка блоков

Как описано в разделе 3, пакет SCTP, передаваемый на нижележащий уровень, содержит общий заголовок, за которым следует один или несколько информационных блоков (chunk), каждый из них содержит пользовательские данные или управляющую информацию SCTP. Реализация SCTP, поддерживающая группировку, может задержать на стороне отправителя отправку пользовательских сообщений для группировки соответствующих блоков DATA.

Пользователь SCTP может запросить у реализации передачу своих сообщений без задержки, связанной с группировкой. Однако даже при выборе пользователем этой опции реализация SCTP может задерживать передачу по другим причинам (например, связанным с контролем перегрузки или управлением потоком данных) и группировать блоки DATA, если это возможно.

1.5.6. Проверка пакетов

Обязательное поле Verification Tag и 32-битовая контрольная сумма (см. Приложение A. Расчет контрольной суммы CRC32c), передаются в общем заголовке SCTP. Значение Verification Tag выбирается каждой стороной в процессе создания ассоциации. Пакеты, полученные без ожидаемого значения Verification Tag, отбрасываются в целях защиты от атак вслепую с маскированием адресов и избавления от старых пакетов SCTP, оставшихся от предыдущей ассоциации. Контрольная сумма CRC32c помещается отправителем в каждый пакет SCTP для обеспечения дополнительной защиты от повреждения данных в сети. Получатель пакета SCTP с некорректной контрольной суммой CRC32 c отбрасывает такие пакеты без уведомления.

1.5.7. Управление путями

Передающий пакеты SCTP пользователь может манипулировать набором транспортных адресов, используемых для указания получателя пакетов SCTP с помощью примитивов, описанных в разделе 11. Функция управления путями отслеживает доступность с помощью блоков heartbeat, когда другой трафик не позволяет получить достоверных данных о доступности адресов, и сообщает пользователю об изменениях состояния доступности любых адресов транспортного уровня на удалённой стороне. Функция управления путями SCTP выбирает транспортный адрес получателя для каждого исходящего пакета SCTP на основе пользовательских инструкций и текущей информации о доступности желанного получателя. Функция управления путями отвечает также за передачу информации о доступных локальных адресах транспортного уровня партнёру в процессе создания ассоциации и за передачу пользователю SCTP сведений, полученных от партнёра.

При создании ассоциации определяется основной путь (primary path) для каждой конечной точки SCTP, который используется для нормальной передачи пакетов SCTP.

На приёмной стороне функция управления путями отвечает за проверку наличия пригодной ассоциации SCTP, к которой относятся входящие пакеты SCTP, до передачи таких пакетов на дальнейшую обработку.

Примечание. Функции Path Management и Packet Validation выполняются одновременно, хотя и описаны по отдельности (в реальности эти функции не могут выполняться независимо одна от другой).

1.6. Порядковые номера

Важно помнить, что пространство порядковых номеров TSN ограничено, хотя и достаточно велико. Значения порядковых номеров могут находиться в диапазоне от 0 до 232 — 1. Ввиду конечности пространства TSN все арифметические операции с ними должны осуществляться по модулю 232 — это обеспечит возможность после достижения максимального значения TSN снова перейти к номеру 0. При сравнении значений порядковых номеров следует принимать во внимание цикличность их изменения. Символы =< применительно к TSN означают «меньше или равно» (модуль 232).

При арифметических операциях и сравнении номеров TSN для протокола SCTP следует пользоваться арифметикой порядковых номеров, определённой в [RFC1982] для случая SERIAL_BITS = 32.

Конечным точкам не следует передавать блоки DATA со значением TSN, которое более чем на 231 — 1 превышает начальное значение TSN для текущего окна передачи. Использование таких значений может привести к возникновению проблем при сравнении TSN.

Порядковые номера TSN сбрасываются в 0 при достижении границы 232 — 1. Т. е., следующий блок DATA после блока с TSN = 232 — 1 должен иметь TSN = 0.

Во всех арифметических операциях с порядковыми номерами в потоках (Stream Sequence Number) следует использовать арифметику порядковых номеров, определённую в [RFC1982] для случая SERIAL_BITS = 16. Все прочие операции с порядковыми номерами в данном документе используют обычную арифметику.

1.7. Отличия от RFC 4960

Протокол SCTP был изначально определён в [RFC4960], который данный документ отменяет. Читателям, интересующимся подробностями отличий, рекомендуется прочесть [RFC8540].

В дополнение к этим и последующим редакторским правкам в документ внесены перечисленные ниже изменения.

  • Обновлены ссылки.
  • Улучшен язык описания уровней требований.
  • Примитиву ASSOCIATE разрешено принимать несколько удалённых адресов (см. спецификацию API сокетов).
  • Ссылка на спецификацию Packetization Layer Path MTU Discovery (PLPMTUD) для определения MTU на пути.
  • Описание обработки ICMP перенесено из приложения в основной текст.
  • Удалено приложение с описанием обработки явных уведомлений о перегрузке (ECN).
  • Более точно описана обработка размера пакетов, путём введения PMTU, PMDCS и AMDCS.
  • Добавлено определение управляющего блока (control chunk).
  • Улучшено описание обработки блоков INIT и INIT ACK с непригодными обязательными параметрами.
  • Разрешено применение L > 1 для подсчёта байтов (Appropriate Byte Counting или ABC) при замедленном старте.
  • Явно описана повторная инициализация контроллера перегрузок при смене маршрутов.
  • Улучшена терминология для более ясного представления, что данная спецификация не описывает полносвязную (full mesh) архитектуру.
  • Улучшено описание генерации номеров (Transmission Sequence Number и Stream Sequence Number).
  • Улучшено описание «отречения» (reneging).
  • Больше не требуется изменение Cumulative TSN Ack для увеличения окна перегрузки. Это улучшает согласованность с действиями по предотвращению перегрузки.
  • Улучшено описание State Cookie.
  • Исправлен API для извлечения сообщений при отказах ассоциации.

2. Соглашения о терминах

Ключевые слова должно (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

3. Формат пакетов SCTP

Пакет SCTP состоит из общего заголовка и блоков (chunk), содержащих пользовательские сообщения или управляющую информацию.

Формат пакетов SCTP показан на рисунке.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Common Header                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          Chunk #1                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           ...                                 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          Chunk #n                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Недопустимо группировать INIT, INIT ACK, и SHUTDOWN COMPLETE с другими блоками в один пакет SCTP. Все прочие блоки можно группировать в одном пакете SCTP, пока его размер не превышает значение PMTU. Более подробное описание группировки блоков приводится в параграфе 6.10.

Если пользовательское сообщение не помещается в пакет SCTP, оно может быть разделено на фрагменты с использованием процедуры, описанной в параграфе 6.9.

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

3.1. Описание полей общего заголовка SCTP

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Source Port Number        |     Destination Port Number   |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      Verification Tag                         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           Checksum                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Source Port Number — 16 битов (целое число без знака)

Номер порта SCTP, используемого отправителем. Это значение, вместе с IP-адресом отправителя, номером порта получателя и (возможно) IP-адресом получателя, может использоваться на приёмной стороне для идентификации ассоциации, к которой относится пакет. Значение 0 для номера порта недопустимо.

Destination Port Number — 16 битов (целое число без знака)

Номер порта SCTP, в который данный пакет адресован. На приёмной стороне это значение будет использоваться для демультиплексирования пакета SCTP соответствующей конечной точке или приложению. Значение 0 для номера порт недопустимо.

Verification Tag — 32 бита (целое число без знака)

Принимающая сторона использует Verification Tag для проверки отправителя пакета SCTP. На передающей стороне значение поля Verification Tag должно устанавливаться в соответствии со значением Initiate Tag, полученным от партнёра при инициализации ассоциации, за исключением перечисленных ниже случаев.

  • В пакетах, содержащих блок INIT, тег Verification должен быть установлен в 0.
  • В пакетах, содержащих блок SHUTDOWN-COMPLETE с установленным флагом T, значение тега Verification должно копироваться из пакета с блоком SHUTDOWN-ACK.
  • В пакетах, содержащих блок ABORT, тег верификации может быть копией Verification Tag из пакета, вызвавшего передачу блока ABORT. Более подробное описание приведено в параграфах 8.4 и 8.5.

Checksum — 32 бита (целое число без знака)

Это поле содержит контрольную сумму для данного пакета SCTP. Расчёт контрольных сумм описан в параграфе 6.8. Протокол SCTP использует алгоритм CRC32c, описанный в Приложении A.

3.2. Описание поля Chunk

На рисунке показан формат блоков (chunk), передаваемых в пакетах SCTP. Каждый блок содержит поле Chunk Type, зависящие от типа флаги (Chunk Flags), поле размера Chunk Length и поле данных Chunk Value.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Chunk Type  | Chunk  Flags  |        Chunk Length           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\                                                               \
/                          Chunk Value                          /
\                                                               \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Chunk Type — 8 битов (целое число без знака)

Это поле указывает тип блока, содержащегося в поле Chunk Value. Поле типа может содержать значения от 0 до 254. Значение 255 зарезервировано для будущего использования в качестве расширения.

Значения идентификаторов типа приведены в таблице.

Таблица 1. Типы блоков.

ID Тип блока ID Тип блока
0 Пользовательские данные (DATA) 12 Резерв для Explicit Congestion Notification Echo (ECNE)9
1 Инициализация (INIT) 13 Резерв для Congestion Window Reduced (CWR)
2 Подтверждение инициирования (INIT ACK) 14 Окончание работы завершен0 (SHUTDOWN COMPLETE)
3 Выборочное подтверждение (SACK) 15 — 62 Не выделены
4 Запрос Heartbeat (HEARTBEAT) 63 Резерв для определённых IETF расширений
5 Подтверждение Heartbeat (HEARTBEAT ACK) 64 — 126 Не выделены
6 Прерывание (ABORT) 127 Резерв для определённых IETF расширений
7 Завершение работы (SHUTDOWN) 128 — 190 Не выделены
8 Подтверждение завершения (SHUTDOWN ACK) 191 Резерв для определённых IETF расширений
9 Ошибка при операции (ERROR) 192 — 254 Не выделены
10 State Cookie (COOKIE ECHO) 255 Резерв для определённых IETF расширений
11 Подтверждение Cookie (COOKIE ACK)

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

Таблица 2. Обработка неизвестных блоков.

00 Прекратить обработку данного пакета SCTP и отбросить нераспознанный блок и следующие за ним блоки.
01 Прекратить обработку данного пакета SCTP и отбросить нераспознанный блок и следующие за ним блоки, а также сообщить о неопознанном блоке в блоке ERROR с причиной ошибки Unrecognized Parameter Type.
10 Пропустить данный блок и продолжить обработку пакета.
11 Пропустить данный блок и продолжить обработку пакета, а также сообщить о неопознанном блоке в блоке ERROR с причиной ошибки Unrecognized Parameter Type.

Chunk Flags — 8 битов

Использование этих битов зависит от поля Chunk Type. Если в документе явно не указано иное, на передающей стороне все биты следует устанавливать в 0, а на приёмной — игнорировать.

Chunk Length — 16 битов (целое число без знака)

Размер блока в байтах с учётом полей Chunk Type, Chunk Flags, Chunk Length и Chunk Value. Для блоков с пустым Chunk Value поле размера имеет значение 4. Байты заполнения блока в поле Chunk Length не включаются, однако считаются байты заполнения имеющихся параметров переменного размера, за исключением последнего10.

Chunk Value — переменный размер

Поле Chunk Value содержит передаваемую в этом блоке информацию. Формат этого поля и способы его использования зависят от значения Chunk Type.

Общий размер блока (включая поля Type, Length и Value) должен быть кратным 4. Если размер блока не кратен 4, отправитель должен дополнить блок байтами со значением 0, не учитывая эти байты в поле Chunk Length. Заполнение размером долее 3 байтов недопустимо. Получатель должен игнорировать байты заполнения.

Подробное описание используемых в SCTP блоков приводится в параграфе 3.3. Руководства для создания расширений, определяемых IETF, приведены в параграфе 15.1.

3.2.1. Необязательные параметры и поля переменного размера

Блоки управления SCTP включают зависящий от типа блока заголовок с набором полей, за которым может следовать то или иное количество параметров. Необязательные параметры и поля переменной длины указываются в формате TLV11 как описано ниже.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Parameter Type        |      Parameter Length         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\                                                               \
/                       Parameter Value                         /
\                                                               \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Parameter Type — 16 битов (целое число без знака)

16-битовый идентификатор типа параметра и может принимать значения от 0 до 65534.

Значение 65535 зарезервировано для определяемых IETF расширений. Все значения, кроме перечисленных в данном документе при описании конкретных блоков SCTP, зарезервированы для использования IETF.

Parameter Length — 16 битов (целое число без знака)

Размер параметра в байтах с учётом полей Parameter Type, Parameter Length и Parameter Value. Для параметров с пустым полем Parameter Value поле размера имеет значение 4. Размер не учитывает байты заполнения.

Parameter Value — переменный размер

Поле Parameter Value содержит информацию, передаваемую с помощью данного параметра.

Общий размер параметра (включая поля Type, Length и Value) должен быть кратным 4. Если размер параметра не кратен 4, отправитель добавляет в конце (после Parameter Value) байты с нулевым значением. Байты заполнения не учитываются в поле размера. Для отправителя недопустимо использование более 3 байтов заполнения. Получатель должен игнорировать байты заполнения.

Поле Parameter Type кодируется так, чтобы два старших бита определяли действия, предпринимаемые обрабатывающей конечной точкой при обнаружении неизвестного типа параметра.

Таблица 3. Обработка неизвестных параметров.

00 Прекратить обработку данного параметра и следующих за ним параметров в этом блоке.
01 Прекратить обработку данного параметра и следующих за ним параметров в этом блоке, а также сообщить о неопознанном параметре, как указано в параграфе 3.2.2.
10 Пропустить данный параметр и продолжить обработку.
11 Пропустить данный параметр и продолжить обработку пакета, а также сообщить о неопознанном параметре, как указано в параграфе 3.2.2.

Следует отметить, что при получении блока INIT или INIT ACK во всех 4 случаях в ответ передаётся блок INIT ACK или COOKIE ECHO. Для случаев 00 и 01 обработка параметров после неизвестного параметра не производится, но уже обработанные параметры не отбрасываются.

Реальные параметры SCTP определяются в параграфах, посвящённых конкретным блокам SCTP. Правила для определённых IETF расширений параметров определены в параграфе 15.3. Отметим, что тип параметра должен быть уникальным для всех блоков. Например, тип параметра 5 используется для представления адресов IPv4 (см. параграф 3.3.2.1.1). Значение 5 в этом случае резервируется во всех блоках для представления адресов IPv4 и недопустимо его использование в ином смысле в любом другом блоке.

3.2.2. Уведомления о неизвестных параметрах

Если получатель блока INIT обнаруживает неизвестный параметр и сообщает о нем в соответствии с параграфом 3.2.1, он должен указать параметр(ы) в поле Unrecognized Parameter блока INIT ACK, передаваемого в ответ на INIT. Отметим, что если получатель блока INIT не организует ассоциацию (например, по причине нехватки ресурсов), поле Unrecognized Parameter не включается в блок ABORT, передаваемый в ответ на INIT.

Если получатель блока любого другого блока (например, INIT ACK) обнаруживает неизвестные параметры и сообщает о них в соответствии с параграфом 3.2.1, ему следует сгруппировать блок ERROR, содержащий поля Unrecognized Parameter с указанием причины ошибки, с блоком, передаваемым в ответ (например, COOKIE ECHO). Если получатель INIT ACK не группирует блок COOKIE ECHO с блоком ERROR, последний можно передать отдельно, но не раньше получения COOKIE ACK.

В любом случае передачи в пакете блока COOKIE ECHO он должен быть первым блоком.

3.3. Определения блоков SCTP

В этом разделе описываются форматы блоков SCTP различных типов.

3.3.1. Пользовательские данные (DATA) (0)

Для блоков DATA должен использоваться показанный на рисунке формат.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Type = 0    |  Res  |I|U|B|E|    Length                     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                              TSN                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      Stream Identifier S      |   Stream Sequence Number n    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                  Payload Protocol Identifier                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\                                                               \
/         User Data (последовательность n потока S)             /
\                                                               \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Res — 4 бита

Отправителю следует заполнить это поле нулями, а получателю — игнорировать его.

I — 1 бит

Бит I (immediate) отправитель может устанавливать всякий раз, когда может при отправке блока DATA получить преимущество в результате отправки соответствующего блока SACK без задержки (см. раздел 4 в [RFC7053].

U — 1 бит

Флаг разупорядочения, устанавливаемый для блоков DATA, которые могут передаваться без сохранения порядка. Для таких блоков значение поля Stream Sequence Number не задаётся и получатель должен его игнорировать.

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

Если неупорядоченное пользовательское сообщение фрагментируется, для каждого фрагмента должен устанавливаться флаг U = 1.

B — 1 бит

Флаг первого фрагмента пользовательского сообщения.

E — 1 бит

Флаг последнего фрагмента пользовательского сообщения.

Length — 16 битов (целое число без знака)

Размер блока DATA в байтах от начала поля типа и до конца поля User Data (без учёта байтов заполнения). Для блока DATA с одним байтом пользовательских данных Length = 17 (17 байтов). Блок DATA с полем User Data размера L будет иметь поле Length со значением (16 + L), где L должно быть больше 0.

TSN — 32 бита (целое число без знака)

Порядковый номер TSN для блока DATA. Значения номеров TSN могут находиться в диапазоне от 0 до 4294967295 (232 — 1). После достижения TSN максимального значения 4294967295 нумерация продолжается с 0.

Stream Identifier S — 16 битов (целое число без знака)

Идентификатор потока, к которому относится блок данных.

Stream Sequence Number n — 16 битов (целое число без знака)

Порядковый номер пользовательских данных в потоке S. Допустимые значения лежат в диапазоне от 0 до 65535.

При фрагментировании пользовательского сообщения протоколом SCTP в каждом фрагмент должен указываться одинаковый порядковый номер в потоке.

Payload Protocol Identifier — 32 бита (целое число без знака)

Заданный приложением или вышележащим протоколом идентификатор протокола данных. SCTP получает идентификатор от вышележащего уровня и передаёт его партнёру. Значение идентификатора не используется протоколом SCTP, но может быть использовано некоторыми сетевыми объектами и приложениями у партнёра для идентификации типа информации, передаваемой в блоке DATA. Это поле должно передаваться даже для фрагментированных блоков DATA (чтобы обеспечить доступность информации для агентов в сети). Отметим, что реализации SCTP не работают с этим полем и за преобразование между сетевым и хостовым порядком байтов в этом поле отвечает вышележащий уровень.

Значение 0 говорит, что протокол вышележащего уровня не указал идентификатор протокола для этого блока.

User Data — переменный размер

Поле переменной длины, содержащее пользовательскую информацию. Реализация протокола должна дополнять поле до 4-байтовой границе путём добавления байтов с нулевым значением. Недопустимо учитывать байты заполнения в поле размера блока. Для отправителя недопустимо использование более 3 байтов заполнения.

В нефрагментированных пользовательских сообщениях должны устанавливаться (1) оба флага B и E. Нулевые значения обоих флагов устанавливаются в средних (не первом и не последнем) фрагментах пакета, как показано в таблице 4.

Таблица 4. Состояния флагов B и E.

B E Описание
1 0 Первый фрагмент.
0 0 Один из средних фрагментов.
0 1 Последний фрагмент.
1 1 Нефрагментированное сообщение.

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

TSN в блоках DATA следует строго упорядочивать.

Примечание. Можно применять расширение, описанное в [RFC8260] для снижения блокировки head-of-line при передаче больших пользовательских сообщений.

3.3.2. Инициализация (INIT) (1)

Этот блок используется для создания ассоциации SCTP между парой конечных точек. Формат блока INIT показан на рисунке.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Type = 1    |  Chunk Flags  |      Chunk Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         Initiate Tag                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Advertised Receiver Window Credit (a_rwnd)          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Number of Outbound Streams   |  Number of Inbound Streams    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          Initial TSN                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\                                                               \
/     Необязательные параметры и параметры переменной длины     /
\                                                               \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Блок INIT содержит перечисленные ниже параметры. Если явно не сказано иное, каждый параметр должен включаться в блок INIT в одном экземпляре.

Таблица 5. Параметры фиксированного размера в блоках INIT.

Фиксированные параметры Статус
Initiate Tag Обязательный
Advertised Receiver Window Credit Обязательный
Number of Outbound Streams Обязательный
Number of Inbound Streams Обязательный
Initial TSN Обязательный

Таблица 6. Параметры переменного размера в блоках INIT.

Переменные параметры Статус Тип
IPv4 Address12 Необязательный 5
IPv6 Address1 Необязательный 6
Cookie Preservative Необязательный 9
Reserved for ECN Capable13 Необязательный 32768 (0x8000)
Host Name Address14 Отменён 11
Supported Address Types15 Необязательный 12

Если принят блок INIT со всеми обязательными параметрами, заданными для блока INIT, получателю следует обработать блок INIT и возвратить отправителю INIT ACK. Получатель блока INIT может позднее сгруппировать блок ERROR с блоком COOKIE ACK. Однако ограниченная реализация может возвратить блок ABORT в ответ на блок INIT.

Поле Chunk Flags в INIT является резервным и отправителю следует устанавливать все его биты в 0, а получателю — игнорировать их.

Initiate Tag — 32 бита (целое число без знака)

Получатель INIT (отвечающая сторона) записывает значение параметра Initiate Tag. Это значение должно включаться в поле Verification Tag каждого пакета SCTP, который получатель данного блока INIT будет передавать через эту ассоциацию.

Поле Initiate Tag может содержать любые значения кроме 0. Рекомендации по выбору значений этого тега приводятся в параграфе 5.3.1.

Если в принятом блоке INIT значение Initiate Tag = 0, получатель должен отбрасывать пакет без иных действий.

Advertised Receiver Window Credit (a_rwnd) — 32 бита (целое число без знака)

Размер (в байтах) выделенного буферного пространства, которое отправитель INIT зарезервировал для данной ассоциации.

Для Advertised Receiver Window Credit недопустимы значения меньше 1500.

Получатель блока INIT с a_rwnd < 1500 должен отбросить пакет, ему следует передать в ответ пакет с блоком ABORT и использовать Initiate Tag как Verification Tag, а также недопустимо менять состояние оюбой имеющейся ассоциации.

В течение срока существования ассоциации не следует снижать размер этого буфера (т. е., буфер может быть удалён из ассоциации), однако конечная точка может изменить размер a_rwnd, передаваемого в SACK.

Number of Outbound Streams (OS) — 16 битов (целое число без знака)

Число исходящих потоков, которые отправитель блока INIT желает открыть для данной ассоциации. Для этого параметра недопустимо использование значения 0.

Получатель блока INIT с OS = 0 должен отбросить пакет, ему следует передать в ответ пакет с блоком ABORT и использовать Initiate Tag как Verification Tag, а также недопустимо менять состояние оюбой имеющейся ассоциации.

Number of Inbound Streams (MIS) — 16 битов (целое число без знака)

Максимальное число потоков, которые отправитель данного блока INIT готов принять от партнёра для этой ассоциации16. Использование значений 0 в данном поле недопустимо.

Получатель блока INIT с с MIS = 0 должен отбросить пакет, ему следует передать в ответ пакет с блоком ABORT и использовать Initiate Tag как Verification Tag, а также недопустимо менять состояние оюбой имеющейся ассоциации.

Initial TSN (I-TSN) — 32 бита (целое число без знака)

Определяет начальное значение TSN, которое будет использовать отправитель. Диапазон допустимых значений — от 0 до 4294967295 и следует устанавливать случайное значение из этого диапазона. Для выбора случайного значения можно использовать методы, описанные в [RFC4086].

3.3.2.1. Необязательные параметры и параметры переменного размера в блоке INIT

Перечисленные ниже параметры используют формат TLV, как описано в параграфе 3.2.1. Любые комбинации параметров TLV должны размещаться в блоке после параметров фиксированного размера, описанных в предыдущем параграфе.

3.3.2.1.1. Параметр IPv4 Address (5)
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|        Type = 5               |      Length = 8               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        IPv4 Address                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

IPv4 Address — 32 бита (целое число без знака)

Адрес IPv4 передающей стороны в двоичном формате.

3.3.2.1.2. Параметр IPv6 Address (6)
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Type = 6           |          Length = 20          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                         IPv6 Address                          |
|                                                               |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

IPv6 Address — 128 битов (целое число без знака)

Адрес IPv6 [RFC2460] передающей стороны в двоичном формате.

Отправителю недопустимо использовать адреса отображённые на IPv4 адреса IPv6 [RFC4291], вместо этого следует применять параметр IPv4 Address для адреса IPv4.

Вместе с Source Port Number в общем заголовке SCTP адрес IPv4 или IPv6 определяет адрес транспортного уровня, который отправитель блока INIT будет поддерживать для создаваемой ассоциации. Т. е., этот IP-адрес в течении срока действия данной ассоциации может появляться в поле отправителя дейтаграмм IP, передаваемых отправителем данного блока INIT, и может использоваться в качестве IP-адреса получателя в дейтаграммах, передаваемых получателем данного блока INIT.

В блоке INIT можно указывать более одного адреса IP, если отправитель INIT является многодомным хостом. Кроме того, многодомные хосты могут быть подключены к разнотипным сетям и в блоках INIT могут указываться одновременно адреса IPv4 и IPv6.

Если INIT содержит хотя бы один параметр IP Address, адрес отправителя в дейтаграмме, содержащей блок INIT, и любые адреса, указанные в INIT, могут использоваться партнёром при ответе в качестве адреса получателя. Если INIT не содержит параметров IP Address, получившая блок INIT конечная точка должна использовать адрес отправителя в заголовке дейтаграммы IP, содержащей блок INIT, как единственный адрес партнёра в данной ассоциации.

Отметим, что отсутствие параметров IP Address в блоках INIT и INIT ACK упрощает организацию ассоциаций при работе через системы трансляции адресов (Network Address Translation или NAT).

3.3.2.1.3. Параметр Cookie Preservative (9)

Отправителю блока INIT следует использовать этот параметр для того, чтобы предложить получателю INIT увеличение срока действия State Cookie.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Type = 9             |          Length = 8           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Suggested Cookie Life-span Increment (мсек.)          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Suggested Cookie Life-Span Increment — 32 бита (целое число без знака)

Показывает получателю размер увеличения срока действия cookie в миллисекундах.

Этот необязательный параметр отправителю следует добавлять в блок INIT при попытке создания ассоциации после отказа в предыдущей попытке по причине ошибки в работе stale cookie. Получатель может проигнорировать предложенное увеличение срока действия cookie в соответствии со своей политикой безопасности.

3.3.2.1.4. Параметр Host Name Address (11)

Отправителю блока INIT или INIT ACK недопустимо включать этот параметр, поскольку его использование отменено. Получатель блока INIT или INIT ACK с параметром Host Name Address должен передать блок ABORT и может включить в него причину Unresolvable Address.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Type = 11            |          Length               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/                          Host Name                            /
\                                                               \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Host Name — переменный размер

Это поле содержит имя хоста с использованием синтаксиса, определённого в параграфе 2.1 RFC1123 [RFC1123]. Метод преобразования имени в адрес выходит за рамки спецификации протокола SCTP.

Имя хоста должно содержать хотя бы один завершающий null-символ, который учитывается в поле размера.

3.3.2.1.5. Параметр Supported Address Types (12)
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Type = 12            |          Length               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|        Address Type #1        |        Address Type #2        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            ......                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Отправитель блока INIT использует этот параметр для перечисления всех поддерживаемых им типов адресов.

Address Type — 16 битов (целое число без знака)

В этом поле указываются типы адреса из соответствующих TLV (например, IPv4 = 5, IPv6 = 6). Значение, указывающее параметр Host Name Address, недопустимо использовать при передачи, а при получении оно должно игнорироваться.

3.3.3. Подтверждение инициализации (INIT ACK) (2)

Блок INIT ACK используется для подтверждения инициирования ассоциации SCTP. Формат блока показан на рисунке.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Type = 2    |  Chunk Flags  |      Chunk Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         Initiate Tag                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|              Advertised Receiver Window Credit                |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Number of Outbound Streams   |  Number of Inbound Streams    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          Initial TSN                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\                                                               \
/     Необязательные параметры и параметры переменной длины     /
\                                                               \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Параметры INIT ACK форматируются подобно параметрам блока INIT и показаны в таблицах ниже.

Таблица 7. Параметры фиксированного размера в блоках INIT ACK.

Фиксированные параметры Статус
Initiate Tag Обязательный
Advertised Receiver Window Credit Обязательный
Number of Outbound Streams Обязательный
Number of Inbound Streams Обязательный
Initial TSN Обязательный

Блоки INIT ACK содержат два дополнительных параметра — State Cookie и Unrecognized Parameter.

Таблица 8. Параметры переменного размера в блоках INIT ACK.

Переменные параметры Статус Тип
State Cookie Обязательный 7
IPv4 Address17 Необязательный 5
IPv6 Address1 Необязательный 6
Unrecognized Parameter Необязательный 8
Reserved for ECN Capable18 Необязательный 32768 (0x8000)
Host Name Address19 Отменён 11

Поле Chunk Flags в блоках INIT ACK является резервным, в нем следует устанавливать 0 при передаче и игнорировать при получении.

Initiate Tag — 32 бита (целое число без знака)

Получатель блока INIT ACK записывает значение параметра Initiate Tag. Это значение должно помещаться в поле Verification Tag каждого пакета SCTP, который получатель INIT ACK будет передавать в данной ассоциации.

Для Initiate Tag недопустимо использование значения 0. Выбор значений параметра Initiate Tag рассматривается в параграфе 5.3.1.

Если в полученном блоке INIT ACK параметр Initiate Tag = 0, приёмная сторона должна отбросить TCB и ей следует передать блок ABORT с установленным флагом T. Если такой блок INIT ACK получен в состоянии, отличном от CLOSED и COOKIE-WAIT, его следует просто отбросить (см. параграф 5.2.3).

Advertised Receiver Window Credit (a_rwnd) — 32 бита (целое число без знака)

Это значение указывает размер буфера (в байтах), выделенного отправителем INIT ACK для данной ассоциации.

Недопустимо устанавливать для этого параметра значение < 1500.

Получатель блока INIT ACK с a_rwnd < 1500 должен отбросить пакет, следует передать блок ABORT и использовать Initiate Tag в качестве Verification Tag. Менять состояние ассоциации недопустимо.

В течение срока действия ассоциации не следует уменьшать размер буфера (т. е., выделенный буфер не удаляется из ассоциациеи), однако конечная точка может изменить значение a_rwnd в блоках SACK.

Number of Outbound Streams (OS) — 16 битов (целое число без знака)

Число исходящих потоков, которые отправитель INIT ACK желает создать для данной ассоциации. Недопустимо устанавливать для этого параметра значение 0, недопустимо также устанавливать значение, превышающее значение MIS, переданное в блоке INIT.

Если конечная точка в состоянии COOKIE-WAIT получает INIT ACK с параметром OS = 0, она должна отбросить TCB и следует передать блок ABORT. Если такой блок INIT ACK получен в состоянии, отличном от CLOSED и COOKIE-WAIT, его следует просто отбросить (см. параграф 5.2.3).

Number of Inbound Streams (MIS) — 16 битов (целое число без знака)

Максимальное число потоков, которые отправитель INIT ACK позволяет создать удалённому партнёру в данной ассоциации20. Недопустимо использование нулевого значения для этого параметра.

Если конечная точка в состоянии COOKIE-WAIT получает INIT ACK с параметром MIS = 0, она должна отбросить TCB и следует передать блок ABORT. Если такой блок INIT ACK получен в состоянии, отличном от CLOSED и COOKIE-WAIT, его следует просто отбросить (см. параграф 5.2.3).

Initial TSN (I-TSN) — 32 бита (целое число без знака)

Начальный номер TSN, который отправитель INIT ACK будет использовать. Корректные значения лежат в диапазоне от 0 до 4294967295 и следует устанавливать случайное значение из этого диапазона. Для выбора случайного значения можно использовать методы, описанные в [RFC4086].

Примечание для разработчиков. Реализации должны быть готовы к получению INIT ACK достаточно большого (более 1500 байтов) размера по причине переменного размера State Cookie и списка адресов. Например, если отвечающая на INIT сторона имеет 1000 адресов IPv4, которые она желает сообщить, для них потребуется не менее 8000 байтов в блоке INIT ACK.

Если принят блок INIT ACK со всеми обязательными для него параметрами, получателю следует обработать блок INIT ACK и передать в ответ COOKIE ECHO. Получатель INIT ACK может группировать блок ERROR с блоком COOKIE ECHO. Однако ограниченные реализации могут передавать блок ABORT в ответ на INIT ACK.

Вместе с параметром Source Port Number в общем заголовке SCTP параметр IP Address в INIT ACK указывает получателю INIT ACK адрес транспортного уровня, который отправитель блока INIT ACK будет поддерживать в течение срока действия создаваемой ассоциации.

Если INIT ACK содержит хотя бы один параметр IP Address, указанные в нем адреса вместе с адресом отправителя в заголовке дейтаграммы IP, содержащей INIT ACK, могут использоваться получателем INIT ACK блока в качестве адресов получателя для этой ассоциации. Если в INIT ACK нет параметра IP Address, получатель блока INIT ACK должен использовать адрес отправителя содержащей этот блок дейтаграммы IP в качестве единственного адреса получателя для этой ассоциации.

Параметры State Cookie и Unrecognized Parameters используют формат TLV в соответствии с определением параграфа 3.2.1 и описаны ниже. Остальные поля соответствуют одноимённым полям блока INIT.

3.3.3.1. Необязательные параметры и параметры переменной длины в INIT ACK

Для State Cookie и Unrecognized Parameters применяется формат TLV, как определено в параграфе 3.2.1 и описано ниже. Параметр IPv4 Address описан в параграфе 3.3.2.1.1, а IPv6 Address — в 3.3.2.1.2. Параметр Host Name Address, описанный в параграфе 3.3.2.1.4, недопустимо включать в блок INIT ACK. Все поля TLV должны размещаться после полей фиксированного размера (они определены в предыдущем параграфе).

3.3.3.1.1. Параметр State Cookie (7)

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 7 | Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / Cookie / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Cookie — переменный размер

Значение этого параметра должно включать всю необходимую информацию о состоянии и параметрах, требуемую отправителю данного блока INIT ACK для создания ассоциации, а также код аутентификации сообщения (Message Authentication Code или MAC). Определение State Cookie дано в параграфе 5.1.3.

3.3.3.1.2. Параметр Unrecognized Parameter (8)

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 8 | Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / Unrecognized Parameter / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Unrecognized Parameter — переменный размер

Это поле содержит нераспознанный параметр (полный TLV), скопированный из блока INIT.

3.3.4. Селективное подтверждение (SACK) (3)

Этот блок передаётся партнёру для подтверждения приёма блоков DATA и информирования партнёра о пропусках в порядковых номерах блоков DATA, представленных в TSN.

Блок SACK должен включать поля Cumulative TSN Ack, Advertised Receiver Window Credit (a_rwnd), Number of Gap Ack Blocks и Number of Duplicate TSNs.

По определению поле Cumulative TSN Ack содержит значение последнего номера TSN, полученного до того, как была нарушена последовательность принятых TSN. Следующее за этим значение TSN (на 1 больше) ещё не получено стороной, передающей SACK. Этот параметр, следовательно, подтверждает доставку всех TSN, номера которых не превышают значение поля.

Обработка a_rwnd получателем SACK рассмотрена в параграфе 6.2.1

SACK может также содержать параметры Gap Ack Block, каждый из которых подтверждает последовательность TSN, полученных после прерывания основной последовательности номеров TSN. Блокам Gap Ack Block следует быть изолированными, т. е. TSN непосредственно перед и сразу после Gap Ack Block не получены. По определению все TSN, подтверждённые Gap Ack Block, имеют значения, превышающие Cumulative TSN Ack.

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 3 |Chunk Flags | Chunk Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cumulative TSN Ack | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Advertised Receiver Window Credit (a_rwnd) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Number of Gap Ack Blocks = N | Number of Duplicate TSNs = X | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Gap Ack Block #1 Start | Gap Ack Block #1 End | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ … \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Gap Ack Block #N Start | Gap Ack Block #N End | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Duplicate TSN 1 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ … \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Duplicate TSN X | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chunk Flags — 8 битов

Заполняется нулями на передающей стороне и игнорируется на приёмной.

Cumulative TSN Ack — 32 бита (целое число без знака)

Наибольшее значение TSN, такое что все значения, не превышающие его, уже получены, а следующее не получено. Если блоков DATA ещё не получено, это поле содержит партнерское значение Initial TSN — 1.

Advertised Receiver Window Credit (a_rwnd) — 32 бита (целое число без знака)

Обновлённое значение размера (в байтах) приёмного буфера на стороне отправителя данного блока SACK (см. параграф 6.2.1).

Number of Gap Ack Blocks — 16 битов (целое число без знака)

Число параметров Gap Ack Block, включённых в SACK.

Number of Duplicate TSNs — 16 битов

Число дубликатов TSN, полученных конечной точкой. Каждый дубликат TSN указывается в последующем списке Gap Ack Block.

Блоки Gap Ack

Эти поля содержат параметры Gap Ack Block, число которых задано значением поля Number of Gap Ack Blocks. Все блоки DATA с номерами TSN не меньше Cumulative TSN Ack + Gap Ack Block Start и не больше Cumulative TSN Ack + Gap Ack Block End из каждого Gap Ack Block предполагаются принятыми без ошибок.

Gap Ack Block Start — 16 битов (целое число без знака)

Показывает стартовое смещение TSN данного Gap Ack Block. Для расчёта реального номера TSN это смещение добавляется к значению параметра Cumulative TSN Ack. Рассчитанное таким способом значение TSN указывает первый номер TSN в данном Gap Ack Block, который был получен.

Gap Ack Block End — 16 битов (целое число без знака)

Показывает финишное смещение TSN данного Gap Ack Block. Для расчёта реального номера TSN это смещение добавляется к значению параметра Cumulative TSN Ack. Рассчитанное таким способом значение TSN указывает последний номер TSN в данном Gap Ack Block для полученного блока DATA.

Предположим для примера, что недавно полученные блоки DATA в момент принятия решения о передаче SACK образуют последовательность, показанную на рисунке.

———- | TSN=17 | ———- | | <- не получен ———- | TSN=15 | ———- | TSN=14 | ———- | | <- не получен ———- | TSN=12 | ———- | TSN=11 | ———- | TSN=10 | ———-
Тогда часть блока SACK должна включать поля, показанные на следующем рисунке (предполагается, что новое значение a_rwnd = 4660).

+———————————+ | Cumulative TSN Ack = 12 | +———————————+ | a_rwnd = 4660 | +—————-+—————+ | num of block=2 | num of dup=0 | +—————-+—————+ |block #1 strt=2 |block #1 end=3 | +—————-+—————+ |block #2 strt=5 |block #2 end=5 | +—————-+—————+

Duplicate TSN — 32 бита (целое число без знака)

Показывает количество случаев, когда номер TSN был принят как дубликат, с момента передачи последнего блока SACK. При получении каждого дубликата TSN (до момента передачи SACK) этот дубликат добавляется в список. Счётчик дубликатов сбрасывается в 0 после отправки каждого блока SACK.

Например, если получатель принял TSN 19 трижды, номер 19 будет указан два раза в блоке SACK. После отправки SACK, если TSN 19 будет принят снова, он будет указан в списке следующего блока SACK.

3.3.5. Запрос Heartbeat (HEARTBEAT) (4)

Конечной точке следует передавать блок HEARTBEAT (HB) своему партнёру для проверки его доступности через конкретный транспортный адрес, заданный для данной ассоциации.

Поле параметров содержит Heartbeat Information — не анализируемую (opaque) структуру данных переменного размера, понятную только отправителю.

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 4 | Chunk Flags | Heartbeat Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \ \ / Heartbeat Information TLV (переменный размер) / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chunk Flags — 8 битов

Устанавливается в 0 на передающей стороне и игнорируется на приёмной.

Heartbeat Length — 16 битов (целое число без знака)

Размер блока в байтах с учётом заголовка и поля Heartbeat Information.

Heartbeat Information — переменный размер

Параметр переменного размера, который использует формат, описанный в параграфе 3.2.1.

Таблица 9. Параметры переменного размера в блоке HEARTBEAT.

Параметр Статус Тип
Heartbeat Info Обязательный 1

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Heartbeat Info Type=1 | HB Info Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / Sender-Specific Heartbeat Info / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

В поле Sender-Specific Heartbeat Info обычно следует включать информацию о текущем времени отправителя на момент передачи данного блока HEARTBEAT и транспортный адрес получателя этого блока (см. параграф 8.3). Эта информация просто «отражается» получателем в его блоке HEARTBEAT ACK (см. параграф 3.3.6). Отметим также, что сообщения HEARTBEAT служат для проверки доступности и верификации пути (см. параграф 5.4). При использовании блока HEARTBEAT для проверки пути он должен включать случайное значение не менее 64 битов (см. рекомендации по созданию случайных чисел в [RFC4086]).

3.3.6. Подтверждение Heartbeat (HEARTBEAT ACK) (5)

Конечная точка должна передавать такой блок в ответ на запрос HEARTBEAT (см. параграф 8.3). Пакет с блоком HEARTBEAT ACK всегда передаётся по тому адресу IP, который был указан в заголовке дейтаграммы, содержавшей запрос HEARTBEAT, на который передаётся отклик.

Поле параметра содержит «непрозрачную» структуру данных с переменным размером.

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 5 | Chunk Flags | Heartbeat Ack Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \ \ / Heartbeat Information TLV (переменный размер) / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chunk Flags — 8 битов

Устанавливается в 0 на передающей стороне и игнорируется на приёмной.

Heartbeat Length — 16 битов (целое число без знака)

Задаёт размер блока в байтах с учётом заголовка и поля Heartbeat Information.

Heartbeat Information — переменный размер

Это поле должно содержать параметр Heartbeat Information из запроса Heartbeat, на который отвечает данный блок Heartbeat Acknowledgement.

Таблица 10. Параметры переменного размера в блоке HEARTBEAT ACK.

Параметр Статус Тип
Heartbeat Info Обязательный 1

3.3.7. Разрыв ассоциации (ABORT) (6)

Блок ABORT передаётся партнёру для разрыва ассоциации. Блок ABORT может содержать параметры Error Cause, информирующие партнёра о причинах разрыва ассоциации. Недопустимо группировать блоки DATA с блоком ABORT. Блоки управления (кроме INIT, INIT ACK и SHUTDOWN COMPLETE) могут группироваться с ABORT, но эти блоки должны размещаться перед блоком ABORT в пакете SCTP, поскольку в противном случае получатель проигнорирует их.

Если конечная точка получает блок ABORT с некорректным форматом или TCB не найден, такой блок должен быть просто отброшен. Более того, в некоторых случаях для получившей такой блок ABORT конечной точки недопустимо передавать в ответ свой блок ABORT.

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 6 |Reserved |T| Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \ \ / Причины ошибок (Error Cause) / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chunk Flags — 8 битов

Reserved — 7 битов

Устанавливается в 0 на передающей стороне и игнорируется на приёмной.

T — 1 бит

Бит T сбрасывается в 0, если отправитель заполнил поле Verification Tag, ожидаемое партнёром. Если в Verification Tag используется «отражённое» значение, должно устанавливаться T = 1. Отражение означает, что переданное значение Verification Tag совпадает с принятым.

Length — 16 битов (целое число без знака)

Указывает размер блока в байтах с учётом заголовка и всех полей Error Cause.

Определения причин ошибки (Error Cause) приведены в параграфе 3.3.10.

Примечание. Для проверки этого типа блоков применяются специальные правила, описанные в параграфе 8.5.1.

3.3.8. Завершение ассоциации (SHUTDOWN) (7)

Конечная точка ассоциации должна использовать этот блок для аккуратного завершения работы ассоциации. Формат блока описан ниже.

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 7 | Chunk Flags | Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cumulative TSN Ack | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chunk Flags — 8 битов

Устанавливается в 0 на передающей стороне и игнорируется на приёмной.

Length — 16 битов (целое число без знака)

Показывает размер параметра и имеет значение 8.

Cumulative TSN Ack — 32 бита (целое число без знака)

Этот параметр содержит номер последнего TSN, принятого без пропусков в нумерации.

Примечание. Поскольку блок SHUTDOWN не содержит параметров Gap Ack Block, он не может служить подтверждением TSN, принятых с нарушением порядка. В блоках SACK отсутствие Gap Ack Block, которые были указаны в предыдущих сообщениях, показывает, что получатель данных отказался от соответствующих блоков DATA.

Поскольку SHUTDOWN не содержит Gap Ack Block, получателю блока SHUTDOWN недопустимо интерпретировать отсутствие Gap Ack Block как отказ (см. параграф 6.2).

Отправитель блока SHUTDOWN может сгруппировать его с блоком SACK для указания пропусков в полученных TSN.

3.3.9. Подтверждение закрытия ассоциации (SHUTDOWN ACK) (8)

Этот блок должен использоваться для подтверждения приёма блока SHUTDOWN при завершении процесса закрытия, описанного в параграфе 9.2.

Блок SHUTDOWN ACK не содержит параметров.

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 8 |Chunk Flags | Length = 4 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chunk Flags — 8 битов

Устанавливается в 0 на передающей стороне и игнорируется на приёмной.

3.3.10. Ошибка при работе (ERROR) (9)

Конечные точки передают блоки этого типа для уведомления партнёра о некоторых типах ошибок. Блок содержит один или несколько кодов ошибок. Приём Operational Error не обязывает партнёра разрывать ассоциацию, однако такие блоки могут передаваться вместе с блоком ABORT в качестве отчёта о причине разрыва. Параметры блока описаны ниже.

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 9 | Chunk Flags | Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \ \ / Одно или несколько полей Error Cause / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chunk Flags — 8 битов

Устанавливается в 0 на передающей стороне и игнорируется на приёмной.

Length — 16 битов (целое число без знака)

Указывает размер блока в байтах с учётом заголовка и всех полей Error Cause.

Причины ошибок указываются как параметры переменного размера в соответствии с параграфом 3.2.1.

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code | Cause Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / Cause-Specific Information / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Cause Code — 16 битов (целое число без знака)

Указывает код причины, которая вызвала передачу блока.

Таблица 11. Коды причин.

Код Описание Код Описание
1 Некорректный идентификатор потока 8 Нераспознанные параметры
2 Отсутствие обязательного параметра 9 Отсутствие пользовательских данных
3 Ошибка Stale Cookie 10 Получение Cookie в процессе закрытия
4 Нехватка ресурсов 11 Перезапуск ассоциации с новыми адресами
5 Не удалось преобразовать адрес 12 Инициированный пользователем разрыв
6 Нераспознанный тип блока 13 Протокольное нарушение
7 Некорректный обязательный параметр

Cause Length — 16 битов (целое число без знака)

Указывает размер параметра в байтах с учётом полей Cause Code, Cause Length и Cause-Specific Information

Cause-Specific Information — переменный размер

В этом поле указываются сведения об ошибке.

Причины ошибок SCTP рассматриваются в параграфах 3.3.10.1 — 3.3.10.13. Рекомендации по определению новых типов ошибок для IETF даны в параграфе 15.4.

3.3.10.1. Неприемлемый идентификатор потока (1)

Показывает, что конечная точка получила блок DATA, переданный в несуществующий поток.

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code=1 | Cause Length=8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Stream Identifier | (Reserved) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Stream Identifier — 16 битов (целое число без знака)

Значение Stream Identifier из блока DATA, вызвавшего ошибку.

Reserved — 16 битов

Зарезервированное поле. Устанавливается в 0 на передающей стороне и игнорируется на приёмной.

3.3.10.2. Отсутствует обязательный параметр (2)

Говорит об отсутствии одного или нескольких обязательных параметров TLV в принятом блоке INIT или INIT ACK.

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code=2 | Cause Length=8+N*2 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Number of missing params=N | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Missing Param Type #1 | Missing Param Type #2 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Missing Param Type #N-1 | Missing Param Type #N | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Number of Missing params — 32 бита (целое число без знака)

Число отсутствующих параметров, перечисленных в Cause-Specific Information (поля Missing Param Type).

Missing Param Type — 16 битов (целое число без знака)

Каждое поле содержит пропущенный обязательный параметр.

3.3.10.3. Ошибка Stale Cookie (3)

Говорит о получении корректного значения State Cookie с истекшим сроком.

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code=3 | Cause Length=8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Measure of Staleness (мксек.) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Measure of Staleness — 32 бита (целое число без знака)

В этом поле указывается разница между текущим временем и временем окончания срока действия State Cookie (в микросекундах с округлением).

Отправитель этого сообщения может указать время, прошедшее после завершения срока действия State Cookie, отличным от нуля значением поля Measure of Staleness. Если отправитель не хочет передавать эти сведения, ему следует установить нулевое значение в поле Measure of Staleness.

3.3.10.4. Нехватка ресурсов (4)

Указывает нехватку ресурсов у отправителя и передаётся обычно в комбинации с блоком ABORT или в нем.

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code=4 | Cause Length=4 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

3.3.10.5. Нераспознаваемый адрес (5)

Говорит о том, что отправителю не удалось распознать указанный адресный параметр (например, отправитель не поддерживает этот тип адресов) и передаётся обычно в комбинации с блоком ABORT или в нем.

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code=5 | Cause Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / Unresolvable Address / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Unresolvable Address — переменный размер

Поле Unresolvable Address содержит полное значение параметра TLV, задающего адрес (или параметра Host Name), который не удалось распознать, или имя хоста.

3.3.10.6. Не распознан тип блока (6)

Эта информация передаётся отправителю блока, если получатель не смог определить тип блока и два старших бита поля Chunk Type имеют значение 01 или 11.

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code=6 | Cause Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / Unrecognized Chunk / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Unrecognized Chunk — переменный размер

Поле Unrecognized Chunk содержит нераспознанный блок из пакета SCTP, включая поля Chunk Type, Chunk Flags и Chunk Length.

3.3.10.7. Недействительный обязательный параметр (7)

Это сообщение передаётся отправителю блока INIT или INIT ACK, когда один или несколько обязательных параметров имеют недействительные значения.

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code=7 | Cause Length=4 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

3.3.10.8. Нераспознанные параметры (8)

Это сообщение возвращается отправителю блока INIT ACK, если получателю не удаётся распознать один или несколько необязательных параметров TLV в блоке INIT ACK.

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code=8 | Cause Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / Unrecognized Parameters / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Unrecognized Parameters — переменный размер

Поле Unrecognized Parameters содержит нераспознанные параметры, скопированные из блока INIT ACK полностью в форме TLV. Это сообщение обычно передаётся в блоках ERROR, объединённых с блоком COOKIE ECHO, при отклике на INIT ACK, когда отправитель блока COOKIE ECHO желает сообщить о нераспознанных параметрах.

3.3.10.9. Нет пользовательских данных (9)

Это сообщение передаётся отправителю блока DATA, если принятый блок не содержит пользовательских данных.

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code=9 | Cause Length=8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / TSN value / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

TSN — 32 бита (целое число без знака)

Значение поля TSN из блока DATA, принятого без пользовательских данных.

Это сообщение обычно передаётся в блоке ABORT (см. параграф 6.2).

3.3.10.10. Получение Cookie во время процедуры закрытия (10)

Это сообщение говорит о приёме COOKIE ECHO в то время, когда конечная точка находилась в состоянии SHUTDOWN-ACK-SENT. Обычно этот код возвращается в блоке ERROR, сгруппированном с повторным блоком SHUTDOWN ACK.

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code=10 | Cause Length=4 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

3.3.10.11. Перезапуск ассоциации с новыми адресами (11)

Был получен блок INIT в существующей ассоциации и этот блок добавляет адреса, которые раньше не были частью данной ассоциации. Новые адреса указываются в коде ошибки. Этот сообщение обычно передаётся как часть блока ABORT, отвергающего INIT (см. параграф 5.2).

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code=11 | Cause Length=Variable | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / New Address TLVs / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Примечание. Каждый элемент New Address TLV является точной копией связанного с новым адресом TLV из блока INIT, включая Parameter Type и Parameter Length.

3.3.10.12. Разрыв по инициативе пользователя (12)

Эта причина ошибки может включаться в блоки ABORT, передаваемые по запросам вышележащего уровня. Этот уровень может указать значение Upper Layer Abort Reason, которое без изменения передаётся протоколом SCTP и может быть доставлено протоколу прикладного уровня у партнёра.

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code=12 | Cause Length=Variable | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / Upper Layer Abort Reason / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3.3.10.13. Протокольное нарушение (13)

Эта причина ошибки может включаться в блоки ABORT, передаваемые в результате обнаружения конечной точкой SCTP нарушения партнёром протокола, которое не может быть описано причинами, указанными в параграфах 3.3.10.1 — 3.3.10.12. Реализация может предоставить дополнительную информацию о нарушении протокола.

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cause Code=13 | Cause Length=Variable | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / Additional Information / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

3.3.11. Cookie Echo (COOKIE ECHO) (10)

Этот блок используется только в процессе создания ассоциации. Он передаётся инициатором удалённому партнёру для завершения процесса создания ассоциации. Такой блок должен предшествовать любому блоку DATA, передаваемому через ассоциацию, но может быть сгруппирован с одним или несколькими блоками DATA в один пакет.

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 10 |Chunk Flags | Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / Cookie / \ \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chunk Flags — 8 битов

Устанавливается в 0 на передающей стороне и игнорируется на приёмной.

Length — 16 битов (целое число без знака)

Указывает размер блока в байтах, включая 4 байта заголовка блока и размер Cookie.

Cookie — переменный размер

Это поле должно содержать точную копию параметра State Cookie, полученного в предыдущем блоке INIT ACK.

Реализациям протокола следует стремиться к уменьшению размера cookie в целях обеспечения взаимодействия.

Примечание. Блок Cookie Echo не включает параметр State Cookie, вместо этого данные из поля Parameter Value в State Cookie становятся Chunk Value в Cookie Echo. Это позволяет реализациям поменять лишь два первых байта параметра State Cookie, чтобы сделать из него блок COOKIE ECHO.

3.3.12. Подтверждение Cookie (COOKIE ACK) (11)

Этот тип блоков используется только при создании ассоциации и служит подтверждением приёма блока COOKIE ECHO. Данный блок должен предшествовать любому блоку DATA или SACK в данной ассоциации, но может группироваться с одним или несколькими блоками DATA или блоком SACK в одном пакете SCTP.

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 11 |Chunk Flags | Length = 4 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Chunk Flags — 8 битов

Устанавливается в 0 на передающей стороне и игнорируется на приёмной.

3.3.13. Закрытие ассоциации завершено (SHUTDOWN COMPLETE) (14)

Этот тип блоков должен использоваться для подтверждения приёма блока SHUTDOWN ACK при завершении ассоциации (см. параграф 9.2).

Блок SHUTDOWN COMPLETE не содержит параметров.

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 14 |Reserved |T| Length = 4 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Chunk Flags — 8 битов

Reserved — 7 битов

Устанавливается в 0 на передающей стороне и игнорируется на приёмной.

T — 1 бит

Бит T сбрасывается в 0, если отправитель заполнил поле Verification Tag, ожидаемое партнёром. Если в Verification Tag используется «отражённое» значение, должно устанавливаться T = 1. Отражение означает, что переданное значение Verification Tag совпадает с принятым.

Примечание. Для проверки этого типа применяются специальные правила, описанные в параграфе 8.5.1.

4. Диаграмма состояний ассоциации SCTP

В течение срока существования ассоциации SCTP участвующие в ней конечные точки могут переходить из одного состояния в другое в результате разных событий. События, способные изменить состояние ассоциации, включают:

  • вызовы пользовательских примитивов SCTP (например, [ASSOCIATE], [SHUTDOWN], [ABORT]);
  • приём управляющих блоков INIT, COOKIE ECHO, ABORT, SHUTDOWN и т. п.;
  • тайм-ауты.

—— ——— (из любого состояния) / \ / rcv ABORT [ABORT] rcv INIT | | | ———- или ———- ————— | v v удалить TCB snd ABORT генерация State \ +———+ удалить TCB Cookie и передача —| CLOSED | INIT ACK +———+ / \ [ASSOCIATE] / \ ————— | | создать TCB | | snd INIT | | запустить таймер T1-init rcv корректн. | | COOKIE ECHO | v (1) —————- | +————+ создать TCB | | COOKIE-WAIT| (2) snd COOKIE ACK | +————+ | | | | rcv INIT ACK | | —————— | | snd COOKIE ECHO | | остановить таймер T1-init | | запустить таймер T1-cookie | v | +—————+ | | COOKIE-ECHOED| (3) | +—————+ | | | | rcv COOKIE ACK | | —————— | | остановить таймер T1-cookie v v +—————+ | ESTABLISHED | +—————+

(продолжение рисунка на следующей странице)

(только из состояния ESTABLISHED) | | /———+———\ [SHUTDOWN] / \ ——————-| | проверить оставшиеся | | блоки DATA | | v | +———+ | |SHUTDOWN-| | rcv SHUTDOWN/проверить |PENDING | | оставшиеся блоки DATA +———+ | ———————- | | нет оставшихся блоков| | ———————| | snd SHUTDOWN | | запустить таймер | | T2-shutdown v v +———+ +————+ (4) |SHUTDOWN-| | SHUTDOWN- | (5,6) |SENT | | RECEIVED | +———+ +————+ | \ | (A) rcv SHUTDOWN ACK | \ | ———————-| \ | ост. таймер T2-shutd. | \ | send SHUTDOWN COMPLETE| \ | удалить TCB | \ | | \ | нет оставшихся блоков | \ | —————— | \ | send SHUTDOWN ACK (B)rcv SHUTDOWN -|- \ | запустить таймер ———————/ | \———-\ | T2-shutdown send SHUTDOWN ACK | \ | зап. таймер T2-shutd. | \ | | \ | | | | | v | | +————+ | | SHUTDOWN- | (7) | | ACK-SENT | | +———-+- | | (A)rcv SHUTDOWN COMPLETE | |—————— | | запустить таймер T2-shutdown | | удалить TCB | | | | (B)rcv SHUTDOWN ACK | |————— | | останов. таймер T2-shutdown | | send SHUTDOWN COMPLETE | | удалить TCB | | \ +———+ / \—>| CLOSED |<—/ +———+

Рисунок 3. Диаграмма состояний протокола SCTP (продолжение).

Приведённые ниже рисунки показывают возможные состояния ассоциации и переходы между ними вместе с вызывающими эти переходы событиями и выполняемыми при смене состояния действиями. Некоторые ошибки не показаны на схеме состояний. Полное описание всех состояний и переходов приводится в тексте документа21.

  1. Если параметр State Cookie в принятом блоке COOKIE ECHO недействителен (например, не прошла проверка целостности), получатель должен отбросить пакет без уведомления. Если получен State Cookie с истекшим сроком (см. параграф 5.1.5), получатель должен оправить в ответ блок ERROR. В обоих случаях получатель остаётся в состоянии CLOSED.
  2. Если истекло время по таймеру T1-init, конечная точка должна повторить передачу INIT и заново запустить таймер T1-init, сохраняя состояние COOKIE-WAIT. Эти действия должны повторяться до Max.Init.Retransmits раз, после чего конечная точка должна прервать процесс инициирования ассоциации и возвратить сообщение об ошибке пользователю SCTP.
  3. Если истекло время по таймеру T1-cookie, конечная точка должна повторить передачу COOKIE ECHO и заново запустить таймер T1-cookie, сохраняя состояние COOKIE-ECHOE. Эта процедура должна повторяться до Max.Init.Retransmits раз, после чего конечная точка должна прервать процесс инициирования ассоциации и возвратить сообщение об ошибке пользователю SCTP.
  4. В состоянии SHUTDOWN-SENT конечная точка должна подтверждать все принятые блоки DATA без задержек.
  5. В состоянии SHUTDOWN-RECEIVED для конечной точки недопустимо воспринимать любые новые запросы на передачу от пользователя SCTP.
  6. В состоянии SHUTDOWN-RECEIVED конечная точка должна передать или повторить данные и выйти из этого состояния после того, как будут переданы все данные из очереди.
  7. В состоянии SHUTDOWN-ACK-SENT для конечной точки недопустимо принимать от пользователя SCTP любые новые запросы на передачу.

Состояние CLOSED на схеме используется для того, чтобы показать, что ассоциация ещё не создана (т. е., не существует).

5. Создание ассоциации

До того, как сможет начаться передача данных от одной конечной точки SCTP (A) к другой (Z), эти две точки должны выполнить весь процесс создания ассоциации между собой.

Пользователь SCTP в конечной точке может применять примитив ASSOCIATE для создания ассоциации с другой конечной точкой SCTP.

Примечание для разработчиков. С точки зрения пользователя SCTP ассоциация может быть создана неявно без обращения к примитиву ASSOCIATE (см. параграф 11.1.2) просто путём передачи первых пользовательских данных удалённому адресату. Инициирующий ассоциацию узел SCTP будет задавать принятые по умолчанию значения для всех обязательных и дополнительных параметров INIT/INIT ACK.

После создания ассоциации организуются двухсторонние потоки данных для передачи информации в обоих направлениях (см. параграф 5.1.1).

5.1. Обычное создание ассоциации

Процесс инициализации описан ниже в предположении, что конечная точка A пытается создать ассоциацию, а точка Z воспринимает вызов.

  1. A создаёт TCB и передаёт блок INIT точке Z. В блоке INIT точка A должна указать свой Verification Tag (Tag_A) в поле Initiate Tag. Для Tag_A следует использовать случайное число из диапазона от 1 до 4294967295 (см. рекомендации по выбору значения тега в параграфе 5.3.1). После передачи блока INIT точка A запускает таймер T1-init и переходит в состояние COOKIE-WAIT.
  2. Z сразу же отвечает на запрос блоком INIT ACK. IP-адрес получателя в блоке INIT ACK должен совпадать с адресом отправителя блока INIT, для которого передаётся INIT ACK. Кроме заполнения других полей отклика точка Z должна скопировать в поле Verification Tag значение Tag_A, а также указать своё значение Verification Tag (Tag_Z) в поле Initiate Tag.
    Кроме того, точка Z должна сгенерировать и передать в INIT ACK значение State Cookie (см. параграф 5.1.3).
  3. При получении блока INIT ACK от Z точка A останавливает таймер T1-init и выходит из состояния COOKIE-WAIT. Далее A передаёт значение State Cookie из принятого блока INIT ACK в ответном блоке COOKIE ECHO, запускает таймер T1-cookie и переходит в состояние COOKIE-ECHOED.
  4. При получении блока COOKIE ECHO точка Z передаёт блок COOKIE ACK после создания TCB и перехода в состояние ESTABLISHED. Блок COOKIE ACK может объединяться с ожидающими передачи блоками DATA и/или SACK, но блок COOKIE ACK должен быть первым в пакете.
    Примечание для разработчиков. Реализация протокола может передавать уведомление Communication Up пользователю SCTP при получении корректного блока COOKIE ECHO.
  5. Приняв блок COOKIE ACK, точка A переходит из состояния COOKIE-ECHOED в состояние ESTABLISHED, останавливая таймер T1-cookie. Она может также уведомить ULP об успешном создании ассоциации с помощью Communication Up (см. раздел 11).
  6. Блок COOKIE ECHO может группироваться с любыми ожидающими передачи блоками DATA, но эти блоки должны размещаться в пакете после COOKIE ECHO. До получения ответного блока COOKIE ACK недопустима передача каких-либо пакетов удалённому партнёру.
  7. После передачи INIT ACK с параметром State Cookie точке Z недопустимо выделять какие-либо ресурсы или сохранять какие-либо состояния для новой ассоциации, поскольку это сделает её уязвимой для атак на ресурсы.

Блоки INIT и INIT ACK недопустимо группировать с другими блоками. Такой блок должен быть единственным в содержащем его пакете SCTP.

Конечная точка должна передавать блок INIT ACK по адресу IP, с которого был получен блок INIT.

Для таймеров T1-init и T1-cookie следует применять правила, описанные в параграфе 6.3. Если приложение сообщает партнёру несколько адресов IP, следует устанавливать таймеры T1-init и T1-cookie для каждого из этих адресов. При повторе блоков INIT и COOKIE ECHO следует искользовать все адреса партнёра как при повторе блоков DATA.

Если конечная точка, получившая блок INIT, INIT ACK или COOKIE ECHO, решает не создавать ассоциацию по причине отсутствия обязательных параметров в блоке INIT или INIT ACK, недействительных значений параметров или нехватки локальных ресурсов, ей следует передать в ответ блок ABORT. Этой точке также следует указать причину отказа (тип отсутствующих обязательных параметров и т. п.), включив соответствующий параметр в блок ABORT. Поле Verification Tag в общем заголовке исходящего пакета SCTP, содержащего блок ABORT, должно содержать значение Initiate Tag, полученное от партнёра в блоке INIT или INIT ACK, вызвавшего отправку блока ABORT.

Отметим, что блок COOKIE ECHO, не прошедший проверки целостности, не считается недействительным обязательным параметром и требует специальной обработки, описанной в параграфе 5.1.5.

После получения первого блока DATA в ассоциации конечная точка должна без промедления передать блок SACK для подтверждения приёма блока DATA. Последующие подтверждения передаются в соответствии с рекомендациями параграфа 6.2.

При создании TCB каждая точка должна установить для внутреннего параметра Cumulative TSN Ack Point значение переданного Initial TSN — 1.

Примечание для разработчиков. В качестве ключей поиска TCB для данного экземпляра SCTP обычно используются IP-адреса и номер порта SCTP.

5.1.1. Обработка параметров потока

В блоках INIT и INIT ACK отправитель должен указывать число исходящих потоков (OS), которые он желает поддерживать для данной ассоциации, а также максимальное число входящих потоков (MIS), которые он будет принимать от удалённого партнёра.

После получения сведений о конфигурации потоков от другой стороны каждая конечная точка должна выполнить ряд проверок. Если значение полученное от партнёра значение MIS меньше локального OS, это означает, что удалённый партнёр не сможет поддерживать все исходящие потоки и данная точка должна установить для числа исходящих потоков полученное значение MIS или может сообщить вышележащему уровню о нехватке ресурсов на удалённой стороне. На основании этого вышележащий уровень может принять решение о разрыве ассоциации, если работа при нехватке ресурсов не приемлема для него.

После того, как ассоциация инициализирована, приемлемые значения идентификаторов исходящих потоков для неё могут находиться в диапазоне [0 — min(local OS, remote MIS)-1].

5.1.2. Обработка адресов

В процессе создания ассоциации конечным точкам следует использовать перечисленные ниже правила для определения и сохранения транспортных адресов своего партнёра.

  1. Если в принятом блоке INIT или INIT ACK нет адресных параметров, конечная точка должна взять адрес отправителя из заголовка пакета IP, в котором был доставлен блок, и сохранить этот адрес вместе с номером порта SCTP, использованным отправителем пакета, как единственный транспортный адрес партнёра.
  2. Если в полученном блоке INIT или INIT ACK присутствует параметр Host Name, конечная точка должна сразу же передать блок ABORT и может указать в нем причину Unresolvable Address. Блок ABORT следует передавать по адресу IP, а которого получен последний пакет от партнёра.
  3. Если в принятом блоке INIT или INIT ACK присутствуют только адреса IPv4/IPv6, получатель должен выделить и записать все транспортные адреса из полученного блока и адреса отправителя в заголовке пакета IP, содержащего блок INIT или INIT ACK. Транспортные адреса представляют собой комбинацию номера порта SCTP (из общего заголовка) и адресов IP, переданных в блоке INIT или INIT ACK и заголовке пакета IP, доставившего блок. Получателю следует использовать только эти транспортные адреса для передачи последующих пакетов партнёру.
  4. Блок INIT или INIT ACK должен трактоваться, как относящийся к организованной ранее (или организуемой сейчас) ассоциации, если использование любого из содержащихся в нем корректных адресных параметров уже зафиксировано в существующих TCB.

Примечание для разработчиков. В некоторых случаях (например, когда реализация не контролирует IP-адреса отправителя, используемые при передаче) конечной точке может потребоваться включение в блок INIT или INIT ACK всех адресов IP, которые могут использоваться для передачи партнёру.

После выделения транспортного адреса из блока INIT или INIT ACK с использованием описанных выше правил конечная точка выбирает один из таких адресов как начальный основной путь.

Блок INIT ACK должен передаваться по адресу отправителя блока INIT.

Отправитель блока INIT может включить в этот блок параметр Supported Address Types, показывающий поддерживаемые типы адресов.

Примечание для разработчиков. В тех случаях, когда получателю блока INIT ACK не удаётся выполнить преобразование адреса вследствие отсутствия поддержки указанного типа, попытка создания ассоциации может быть прервана, после чего предпринимается попытка повторной организации с использованием параметра Supported Address Types в новом блоке INIT для индикации предпочтительных типов адресов.

Если конечная точка SCTP, поддерживающая только один из типов адресов (IPv4 или IPv6), получает адреса IPv4 и IPv6 в блоке INIT или INIT ACK от своего партнёра, она должна использовать все указанные партнёром адреса, которые относятся к поддерживаемому типу. Остальные адреса можно игнорировать. Не следует в таких случаях передавать какие-либо сообщения об ошибке.

Если конечная точка SCTP указывает в параметре Supported Address Types только один из типов IPv4 и IPv6, но использует для передачи пакета с блоком INIT другой тип или перечисляет адрес другого типа в блоке INIT, адреса не указанного в параметре Supported Address Types типа получателю блока INIT также следует считать поддерживаемыми. Не следует в таких случаях передавать какие-либо сообщения об ошибке.

5.1.3. Генерация State Cookie

При передаче блока INIT ACK в ответ на INIT отправитель INIT ACK создаёт значение State Cookie и передаёт его в одноимённом параметре блока INIT ACK. В параметр State Cookie отправитель должен включить MAC (см., например, [RFC2104]) для защиты целостности. Следует также включать временную метку генерации State Cookie и время действия параметра State Cookie, а также другую информацию, требуемую для создания ассоциации, включая номера портов и Verification Tag.

Метод, используемый для генерации MAC является строго приватным для получателя блока INIT. Использование MAC обязательно для предотвращения атак на службы. Алгоритмы MAC могут различаться по производительности в зависимости от платформы. Выбор скоростного алгоритма MAC повышает устойчивость к лавинным атакам на Cookie. Следует применять MAC с подходящими свойствами защиты. В качестве секретного ключа следует использовать случайное значение (см. рекомендации [RFC4086]) подходящего размера, которое следует менять достаточно часто (например, каждый час). Для идентификации ключа, который будет использоваться для проверки MAC, может служить временная метка момента создания State Cookie.

Если State Cookie не шифруется, недопустимо включать в него сведения, не рассчитанные на общее применение.

Для обеспечения взаимодействия реализациям протокола следует минимизировать размер cookie.

5.1.4. Обработка State Cookie

Когда конечная точка (в состоянии COOKIE WAIT) получает блок INIT ACK с параметром State Cookie, она должна незамедлительно передать своему партнёру блок COOKIE ECHO с полученным значением State Cookie. Отправитель может также добавить в пакет ожидающие обработки блоки DATA после блока COOKIE ECHO.

Конечная точка должна также запустить таймер T1-cookie после передачи блока COOKIE ECHO. По истечении заданного для таймера интервала конечная точка должна повторить передачу блока COOKIE ECHO и заново включить таймер T1-cookie. Эту процедуру следует повторять до получения блока COOKIE ACK или исчерпания числа попыток Max.Init.Retransmits (см. раздел 16). Если заданное число попыток не привело к успеху, партнёр помечается как недоступный (и ассоциация переходит в статус CLOSED).

5.1.5. Аутентификация State Cookie

Когда конечная точка получает блок COOKIE ECHO от другой конечной точки, с которой нет действующей ассоциации, ей следует выполнить перечисленные ниже операции.

  1. Рассчитать MAC с использованием данных TCB, полученных в State Cookie, и секретного ключа. Для выбора секретного ключа может использоваться временная метка из State Cookie. Если секрет хранится лишь ограниченное время и секретный ключ больше не доступен, пакет с COOKIE ECHO должен отбрасываться без уведомления. Расчёт MAC можно выполнять в соответствии с рекомендациями [RFC2104].
  2. Проверить подлинность State Cookie, сравнивая рассчитанное значение MAC с полученным в State Cookie. При наличии расхождений пакет SCTP, включающий COOKIE ECHO и любые блоки DATA, должны отбрасываться без уведомления отправителя.
  3. Сравнить номера портов и Verification Tag в блоке COOKIE ECHO с реальными номерами портов и полем Verification Tag в общем заголовке SCTP принятого пакета. При наличии расхождений пакет должен быть отброшен без уведомления отправителя.
  4. Сравнить временную метку в State Cookie с текущим временем локальной системы. Если разница превышает заданный срок существования State Cookie, пакет, содержащий COOKIE ECHO и любые блоки DATA, следует отбросить. Конечная точка в таком случае должна передать партнёру блок ERROR с причиной ошибки Stale Cookie.
  5. Если значение State Cookie действительно, создать ассоциацию с отправителем COOKIE ECHO, создать TCB с использованием данных из блока COOKIE ECHO и перевести конечную точку в состояние ESTABLISHED.
  6. Передать блок COOKIE ACK удалённому партнёру для подтверждения приёма COOKIE ECHO. Блок COOKIE ACK может группироваться с пользовательскими блоками DATA или блоком SACK, однако блок COOKIE ACK должен размещаться в пакете SCTP первым.
  7. Незамедлительно подтвердить получение любых блоков DATA, сгруппированных с COOKIE ECHO, путём передачи блока SACK (подтверждения последовательных блоков DATA передаются с использованием правил, рассмотренных в параграфе 6.2). Как было отмечено в п. 6), при группировке COOKIE ACK с блоком SACK, блок COOKIE ACK должен размещаться в пакете SCTP первым.

При получении блока COOKIE ECHO от конечной точки, с которой получатель имеет работающую ассоциацию, следует выполнять операции, рассмотренные в параграфе 5.2.

5.1.6. Пример нормального создания ассоциации

В показанном на рисунке примере точка A инициирует создание ассоциации и передаёт пользовательское сообщение точке Z, а Z, в свою очередь, передаёт точке A два пользовательских сообщения (предполагается отсутствие группировки и фрагментирования).

Точка A Точка Z {приложение создает ассоциацию с Z} (создание TCB) INIT [I-Tag=Tag_A и др. инфор.] ———\ (запуск таймера T1-init) \ (Переход в сост. COOKIE-WAIT) \—> (созд. времен. TCB и Cookie_Z) /— INIT ACK [Veri Tag=Tag_A, / I-Tag=Tag_Z, (Выкл. таймера T1-init)<———/ Cookie_Z и др. информ.] (удаление времен. TCB) COOKIE ECHO [Cookie_Z] ——\ (Запуск таймера T1-init) \ (Переход в сост. COOKIE-ECHOED)\—> (создание TCB и переход в сост. ESTABLISHED) /—- COOKIE-ACK / (Выкл. таймера T1-init,<——/ Переход в сост. ESTABLISHED) {прил. начинает перед. данных; strm 0} DATA [TSN=initial TSN_A Strm=0,Seq=1 & user data]—\ (Запуск таймера T3-rtx) \ \-> /—— SACK [TSN Ack=init (Выкл. таймера T3-rtx)<——/ TSN_A,Block=0] … {прилож. шлет 2 сообщ.; strm 0} /—- DATA / [TSN=init TSN_Z <—/ Strm=0, Seq=1 & user data 1] SACK [TSN Ack=init TSN_Z, /—- DATA Block=0] ———\ / [TSN=init TSN_Z +1, \/ Strm=0,Seq=2 & user data 2] <——/\ \ \——>

Рисунок 4. Пример создания ассоциации.

Если закончилось время T1-init в точке A после передачи блока INIT или COOKIE ECHO, повторяется передача блока INIT или COOKIE ECHO с тем же значением Initiate Tag (т. е., Tag_A) или State Cookie и таймер запускается снова. Эта процедура повторяется до Max.Init.Retransmits раз после чего точка A принимает решение о недоступности Z и сообщает вышележащему протоколу об ошибке (ассоциация переводится в состояние CLOSED).

При повторной передаче INIT конечная точка должна следовать правилам, описанным в параграфе 6.3, для определения подходящего значения таймера.

5.2. Обработка дубликатов и неожиданных установочных блоков

В течение срока действия ассоциации (в одном из возможных состояний) конечная точка может получить от своего партнёра один из установочных блоков (INIT, INIT ACK, COOKIE ECHO, COOKIE ACK). Получателю следует трактовать такие установочные блоки, как дубликаты и обрабатывать их в соответствии с приведёнными здесь рекомендациями.

Примечание. Конечная точка не получит блок, если тот не передан по транспортному адресу SCTP с транспортного адреса SCTP, связанного с данной точкой. Следовательно, обрабатывающая такие блоки конечная точка является элементом текущей ассоциации.

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

  1. Критическая ошибка на удалённой стороне с перезапуском партнёра и передачей нового блока INIT для восстановления ассоциации.
  2. Обе стороны предприняли одновременные попытки создания ассоциации.
  3. Блок был получен в старом пакете, который использовался для предыдущей ассоциации или ассоциации, которой уже нет.
  4. Блок является фальшивым (атака).
  5. Партнёр не получил блок COOKIE ACK и повторно передаёт COOKIE ECHO.

При получении таких блоков следует применять описанные ниже правила, позволяющие идентифицировать и корректно обрабатывать подобные ситуации.

5.2.1. Блок INIT получен в состоянии COOKIE-WAIT или COOKIE-ECHOED (п. B)

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

При получении блока INIT в состоянии COOKIE-WAIT конечная точка должна ответить блоком INIT ACK, используя те же параметры, которые она передавала в исходном блоке INIT (включая параметр Initiate Tag). При ответе должны применяться приведённые ниже правила.

  1. Пакет с блоком INIT ACK должен отправляться только по тому адресу, который был передан вышележащим уровнем в запросе на создание ассоциации.
  2. Пакет с блоком INIT ACK должен отправляться только по адресу, указанному в принятом блоке INIT.
  3. Пакет с блоком INIT ACK следует передавать по адресу отправителя принятого пакета с блоком INIT.

При получении блока INIT в состоянии COOKIE-ECHOED конечная точка должна ответить блоком INIT ACK, используя те же параметры, которые она передавала в исходном блоке INIT (включая параметр Initiate Tag), чтобы в создаваемую ассоциацию не добавлялись новые адреса. Если блок INIT показывает добавление к ассоциации нового адреса, весь блок INIT должен быть отброшен и в существующую ассоциацию не следует вносить изменений. В ответ следует передать блок ABORT, который может включать информацию об ошибке Restart of an association with new addresses (перезапуск ассоциации с новыми адресами). В информацию об ошибке следует включать список адресов, которые были добавлены при перезапуске ассоциации.

При отклике INIT ACK из состояния COOKIE-WAIT или COOKIE-ECHOED исходные параметры комбинируются с параметрами из полученного недавно блока INIT. Конечная точка должна также генерировать параметр State Cookie для блока INIT ACK, используя параметры, переданные ею в блоке INIT.

После этого для конечной точки недопустимо изменение своего состояния и удаление соответствующего TCB, таймер T1-init должен продолжать отсчёт. Обычная процедура обработки State Cookie при наличии TCB позволит избавиться от дубликатов INIT в одной ассоциации.

Конечная точка, находящаяся в состоянии COOKIE-ECHOED при получении блока INIT должна заполнить поля Tie-Tag в TCB ассоциации и State Cookie (см. параграф 5.2.2).

5.2.2. INIT в состоянии, отличном от CLOSED, COOKIE-ECHOED, COOKIE-WAIT, SHUTDOWN-ACK-SENT

Если явно не указано иное, при получении блока INIT в таких случаях конечная точка должна генерировать блок INIT ACK с параметром State Cookie. Перед отправкой отклика конечная точка должна проверить, добавляет ли неожиданный блок INIT новые адреса для ассоциации. При наличии новых адресов конечная точка должна отвечать блоком ABORT, копируя Initiate Tag из неожиданного блока INIT в поле Verification Tag исходящего пакета с блоком ABORT. В блоке ABORT можно указать причину ошибки Restart of an association with new addresses (перезапуск ассоциации с новыми адресами). В информацию об ошибке следует включать список адресов, добавленных к ассоциации. Если новых адресов нет, в ответ на неожиданный блок INIT блоком INIT ACK конечная точка должна копировать свои текущие значения Tie-Tag в резервное пространство State Cookie и TCB этой ассоциации. Эти места внутри cookie по-прежнему обозначаются Peer’s-Tie-Tag и Local-Tie-Tag. Копии внутри TCB ассоциации будем обозначать Local Tag и Peer’s Tag. Исходящий пакет SCTP с блоком INIT ACK должен включать значение Verification Tag, совпадающее с Initiate Tag в неожиданном блоке INIT. Блок INIT ACK должен включать новое значение Initiate Tag (случайное, см. параграф 5.3.1). Остальные параметры для конечной точки (например, число исходящих потоков) следует скопировать из существующих параметров ассоциации в блок INIT ACK и cookie.

После передачи INIT ACK или ABORT конечная точка должна отказаться от каких-либо действий, т. е., существующую ассоциацию, включая текущее состояние и соответствующее значение TCB, изменять недопустимо.

Поля Tie-Tag заполняются отличными от 0 случайными значениями только в том случае, когда существует TCB и ассоциация не находится в состоянии COOKIE-WAIT или SHUTDOWN-ACK-SENT. При обычном создании ассоциации (конечная точка находится в состоянии CLOSED) для Tie-Tag должно устанавливаться значение 0 (это показывает отсутствие предыдущего TCB).

5.2.3. Неожиданный блок INIT ACK

При получении блока INIT ACK конечной точкой, находящейся в отличном от COOKIE-WAIT состоянии, этой точке следует отбросить блок INIT ACK. Неожиданные блоки INIT ACK обычно связаны с обработкой старых или дублированных блоков INIT.

5.2.4. Обработка COOKIE ECHO при наличии TCB

При получении блока COOKIE ECHO конечной точкой, находящейся в любом состоянии, для существующей ассоциации (состояние отлично от CLOSED) нужно следовать приведённым ниже правилам.

  1. Рассчитать MAC в соответствии с рекомендациями п. 1 в параграфе 5.1.5,
  2. Проверить подлинность State Cookie, как описано в п. 2 параграфа 5.1.5 (случай C или D в начале параграфа 5.2).
  3. Сравнить временную метку State Cookie с текущим временем. Если срок действия State Cookie истёк и значение Verification Tag, содержащееся в State Cookie, не соответствует Verification Tag для текущей ассоциации, пакет вместе с входящими в него блоками COOKIE ECHO и DATA следует отбросить. Конечная точка должна также передать партнёру блок ERROR с причиной ошибки Stale Cookie (случай C или D в параграфе 5.2).
  4. При действительном значении State Cookie распаковать TCB во временный TCB.
  5. Выполнить подходящее действие из таблицы 12.
  6. Если параметры Verification Tag в State Cookie и текущей ассоциации совпадают, следует считать параметр State Cookie действительным (случай E в параграфе 5.2) даже по истечении срока действия.

Таблица 12. Обработка COOKIE ECHO при наличии TCB.

Local Tag Peer’s Tag Local-Tie-Tag Peer’s-Tie-Tag Действие
X X M M (A)
M X A A (B)
M 0 A A (B)
X M 0 0 (C)
M M A A (D)

X — тег не соответствует существующему TCB;
M — тег соответствует существующему TCB;
0 — нет Tie-Tag в Cookie (неизвестно);
A — Все случаи (M, X, 0).

Для всех ситуаций, не рассмотренных в таблице 12, cookie следует отбрасывать без уведомления.

Действия

  1. Этот случай может быть связан с рестартом на удалённой стороне. Когда конечная точка распознает возможный рестарт, существующая сессия трактуется, как случай получения блока ABORT, за которым сразу же следовал новый блок COOKIE ECHO, с перечисленными ниже исключениями:
    • любые блоки DATA могут быть сохранены (в зависимости от реализации протокола);
    • протоколу вышележащего уровня следует передать уведомление RESTART взамен COMMUNICATION LOST.

    Все параметры контроля перегрузки (например, cwnd, ssthresh), связанные с этим партнёром, должны быть сброшены в исходное состояние (см. параграф 6.2.1).Если конечная точка находится в состоянии SHUTDOWN-ACK-SENT и определяет рестарт партнёра (п. A), для этой точки недопустимо создание новой ассоциации и следует передать своему партнёру блок SHUTDOWN ACK и ERROR с причиной ошибки Cookie Received while Shutting Down.

  2. В этой ситуации обе стороны могут пытаться организовать ассоциацию одновременно, но удалённая точка передаст свой блок INIT уже после отклика на INIT от локальной точки. В результате новое значение Verification Tag не будет включать информацию из тега, переданного ранее той же конечной точкой. Конечной точке следует сохранить состояние ESTABLISHED или перейти в него, но она должна обновить значение Verification Tag из параметра State Cookie, остановить запущенные таймеры T1-init и T1-cookie и передать блок COOKIE ACK.
  3. В этом случае информация cookie локальной точки поступает с опозданием. До этого локальная точка передала блок INIT и приняла INIT-ACK, а также передала блок COOKIE ECHO с тегом партнёра, но новый тег принадлежит локальной точке. Данные cookie следует отбросить без уведомления. Конечной точке не следует менять своё состояние, а запущенные таймеры следует сохранить.
  4. Когда теги локальной и удалённой точки совпадают, конечной точке следует перейти в состояние ESTABLISHED, если она находится в состоянии COOKIE-ECHOED. Ей следует остановить таймер T1-cookie и передать блок COOKIE ACK.
  5. После этого конечной точке следует перейти в состояние ESTABLISHED.

Примечание. Verification Tag партнёра — это тег, полученный в поле Initiate Tag блока INIT или INIT ACK.

5.2.4.1. Пример перезапуска ассоциации

В приведённом на рисунке 5 примере точка A инициирует ассоциацию после рестарта. Точка Z пока не знает о перезапуске (т. е., Heartbeat ещё не удалось обнаружить недоступность точки A). Предполагается отсутствие группировки и фрагментирования.

Точка A Точка Z <—————- Ассоциация организована ———————-> Tag=Tag_A Tag=Tag_Z <—————————————————————> {A выполняет рестарт после сбоя} {приложение организует ассоциацию с Z} (создание TCB) INIT [I-Tag=Tag_A’ и др. инф.] ———\ (Запуск таймера T1-init) \ (Переход в сост. COOKIE-WAIT) \—> (поиск существующего TCB создание врем. TCB и Cookie_Z с Tie-Tag для предыдущ. асс.) /— INIT ACK [Veri Tag=Tag_A’, / I-Tag=Tag_Z’, (Выкл. таймера T1-init)<——/ Cookie_Z] (возврат исходного TCB) COOKIE ECHO [Veri=Tag_Z’, Cookie_Z]——-\ (Запуск таймера T1-init) \ (Перех. В сост. COOKIE-ECHOED) \—> (Найдена существ. ассоциация, Tie-Tag в Cookie_Z соотв. Tie-Tag в TCB. Теги не соотв. (случай X X M M), анонсиров. рестарта ULP и сброс ассоциации). /—- COOKIE-ACK / (Выкл. таймера T1-init,<——/ переход в состояние ESTABLISHED) {прилож. передаёт польз. данные; strm 0} DATA [TSN=initial TSN_A Strm=0,Seq=1 & user data]—\ (Запуск таймера T3-init) \ \-> /—— SACK [TSN Ack=init TSN_A,Block=0] (Выкл. таймера T3-rtx)<——/

Рисунок 5. Пример перезапуска.

5.2.5. Обработка дубликатов COOKIE-ACK

Во всех состояниях, кроме COOKIE-ECHOED, конечной точке следует отбрасывать без уведомления блоки COOKIE ACK.

5.2.6. Обработка ошибок Stale COOKIE

Приём блока ERROR с причиной Stale Cookie может быть обусловлен одной из перечисленных ниже ситуаций.

  1. Создание ассоциации завершилось неудачей до того, как была выполнена обработка State Cookie.
  2. После создания ассоциации обработана старая переменная State Cookie.
  3. Получена старая переменная State Cookie от кого-то, с кем получатель не намерен создавать ассоциацию, но блок ABORT был утерян.

При обработке блока ERROR с причиной ошибки Stale Cookie конечной точке следует сначала проверить завершился ли процесс создания ассоциации (состояние отличается от COOKIE-ECHOED). Если ассоциация не находится в состоянии COOKIE-ECHOED, блок ERROR следует отбросить без уведомления.

Если ассоциация находится в состоянии COOKIE-ECHOED, конечная точка может выбрать один из перечисленных вариантов.

  1. Передать новый блок INIT удалённой конечной точке для генерации нового значения State Cookie и повторить процедуру создания ассоциации.
  2. Отбросить TCB и сообщить вышележащему уровню о невозможности создания ассоциации.
  3. Передать новый блок INIT удалённой конечной точке, добавив в него параметр Cookie Preservative, запрашивающий продление срока действия State Cookie. При расчёте дополнительного времени реализации протокола следует использовать данные RTT, полученные во время предыдущего обмена блоками COOKIE ECHO/ERROR. К полученному значению RTT следует добавлять не более 1 секунды, поскольку увеличение срока действия State Cookie подвергает конечную точку риску replay-атак.

5.3. Другие вопросы инициализации

5.3.1. Выбор значений тегов

Значения Initiate Tag следует выбирать из диапазона 1 — 232-1. Важно, чтобы значение Initiate Tag было случайным — это поможет в защите от атак извне пути22. Для создания случайных значений Initiate Tag можно использовать методы, описанные в [RFC4086]. Аккуратный подбор Initiate Tag позволяет также избавиться от появления дубликатов из предыдущих ассоциаций, которые могут быть ошибочно направлены в текущую ассоциацию.

Важно помнить, что значение Verification Tag, используемое любой из конечных точек данной ассоциации, недопустимо изменять в течение срока существования ассоциации. Каждый раз, когда конечная точка перезапускается и снова создаёт ассоциацию с тем же партнёром, должно выбираться новое значение Verification Tag.

5.4. Проверка пути

В процессе создания ассоциации партнёры обмениваются списками адресов. Чаще всего эти списки содержат адреса, принадлежащие каждому из партнёров. Однако возможны ситуации, когда некорректно ведущий себя партнёр предложит адреса, которые ему не принадлежат. Для предотвращения нежелательных последствий этого ко всем адресам в новой ассоциации применяются приведённые ниже правила.

  1. Любой адрес, переданный отправителю блока INIT его вышележащим уровнем в запросе на создание ассоциации, автоматически считается подтверждённым.
  2. Для получателя COOKIE ECHO единственным подтверждённым адресом является тот, по которому был передан блок INIT-ACK.
  3. Остальные адреса (кроме перечисленных в п. 1 и 2) считаются неподтверждёнными и должны проверяться.

Для проверки адреса конечная точка передаёт блоки HEARTBEAT, включающее 64-битовое случайное значение nonce и индикатор пути (для идентификации адреса, по которому передаётся HEARTBEAT) в параметре HEARTBEAT.

При получении HEARTBEAT ACK проверяется значение nonce в параметре Heartbeat Info на предмет совпадения с переданным по адресу, указанному в Heartbeat Info. При совпадении адрес, по которому был передан исходный блок HEARTBEAT, считается подтверждённым и может применяться для обычной передачи данных.

Эти процедуры проверки запускаются при переходе ассоциации в состояние ESTABLISHED и завершаются после проверки всех путей.

В каждый период RTO может быть отправлен пробный пакет для активного неподтверждённого пути в попытке перевести этот путь в состояние подтверждённого. Если в процессе проверки путь становится неактивным, скорость отправки проб снижается до обычной скорости передачи HEARTBEAT. По завершении отсчёта таймера RTO значения счётчика ошибок для протестированного, но не подтверждённого пути увеличивается на 1 и рассматривается вопрос отказа на этом пути (см. параграф 8.2). При проверке неподтвержденных адресов значение общего счётчика ошибок в ассоциации не инкрементируется.

Число HEARTBEAT, передаваемых в течение RTO, следует ограничивать значением параметра HB.Max.Burst. Распределение HEARTBEAT по адресам партнёра при проверке путей реализация определяет самостоятельно.

При подтверждении пути вышележащему уровняю может передаваться уведомление.

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

  • Блоки HEARTBEAT, включающие nonce, можно передавать по неподтвержденным адресам.
  • Блоки HEARTBEAT ACK можно передавать по неподтвержденным адресам.
  • Блоки COOKIE ACK можно передавать по неподтвержденным адресам, но они должны группироваться с блоками HEARTBEAT, включающими nonce. Реализациям, не поддерживающим группировку блоков, недопустимо передавать COOKIE ACK по неподтвержденным адресам.
  • Блоки COOKIE ECHO можно передавать по неподтвержденным адресам, но они должны группироваться с блоками HEARTBEAT, включающими nonce, и недопустимо использование пакетов с размером больше MTU на этом пути. Если реализация не поддерживает группировку блоков или после группировки COOKIE ECHO с HEARTBEAT (включающим nonce) размер пакета превысит MTU для пути, недопустимо передавать COOKIE ECHO по неподтвержденным адресам.

6. Передача пользовательских данных

Данные должны передаваться только в состояниях ESTABLISHED, SHUTDOWN-PENDING и SHUTDOWN-RECEIVED. Единственным исключением из этого правила является возможность включения блоков DATA в пакеты, содержащие блок COOKIE ECHO, в состоянии COOKIE-WAIT.

Блоки DATA должны приниматься только в соответствии с приведёнными ниже правилами в состояниях ESTABLISHED, SHUTDOWN-PENDING, SHUTDOWN-SENT. Блок DATA, полученный в состоянии CLOSED, считается неожиданным и его следует обрабатывать в соответствии с правилами, описанными в параграфе 8.4. Блоки DATA, полученные во всех прочих состояниях, следует отбрасывать.

Подтверждения SACK должны обрабатываться в состояниях ESTABLISHED, SHUTDOWN-PENDING и SHUTDOWN-RECEIVED. Входящий блок SACK может быть обработан ассоциацией в состоянии COOKIE-ECHOED. Блок SACK в состоянии CLOSED считается неожиданным и его следует обрабатывать в соответствии с правилами, приведенными в параграфе 8.4. Во всех прочих состояниях блоки SACK следует отбрасывать.

Для эффективной передачи трафика протокол SCTP поддерживает механизм группировки мелких пользовательских сообщений и фрагментации больших сообщений. На рисунке 6 показана схема обмена пользовательскими сообщениями в SCTP.

В этом параграфе термин «отправитель» (data sender) будет указывать конечную точку, которая передаёт блок DATA, а термин «получатель» (data receiver) — точку, принимающую блок DATA. Получатель подтверждает приём данных блоком SACK.

+—————————-+ | Пользовательское сообщение | +—————————-+ Пользователь SCTP ^ | ==================|==|=================================== | v (1) +——————+ +———————-+ | Блоки SCTP DATA | |Блоки управления SCTP | +——————+ +———————-+ ^ | ^ | | v (2) | v (2) +—————————+ | Пакеты SCTP | +—————————+ SCTP ^ | =============================|==|======================== | v Пакетный сервис без организации соединений (например, IP)

Примечания.

  1. При преобразовании пользовательских сообщений в блоки DATA конечная точка должна фрагментировать большие сообщения. Размер каждого блока DATA следует делать не больше максимального размера блока данных в ассоциации (Association Maximum DATA Chunk Size или AMDCS). Получатель обычно будет собирать принятые фрагменты из блоков DATA до передачи сообщения пользователю (см. параграф 6.9).
  2. Несколько блоков DATA и блоков управления может группироваться отправителем в один пакет SCTP, пока размер результирующего пакета не будет превышать значение PMTU. Получатель будет разбирать групповой пакет, выделяя из него отдельные блоки. Блоки управления должны размещаться в пакете перед блоками DATA.

Рисунок 6. Пример передачи пользовательских данных.

Механизмы фрагментации и группировки, описанные в параграфах 6.9 и 6.10, являются необязательными для отправителя, но они должны быть реализованы на приёмной стороне (т. е., конечная точка должна принимать и обрабатывать фрагментированные и сгруппированные данные).

6.1. Передача блоков DATA

В этом параграфе приведены правила для отправки блоков DATA. В частности, определена проба нулевого окна, требуемая для предотвращения неопределённого ожидания ассоциации в случае потери пакетов с блоками SACK для обновления окна.

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

Ниже приведены правила общего назначения, используемые отправителем для передачи или повтора исходящих блоков DATA.

  1. В любой момент для отправителя недопустимо передавать новые данные по какому-либо транспортному адресу партнёра, если значение rwnd, полученное от того, говорит об отсутствии свободного пространства в буфере (т. е., rwnd меньше размера следующего блока данных, см. параграф 6.2.1), за исключением пробы нулевого окна.Если отправитель продолжает принимать новые пакеты от партнёра во время проверки нулевого окна, отсутствие подтверждения проб не следует использовать для инкрементирования счётчика ошибок ассоциации или каких-либо транспортных адресов партнёра. Это связано с тем, что получатель может держать своё окно закрытым в течение неопределённого времени. Поведение получателя, анонсирующего нулевое окно, описано в параграфе 6.2. Отправителю следует передавать первую пробу нулевого окна по истечении 1 RTO с момента обнаружения закрытия окна получателем, а также следует экспоненциально увеличивать интервал между проверками. Отметим также, что значение cwnd следует подстраивать в соответствии с параграфом 7.2.1. Проверки нулевого окна не оказывают влияния на расчёт cwnd.
  2. В любой момент времени для отправителя недопустимо передавать информацию по данному транспортному адресу, если у него имеется не менее cwnd + (PMDCS — 1) неподтвержденных байтов данных для этого адреса. Если данные доступны, отправителю следует превышать cwnd на величину до PMDCS — 1 при новой передаче данных, если размер находящихся в пути данных не достигает значения cwnd. Нарушение cwnd должно составлять лишь 1 пакет.
  3. Когда приходит время отправителю передавать новые блоки DATA, перед их отправкой он должен сначала передать неподтвержденные блоки DATA, которые помечены для повтора (не более cwnd).
  4. Когда приходит время отправителю передавать новые блоки DATA, следует использовать протокольный параметр Max.Burst для ограничения числа передаваемых пакетов. Ограничение может быть реализовано путём изменения cwndif((flightsize + Max.Burst*PMDCS) < cwnd)
      cwnd = flightsize + Max.Burst*PMDCS

    или просто может быть строго ограничено число пакетов, выдаваемых модулем отправки. При расчёте числа пакетов для передачи, в частности, по приведённой выше формуле, не следует менять cwnd на постоянной основе.

  5. Отправитель может передать столько новых блоков DATA, сколько позволяют правила A и B.
  6. Отправитель должен также поддерживать алгоритм отправки новых блоков DATA, позволяющий предотвратить синдром SWS23, как описано в [RFC1122]. Алгоритм может быть похож на описанный в параграфе 4.2.3.4 [RFC1122].
  7. Пробой нулевого окна (zero window probe) является, передаваемый, когда анонсированное получателем окно имеет нулевой размер. Это позволяет отправителю проверить изменение rwnd, которое он пропустил из-за потери блоков SACK, направленных от получателя к отправителю. Зонд нулевого окна должен передаваться лишь в том случае, когда это разрешает cwnd (см. п. B). Такие пробы следует передавать только в тех случаях, когда все остающиеся блоки DATA имеют кумулятивное подтверждение и нет находящихся в пути блоков DATA. Реализации должны поддерживать проверку нулевого окна.

Несколько блоков DATA, подготовленных для передачи, можно сгруппировать в один пакет. Кроме того, передаваемые повторно блоки DATA можно группировать с новыми блоками DATA, пока размер результирующего пакета не превышает PMTU. Протокол вышележащего уровня (ULP) может запросить передачу сообщений без группировки, но это означает лишь отключение задержек, которые реализация SCTP может использовать для повышения эффективности группировки. Группировка может происходить и в этом случае (например, при перегрузках или повторе передачи).

До того, как конечная точка передаст блок DATA, если имеются неподтвержденные блоки DATA, отправителю следует создать блок SACK для всех неподтвержденных данных и сгруппировать его с передаваемыми блоками DATA, пока размер результирующего пакета не превышает значение PMTU (см. параграф 6.2).

При заполнении окна (передача запрещена правилом A и/или B), отправитель может по-прежнему принимать запросы на передачу от вышележащего протокола, но он должен остановить передачу блоков DATA, пока некоторые или все остающиеся блоки DATA не будут подтверждены и правила A и B не будут выполнены.

При старте или перезапуске таймера T3-rtx его значение следует устанавливать в соответствии с правилами, приведёнными в параграфах 6.3.2 и 6.3.3.

Отправителю недопустимо использовать значения TSN, которые превышают стартовое значение TSN для текущего окна более, чем на 231 — 1.

Для каждого потока отправителю недопустимо иметь более 216 — 1 упорядоченных пользовательских сообщений в текущем окне передачи.

Когда отправитель блока DATA может получить преимущества от незамедлительной передачи ему соответствующего блока SACK, отправитель может установить флаг I в заголовке блока DATA. Следует отметить, что причина установки отправителем бита I не имеет значения для получателя.

Причины установки бита I включают (но не ограничиваются) указанные ниже (см. раздел 4 в [RFC7053]):

  • приложение запрашивает установку бита I в последнем блоке DATA пользовательского сообщения для представления этого сообщения реализации SCTP (параграф 11.1);
  • отправитель находится в состоянии SHUTDOWN-PENDING;
  • отправка блока DATA заполняет окно перегрузки или окно получателя.

6.2. Подтверждение приёма блоков DATA

Конечная точка SCTP всегда должна подтверждать получение каждого корректного блока DATA, когда этот блок приходит в окне приёма.

Когда получатель анонсирует размер окна 0, он должен отбрасывать все новые входящие блоки DATA со значением TSN, превышающим максимальное полученное до этого значение TSN. Если в новом входящем блоке DATA значение TSN меньше максимального из принятых до этого блоков, получателю следует отбросить наибольшее значение TSN, хранящееся для упорядочения, и воспринять новый блок DATA. В любом случае при отбрасывании блока DATA получатель должен незамедлительно вернуть блок SACK с текущим окном приёма, показывающим лишь блоки DATA, полученные и воспринятые к этому моменту. Отброшенные блоки DATA недопустимо включать в SACK, поскольку они не были восприняты. Получатель должен также иметь алгоритм анонсирования своего приёмного окна для предотвращения синдрома SWS, как описано в [RFC0813]. Это алгоритм может быть похож на описанный в параграфе 4.2.3.3 [RFC1122].

Следует придерживаться рекомендаций по использованию алгоритма отложенных подтверждений, описанного в параграфе 4.2 [RFC5681]. В частности, подтверждения следует генерировать по меньшей мере для каждого второго принятого пакета (не обязательно с блоком DATA), а также следует в течение 200 мсек генерировать подтверждение для любого ещё не подтверждённого блока DATA. В некоторых случаях для отправителя SCTP разумно быть более консервативным, нежели предлагает описанный в данном документе алгоритм подтверждения. Однако для отправителей SCTP недопустимо быть более агрессивными, нежели предлагает описанный ниже алгоритм.

Для отправителя SCTP недопустимо генерировать более 1 блока SACK для каждого входящего пакета, который не является обновлением предложенного размера окна при по мере потребления данных принимающим приложением. При расширении окна (opens up) получателю SCTP следует передавать дополнительные блоки SACK для обновления окна, даже если новых данных не получено. Получатель должен избегать передачи многочисленных обновлений окна и, в частности, больших пиков (large burst) таких обновлений. Одним из способов достижения этого является передача обновления окна лишь при его увеличении по меньшей мере на четверть размера приёмного буфера ассоциации.

Примечание для разработчиков. Максимальная задержка при генерации подтверждений может задаваться администратором SCTP статически или динамически в соответствии с реальными требованиями протоколов вышележащих уровней.

Для реализации протокола недопустимо разрешать установку максимальной задержки (параметр SACK.Delay) более 500 мсек. Иными словами, реализация может устанавливать SACK.Delay менее 500 мсек, но в любом случае недопустимо устанавливать значение более 500 мсек.

Подтверждения должны передаваться в блоках SACK до тех пор, пока от ULP не поступит запроса на завершение ассоциации (в последнем случае подтверждение может быть передано в блоке SHUTDOWN). Блок SACK может использоваться для подтверждения доставки нескольких блоков DATA (формат блоков SACK описан в параграфе 3.3.4). Конечная точка SCTP должна заполнить поле Cumulative TSN Ack, чтобы показать последний номер TSN для полученных без пропусков корректных блоков DATA. Все принятые блоки DATA с номерами TSN, превышающими значение Cumulative TSN Ack, указываются в полях Gap Ack Block. Конечная точка SCTP должна включать столько Gap Ack Block, сколько можно поместить в один блок SACK с учётом текущего значения PMTU.

Блок SHUTDOWN не включает поля Gap Ack Block. Поэтому конечной точке следует использовать SACK, а не SHUTDOWN для подтверждения доставки блоков DATA, принятых с нарушением порядка.

При получении пакета SCTP, содержащего блок DATA с установленным битом I, получателю не следует задерживать отправку соответствующего блока SACK, т. е. ему следует передать этот блок SACK незамедлительно.

При получении пакета с дубликатом блока(ов) DATA, в котором нет нового блока(ов) DATA, конечная точка должна незамедлительно передать SACK. Если пакет с дубликатом DATA содержит также новый блоки DATA, конечная точка может передать SACK незамедлительно. Обычно получение дубликатов DATA связано с потерей исходного блока SACK и тайм-аутом RTO у партнёра. Номера TSN для дубликатов следует указывать в блоке SACK как дубликаты.

При получении блока SACK конечная точка может использовать сведения о дубликатах TSN для обнаружения потери блоков SACK. Другие варианты использования этой информации требуют дальнейшего изучения.

Получатель данных отвечает за поддержку буферов приёма. Получателю следует своевременно уведомлять отправителя об изменении своих возможностей приёма данных. Способы управления приёмными буферами в реализации протокола зависят от множества факторов (например, от операционной системы, системы управления памятью, размера ОЗУ и т. п.). Однако описанная в параграфе 6.2.1 стратегия передачи основана на предположении, что получатель использует описанный ниже алгоритм.

  1. При создании ассоциации конечная точка сообщает партнёру размер своего приёмного буфера для данной ассоциации в блоке INIT или INIT ACK. Это значение размера буфера устанавливается для переменной a_rwnd.
  2. При получении и буферизации блоков DATA значение a_rwnd уменьшается на размер принятых и помещённых в буфер данных. Это, по сути, сокращает окно rwnd у отравителя и ограничивает количество данных, которые тот может передать.
  3. Когда блоки DATA передаются ULP и буфер освобождается, значение a_rwnd увеличивается на размер данных, которые отправлены протоколу вышележащего уровня. Таким образом окно rwnd открывается снова, позволяя отправителю передавать новые данные. Получателю не следует увеличивать значение a_rwnd, пока данные не будут освобождены из буфера. Например, если получатель удерживает фрагментированные блоки DATA в очереди на сборку, ему не следует увеличивать значение a_rwnd.
  4. При передаче блока SACK получателю данных следует поместить текущее значение переменной a_rwnd в поле a_rwnd передаваемого блока. Получателю данных следует принимать во внимание, что отправитель не будет повторять передачу блоков DATA, указанных в Cumulative TSN Ack (т. е., удалит их из очереди на повтор).

В некоторых случаях получатель может отбросить блоки DATA, которые были приняты, но ещё не освобождены из приёмного буфера (т. е., не переданы ULP). Такие блоки DATA могут быть подтверждены в Gap Ack Block. Например, получатель может удерживать принятые данные в буфере для сборки фрагментов пользовательского сообщения, когда обнаружится нехватка буферного пространства. Получатель в этом случае может отбросить блоки DATA из буфера, хотя они уже подтверждены в Gap Ack Block. Если получатель отбрасывает блоки DATA, их недопустимо включать в Gap Ack Block последующих блоков SACK, пока отброшенные блоки не будут получены снова в повторных пакетах. В дополнение к сказанному конечной точке следует учитывать отброшенные блоки при расчёте a_rwnd.

Конечной точке не следует отзывать SACK и отбрасывать данные. Этой процедурой следует пользоваться только в экстремальных ситуациях (например, при нехватке памяти). Получателю данных следует учитывать, что отбрасывание данных, подтверждённых в Gap Ack Block, может привести к неоптимальной работе отправителя и потере производительности.

Приведённый на рисунке 7 пример иллюстрирует использование отложенных подтверждений.

Точка A Точка Z {Приложение передает 3 сообщения; strm 0} DATA [TSN=7,Strm=0,Seq=3] ————> (подтверждение отложено) (Запуск таймера T3-rtx) DATA [TSN=8,Strm=0,Seq=4] ————> (передача подтверждения) /——- SACK [TSN Ack=8,block=0] (Остан. таймера T3-rtx)<——/ DATA [TSN=9,Strm=0,Seq=5] ————> (подтверждение отложено) (Запуск таймера T3-rtx) … {Прил. перед. 1 сообщ.; strm 1} (групп. SACK с DATA) /—— SACK [TSN Ack=9,block=0] \ / DATA [TSN=6,Strm=1,Seq=2] (Остан. таймера T3-rtx)<——/ (Запуск таймера T3-rtx) (подтверждение отложено) (передача подтверждения) SACK [TSN Ack=6,block=0] ————-> (Остан. таймера T3-rtx)

Рисунок 7. Пример подтверждения с задержкой.

Если конечная точка получает блок DATA без пользовательских данных (Length = 16), ей следует передать блок ABORT с причиной ошибки No User Data.

Конечной точке не следует передавать блоков DATA без пользовательских данных. Это избавляет от необходимости возврата пустых пользовательских сообщений в API сокета, как отмечено в [RFC6458].

6.2.1. Обработка подтверждений SACK

Каждый блок SACK, полученный конечной точкой, содержит значение a_rwnd. Это значение представляет объем свободного буферного пространства на приёмной стороне в момент передачи блока SACK, которое осталось от приёмного буфера, указанного в блоке INIT/INIT ACK. Используя значения a_rwnd, Cumulative TSN Ack и Gap Ack Block, отправитель может создать своё представление о буферном пространстве партнёра.

Одна из проблем, возникающих при обработке отправителем данных блока SACK, связана с тем, что подтверждения SACK могут доставляться с нарушением порядка (т. е., отправленный раньше блок SACK может быть доставлен позднее своих последователей). При нарушении порядка доставки блоков SACK у отправителя данных может сложиться превратное представление о буферном пространстве его партнёра.

Поскольку явных идентификаторов, позволяющих обнаружить нарушение порядка доставки SACK, не предусмотрено, отправитель данных должен использовать эвристические методы проверки полученных подтверждений SACK.

Конечной точке следует использовать приведённые ниже правила расчёта rwnd на основе значений a_rwnd, Cumulative TSN Ack и Gap Ack Block, полученных в блоке SACK.

  1. При создании ассоциации конечная точка устанавливает rwnd = a_rwnd24 из блока INIT или INIT ACKот партнёра.
  2. Всякий раз при передаче (или повторе) блока DATA партнёру конечная точка вычитает размер переданной информации из значения rwnd для этого партнёра.
  3. Всякий раз, когда блок DATA помечается для повтора по таймеру T3-rtx (параграф 6.3.3) или fast retransmit (параграф 7.2.4), размер этого блока добавляется к значению rwnd.
  4. Всякий раз при получении SACK конечная точка выполняет указанные ниже операции.
    1. Если Cumulative TSN Ack < Cumulative TSN Ack Point, блок SACK отбрасывается. Поскольку Cumulative TSN Ack возрастает монотонно, блок SACK, в котором Cumulative TSN Ack < Cumulative TSN Ack Point говорит о нарушении порядка доставки SACK.
    2. Для переменной rwnd устанавливается значение a_rwnd за вычетом числа байтов, остающихся не подтверждёнными, после обработки Cumulative TSN Ack и Gap Ack Block.
    3. Если в SACK отсутствует TSN, который был ранее подтверждён в Gap Ack Block (например, получатель отказался от данных), рассматривается соответствующий блок DATA, который может оказаться пропущенным. Блок считается отсутствующим для Fast Retransmit (параграф 7.2.4) и если нет запущенного таймера для адреса получателя, по которому блок DATA был передан изначально, для этого адреса запускается таймер T3-rtx.
    4. Если Cumulative TSN Ack совпадает со значением для точки выхода из процедуры Fast Recovery (параграф 7.2.4) или превышает его, процедура Fast Recovery завершается.

6.3. Управление таймером повтора передачи

Конечная точка SCTP использует таймер повтора передачи T3-rtx для обеспечения доставки данных при отсутствии обратной связи от партнёра. Время этого таймера называют тайм-аутом повтора или RTO.

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

Расчёт и обслуживание RTO для протокола SCTP осуществляются так же, как это делается для таймера повтора передачи в TCP. Для расчёта текущего значения RTO конечная точка поддерживает две переменных состояния для каждого адреса получателя — SRTT и RTTVAR.

6.3.1. Расчёт RTO

Ниже приводятся правила расчёта значений SRTT, RTTVAR и RTO.

  1. До того, как будет измерено значение RTT для пакета, переданного по данному транспортному адресу, для RTO следует использовать параметр протокола RTO.Initial.
  2. После того, как будет определено значение RTT (обозначим его R), следует установитьSRTT = R RTTVAR = R/2 RTO = SRTT + 4 * RTTVAR
  3. Когда будет получено для RTT новое значение R’, следует установитьRTTVAR = (1 — RTO.Beta) * RTTVAR + RTO.Beta * |SRTT — R’| SRTT = (1 — RTO.Alpha) * SRTT + RTO.Alpha * R’Примечание. Значение SRTT, используемое для обновления RTTVAR, представляет собой SRTT до обновления с использованием второго назначения. RTO = SRTT + 4 * RTTVAR.
  4. Когда данные находятся в процессе доставки и выполняется правило C5, для каждого кругового обхода должно быть выполнено новое измерение RTT. Новое измерение RTT следует проводить не более одного раза на круговой обход для данного транспортного адреса. Такое ограничение обусловлено 2 причинами. Во-первых, более частые измерения не имеют смысла, поскольку не дают заметных преимуществ [ALLMAN99], во-вторых, при частых измерениях значения RTO.Alpha и RTO.Beta в правиле C3 следует подбирать так, чтобы значения SRTT и RTTVAR корректировались примерно с одной же частотой (в терминах числа круговых обходов, при котором новые значения вступают в силу), как при одном измерении на круговой обход и с использованием RTO.Alpha и RTO.Beta в правиле C3. Однако точная процедура расчётов требует дополнительных исследований.
  5. Алгоритм Karn — измерение RTT недопустимо выполнять с использованием передаваемых повторно блоков, поскольку нет возможности различить, к какой из переданных копий относится полученный отклик.
  6. Если после расчёта RTO получается значение меньше RTO.Min, устанавливается RTO = RTO.Min. Причина этого заключается в том, что использование слишком малых значений RTO будет приводить к возникновению неоправданных тайм-аутов [ALLMAN99].
  7. Максимальное значение можно поместить в RTO при условии, что оно не меньше RTO.max секунд.
  8. Измерение RTT с использованием блока с TSN r следует выполнять лишь в тех случаях, когда нет блоков с номерами TSN не больше r, повторно переданными с момента первой передачи TSN r.
  9. После расчёта следует обновить

К дискретности часов (G) при измерении RTT и различных переменных состояния требований не предъявляется.

G1) Если при расчёте RTTVAR получено нулевое значение, следует установить RTTVAR = G.

Опыт показывает [ALLMAN99], что предпочтительной является дискретность часов не более 100 мсек.

Предложенные значения параметров приведены в разделе 16.

6.3.2. Правила для таймера повторной передачи

  1. Каждый раз при передаче блока DATA (включая повторы) по любому из адресов следует запустить для этого адреса таймер T3-rtx (если он не работает) на время RTO. Используемое для таймера значение RTO удваивается после каждого тайм-аута предыдущего таймера T3-rtx, связанного с этим адресом, как указано ниже в правиле E2.
  2. После подтверждения всех неподтвержденных для этого адреса данных таймер T3-rtx для адреса сбрасывается.
  3. Всякий раз при получении SACK, подтверждающего блок DATA с неподтвержденным TSN для данного адреса, таймер T3-rtx для этого адреса запускается заново с текущим значением RTO (если для этого адреса есть неподтвержденные данные).
  4. При получении SACK для пропущенного TSN, который ранее был подтверждён с помощью Gap Ack Block, включается таймер T3-rtx для адреса получателя, по которому блок DATA был передан изначально (если этот таймер ещё не запущен).

Точка A Точка Z {приложение начинает передачу} Data [TSN=7,Strm=0,Seq=3] ————> (задержка ack) (Пуск таймера T3-rtx) {Прил. перед. 1 сообщ.; strm 1} (группировка ACK и DATA) DATA [TSN=8,Strm=0,Seq=4] —-\ /— SACK [TSN Ack=7,Block=0] \ / DATA [TSN=6,Strm=1,Seq=2] \ / (Запуск таймера T3-rtx) \ / \ (Перезап. таймера T3-rtx)<——/ \—> (задержка ACK) (задержка ACK) {передача ACK} SACK [TSN Ack=6,Block=0] —————> (Остан. таймера T3-rtx) .. (передача ACK) (Остан. таймера T3-rtx) <————— SACK [TSN Ack=8,Block=0]

Рисунок 8. Пример правил для таймера.

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

6.3.3. Обработка завершения отсчёта T3-rtx

При завершении отсчёта T3-rtx для адреса получателя выполняются перечисленные ниже действия.

  1. Для этого адреса изменяется значение ssthresh в соответствии с правилами, приведёнными в параграфе 7.2.3, и устанавливается cwnd = PMDCS.
  2. Для этого адреса устанавливается RTO = RTO * 2. Максимальное значение, рассмотренное в правиле C7 (RTO.max), может служить верхней границей для операций удваивания.
  3. Определяется количество более ранних (т. е., с меньшими TSN) неподтвержденных блоков DATA для этого адреса, которые можно поместить в один пакет с учётом ограничений PMTU на пути доставки по этому транспортному адресу (для разных путей могут быть разные значения, см. параграф 6.4). Обозначим найденное число блоков K. Эти K блоков DATA группируются в один пакет для получателя.
  4. Запускается таймер повтора T3-rtx для адреса, по которому был передан повторный пакет, если приведённое выше правило R1 указывает это. Используемое для таймера значение RTO следует брать для одного из адресов, по которым передаётся повтор — в случае многодомного получателя значения могут различаться для разных адресов получателя (см. параграф 6.4).

После повтора передачи, когда будет проведено новое измерение RTT (это может случиться только в том случае, когда новые данные были переданы и подтверждены в соответствии с правилом C5 или измерение сделано на основе HEARTBEAT, см. параграф 8.3), выполняется расчёт по правилу C3 (включая вычисление RTO), который может привести к «коллапсу» RTO (со снижением значения до начального уровня) после того, как это значение было удвоено (правило E2).

Любые блоки DATA, переданные по адресу, для которого истекло время T3-rtx, но не был заполнен пакет SCTP размером не более PMTU (правило E3), следует пометить для повторной передачи и передать, как только позволит cwnd (обычно при получении SACK).

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

  1. Всякий раз, когда конечная точка переключается с текущего транспортного адреса получателя на другой транспортный адрес, текущий таймер повтора передачи продолжает работать. Как только конечная точка передаст пакет, содержащий блок(и) DATA, по новому транспортному адресу, запускается таймер для этого адреса с использованием значения RTO для адреса получателя, по которому были переданы данные, если правило R1 указывает, что это нужно сделать.

6.4. Многодомные точки SCTP

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

ULP в конечной точке выбирает один из адресов многодомного партнёра для основного пути (параграфы 5.1.2 и 10.1).

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

Конечной точке следует передавать блоки откликов (например, INIT ACK, COKIE ACK, HEARTBEAT ACK) по тому же транспортному адресу, с которого был получен управляющий блок, вызвавший передачу отклика.

Выбор транспортного адреса получателя пакетов с блоками SACK зависит от реализации. Однако конечной точке не следует менять транспортный адрес получателя SACK в случае приёма блоков DATA с тем же адресом отправителя.

При подтверждении нескольких блоков DATA, полученных в пакетах с разных адресов, в одном SACK этот блок SACK может передаваться по одному из транспортных адресов, с которых были получены подтверждаемые блоки DATA или управляющие блоки.

Когда получатель дубликата блока DATA передаёт блок SACK многодомной конечной точке, он может воспользоваться выбором адреса получателя и не применять адрес отправителя блока DATA. Причина этого заключается в том, что получение дубликата от многодомной конечной точки может указывать на то, что путь возврата, указанный в поле отправителя блока DATA, может быть недоступен (разорван) для передачи SACK.

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

Когда партнёр конечной точки является многодомным, ей следует передавать ускоренные повторы по тому же транспортному адресу получателя, куда данные направлялись исходно. Если основной путь сменился, а исходные данные переданы по старому основному пути до Fast Retransmit, реализация может отправить повтор по новому пути.

Повтор передачи не оказывает влияния на общий счётчик неподтвержденных данных. Однако, если блок DATA передаётся повторно с использованием другого адреса получателя, счётчики неподтвержденных данных для старого и нового адресов получателя должны быть согласованно изменены.

6.4.1. Переключение с неактивного адреса получателя

Некоторые транспортные адреса многодомной конечной точки SCTP могут утратить активность в результате ошибок (см. параграф 8.2) или по желанию пользователя SCTP.

Когда имеются данные для передачи и основной путь становится неактивным (например, по причине отказа) или пользователь SCTP явно запрашивает передачу данных по неактивному транспортному адресу получателя, до передачи сообщения об ошибке ULP, конечной точке SCTP следует предпринять попытку передачи данных по другому активному адресу получателя, если таковой имеется.

При повторе передачи данных в результате тайм-аута, если конечная точка является многодомной, ей следует рассматривать каждую пару адресов «отправитель-получатель» в политике выбора при повторе. Передающей конечной точке следует пытаться выбрать для повтора пару адресов, наиболее сильно отличающуюся от использованной при первой попытке пары «отправитель-получатель».

Примечание. Правила выбора максимально отличающейся пары зависят от реализации и не определяются данной спецификацией.

6.5. Идентификаторы и порядковые номера в потоке

Каждый блок DATA должен содержать действительный идентификатор потока. Если конечная точка принимает блок DATA с недействительным идентификатором, ей следует подтвердить получение данных в соответствии с обычной процедурой, незамедлительно передать блок ERROR с причиной ошибки Invalid Stream Identifier (недейсвительный идентификатор потока, см. параграф 3.3.10) и отбросить блок DATA. Конечная точка может группировать блок ERROR в один пакет с блоком SACK.

Порядковые номера во всех потоках должны начинаться с нуля при создании ассоциации. Значение Stream Sequence Number должно увеличиваться на 1 для каждого упорядоченного пользовательского сообщения, переданного в выходной поток. При достижении порядковым номером в потоке значения 65535 следующим номером снова должен быть 0. Для неупорядоченных пользовательских сообщение менять Stream Sequence Number недопустимо.

6.6. Упорядоченная и неупорядоченная доставка

Внутри потока конечная точка должна доставлять блоки DATA, полученные с флагом U = 0, на вышележащий уровень в соответствии с порядковыми номерами блоков в потоке. Если блоки DATA поступают с нарушением порядка, конечная точка должна удерживать полученные блоки DATA от передачи ULP, пока не будет восстановлен порядок.

Однако конечная точка SCTP может запросить неупорядоченную доставку для определённого блока DATA, передаваемого в потоке, установив для этого блока флаг U = 1.

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

Это обеспечивает эффективный способ передачи «дополнительных» (out-of-band) данных в потоке. Кроме того, весь поток можно сделать неупорядоченным, устанавливая флаг U = 1 для каждого блока DATA в этом потоке.

Примечание для разработчиков. При передаче неупорядоченного блока DATA реализация протокола может помещать такой блок DATA в начало очереди на передачу, если такая возможность имеется.

Поле Stream Sequence Number в блоке DATA с флагом U = 1 не имеет смысла. Отправитель может указывать в этом поле произвольное значение, а получатель должен игнорировать это поле.

Примечание. При передаче упорядоченных и неупорядоченных данных, конечная точка не увеличивает своё значение поля Stream Sequence Number, передавая блок DATA с флагом U = 1.

6.7. Информация о пропусках в TSN блоков DATA

При получении нового блока DATA конечная точка проверяет непрерывность порядковых номеров TSN. Если обнаружен пропуск в порядковых номерах принятых блоков DATA, конечной точке следует незамедлительно передать блок SACK с Gap Ack Block. Получатель продолжает передачу SACK после приёма каждого пакета SCTP, который не закрывает пропуск в порядковых номерах.

На основе Gap Ack Block из полученного блока SACK конечная точка может определить пропущенные блоки DATA и принять решение о необходимости повторной передачи таких блоков (см. параграф 6.2.1).

В одном блоке SACK может передаваться информация о нескольких обнаруженных пропусках (см. параграф 3.3.4).

Если партнёр является многодомным, конечной точке SCTP всегда следует пытаться передать SACK по тому адресу, с которого был получен последний блок DATA.

При получении блока SACK конечная точка должна удалить из выходной очереди все блоки DATA, которые были подтверждены в Cumulative TSN Ack блока SACK. Передающая конечная точка должна считать «отсутствующими» все блоки DATA с номерами TSN, не включёнными в Gap Ack Block, которые меньше максимального TSN из блока SACK. Число отчётов о «потерях» для каждого неподтвержденного блока DATA должно быть записано отправителем, чтобы принять решение о повторной передаче (см. параграф 7.2.4).

На рисунке 9 приведён пример использования SACK для передачи информации о пропуске порядковых номеров.

Точка A Точка Z {Приложение передало 3 сообщения; strm 0} DATA [TSN=6,Strm=0,Seq=2] —————> (задержка ack) (Запуск таймера T3-rtx) DATA [TSN=7,Strm=0,Seq=3] ———> X (потерян) DATA [TSN=8,Strm=0,Seq=4] —————> (обнаружен пропуск, немедленная передача ack) /—— SACK [TSN Ack=6,Block=1, / Strt=2,End=2] <——/ (удаляем 6 из выходной очереди и помечаем 7 как отчёт о пропуске «1»)

Рисунок 9. Отчет о пропуске с использованием SACK.

Максимальное число Gap Ack Block, которые могут быть включены в один блок SACK, ограничивается текущим значением PMTU. Когда в один блок SACK невозможно включить все Gap Ack Block, которые нужно передать, по причине ограничения PMTU, конечная точка должна передать только один блок SACK, который должен включать все Gap Ack Block от младших номеров TSN к старшим, помещающиеся в блок, ограниченный PMTU, и оставить старшие номера TSN неподтвержденными.

6.8. Расчёт контрольных сумм CRC32c

При передаче пакета SCTP конечная точка должна для обеспечения возможности контроля целостности данных включить в пакет значение контрольной суммы CRC32c в соответствии с приведённым ниже описанием.

После создания пакета (общий заголовок SCTP и один или несколько управляющих блоков или блоков DATA) отправитель должен выполнить перечисленные ниже операции.

  1. Заполнить поле Verification Tag общего заголовка SCTP и установить нулевое значение в поле контрольной суммы.
  2. Рассчитать контрольную сумму CRC32c с включением общего заголовка SCTP и всех блоков из пакета. Описание алгоритма CRC32c приводится в Приложении A.
  3. Поместить полученное значение в поле контрольной суммы общего заголовка, не изменяя остальных битов.

При получении пакета SCTP принимающая конечная точка должна сначала проверить значение контрольной суммы CRC32c в заголовке, как описано ниже.

  1. Сохранить полученное в пакете значение контрольной суммы CRC32c.
  2. Заменить 32-битовое поле контрольной суммы принятого пакета SCTP значением 0 и рассчитать контрольную сумму CRC32c для полученного пакета.
  3. Сравнить сохранённое значение (из пакета) CRC32c с контрольной суммой, полученной в результате расчёта. Если значения не совпадут, получатель должен считать принятый пакет недействительным.

По умолчанию недействительные пакеты SCTP отбрасываются без уведомления.

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

6.9. Фрагментация и сборка

Конечная точка может поддерживать фрагментацию при передаче блоков DATA и должна поддерживать сборку фрагментов для принимаемых блоков DATA. Если конечная точка поддерживает фрагментацию, она должна фрагментировать пользовательские сообщения, когда их размер приводит к созданию пакетов SCTP, превышающих по своему размеру значение PMTU. Если реализация не поддерживает фрагментацию, конечная точка должна возвращать вышележащему уровню код ошибки, когда размер пакета SCTP превышает текущее значение PMTU, передать сообщения избыточного размера недопустимо.

Реализация SCTP может обеспечивать вышележащему уровню механизм запрета фрагментирования при передаче блоков DATA. При отключённой фрагментации блоков DATA реализация SCTP должна вести себя так, будто фрагментация не поддерживается, т. е. отвергать вызовы, приводящие к созданию пактов SCTP, размер которых превышает PMTU.

Примечание для разработчиков. В случае ошибки для возврата кода вышележащему уровню нужно использовать примитив SEND, рассматриваемый в параграфе 11.1.5.

Если партнёр является многодомным, конечной точке следует выбирать размер блока DATA, не превышающий значение AMDCS.

После фрагментации сообщения оно не может быть фрагментировано ещё раз. Если же значение PMTU уменьшилось, должна использоваться фрагментация IP. Поэтому реализация SCTP может сталкиваться в отказом, если фрагментация IP не работает на каком-либо пути. Определение значений PMTU рассматривается в параграфе 7.3.

При решении вопроса о необходимости фрагментирования реализация SCTP должна принимать во внимание размер заголовка пакета SCTP и заголовков блоков DATA. Должен также приниматься во внимание размер блоков SACK, если они группируются с блоком DATA.

Фрагментация выполняется следующим образом.

  1. Отправитель должен разбить пользовательское сообщение на несколько блоков DATA. Отправителю следует выбирать размер блоков DATA, не превышающий AMDCS.
  2. Передающая сторона должна выделять по порядку номера TSN для каждого из блоков DATA, содержащих фрагменты сообщения. Всем блокам DATA, содержащим фрагменты одного сообщения, присваиваются одинаковые номера SSN. Если пользователь указал, что сообщение доставляется без соблюдения порядка, для каждого блока DATA должен быть установлен флаг U = 1.
  3. Отправитель должен также установить для битов B/E в первом блоке DATA значение 10, в последнем — 01, а в остальных — 00.

Конечная точка должна распознавать фрагментированные блоки DATA путём проверки битов B/E в каждом принятом блоке DATA и помещать фрагменты в очередь для сборки. После сборки пользовательского сообщения из фрагментов, протокол SCTP будет передавать собранное сообщение в конкретный поток для возможного упорядочивания и окончательной диспетчеризации.

Если на передающей стороне недостаточно памяти для буферизации фрагментов в процессе ожидания их доставки, следует направить полученную часть входящего сообщения через API частичной доставки (см. раздел 11) для освобождения буферного пространства.

6.10. Группировка блоков

Конечная точка группирует блоки путём простого включения множества блоков в один исходящий пакет SCTP. Суммарный размер получающейся в результате дейтаграммы IP (включая пакет SCTP и заголовок IP) должен быть не более текущего значения PMTU.

Если партнёр является многодомным, передающей стороне следует выбирать размер пакета так, чтобы он не превышал значение PMTU для текущего основного пути.

При группировке управляющих блоков с блоками DATA конечная точка должна помещать управляющие блоки в начале пакета SCTP. Отправитель должен передавать блоки DATA в пакете SCTP в соответствии с ростом TSN.

Примечание. Поскольку управляющие блоки размещаются в пакете первыми, а блоки DATA должны передаваться до управляющих блоков SHUTDOWN и SHUTDOWN ACK, блоки DATA не могут группироваться с блоками SHUTDOWN или SHUTDOWN ACK.

Недопустимо включение в пакет SCTP неполных блоков (Partial chunk). Неполным является блок, которым не помещается в пакет SCTP (пакет слишком мал для включения всех байтов, указанных в поле размера блока).

Принимающая сторона должна обрабатывать полученные блоки в порядке их следования в пакете. Получатель использует поле длины блока для определения конца данного блока и начала следующего. При определении начала блока не следует забывать о выравнивании блоков по 4-байтовой границе. Если получатель обнаруживает в пакете неполный блок, такой блок должен быть отброшен.

Недопустимо группировать блоки INIT, INIT ACK, SHUTDOWN COMPLETE с любыми другими блоками.

7. Контроль перегрузки

Контроль перегрузки является одной из базовых функций SCTP. Для контроля перегрузок применяются механизмы, описанные в этом разделе.

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

Алгоритмы контроля перегрузки протокола SCTP основаны на [RFC5681]. В этом разделе описано, как алгоритмы, определённые в [RFC5681], адаптированы для использования в SCTP. Сначала рассматриваются различия между протоколами TCP и SCTP, а после этого описывается схема контроля перегрузки в SCTP. В описании используется та же терминология, которая принята для протокола TCP.

Контроль перегрузки в SCTP всегда применяется ко всей ассоциации (соединению), а не к отдельным потокам.

7.1. Различия в контроле перегрузки для SCTP и TCP

Gap Ack Block в SCTP SACK имеют такой же смысл, как TCP SACK. Протокол TCP рассматривает информацию в SACK только как консультативную и в SCTP сведения из Gap Ack Blocks блоков SACK являются лишь консультативными. В SCTP любой блок DATA, подтверждённый с помощью SACK (включая блоки DATA, полученные с нарушением порядка), не считается доставленным окончательно, пока Cumulative TSN Ack Point не перейдёт значение TSN блока DATA (т. е., пока блок DATA не будет подтверждён полем Cumulative TSN Ack в SACK). Поэтому значение параметра cwnd контролирует количество неподтвержденных данных, а не (как в случае TCP без SACK) верхнюю границу между максимальным подтверждённым порядковым номером и последним блоком DATA, который может быть передан в окне перегрузки. SCTP SACK обусловливает отличие реализации механизмов ускоренного повтора (fast-retransmit) и быстрого восстановления (fast-recovery) от случая TCP без SACK. Пример этого приведён в [FALL96].

Наиболее серьёзным различием между SCTP и TCP является поддержка в SCTP многодомных конечных точек. Протокол SCTP разработан для организации устойчивых ассоциаций между конечными точками, каждая из которых может быть доступна по нескольким транспортным адресам. Использование различных адресов может вести к организации разных путей между парой конечных точек и в идеальном случае для каждого пути нужно применять свои параметры контроля перегрузки. Приведённая здесь трактовка контроля перегрузки для многодомных получателей является новинкой протокола SCTP и может быть уточнена в будущем. Текущие алгоритмы основаны на приведённых ниже допущениях.

  • Отправитель обычно не меняет адрес получателя, пока не получит запрос на такую замену от протокола вышележащего уровня. Однако SCTP может переключиться на другой адрес получателя, если прежний адрес был помечен, как неактивный (см. параграф 8.2). Кроме того, SCTP может повторять передачу пакетов по адресам, отличающимся от тех, которые использовались для передачи исходного пакета.
  • Отправитель сохраняет отдельный набор параметров контроля перегрузки для каждого адреса получателя, по которому он может передавать данные (не для каждой пары адресов «отправитель-получатель», а для каждого адреса получателя). Параметры следует отбрасывать, если адрес не используется достаточно долго. В [RFC5681] этот период указан как тайм-аут повторной передачи.
  • Для каждого адреса получателя конечная точка выполняет процедуру замедленного старта (slow-start) при первой передаче по этому адресу.

Примечание. TCP гарантирует упорядоченную доставку данных протоколу вышележащего уровня в рамках одной сессии TCP. Это означает, что при получении протоколом TCP информации о пропуске в порядковых номерах он будет ждать заполнения пропуска и только после этого передаст данные вышележащему уровню. SCTP может доставлять данные на вышележащий уровень даже при наличии пропусков в порядковых номерах TSN, если порядковые номера в потоке (Stream Sequence Number) упорядочены в рамках данного потока (т. е., пропущенный блок DATA относится к другому потоку) или при запросе неупорядоченной доставки. Это различие не оказывает влияния на cwnd, но может влиять на расчёт rwnd.

7.2. Процедуры Slow-Start и Congestion Avoidance

Алгоритмы замедленного старта и предотвращения перегрузки должны использоваться конечной точкой для контроля количества данных, передаваемых в сеть. Контроль перегрузки работает в SCTP на уровне ассоциаций, а не отдельных потоков в ассоциации. В некоторых ситуациях отправителю SCTP может давать некоторые преимущества более консервативное поведение, нежели предлагают алгоритмы, однако для отправителя недопустимо быть более агрессивным, нежели позволяют алгоритмы.

Подобно TCP, конечная точка SCTP использует 3 указанных ниже переменных для управления скоростью передачи.

  • Анонсируемый получателем размер окна приёма (rwnd25, в байтах) устанавливается получателем данных с учётом возможностей выделения буферов для принимаемых пакетов.
  • Окно контроля перегрузки (cwnd26, в байтах) устанавливается отправителем с учётом условий в сети.
  • Порог замедленного старта (ssthresh27, в байтах) используется отправителем для принятия решения о выборе используемого алгоритма контроля перегрузки (slow start или congestion avoidance).
  • Примечание. Эта переменная поддерживается для каждого адреса получателя.
  • Примечание. Эта переменная поддерживается для каждого адреса получателя.
  • Примечание. Эта переменная имеет общее значение для всей ассоциации.

Протокол SCTP использует также одну дополнительную переменную — partial_bytes_acked, которая применяется в фазе предотвращения перегрузки для упрощения расчёта значения cwnd.

В отличие от TCP, отправитель SCTP должен хранить набор из трёх переменных (cwnd, ssthresh и partial_bytes_acked) для каждого адреса получателя у партнёра (если тот является многодомным). При расчёте этих переменных следует использовать размер блоков DATA с учётом заполнения.

Только переменная rwnd имеет общее значение для всей ассоциации (независимо от того, является ли партнёр многодомным).

7.2.1. Замедленный старт

Начиная передачу данных в сеть с неизвестными условиями или возобновляя передачу после достаточно долгого простоя, протокол SCTP должен проверить сеть на предмет пропускной способности. Для этих целей используется алгоритм slow start в начале передачи или при восстановлении потерь, обнаруженных по таймеру повтора передачи.

  • В качестве стартового значения cwnd до передачи блоков DATA или после достаточно долгого бездействия должно выбираться значение min(4*PMDS, max (2*PMDS, 4404) байт для адреса партнёра IPv4 и min(4*PMDS, max (2*PMDS, 4344) байт для IPv6.
  • Начальное значение cwnd после тайм-аута повтора передачи должно быть не более PMDS и разрешается лишь один находящийся в пути пакет без подтверждения.
  • Начальному значению ssthresh следует быть произвольно большим (например, размер наибольшего возможного анонсируемого окна).
  • При положительном значении cwnd конечная точка может иметь cwnd ожидающих подтверждения байтов данных для этого транспортного адреса. Следует поддерживать ограниченное превышение, как указано в правиле B параграфа 6.1.
  • Если cwnd не больше ssthresh, конечная точка SCTP должна использовать алгоритм slow-start для увеличения размера cwnd только в том случае, когда текущее окно перегрузки полностью использовано и отправитель данных не находится в состоянии Fast Recovery. Размер окна cwnd можно увеличивать только при выполнении обох условий, в противном случае увеличение недопустимо. Если все условия выполнены, значение cwnd должно увеличиваться не более чем на меньшее из двух значений:
    1. общий размер подтверждённых блоков DATA
    2. L раз по PMDS получателя.

    Первое ограничение обеспечивает защиту от атак ACK-Splitting, описанных в [SAVAGE99]. Положительному целому числу L следует иметь значение 1 и можно использовать большее значение. Выбор L описан в [RFC3465].

  • В случаях, когда партнёр является многодомным и конечная точка получает подтверждение SACK, ведущее к обновлению cwnd, ей следует обновить значение cwnd (или несколько значений cwnd) для адреса получателя, по которому были переданы подтверждённые данные.
  • Когда конечная точка не передаёт по данному транспортному адресу, в качестве cwnd для этого адреса следует установить max(cwnd/2, 4*PMDS) один раз за RTO. До первого обновления cwnd для параметра ssthresh следует установить значение cwnd.

7.2.2. Предотвращение перегрузки

При cwnd > ssthresh, значение cwnd следует увеличивать на PMDS за каждый период RTT, если у отправителя имеется не менее cwnd байтов неподтвержденных данных для соответствующего транспортного адреса. Базовые рекомендации по увеличению cwnd в случае предотвращения перегрузки приведены ниже.

  • SCTP может увеличивать cwnd на PMDS.
  • SCTP следует увеличивать cwnd на PMDS 1 раз за период RTT, когда у отправителя есть не менее cwnd остающихся байтов данных для соответствующего транспортного адреса.
  • SCTP недопустимо увеличивать cwnd более чем на PMDS за период RTT.

На практике эта процедура может быть реализована описанным ниже способом.

  • Устанавливается partial_bytes_acked = 0.
  • Если cwnd > ssthresh, всякий раз при получении SACK значение partial_bytes_acked увеличивается на общее число байтов (включая заголовок блока и заполнение) во всех новых блоках DATA, подтверждённых этим SACK, включая блоки, подтверждённые новым значением Cumulative TSN Ack, Gap Ack Block и и число байтов в блоках-дубликатах, указанных в Duplicate TSN.
  • Когда (1) значение partial_bytes_acked становится больше cwnd и (2) до прибытия SACK у отправителя имеется менее cwnd остающихся данных (т. е., до прибытия SACK, объем переданных, но ещё не подтверждённых данных меньше cwnd), устанавливается partial_bytes_acked = cwnd.
  • Когда (1) значение partial_bytes_acked становится равным cwnd или превышает его и до прибытия SACK у отправителя имеется не менее cwnd остающихся данных (т. е., до прибытия SACK, объем переданных, но еще не подтверждённых данных не меньше cwnd), значение partial_bytes_acked уменьшается на cwnd, а затем cwnd увеличивается на PMDS.
  • Как и при замедленном старте в качестве значения cwnd для адреса получателя следует установить max(cwnd/2, 4*PMDS) за период RTO, если отправитель не передаёт блоков DATA по данному адресу.
  • Когда все переданные отправителем данные подтверждены получателем, устанавливается partial_bytes_acked = 0.

7.2.3. Контроль перегрузки

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

ssthresh = max(cwnd/2, 4*PMDS) cwnd = ssthresh partial_bytes_acked = 0

Обычно потеря пакета приводит к уменьшению cwnd вдвое.

По завершении отсчёта таймера T3-rtx для адреса, SCTP следует выполнить процедуру slow start, установив

ssthresh = max(cwnd/2, 4*PMDS) cwnd = PMDS partial_bytes_acked = 0

и обеспечить наличие не более одного пакета SCTP на пути от отправителя к получателю, пока конечная точка не получит подтверждения доставки данных по этому адресу.

7.2.4. Ускоренный повтор при пропуске

При отсутствии потерь данных конечная точка использует отложенные подтверждения. Однако при обнаружении пропуска в TSN следует начать передачу подтверждений SACK сразу после доставки каждого пакета, пока пропуск в порядковых номерах не будет заполнен.

Всякий раз при получении SACK, указывающего на пропуск TSN, конечной точке следует дождаться 2 последующих индикаций потери (в следующих подтверждениях SACK) для тех же номеров, прежде, чем начать реализацию механизма ускоренного повтора (Fast Retransmit).

Для индикации пропусков следует применять алгоритм HTNA28. Для каждого входящего блока SACK значение счётчика индикации пропуска увеличивается только для пропущенных TSN до HTNA в SACK. Недавно подтверждённым блоком DATA считается блок, который не был ранее указан в SACK. Если конечная точка в состоянии Fast Recovery получает блок SACK, указывающий за пределы Cumulative TSN Ack Point, значения индикации пропуска увеличиваются для всех TSN, пропуск которых указывает этот блок SACK.

При получении третьей индикации отсутствующих TSN отправитель выполняет указанные ниже действия.

  1. Пометить указанные блоки DATA для повторной передачи.
  2. Если не введён режим Fast Recovery, изменить значения ssthresh и cwnd для адреса (или нескольких адресов) получателя, по которому были переданы утерянные данные в последний раз, согласно выражениям, приведённым в параграфе 7.2.3.
  3. Если не введён режим Fast Recovery, определить, сколько наиболее ранних (т. е., с меньшими TSN) блоков DATA может быть включено в один пакет с учётом значения PMTU для транспортного адреса получателя, по которому будут передаваться данные (обозначим это количество буквой K). Повторно передать эти K блоков DATA в одном пакете. В режиме Fast Retransmit отправителю следует игнорировать значение cwnd и не следует задерживать повтор передачи для одного данного пакета.
  4. Заново запустить таймер T3-rtx, если последнее подтверждение SACK относится к меньшему из неподтвержденных TSN для данного адреса получателя или конечная точка повторяет передачу первого из неподтвержденных блоков DATA, переданных по этому адресу.
  5. Пометить блок(и) DATA, как ускоренно повторённый и не приемлемый для последующего режима Fast Retransmit. Эти TSN маркируются для повторной передачи по причине того, что алгоритм Fast Retransmit не подходит для дейтаграммы, содержащей K других TSN, которые также отмечены неприемлемыми для последующего ускоренного повтора. Однако в результате маркировки для повтора они будут переданы заново, как только позволит cwnd.
  6. Перейти в режим Fast Recovery (если он ещё не введён) и указать старший остающийся номер TSN как точку выхода из режима быстрого восстановления. Когда блок SACK подтвердит все TSN, вплоть до указанной точки выхода, режим быстрого восстановления завершается. В режиме Fast Recovery значения ssthresh и cwnd не следует менять для каких-либо получателей в результате следующего события Fast Recovery (т. е. не следует снижать значение cwnd в результате последующего ускоренного повтора).

Примечание. Если полученный блок SACK также подтверждает новые блоки DATA за пределами Cumulative TSN Ack Point, перед выполнением перечисленных в пп. 1-6 операций сначала должно быть изменено значение cwnd в соответствии с правилами, приведёнными в параграфах 7.2.1 и 7.2.2.

7.2.5. Повторная инициализация

В течение срока действия ассоциации SCTP могут происходить события, вдещие к использованию сети в новых изменившихся условиях. При обнаружении этого реализацией SCTP контроль перегрузок должен инициализироваться заново.

7.2.5.1. Смена кодов дифференцированного обслуживания

Реализации SCTP могут разрешать приложениям настраивать коды DSCP (Differentiated Services Code Point) для передаваемых пакетов. Если смена DSCP может приводить к размещению пакетов в разных очередях, параметры контроля перегрузок для всех затрагиваемых адресов получателя должны быть сброшены к начальным значениям.

7.2.5.2. Смена маршрутов

Реализации SCTP могут знать об изменении маршрутов, влияющем на пакеты, отправленные получателю. В частности, это включает выбор другого адреса отправителя в передаваемых пакетах. При таких изменениях маршрутов параметры контроля перегрузок для всех затрагиваемых адресов получателя должны быть сброшены к начальным значениям.

7.3. Определение PMTU

В [RFC8899], [RFC8201] и [RFC1191] описан алгоритм определения MTU на пути для уровня пакетизации (Packetization Layer Path MTU Discovery), позволяющий конечным точкам оценить PMTU для данного пути через Internet и воздерживаться от передачи по этому пути пакетов, размер которых превышает PMTU, без использования методов зондирования с целью определения изменений PMTU. В [RFC8899] подробно рассмотрен механизм определения PMTU и стратегия установки сквозного значения PMTU, а также детектирования изменений PMTU.

Конечной точке следует применять эти методы определения MTU, а также следует выполнять такое определение PMTU независимо для каждого адреса получателя.

При определении значения PMTU для протокола SCTP существуют несколько специфических аспектов.

  1. Ассоциация SCTP может включать множество адресов. Конечная точка должна поддерживать отдельную оценку значения PMTU для каждого из адресов своего партнёра.
  2. Отправителю следует отслеживать значение AMDCS, которое будет меньшим из PMDCS среди всех адресов партнёра. При фрагментации сообщений значение AMDCS следует использовать для определении размера каждого блока DATA. Такой подход позволит передавать фрагменты по любому из возможных путей без дополнительной фрагментации на уровне IP.

8. Контроль отказов

8.1. Обнаружение отказов конечных точек

Конечной точке следует подсчитывать общее количество последовательных повторов передачи своему партнёру (включая повторы по всем адресам для многодомных партнёров) с учётом неподтвержденных блоков HEARTBEAT, наблюдаемых на текущем пути передачи данных. Неподтвержденные блоки HEARTBEAT на других путях не следует учитывать в счетчике ошибок, поскольку это ведёт к закрытию ассоциации даже если текущий путь передачи данных доступен (но бездействует). Если значение этого счётчика превысит порог, указанный параметром протокола Association.Max.Retrans29, конечной точке следует рассмотреть вопрос о доступности партнёра и нужно прекратить передачу ему каких-либо данных (т. е. перевести ассоциацию в состояние CLOSED). Кроме того, конечной точке следует передать информацию об отказе (и, возможно, об оставшихся в выходной очереди данных) протоколу вышележащего уровня. Ассоциация автоматически закрывается, когда удалённый партнёр становится недоступным.

Счётчик повторов должен сбрасываться всякий раз, когда переданный партнёру блок DATA подтверждается (приём SACK) и его следует сбрасывать при получении от удалённого партнёра блока HEARTBEAT ACK. Получатель блока HEARTBEAT ACK может не сбрасывать счётчик, если имеет в ассоциации остающиеся данные. Это позволяет обрабатывать возможные различия в доступности на основе блоков DATA и HEARTBEAT.

8.2. Обнаружение отказов на пути

Если партнёр является многодомным, конечной точке следует поддерживать счётчики ошибок для каждого транспортного адреса этого партнёра.

Каждый раз, когда завершается отсчёт таймера T3-rtx для любого из адресов или передача HEARTBEAT по бездействующему адресу не подтверждается в течение RTO, значение счётчика ошибок для соответствующего адреса будет увеличиваться на 1. Когда значение счётчика превысит значение параметра протокола Path.Max.Retrans30 для данного адреса, конечной точке следует пометить этот адрес как неактивный, а также следует передать уведомление об этом протоколу вышележащего уровня.

Когда остающиеся TSN подтверждаются или блок HEARTBEAT, переданный по бездействующему адресу, подтверждается блоком HEARTBEAT ACK, конечной точке следует сбрасывать счётчик ошибок для транспортного адреса получателя, по которому был отправлен последний блок DATA (или HEARTBEAT), а также следует информировать вышележащий уровень при активизации неактивного адреса. Если партнёр является многодомным и последний блок был передан ему в качестве повтора с изменением адреса получателя, возникает неоднозначность в выборе адреса, для которого следует учитывать полученное подтверждение. Однако эта неоднозначность не оказывает существенного влияния на дальнейшее поведение SCTP. Если такие неоднозначности нежелательны, отправитель может не сбрасывать счётчик ошибок, когда последний блок передавался повторно.

Примечание. При настройке конфигурации конечной точки SCTP пользователь должен избегать установки для параметра Association.Max.Retrans значения, превышающего любое из значений Path.Max.Retrans для адресов партнёра. В противном случае все адреса удалённого партнёра могут стать неактивными, а данная точка будет по-прежнему считать этого партнёра доступным. При возникновении такой ситуации поведение протокола SCTP будет зависеть от реализации.

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

8.3. Проверка жизнеспособности пути

По умолчанию конечной точке SCTP следует вести мониторинг доступности бездействующих транспортных адресов своего партнёра путём периодической отправки по таким адресам блоков HEARTBEAT. Передача HEARTBEAT может начинаться с момента перехода в состояние ESTABLISHED и завершаться после отправки блока SHUTDOWN или SHUTDOWN-ACK. Получатель HEARTBEAT должен отвечать на него блоком HEARTBEAT-ACK после перехода в состояние COOKIE-ECHOED (отправитель INIT) или ESTABLISHED (получатель INIT), пока не перейдёт в состояние SHUTDOWN-SENT (отправитель SHUTDOWN) или SHUTDOWN-ACK-SENT (получатель SHUTDOWN).

Транспортный адрес рассматривается как бездействующий (idle), если нет новых блоков, которые можно использовать для обновления периода RTT на пути (обычно, первая передача DATA, INIT, COOKIE ECHO, HEARTBEAT и т. п.), и в течение текущего периода «проверки пульса»31 по этому адресу не было передано блоков HEARTBEAT. Эта трактовка относится как к активным адресам, так и к неактивным.

Вышележащий уровень может дополнительно инициировать перечисленные ниже функции.

  1. Запрет HEARTBEAT для определённого транспортного адреса в данной ассоциации.
  2. Изменение HB.interval.
  3. Восстановление передачи HEARTBEAT для указанного адреса в данной ассоциации.
  4. Запрос на передачу HEARTBEAT по указанному адресу в данной ассоциации.

Конечной точке следует увеличивать значение соответствующего счётчика ошибок для транспортного адреса партнёра всякий раз, когда переданный по этому адресу блок HEARTBEAT не подтверждён в течение периода RTO.

Когда значение счётчика достигает значения протокольного параметра Path.Max.Retrans, конечной точке следует пометить соответствующий адрес получателя как неактивный (если он ещё не помечен). Кроме того, конечной точке следует уведомить вышележащий уровень об изменении состояния доступности данного адреса. После этого конечной точке следует продолжать передачу блоков HEARTBEAT по этому адресу, но без увеличения значения счётчика ошибок.

Отправителю блока HEARTBEAT следует включать в поле Heartbeat Information этого блока текущее время в момент передачи пакета и адрес получателя пакета.

Примечание для разработчиков. Можно использовать иной механизм, при котором значение счётчика увеличивается при передаче каждого блока HEARTBEAT. В таких случаях по прибытию подтверждения HEARTBEAT ACK следует сбрасывать счётчик для того адреса, по которому был передан подтверждённый блок HEARTBEAT. Такое уменьшение будет компенсировать рост значения счётчика при передаче каждого блока, а также сбрасывать результаты увеличения счётчика вследствие других ошибок.

Получателю блока HEARTBEAT следует незамедлительно передать в ответ подтверждение HEARTBEAT ACK, содержащее Heartbeat Information TLV из полученного блока HEARTBEAT.

При получении блока HEARTBEAT ACK отправителю блока HEARTBEAT следует сбросить счётчик ошибок для транспортного адреса получателя, по которому был отправлен подтверждённый блок HEARTBEAT, и пометить адрес как активный (если он не был помечен ранее). Конечной точке следует сообщать вышележащему уровню об активизации транспортного адреса в результате получения последнего блока HEARTBEAT ACK. Получателю блока HEARTBEAT ACK следует также сбросить значение общего счётчика ошибок для ассоциации (см. параграф 8.1).

Получателю HEARTBEAT ACK следует также выполнить определение RTT для транспортного адреса партнёра, используя значение времени из блока HEARTBEAT ACK.

Для бездействующего транспортного адреса, по которому разрешено передавать блоки HEARTBEAT, рекомендуется передавать один блок HEARTBEAT в каждый период RTO для данного адреса + HB.interval с вариациями ± 50% от RTO и экспоненциальным откатом RTO, если доставка предыдущего блока HEARTBEAT не подтверждена.

Для пользователей SCTP обеспечивается примитив, позволяющий изменять значение HB.interval и включать/выключать передачу HEARTBEAT для данного адреса. Интервал HB.interval, заданный пользователем SCTP, добавляется к RTO для данного адресата (с учётом экспоненциального отката RTO). Следует передавать только один блок HEARTBEAT в течение каждого периода отсчёта heartbeat-таймера (если бездействует множество адресов). Разработчики вольны определить способ выбора кандидата для передачи блока при наличии множества бездействующих адресов.

При подстройке HB.interval может возникать побочный эффект, который следует принимать во внимание. Когда этот интервал возрастает (блоки HEARTBEAT передаются реже), обнаружение потери блоков ABORT также замедляется. Если партнёр прервёт (ABORT) ассоциацию по какой-либо причине и блок ABORT будет потерян, локальная точка обнаружит прерывание ассоциации только при передаче блока DATA или HEARTBEAT (это вынудит партнёра передать ABORT повторно). Такой эффект следует учитывать при установке значения для таймера HEARTBEAT. Если передача HEARTBEAT запрещена, потеря блока ABORT будет обнаружена только после передачи блока DATA.

8.4. Обработка неожиданных пакетов

Пакет SCTP называется неожиданным (OOTB32), если он правильно сформирован (т. е. включает корректное значение CRC32c, см. параграф 6.8), но получатель не может идентифицировать ассоциацию, к которой этот пакет относится.

Получатель пакета OOTB выполняет перечисленные ниже операции с соблюдением их порядка.

  1. Если в пакете OOTB указан отличный от индивидуального (non-unicast) адрес отправителя или получателя, такой пакет следует отбрасывать без уведомления.
  2. Если пакет OOTB содержит блок ABORT, получатель должен отбросить пакет без уведомления и выполнения каких-либо иных действий.
  3. Если пакет содержит блок INIT с Verification Tag = 0, он обрабатывается, как описано в параграфе 5.1. Если по той или иной причине нормальная обработка INIT невозможна и в ответ передаётся блок ABORT, поле Verification Tag в пакете с блоком ABORT должно иметь значение Initiate Tag из полученного блока INIT, а бит T в блоке ABORT должен быть сброшен (0) для индикации того, что значение Verification Tag не отражено.
  4. Если пакет содержит COOKIE ECHO в первом блоке, он должен обрабатываться в соответствии с параграфом 5.1.
  5. Eсли пакет содержит блок SHUTDOWN ACK, получателю следует передать отправителю пакета OOTB блок SHUTDOWN COMPLETE. При передаче блока SHUTDOWN COMPLETE получатель пакета OOTB должен заполнить поле Verification Tag, скопировав в него значение Verification Tag из блока SHUTDOWN ACK, и установить бит T в поле флагов блока для индикации отражения Verification Tag.
  6. Если пакет содержит блок SHUTDOWN COMPLETE, получателю следует отбросить пакет без уведомления и выполнения каких-либо иных действий.
  7. Если пакет содержит блок ERROR с причиной ошибки Stale cookie или блок COOKIE ACK, пакет SCTP следует отбросить без уведомления.
  8. В остальных случаях получателю следует ответить отправителю OOTB пакетом с блоком ABORT. При передаче блока ABORT получатель пакета OOTB должен указать в поле Verification Tag значение Verification Tag из пакета OOTB и установить бит T в поле флагов для индикации отражения Verification Tag. После передачи блока ABORT получатель пакета OOTB должен отбросить этот пакет, не выполняя каких-либо иных действий.

8.5. Тег верификации

Правила Verification Tag, определённые в этом параграфе, применяются для передачи и приёма пакетов SCTP, не содержащих блоков INIT, SHUTDOWN COMPLETE, COOKIE ECHO (см. параграф 5.1), ABORT или SHUTDOWN ACK. Для перечисленных блоков правила рассмотрены отдельно в параграфе 8.5.1.

При передаче пакета SCTP конечная точка должна заполнить поле Verification Tag, указав в нем значение параметра Initiate Tag из полученного от партнёра блока INIT или INIT ACK.

При получении пакета SCTP конечная точка должна проверить соответствие полученного значения Verification Tag своему значению тега. Если полученное значение Verification Tag не соответствует тегу локальной точки, получатель должен отбросить пакет без уведомления и недопустимо выполнять каких-либо иные операции за исключением случаев, описанных в параграфе 8.5.1.

8.5.1. Исключения из правил для Verification Tag

  1. Правила для пакетов с блоками INIT.
  • Отправитель должен установить Verification Tag = 0.
  • Когда конечная точка получает пакет SCTP с Verification Tag = 0, ей следует убедиться, что пакет содержит только блок INIT. В противном случае пакет должен быть отброшен без уведомления.
  1. Правила для пакетов с блоками ABORT.
  • Конечная точка всегда должна указывать в поле Verification Tag передаваемых пакетов значение тега адресата, если этот тег известен.
  • Если блок ABORT передаётся в ответ на пакет OOTB, конечная точка должна выполнить процедуру, описанную в параграфе 8.4.
  • Получатель блока ABORT должен воспринять пакет, если значение Verification Tag соответствует его собственному тегу при сброшенном бите T или тегу партнёра при установленном бите T. В иных случаях пакет должен отбрасываться без уведомления и выполнения каких-либо других действий.
  1. Правила для пакетов с блоками SHUTDOWN COMPLETE.
  • При передаче блока SHUTDOWN COMPLETE, если получатель блока SHUTDOWN ACK имеет TCB, в поле верификации должен использоваться тег адресата, а установка флага T недопустима. При отсутствии TCB отправителю следует использовать значение Verification Tag из блока SHUTDOWN ACK и он должен установить флаг T.
  • Получатель SHUTDOWN COMPLETE должен воспринять пакет, если поле Verification Tag соответствует его собственному тегу при сброшенном флаге T или тегу партнёра при установленном бите T. В противном случае получатель должен отбрасывать пакет без уведомления и выполнения каких-либо иных действий. Конечная точка должна игнорировать SHUTDOWN COMPLETE, если она не находится в состоянии SHUTDOWN-ACK-SENT.
  1. Правила для пакетов с блоками COOKIE ECHO.
  • При передаче COOKIE ECHO конечная точка должна использовать Initiate Tag из принятого блока INIT ACK.
  • Получателю COOKIE ECHO следует выполнить процедуры, описанные в разделе 5.
  1. Правило для пакетов с блоками SHUTDOWN ACK.
    1. Если получатель находится в состоянии COOKIE-ECHOED или COOKIE-WAIT, следует выполнить процедуры, описанные в параграфе 8.4 (т. е., пакет должен трактоваться как OOTB).

9. Прекращение работы ассоциации

Конечной точке следует прерывать ассоциацию, когда сервис более не требуется. Ассоциация может быть прервана путём разрыва (abort) или завершения (shutdown). Разрыв ассоциации представляет собой прекращение всякой передачи данных с отбрасыванием всех оставшихся не доставленными данных. Завершение ассоциации представляет собой процесс контролируемого прекращения обмена данными с доставкой партнёру всех данных, остающихся в очередях. Однако в случае завершения (shutdown) протокол SCTP не поддерживает полуоткрытых состояний (как в TCP), когда одна сторона может продолжать передачу данных в то время, как другая уже закрыла ассоциацию. Когда конечная точка выполняет процедуру завершения, обе партнёра прекращают приём новых данных от пользователя и доставляются лишь данные, которые были в очередях на момент приёма или передачи блока SHUTDOWN.

9.1. Разрыв ассоциации (Abort)

Когда конечная точка принимает решение о разрыве существующей ассоциации, она должна передать своему партнёру блок ABORT. Отправитель должен включить значение Verification Tag своего партнёра в исходящий пакет. Недопустимо группировать блок ABORT с блоками DATA. Если ассоциация прерывается по запросу вышележащего уровня, в блоке ABORT следует указать причину User-Initiated Abort (см. параграф 3.3.10.12).

Для конечной точки недопустима передача откликов на любой принятый пакет с блоком ABORT (см. параграф 8.4).

Конечная точка, получившая блок ABORT, должна выполнить специальную проверку Verification Tag в соответствии с правилами параграфа 8.5.1.

После проверки Verification Tag принявшая ABORT конечная точка должна удалить ассоциацию из своих записей и ей следует также сообщить о разрыве ассоциации на вышележащий уровень. Если в блоке ABORT указана причина User-Initiated Abort, её следует сделать доступной вышележащему уровню.

9.2. Завершение ассоциации (Shutdown)

Используя примитив SHUTDOWN (параграф 10.1), вышележащий уровень конечной точки ассоциации может выполнить аккуратное завершение работы ассоциации. В этом случае все остающиеся блоки DATA от партнёра инициатора завершения будут доставлены до прерывания ассоциации.

При получении от вышележащего уровня примитива SHUTDOWN конечная точка переходит в состояние SHUTDOWN-PENDING и продолжает находиться в этом состоянии, пока все остающиеся данные не будут подтверждены партнёром. Конечная точка не принимает новых данных от вышележащего уровня, но будет повторять передачу данных партнёру, если в этом возникает необходимость (заполнение пропуска в порядковых номерах).

После того, как все остающиеся данные будут подтверждены партнёром, конечная точка передаёт партнёру блок SHUTDOWN, содержащий в поле Cumulative TSN Ack последний номер TSN, полученный от партнёра. После этого ей следует запустить таймер T2-shutdown и перейти в состояние SHUTDOWN-SENT. По завершении отсчёта таймера конечная точка должна повторно передать блок SHUTDOWN с обновлённым значением последнего порядкового номера TSN, полученного от партнёра.

Должны быть выполнены правила параграфа 6.3 для определения корректного значения таймера T2-shutdown. Для индикации пропусков в TSN конечная точка может группировать блоки SACK и SHUTDOWN в одном пакете SCTP.

Конечной точке следует ограничивать число повторов передачи блока SHUTDOWN с помощью протокольного параметра Association.Max.Retrans. После превышения этого порога конечной точке следует уничтожить TCB, а также следует передать информацию о недоступности партнёра на вышележащий уровень (тем самым ассоциация переводится в состояние CLOSED). При получении любых пакетов от партнёра (блоки DATA из очереди) следует сбрасывать счётчик повтора передачи и заново запускать таймер T2-Shutdown, давая партнёру дополнительную возможность передачи остающихся блоков DATA из его очередей.

При получении блока SHUTDOWN конечная точка:

  • переходит в состояние SHUTDOWN-RECEIVED;
  • прекращает приём новых данных от своего пользователя SCTP;
  • проверяет по полю Cumulative TSN Ack, что все блоки DATA приняты отправителем блока SHUTDOWN.

После перехода конечной точки в состояние SHUTDOWN-RECEIVED она должна игнорировать запросы ULP на завершение и должна отвечать на блоки SHUTDOWN от партнёра.

При наличии остающихся блоков DATA получатель SHUTDOWN должен продолжать обычные процедуры передачи, описанные в разделе 6, пока все остающиеся блоки DATA не будут подтверждены; однако для получателя блока SHUTDOWN недопустимо принимать новые данные от своего пользователя SCTP.

Находясь в состоянии SHUTDOWN-SENT, отправитель блока SHUTDOWN должен незамедлительно передавать в ответ на каждый принятый пакет, содержащий хотя бы один блок DATA, подтверждение SACK и блок SHUTDOWN, а также заново запускать таймер T2-shutdown. Если блок SHUTDOWN сам по себе не может подтвердить все принятые блоки DATA (т. е., имеются номера TSN, которые могут быть подтверждены, но больше кумулятивного значения TSN и в последовательности TSN возникает пропуск) или получены дубликаты TSN, должен передаваться также блок SACK.

Отправитель блока SHUTDOWN может также запустить таймер T5-shutdown-guard для ограничения общей продолжительности процедуры завершения ассоциации. По завершению отсчёта этого таймера отправителю следует разорвать ассоциацию передачей блока ABORT. При использовании таймера T5-shutdown-guard для него следует устанавливать рекомендуемое значение 5 * RTO.Max.

Если у получателя блока SHUTDOWN больше не остаётся блоков DATA, он должен передать блок SHUTDOWN ACK и запустить таймер T2-shutdown, перейдя в состояние SHUTDOWN-ACK-SENT. По завершении отсчёта таймера конечная точка должна повторить передачу SHUTDOWN ACK.

Отправителю SHUTDOWN ACK следует ограничивать число повторов передачи SHUTDOWN ACK с помощью протокольного параметра Association.Max.Retrans. После превышения заданного порога конечной точке следует уничтожить TCB, а также следует сообщить вышележащему уровню о недоступности партнёра (тем самым ассоциация переводится в состояние CLOSED).

При получении блока SHUTDOWN ACK отправитель SHUTDOWN должен остановить таймер T2-shutdown, передать своему партнёру блок SHUTDOWN COMPLETE и удалить все записи для данной ассоциации.

При получении блока SHUTDOWN COMPLETE конечная точка проверяет, что она находится в состоянии SHUTDOWN-ACK-SENT и ей следует отбросить полученный блок, если состояние отличается от указанного. Если же конечная точка находится в состоянии SHUTDOWN-ACK-SENT, ей следует остановить таймер T2-shutdown и удалить все сведения об ассоциацией (тем самым ассоциация переводится в состояние CLOSED).

Конечной точке перед началом процедуры завершения ассоциации следует удостовериться, что все остающиеся блоки DATA были подтверждены.

Конечной точке, находящейся в состоянии SHUTDOWN-PENDING, SHUTDOWN-SENT, SHUTDOWN-RECEIVED или SHUTDOWN-ACK-SENT, следует отвергать все новые запросы данных от вышележащего уровня.

Если конечная точка в состоянии SHUTDOWN-ACK-SENT получает блок INIT (например, при утере блока SHUTDOWN COMPLETE) с транспортными адресами отправителя и получателя (в заголовке IP или блоке INIT), относящимися к данной ассоциации, ей следует отбросить блок INIT и повторить передачу блока SHUTDOWN ACK.

Примечание. Получение пакета с блоком INIT с теми же адресами IP отправителя и получателя, которые назначены конечной точке, но другим номером порта говорит о попытке создания новой ассоциации.

Отправителю блока INIT или COOKIE ECHO следует отвечать на получение блока SHUTDOWN-ACK пакетом SCTP, содержащим только блок SHUTDOWN COMPLETE, а в поле Verification Tag общего заголовка следует включать значение тега из полученного пакета с SHUTDOWN ACK. Такой пакет рассматривается, как OOTB (см. параграф 8.4). Отправитель INIT оставляет работать свой таймер T1-init и сохраняет состояние COOKIE-WAIT или COOKIE-ECHOED. Завершение отсчёта T1-init будет приводить к повтору передачи блока INIT или COOKIE и созданию новой ассоциации.

Если получатель блока SHUTDOWN находится в состоянии COOKIE WAIT или COOKIE ECHOED, блок SHUTDOWN следует отбрасывать без уведомления.

Если конечная точка находится в состоянии SHUTDOWN-SENT и получает от своего партнёра блок SHUTDOWN, ей следует незамедлительно ответить блоком SHUTDOWN ACK и перейти в состояние SHUTDOWN-ACK-SENT с перезапуском своего таймера T2-shutdown.

Если конечная точка находится в состоянии SHUTDOWN-ACK-SENT и получает от партнёра блок SHUTDOWN ACK, она должна остановить таймер T2-shutdown, передать партнёру блок SHUTDOWN COMPLETE и удалить все связанные с ассоциацией записи.

10. Обработка ICMP

При получении конечной точкой SCTP сообщения ICMP должны выполняться указанные ниже процедуры для подобающего использования информации, предоставленной уровнем 3.

ICMP1)

Реализация может игнорировать все сообщения ICMPv4 с полем типа, отличным от Destination Unreachable.

ICMP2)

Реализация может игнорировать все сообщения ICMPv6 с полем типа, отличным от Destination Unreachable, Parameter Problem, Packet Too Big.

ICMP3)

Реализации следует игнорировать все сообщения ICMP с кодом Port Unreachable.

ICMP4)

Реализация может игнорировать все сообщения ICMPv6 с полем типа Parameter Problem, если код отличается от Unrecognized Next Header Type Encountered.

ICMP5)

Реализация должна использовать содержимое сообщения ICMP (v4 или v6) для нахождения ассоциации, передавшей сообщение, на которое получен отклик ICMP. Если ассоциация не найдена реализации следует игнорировать сообщение ICMP.

ICMP6)

Реализация должна проверить совпадение Verification Tag в сообщении ICMP значению Verification Tag партнёра. Если Verification Tag отличается от 0 и не совпадает, сообщение ICMP отбрасывается. Если тег имеет значени 0 и сообщение ICMP содержит достаточно байтов для проверки того, что блок имеет тип INIT, а значение Initiate Tag совпадает с тегом партнёра, выполняется ICMP7. Если сообщение ICMP слишком короткое, тип блока или Initiate Tag не совпадает, пакет просто отбрасывается.

ICMP7)

Если сообщение является ICMPv6 типа Packet Too Big или ICMPv4 типа Destination Unreachable с кодом Fragmentation Needed, реализации следует обработать эти сведения как задано для определения PMTU.

ICMP8)

Если сообщение ICMP имеет код Unrecognized Next Header Type Encountered или Protocol Unreachable, реализация должна трактовать его как прерывание с установленным битом T, когда в нем не содержится блока INIT. Если сообщение включает блок INIT и ассоциация находится в состоянии COOKIE-WAIT, сообщение ICMP обрабатывается подобно блоку ABORT.

ICMP9)

Если сообщение ICMP имеет тип Destination Unreachable, реализация может перевести получателя в число недоступных или увеличить счётчик ошибок для пути. SCTP может передавать вышележащему уровню сведения о приёме сообщений ICMP при указании смены состояния сети.

Эти процедуры отличаются от [RFC1122], требований по обработке сообщений о недоступности порта и требований, в соответствии с которыми реализация должна разрывать ассоциации в ответ на сообщение о недоступности протокола. Сообщения о недоступности порта не обрабатываются, поскольку реализации передают блок ABORT вместо port-unreachable. Более строгая обработка сообщений о недоступности протокола обусловлена соображениями безопасности хостов, не поддерживающих SCTP.

11. Интерфейс с вышележащим уровнем

Протоколы вышележащих уровней (ULP) запрашивают сервис путём передачи примитивов протоколу SCTP и получают уведомления о различных событиях от SCTP.

Примитивы и уведомления, описанные в этом разделе, следует рассматривать, как рекомендации для разработчиков SCTP. Приведённое ниже функциональное описание примитивов интерфейса с ULP служит для иллюстрации. Реализации SCTP могут использовать разные интерфейсы с ULP, однако все реализации должны обеспечивать некий минимальный сервис, гарантирующий поддержку одной иерархии протоколов всеми реализациями SCTP.

Отметим, что этот раздел предназначен лишь для информации (не нормативный).

[RFC6458] и раздел 7 (Socket API Considerations) в [RFC7053] определяют расширение API сокетов для SCTP, как описано в этом документе.

11.1. ULP -> SCTP

В последующих параграфах приведены функциональные характеристики интерфейса ULP-SCTP. Используемая нотация похожа на описания вызовов процедур или функций в большинстве языков высокого уровня.

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

11.1.1. Initialize — инициализация

INITIALIZE ([local port],[local eligible address list]) -> local SCTP instance name

Этот примитив позволяет протоколу SCTP инициализировать внутренние структуры данных и выделить ресурсы, требуемые для создания рабочей среды. После инициализации SCTP протокол ULP может напрямую обмениваться информацией с другими конечными точками без повторного использования данного примитива.

SCTP будет возвращать ULP имя локального экземпляра SCTP.

Необязательные атрибуты

С примитивом могут передаваться следующие типы атрибутов:

  • local port — номер порта SCTP, если ULP хочет задать порт;
  • local eligible address list — список адресов, с которыми следует связать локальную точку SCTP. По умолчанию при отсутствии списка локальная точка связывается со всеми адресами IP, присвоенными данной точке.

Примечание для разработчиков. Если реализация поддерживает этот атрибут, она принимает на себя ответственность за то, что в любом исходящем от данной точки пакете SCTP будет указан в поле отправителя адрес IP из заданного параметром списка.

11.1.2. Associate — создать ассоциацию

ASSOCIATE(local SCTP instance name, initial destination transport addr list, outbound stream count) -> association id [,destination transport addr list] [,outbound stream count]

Этот примитив позволяет инициировать создание ассоциации с указанным партнёром.

Конечная точка партнёра указывается одним или несколькими из её транспортных адресов (см. параграф 1.3). Если локальный экземпляр SCTP ещё не инициализирован, вызов ASSOCIATE считается ошибкой.

При успешном создании ассоциации возвращается идентификатор ассоциации SCTP. Если SCTP не может создать ассоциацию с удаленным партнёром, возвращается код ошибки.

При создании ассоциации могут возвращаться другие параметры ассоциации, включая полные транспортные адреса партнёра, а также число исходящих потоков локальной точки. Один из транспортных адресов удалённого партнёра выбирается локальной точкой в качестве первичного (используемого по умолчанию) транспортного адреса для передачи пакетов SCTP этому партнёру. Возвращаемый список транспортных адресов партнёра (destination transport addr list) может использоваться ULP для смены первичного пути или задания передачи по определённому транспортному адресу партнёра.

Примечание для разработчиков. Если примитив ASSOCIATE реализован как блокируемый вызов функции, он может возвращать кроме идентификатора ассоциации дополнительные параметры. Если примитив ASSOCIATE реализован как неблокируемый вызов, возвращается только идентификатор ассоциации, а параметры созданной ассоциации передаются с использованием уведомления COMMUNICATION UP.

Обязательные атрибуты

  • local SCTP instance name — возвращается операцией INITIALIZE.
  • initial destination transport addr list — непустой список транспортных адресов партнёра, с которым создаётся ассоциация.
  • outbound stream count — число исходящих потоков, которые ULP будет открывать для обмена данными с партнёром.

11.1.3. Shutdown — завершение ассоциации

SHUTDOWN(association id) -> result

Завершает работу ассоциации с доставкой партнёру всех данных из локальных очередей. Ассоциация будет разрываться лишь после того, как будут подтверждены все переданные пакеты SCTP. При успешном завершении ассоциации будет возвращаться код завершения, а при отказе — код ошибки.

Обязательный атрибут

association id — локальный идентификатор ассоциации SCTP.

11.1.4. Abort — разрыв ассоциации

ABORT(association id [, cause code]) -> result

Прерывает работу ассоциации без завершения процесса передачи данных из очередей. Все пользовательские данные из локальных очередей отбрасываются, а партнёру передаётся блок ABORT. При успешном разрыве ассоциации возвращается код разрыва, а при отказе — код ошибки.

Обязательный атрибут

association id — локальный идентификатор ассоциации SCTP.

Необязательный атрибут

Upper Layer Abort Reason — причина разрыва ассоциации, передаваемая партнёру.

11.1.5. Send — передача данных

SEND(association id, buffer address, byte count [,context] [,stream id] [,life time] [,destination transport address] [,unorder flag] [,no-bundle flag] [,payload protocol-id] [,sack-immediately flag]) -> result

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

Обязательные атрибуты

  • association id — локальный идентификатор ассоциации SCTP;
  • buffer address — адрес, по которому сохраняется передаваемое пользовательское сообщение;
  • byte count — размер пользовательских данных в байтах.

Необязательные атрибуты

  • context — необязательное 32-битовое целое число, которое будет передаваться в уведомлении SEND FAILURE
  • stream id — идентификатор потока, используемого для передачи данных (по умолчанию используется поток 0).
  • life time — задаёт время действия пользовательских данных. По истечении заданного времени SCTP уже не будет пытаться передавать эти данные. Параметр может использоваться для предотвращения передачи устаревших пользовательских сообщений. SCTP уведомляет ULP, если данные не удаётся передать с помощью примитива SEND в течение заданного этим параметром времени. Однако пользовательские данные будут переданы, если протокол SCTP начал попытки отправки блока данных до истечения заданного времени.
  • протоколу ULP, если при передаче пользовательского сообщения произойдёт ошибка.

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

  • destination transport address — задаёт один из транспортных адресов получателя, по которому пакет должен передаваться. По возможности протокол SCTP использetn заданный адрес вместо адреса первичного пути.
  • unorder flag — этот флаг указывает что пользовательские данные доставляются партнёру без соблюдения порядка (т. е., устанавливается U = 1 во всех блоках DATA, содержащих это сообщение).
  • no-bundle flag — указывает протоколу SCTP, что эти данные не должны группироваться с другими блоками DATA. SCTP может выполнять в целях предотвращения перегрузки группировку блоков, игнорируя этот флаг.
  • payload protocol-id — 32-битовое целое число без знака, которое будет передаваться партнёру для индикации типа передаваемых данных. Отметим, что вышележащий уровень отвечает за преобразование порядка байтов этого поля из хостового в сетевой; SCTP передаёт поле как 4 необрабатываемых (opaque) байта.
  • sack-immediately flag — установить флаг I в последнем блоке DATA передаваемого пользовательского сообщения.

11.1.6. Set Primary — выбор основного пути

SETPRIMARY(association id, destination transport address, [source transport address]) -> result

Задаёт для локальной точки SCTP использование указанного транспортного адреса в качестве первичного пути передачи пакетов.

Примитив должен возвращать результат попытки задания первичного пути. Если заданного адреса нет в destination transport address list, возвращённом ранее примитивом ASSOCIATE или уведомлением COMMUNICATION UP, возвращается код ошибки.

Обязательные атрибуты

  • association id — локальный идентификатор ассоциации SCTP;
  • destination transport address — задаёт один из транспортных адресов партнёра для использования в качестве основного пути передачи пакетов. Это значение заменяет собой адрес первичного пути, поддерживавшегося до этого локальной точкой SCTP.

Необязательный атрибут

source transport address — некоторые реализации могут поддерживать задание адреса отправителя, который будет по умолчанию включаться во все исходящие дейтаграммы IP.

11.1.7. Receive — приём данных

RECEIVE(association id, buffer address, buffer size [,stream id]) -> byte count [,transport address] [,stream id] [,stream sequence number] [,partial flag] [,payload protocol-id]

Этот примитив считывает первое пользовательское сообщение из входной очереди SCTP в буфер, указанный ULP, если такой буфер имеется. После выполнения команды возвращается размер прочитанных данных в байтах. В зависимости от реализации может также возвращаться такая информация, как адрес отправителя, идентификатор потока, из которого получены данные, сведения о наличии дополнительных данных для прочтения и т. п. Для упорядоченных сообщений может также возвращаться порядковый номер в потоке (Stream Sequence Number).

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

Обязательные атрибуты

  • association id — локальный идентификатор ассоциации SCTP;
  • buffer address — адрес в памяти, указанный ULP для считывания сообщения;
  • buffer size — максимальный размер считываемых данных в байтах.

Необязательные атрибуты

  • stream id — для индикации потока, из которого были получены данные.
  • Stream Sequence Number — порядковый номер в потоке, присвоенный передающим партнёром SCTP.
  • partial flag — наличие этого флага говорит о том, что данный примитив возвращает лишь часть данных сообщения. Установка этого флага сопровождается возвратом идентификатора потока и порядкового номера в потоке. Нулевое значение флага показывает, что для этого порядкового номера в потоке больше нет данных.
  • payload protocol-id — 32-битовое целое число без знака, полученное от партнёра и указывающее тип данных в принятом сообщении. Отметим, что вышележащий уровень отвечает за преобразование порядка байтов этого поля из хостового в сетевой; SCTP передаёт поле как 4 необрабатываемых (opaque) байта.

11.1.8. Status — статус

STATUS(association id) -> данные о состоянии

Этот примитив возвращает блок данных, содержащий:

  • состояние соединения для ассоциации;
  • список адресов транспортного уровня для получателя;
  • состояния доступности транспортных адресов получателя;
  • текущий размер окна приёма;
  • текущий размер окна перегрузки;
  • число неподтвержденных блоков DATA;
  • число блоков DATA ожидающих приёма;
  • основной путь;
  • самое новое значение SRTT на основном пути;
  • значение RTO для основного пути;
  • значения SRTT и RTO для других путей и т. п.

Обязательный атрибут

association id — локальный идентификатор ассоциации SCTP.

11.1.9. Change Heartbeat — смена режима Heartbeat

CHANGEHEARTBEAT(association id, destination transport address, new state [,interval]) -> result

Говорит локальной точке о необходимости включить или отключить функцию heartbeat для указанного адреса получателя, возвращая результат операции.

Примечание. Даже при включённой функции heartbeat реальных проверок может не выполняться, если указанный адрес не относится к бездействующим.

Обязательные атрибуты

  • association id — локальный идентификатор ассоциации SCTP;
  • destination transport address — один из транспортных адресов партнёра;
  • new state — новое состояние heartbeat для данного транспортного адреса (enabled или disabled).

Необязательный атрибут

interval — определяет частоту передачи heartbeat, если эта функция включена для транспортного адреса партнёра. Значение параметра добавляется к RTO транспортного адреса. Параметр действует для всех транспортных адресов получателя.

11.1.10. Request Heartbeat — запрос на выполнение Heartbeat

REQUESTHEARTBEAT(association id, destination transport address) -> result

Говорит локальной точке о необходимости выполнения Heartbeat для указанного транспортного адреса в данной ассоциации. Возвращаемый результат показывает, была ли передача блока HEARTBEAT по заданному транспортному адресу успешной.

Обязательный атрибут

  • association id — локальный идентификатор ассоциации SCTP;
  • destination transport address — транспортный адрес, для которого запрашивается передача блока HEARTBEAT.

11.1.11. Get SRTT Report — запрос значения SRTT

GETSRTTREPORT(association id, destination transport address) -> srtt result

Запрашивает у локального SCTP результаты текущего измерения SRTT для указанного транспортного адреса в данной ассоциации. Возвращаемое значение может быть целым числом, указывающим последнее измеренное значение SRTT в миллисекундах.

Обязательные атрибуты

  • association id — локальный идентификатор ассоциации SCTP;
  • destination transport address — транспортный адрес партнёра, для которого определяется значение SRTT.

11.1.12. Set Failure Threshold — задать порог детектирования отказа

SETFAILURETHRESHOLD(association id, destination transport address, failure threshold) -> result

Этот примитив позволяет локальному модулю SCTP задать значение порога детектирования отказа Path.Max.Retrans для заданного транспортного адреса. Отметим, что это можно сделать с помощью примитива SETPROTOCOLPARAMETERS (параграф 11.1.13).

Обязательные атрибуты

  • association id — локальный идентификатор ассоциации SCTP;
  • destination transport address — транспортный адрес партнёра в данной ассоциации, для которого задаётся порог;
  • failure threshold — новое значение параметра Path.Max.Retrans для транспортного адреса.

11.1.13. Set Protocol Parameters — установить параметры протокола

SETPROTOCOLPARAMETERS(association id, [,destination transport address,] protocol parameter list) -> result

Этот примитив позволяет локальному модулю SCTP установить параметры протокола.

Обязательные атрибуты

  • association id — локальный идентификатор ассоциации SCTP;
  • protocol parameter list — список имён и значений протокольных параметров (например, Association.Max.Retrans, см. раздел 16 или таких параметров как DSCP), которые пользователь SCTP желает установить.

Необязательный атрибут

destination transport address — некоторые параметры протокола могут независимо устанавливаться для каждого транспортного адреса партнёра.

11.1.14. Receive unsent message — получить неотправленное сообщение

RECEIVE_UNSENT(data retrieval id, buffer address, buffer size [,stream id] [, stream sequence number] [,partial flag] [,payload protocol-id])

Обязательные атрибуты

  • data retrieval id — идентификатор, переданный ULP в уведомлении SEND FAILURE.
  • buffer address — адрес буфера, указанный ULP для записи полученного сообщения.
  • buffer size — максимальный размер принимаемых данных в байтах.

Необязательные атрибуты

  • stream id — идентификатор потока, в который были переданы данные.
  • Stream Sequence Number — порядковый номер в потоке, связанный с сообщением.
  • partial flag — указывает на частичную доставку сообщения. При установке этого флага также возвращаются идентификатор потока и порядковый номер в потоке. Нулевое значение флага показывает, что для данного порядкового номера в потоке больше не будет получено данных.
  • payload protocol-id — 32-битовое целое число без знака, которое было задано для передачи партнёру с целью идентификации протокола полученных данных.

11.1.15. Receive Unacknowledged Message — приём неподтвержденного сообщения

RECEIVE_UNACKED(data retrieval id, buffer address, buffer size, [,stream id] [, stream sequence number] [,partial flag] [,payload protocol-id])

Обязательные атрибуты

  • data retrieval id — идентификатор, переданный ULP в уведомлении SEND FAILURE.
  • buffer address — адрес буфера, указанный ULP для записи полученного сообщения.
  • buffer size — максимальный размер принимаемых данных в байтах.

Необязательные атрибуты

  • stream id — идентификатор потока, в который были переданы данные.
  • Stream Sequence Number — порядковый номер в потоке, связанный с сообщением.
  • partial flag — указывает на частичную доставку сообщения. При установке этого флага также возвращаются идентификатор потока и порядковый номер в потоке. Нулевое значение флага показывает, что для данного порядкового номера в потоке больше не будет получено данных.
  • payload protocol-id — это 32-битовое целое число без знака, которое было передано для идентификации протокола полученных данных.

11.1.16. Destroy SCTP instance — уничтожить экземпляр SCTP

DESTROY(local SCTP instance name)

Обязательный атрибут

local SCTP instance name — значение, переданное приложению из примитива инициализации; указывает уничтожаемый экземпляр SCTP.

11.2. SCTP -> ULP

Предполагается, что операционная система или прикладная среда обеспечивает асинхронную передачу сигналов SCTP процессу ULP. Когда SCTP подаёт сигнал процессу ULP на вышележащий уровень передаётся та или иная информация.

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

11.2.1. Уведомление DATA ARRIVE

SCTP передаёт такое уведомление ULP, когда пользовательское сообщение получено и готово для считывания. Уведомление может включать следующие необязательные параметры:

  • association id — локальный идентификатор ассоциации SCTP;
  • stream id — идентификатор потока, в котором были получены данные.

11.2.2. Уведомление SEND FAILURE

Если сообщение не может быть доставлено, протокол SCTP передаёт это уведомление ULP. Уведомление может включать следующие необязательные параметры:

  • association id — локальный идентификатор ассоциации SCTP;
  • data retrieval id — идентификатор, используемый для считывания неотправленных или неподтвержденных данных;
  • cause code — указывает причину отказа (например, слишком большой размер сообщения, завершение срока действия сообщения и т. п.);
  • mode — указывает, была ли какая-либо часть сообщения отправлена, но не подтверждена полностью;
  • context — дополнительная информация, связанная с сообщением (см. параграф 11.1.5).

11.2.3. Уведомление NETWORK STATUS CHANGE

Когда транспортный адрес получателя помечается, как неактивный (например, при обнаружении отказа) или, наоборот, становится активным (например, при обнаружении восстановления), SCTP передаёт такое уведомление ULP. В уведомлении содержится следующая информация:

  • association id — локальный идентификатор ассоциации SCTP;
  • destination transport address — транспортный адрес партнёра, для которого зафиксировано изменение состояния;
  • new-status — новое состояние.

11.2.4. Уведомление COMMUNICATION UP

Этот тип уведомлений используется для индикации готовности протокола SCTP к приёму или передаче пользовательских сообщений, а также после восстановления разорванной связи с удалённой точкой.

Примечание для разработчиков. Если примитив ASSOCIATE реализован, как блокируемый вызов функции, параметры ассоциации возвращаются самим примитивом ASSOCIATE. В таких случаях на стороне инициатора ассоциации уведомления COMMUNICATION UP становятся необязательными.

В уведомлении содержится следующая информация:

  • association id — локальный идентификатор ассоциации SCTP;
  • status — указывает тип события, с которым связано уведомление;
  • destination transport address list — полный набор транспортных адресов партнёра;
  • outbound stream count — максимальное число исходящих потоков, которые ULP может использовать в данной ассоциации;
  • inbound stream count — число потоков, запрошенных партнёром (может отличаться от outbound stream count).

11.2.5. Уведомление COMMUNICATION LOST

Это уведомление передаётся протоколом SCTP в случае полной утраты связи с удалённой точкой (например, через Heartbeat) или обнаружения вызова удалённой точкой операции прерывания ассоциации (abort). В уведомлении содержится следующая информация:

  • association id — локальный идентификатор ассоциации SCTP;
  • status — указывает тип события, с которым связано уведомление; этот параметр может говорить об отказе или обычном прекращении работы ассоциации с помощью запроса shutdown или abort.

Уведомление может включать следующие необязательные параметры:

  • last-acked — последний номер TSN, подтверждённый партнёром;
  • last-sent — последний номер TSN, переданный партнёру;
  • Upper Layer Abort Reason — причина прерывания указывается в случае разрыва по инициативе пользователя.

11.2.6. Уведомление COMMUNICATION ERROR

Когда SCTP получает блок ERROR от партнёра и решает уведомить об ошибке ULP, этот тип служит для передачи уведомления. Уведомление может включать следующие параметры:

  • association id — локальный идентификатор ассоциации SCTP;
  • error info — указывает тип ошибки и может содержать дополнительную информацию из блока ERROR.

11.2.7. Уведомление RESTART

При обнаружении рестарта на стороне партнёра SCTP может использовать этот тип для передачи уведомления ULP. Уведомление может включать параметр association id — локальный идентификатор ассоциации SCTP.

11.2.8. Уведомление SHUTDOWN COMPLETE

Это уведомление SCTP передаёт на вышележащий уровень при завершении процедуры SHUTDOWN (параграф 9.2). Уведомление может включать параметр association id — локальный идентификатор ассоциации SCTP.

12. Вопросы безопасности

12.1. Цели защиты

Для протоколов транспортного уровня общего назначения, разработанных для гарантированной доставки чувствительной к задержкам информации (например, сигнальных сообщений телефонных систем или данных билинга) между парами точек сети важны следующие аспекты, связанные с безопасностью:

  • доступность сервиса с гарантией своевременной доставки;
  • целостность пользовательской информации, передаваемой через SCTP.

12.2. Реакция SCTP на потенциальные угрозы

Протокол SCTP может использоваться в различных системах, связанных с риском. Для операторов систем, использующих SCTP, важен анализ конкретной среды для принятия соответствующих мер безопасности.

Операторам систем, применяющих SCTP, следует использовать [RFC2196] в качестве руководства по обеспечению безопасности своего сайта.

12.2.1. Учёт возможности атак изнутри

Следует использовать принципы, изложенные в [RFC2196] для минимизации риска утечки информации или саботажа со стороны сотрудников. Такие процедуры включают публикацию политики безопасности, контроль доступа к оборудованию, программам и сети, а также разделение служб.

12.2.2. Защита от повреждения данных в сети

Если риск возникновения незаметных ошибок в дейтаграммах, доставляемых с помощью транспорта нижележащих уровней, слишком велик, нужны дополнительные меры по обеспечению целостности данных. Если дополнительная защита обеспечивается на прикладном уровне, заголовок SCTP остаётся уязвимым для преднамеренных атак с целью повреждения данных. Хотя существующих механизмов обнаружения подмены пакетов в SCTP вполне достаточно для работы в нормальных условиях, требуется более сильная защита SCTP в тех случаях, когда рабочая среда характеризуется высоким уровнем риска преднамеренных атак со стороны изощрённых противников.

Можно использовать расширение SCTP-AUTH [RFC4895], если среда с угрозами требует сильной защиты целостности, не требуя защиты конфиденциальности.

12.2.3. Защита конфиденциальности

В большинстве случаев вопросы конфиденциальности относятся к данным, передающим сигнальную информацию, а не к заголовкам SCTP или протоколов нижележащих уровней. В этом случае можно ограничиться шифрованием пользовательских данных SCTP. Как и дополнительные контрольные суммы, шифрование данных может выполняться пользовательским приложением SCTP. Для этого можно воспользоваться [RFC6083]. Как вариант, пользовательское приложение может применять специфические для реализации API для запроса сервиса IP ESP [RFC4303], обеспечивающего конфиденциальность и целостность.

Практические требования конфиденциальности для мобильных пользователей могут включать маскирование адресов IP и номеров портов. В таких случаях следует использовать ESP вместо обеспечения конфиденциальности на уровне приложений. При использовании ESP для обеспечения конфиденциальности трафика SCTP должно применяться криптографическое преобразование ESP, которое включает криптографическую защиту целостности, поскольку в таких случаях кроме угрозы конфиденциальности данных имеется достаточно серьёзная угроза их целостности.

Независимо от способа защиты конфиденциальности следует использовать механизмы IKEv2 [RFC7296] для управления ключами ESP.

Операторы могут обратиться к [RFC4301] для получения дополнительной информации по средствам обеспечения безопасности непосредственно поверх уровня IP.

12.2.4. Защита от атак на службы вслепую (Blind DoS)

Атака вслепую представляет собой случай, когда атакующий не может перехватывать и просматривать содержимое потока данных, передаваемых узлу SCTP или от него. Атаки вслепую на службы могут иметь форму лавинной рассылки (flooding), маскирования (masquerade) или недозволенного монопольного захвата сервиса.

12.2.4.1. Лавинная атака (Flooding)

Целью лавинной атаки является выведение сервиса из строя и некорректное поведение системы из-за истощения ресурсов, интерференции с легитимными транзакциями или использования связанных с буферами программных ошибок. Лавинная атака может быть направлена на узел SCTP, каналы доступа или Internet. В последних случаях лавинная атака будет проявляться как прекращение работы сетевых служб при наличии межсетевых экранов.

В общем случае защита от лавинной атаки начинается при разработке оборудования и включает такие меры, как:

  • предотвращение выделения ограниченных ресурсов до проверки легитимности сервисного запроса;
  • предоставление более высокого приоритета уже выполняющимся процессам по сравнению с новыми;
  • идентификация и удаление дубликатов и просроченных запросов из очередей;
  • игнорирование неожиданных пакетов, переданных по адресам, не являющимся индивидуальными (non-unicast).

Сетевое оборудование должно обеспечивать возможность генерации сигналов и записи в журнал сведений о подозрительном трафике. В журнальный файл следует включать информацию, которая позволит идентифицировать входящий канал и адреса источников, что может помочь администратору сети или системы SCTP принять меры по защите. Предполагается, что оператор будет действовать в соответствии с сигналами тревоги при возникновении чёткой схемы злоупотребления.

Протокол SCTP устойчив к лавинным атакам, в частности, благодаря использованию четырёхэтапного согласования при старте ассоциации, механизма cookie для блокирования ресурсов отвечающего узла до тех пор, пока не будет завершено согласование, и тегов верификации (Verification Tag) для защиты от вставки дополнительных пакетов в поток данных действующей ассоциации.

Механизм ESP может также оказаться полезным для снижения риска при некоторых типах атак на службы.

Поддержка параметра Host Name исключена из протокола. Конечная точка, получившая блок INIT или INIT ACK с параметром Host Name, должна передать в ответ блок ABORT и может включить в него код причины Unresolvable Address.

12.2.4.2. Слепое маскирование

Маскирование (Masquerade) может использоваться для атак на службы несколькими способами.

  • Путём связывания ресурсов целевого узла SCTP, к которому ролевой (impersonated) узел имеет ограниченный доступ. Например, политика целевого узла может разрешать не более одной ассоциации SCTP с ролевым узлом SCTP. Замаскированный атакующий может попытаться организовать ассоциацию и прикинуться ролевым узлом, чтобы впоследствии настоящий ролевой узел не мог подключиться к сервису.
  • Посредством преднамеренного раскрытия подмены для провоцирования блокировки ролевого узла целевым узлом SCTP.
  • Путём взаимодействия с действующей ассоциацией посредством вставки в поток добавочного содержимого (например, блока SHUTDOWN).

SCTP снижает риск слепого маскирования с подменой адресов (IP spoofing) за счёт использования четырёхэтапного согласования при старте ассоциации. Поскольку начальный обмен не занимает памяти, атаки с маскированием вслепую не вызывают никакой блокировки. Кроме того, подтверждение INIT ACK, содержащее State Cookie, передаётся по адресу IP, с которого был получен блок INIT. Таким образом атакующий не получит блок INIT ACK, содержащий State Cookie. SCTP обеспечивает защиту от вставки дополнительных пакетов в поток данных ассоциации за счёт использования тегов верификации (Verification Tag).

Запись (log) полученных запросов INIT и аномалий вроде неожиданных блоков INIT ACK может быть полезна в целях обнаружения враждебных действий. Однако пользу от такого протоколирования нужно сопоставить с усложнением обработки при старте ассоциации SCTP, которое к тому же делает узел SCTP более уязвимым к лавинным атакам. Запись не имеет смысла без создания рабочих процедур повседневного просмотра и анализа журнальных файлов.

12.2.4.3. Неправомерная монополизация

Атаки этого типа выполняются злоумышленником открыто с использованием легитимного доступа. Они направлены против других пользователей узла SCTP или ресурсов, разделяемых между атакующим и целевым узлом. Возможные атаки включают создание большого числа ассоциаций между атакующим узлом и объектом атаки или перенос больших объёмов данных в рамках легитимных ассоциаций.

Следует вводить административные ограничения на число ассоциаций, создаваемых узлами. Пользовательским приложениям SCTP следует обеспечивать возможность обнаружения передачи больших объёмов информации или сообщений no-op в данной ассоциации, а также другие механизмы фиксации и разрыва ассоциаций в соответствии с принятой локальной политикой.

12.3. Взаимодействие SCTP с межсетевыми экранами

Для некоторых межсетевых экранов будет полезна возможность проверки первого фрагмента фрагментированного пакета SCTP и однозначного определения его соответствия блоку INIT (см. дополнительную информацию в [RFC1858]). Поэтому ещё раз подчёркиваются требования, приведённые в параграфе 3.1, — (1) блок INIT недопустимо группировать с каким-либо другим блоком в одном пакете, (2) пакет с блоком INIT должен иметь Verification Tag = 0. Получатель INIT должен отбрасывать этот блок и все последующие блоки, если INIT сгруппирован с другими блоками или имеет отличный от нуля тег верификации.

12.4. Защита хостов, не поддерживающих SCTP

Для обеспечения не поддерживающим SCTP хостам такого же уровня защиты от атак, как для хостов SCTP, все реализации протокола SCTP должны поддерживать обработку ICMP, описанную в разделе 10.

Когда стек SCTP получает пакет, содержащий несколько блоков управления или DATA, и обработка такого пакета ведёт к передаче в ответ нескольких блоков, отправителю этих блоков недопустимо передавать более одного пакета с блоками, отличными от DATA. Это защищает сеть от передачи «пика» пакетов в ответ на единственный пакет. Если поддерживается группировка, несколько блоков отклика можно собрать в один пакет отклика. Если группировка блоков не поддерживается, отправителю недопустимо передавать более одного блока-отклика, а остальные он должен отбросить. Отметим, что это правило не применимо к блокам SACK, поскольку они сами по себе являются откликами на блоки DATA, и SACK не требует передачи в ответ блоков DATA.

Реализация SCTP должна прерывать ассоциацию при получении блока SACK с подтверждением номера TSN, который не был передан.

Реализация SCTP, получающая блок INIT, для отклика на который требуется большой пакет по причине включения в него множества параметров Unrecognized Parameter, может (по своему усмотрению) опустить часть или все такие параметры для снижения размера INIT ACK. С учётом размера параметра State Cookie и множества адресов, которые получатель INIT может указывать своему партнёру, размер блока INIT ACK может превышать размер исходного блока INIT. Реализациям SCTP следует пытаться максимально сократить размер блоков INIT ACK для снижения возможности организации «атак с усилением» (byte amplification attack).

13. Вопросы управления сетью

Модуль MIB для протокола SCTP, определённый в [RFC3873], применим для описанной здесь версии протокола.

14. Рекомендуемые параметры TCB

В этом разделе описываются рекомендуемые параметры, которые предполагаются в TCB. Раздел имеет иллюстративное значение и его содержимое не следует трактовать, как требования к реализациям или исчерпывающий список параметров, включаемых в SCTP TCB. Конкретной реализации для обеспечения оптимальной работы может потребоваться свой набор параметров.

14.1. Параметры, требуемые для экземпляра SCTP

Associations

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

Secret Key

Секретный ключ используется данной конечной точкой для расчёта MAC. В качестве ключа следует использовать случайное число криптографического качества и достаточной длины. Для выбора ключей могут быть полезны рекомендации [RFC4086].

Address List

Список адресов IP, с которыми связан данный экземпляр. Эти сведения передаются партнёру в блоках INIT и INIT ACK.

SCTP Port

Локальный номер порта, с которым связана конечная точка SCTP.

14.2. Параметры, требуемые для ассоциации в целом (например, TCB)

Peer Verification Tag

Значение тега партнёра, передаваемое в каждом пакете и полученное из блока INIT или INIT ACK.

My Verification Tag

Значение тега, ожидаемое в каждом входящем пакете и передаваемое партнёру в блоке INIT или INIT ACK.

State

COOKIE-WAIT, COOKIE-ECHOED, ESTABLISHED, SHUTDOWN-PENDING, SHUTDOWN-SENT, SHUTDOWN-RECEIVED, SHUTDOWN-ACK-SENT.

Примечание. Состояние CLOSED не указано, поскольку для ассоциации в этом состоянии TCB следует удалять.

Peer Transport Address List

Список транспортных адресов SCTP, с которыми связан партнёр. Эта информация извлекается из блоков INIT или INIT ACK и используется для связывания входящих пакетов с данной ассоциацией. Обычно эта информация хэшируется или индексируется (keyed) для быстрого поиска и доступа к TCB.

Primary Path

Текущее значение основного транспортного адреса партнёра. Это значение может также указывать адрес источника пакетов от этой точки.

Overall Error Count

Общий счётчик ошибок для всей ассоциации.

Overall Error Threshold

Значение числа ошибок для ассоциации, при достижении которого данная ассоциация будет разорвана.

Peer Rwnd

Текущее значение окна приёма (rwnd), рассчитанное для партнёра.

Next TSN

Значение следующего номера TSN, которое будет присвоено новому блоку DATA. Начальный номер передаётся партнёру в блоке INIT или INIT ACK и далее номер увеличивается каждый раз, когда блоку DATA выделяется значение TSN (обычно непосредственно перед передачей или в процессе фрагментации).

Last Rcvd TSN

Последний номер TSN, полученный с сохранением порядка. Начальное значение устанавливается на основе параметра Initial TSN в блоке INIT или INIT ACK, путём вычитания 1 из полученного значения.

Mapping Array

Массив битов или байтов, показывающий, какие переупорядоченных номеров TSN были получены (относительно Last Rcvd TSN). При отсутствии пропусков (т. е., все пакеты получены с сохранением порядка доставки), этот массив может содержать только нули. Эта структура может быть кольцевым буферои или битовым массивом.

Ack State

Этот флаг показывает, будет ли передано подтверждение SACK при получении следующего пакета. Начальное значение равно 0. При получении пакета значение инкрементируется. При достижении значения 2 или более в ответ на получение пакета передаётся SACK и значение сбрасывается в 0. Отметим, что описанный механизм используется лишь при отсутствии нарушений в порядке доставки блоков DATA. Если имеется нарушение порядка доставки DATA, подтверждения SACK не задерживаются (см. раздел 6).

Inbound Streams

Массив структур для отслеживания входящих потоков. Обычно данные о потоках включают следующий (ожидаемый) порядковый номер и могут включать номер потока.

Outbound Streams

Массив структур для отслеживания исходящих потоков. Обычно данные о потоках включают следующий порядковый номер для передачи в поток.

Reasm Queue

Очередь сборки.

Local Transport Address List

Список локальных адресов IP, связанных с данной ассоциацией.

Association Maximum DATA Chunk Size

Наименьшее значение Path Maximum DATA Chunk Size среди всех адресов партнёра.

14.3. Данные для транспортного адреса

Для каждого транспортного адреса партнёра из списка, полученного в блоке INIT или INIT ACK, поддерживается группа параметров, включающая перечисленные ниже.

Error count

Текущее значение счётчика ошибок для данного получателя.

Error Threshold

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

cwnd

Текущий размер окна перегрузки.

ssthresh

Текущее значение порога Slow Start (ssthresh).

RTO

Текущее значение тайм-аута повтора передачи.

SRTT

Текущее значение сглаженного времени кругового обхода.

RTTVAR

Вариации текущего значения RTT.

partial bytes acked

Метод слежения, используемый для увеличения размера cwnd в режиме предотвращения перегрузки (congestion avoidance, см. параграф 7.2.2).

state

Текущее состояние адресата (DOWN, UP, ALLOW-HB, NO-HEARTBEAT и т. п.).

PMTU

Текущее известное значение PMTU.

PMDCS

Текущее известное значение PMDCS.

Per Destination Timer

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

RTO-Pending

Флаг, указывающий на то, что один из блоков DATA, переданных по этому адресу, в данный момент используется для расчёта RTT. Если флаг сброшен (0), ближайший блок DATA, отправляемый по этому адресу, следует использовать для расчёта RTT и установить данный флаг. При завершении расчёта RTT (получение подтверждения SACK для блока DATA) флаг сбрасывается.

last-time

Время передачи адресату последнего пакета. Это значение может использоваться для определения необходимости передачи HEARTBEAT.

14.4. Требуемые параметры общего назначения

Out Queue

Очередь исходящих блоков DATA.

In Queue

Очередь входящих блоков DATA.

15. Взаимодействие с IANA

SCTP определяет пять реестров, поддерживаемых агентством IANA:

  • типы блоков;
  • флаги блоков;
  • типы параметров;
  • коды причины ошибки в блоках ERROR;
  • идентификаторы протоколов данных.

Агентство IANA внесло в упомянутые реестры перечисленные ниже изменения.

  • В реестре Chunk Types ссылки на [RFC4960] и [RFC6096] заменены ссылками на этот документ. В разделе Notes ссылка на параграф 3.2 в [RFC6096] заменена ссылкой на параграф 15.2 этого документа. Кроме того, ссылки на [RFC4960] были заменены ссылками на данный документ для типов:
    • Payload Data (DATA);
    • Initiation (INIT);
    • Initiation Acknowledgement (INIT ACK);
    • Selective Acknowledgement (SACK);
    • Heartbeat Request (HEARTBEAT);
    • Heartbeat Acknowledgement (HEARTBEAT ACK);
    • Abort (ABORT);
    • Shutdown (SHUTDOWN);
    • Shutdown Acknowledgement (SHUTDOWN ACK);
    • Operation Error (ERROR);
    • State Cookie (COOKIE ECHO);
    • Cookie Acknowledgement (COOKIE ACK);
    • Reserved for Explicit Congestion Notification Echo (ECNE);
    • Reserved for Congestion Window Reduced (CWR);
    • Shutdown Complete (SHUTDOWN COMPLETE);
    • Reserved for IETF-defined Chunk Extensions.
  • В реестре Chunk Parameter Types ссылки на [RFC4960] заменены ссылками на этот документ. Агентство IANA сменило имя Unrecognized Parameters для типа параметров блока на Unrecognized Parameter в реестре Chunk Parameter Types. Кроме того, ссылки на [RFC4960] были заменены ссылками на данный документ для типов:
    • Heartbeat Info;
    • IPv4 Address;
    • IPv6 Address;
    • State Cookie;
    • Unrecognized Parameter;
    • Cookie Preservative;
    • Host Name Address;
    • Supported Address Types

    Агентство IANA добавило ссылку на данный документ для типа параметров блока:

    • Reserved for ECN Capable (0x8000).

    Кроме того, агентство IANA добавило значение 65535 к зарезервированным для заданных IETF расширений.

  • В реестре Chunk Flags ссылки на [RFC6096] заменены ссылками на данный документ. Кроме того, ссылки на [RFC4960] были заменены ссылками на данный документ для следующих флагов блока DATA:
    • E;
    • B;
    • U.

    Агентство IANA заменило ссылку на [RFC7053] ссылкой на этот документ для флага блока DATA:

    • I.

    Агентство IANA заменило ссылку на [RFC4960] ссылкой на этот документ для флага блока ABORT:

    • T.

    Агентство IANA заменило ссылку на [RFC4960] ссылкой на этот документ для флага блока SHUTDOWN COMPLETE:

    • T.
  • В реестре Error Cause Codes ссылки на [RFC4960] заменены ссылками на этот документ. Имя причины ошибки User Initiated Abort заменено на User-Initiated Abort. А Stale Cookie Error — на Stale Cookie. Кроме того, ссылки на [RFC4960] были заменены ссылками на данный документ для следующих кодов причин:
    • Invalid Stream Identifier;
    • Missing Mandatory Parameter;
    • Stale Cookie;
    • Out of Resource;
    • Unresolvable Address;
    • Unrecognized Chunk Type;
    • Invalid Mandatory Parameter;
    • Unrecognized Parameters;
    • No User Data;
    • Cookie Received While Shutting Down;
    • Restart of an Association with New Addresses.

    Агентство IANA заменило ссылку на [RFC4460] ссылкой на этот документ для следующих кодов причин:

    • User-Initiated Abort;
    • Protocol Violation.
  • В реестре SCTP Payload Protocol Identifiers ссылки на [RFC4960] заменены ссылками на этот документ. Агентство IANA заменило ссылку на [RFC4460] ссылкой на этот документ для следующих идентификаторов протоколов в данных SCTP:
    • Reserved by SCTP

Протокол SCTP требует, чтобы реестр IANA Port Numbers был открыт для регистрации портов SCTP, как описано в параграфе 15.6. Назначенный IESG эксперт поддерживает IANA при оценке запросов на выделение порта SCTP.

В реестре Service Name and Transport Protocol Port Number Registry ссылки на [RFC4960] заменены ссылками на этот документ для портов SCTP:

  • 9 (discard);
  • 20 (ftp-data);
  • 21 (ftp);
  • 22 (ssh);
  • 80 (http);
  • 179 (bgp);
  • 443 (https).

В реестре Hypertext Transfer Protocol (HTTP) Digest Algorithm Values ссылка на приложение B к [RFC4960] заменена ссылкой на приложение A к данному документу.

В реестре ONC RPC Netids (Standards Action) каждая ссылка на [RFC4960] заменена ссылкой на данный документ для:

  • sctp;
  • sctp6.

В реестре IPFIX Information Elements каждая ссылка на [RFC4960] заменена ссылкой на данный документ для:

  • sourceTransportPort;
  • destinationTransportPort;
  • collectorTransportPort;
  • exporterTransportPort;
  • postNAPTSourceTransportPort;
  • postNAPTDestinationTransportPort.

15.1. Расширения для блоков, определяемые IETF

Выделение новых кодов для блоков SCTP выполняется по процедуре IETF Review, определённой в [RFC8126]. Документация для нового блока должна включать:

  1. полное и сокращённое имя нового типа блоков;
  2. подробное описание структуры блока, которое должно соответствовать базовой структуре, определённой в параграфе 3.2;
  3. определение и подробное описание каждого поля блока, включая флаги, если они используются; определённые флаги блока будут служить начальными значениями таблицы флагов для нового типа блока;
  4. подробное описание процедур использования нового типа блоков в работе протокола.

Последний номер типа (255) зарезервирован для будущих расширений.

Для каждого нового типа блоков IANA создаёт таблицу регистрации флагов нового блока. Процедура регистрации флагов конкретного блока описана в параграфе 15.2.

15.2. Регистрация определённых IETF флагов блока

Выделение новых флагов блоков выполняется по процедуре RFC Required [RFC8126]. Документация для флагов блока должна включать:

  1. имя нового флага блока;
  2. подробное процедурное описание использования нового в работе протокола; должно учитываться, что не поддерживающие флаг реализации будут устанавливать значение 0 при отправке и игнорировать флаг при получении.

IANA выбирает значение для нового флага. Это должно быть одно из значений 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, которое должно быть уникальным среди значений флагов для конкретного типа блока.

15.3. Определяемые IETF расширения для типа параметров блоков

Выделение новых кодов для типа параметров блоков SCTP (chunk parameter type code) выполняется по процедуре IETF Review, определённой в [RFC8126]. Документация для параметров блока должна включать:

  1. имя типа параметра;
  2. подробное описание структуры поля параметра, которая должна соответствовать базовому форматы TLV, определённому в параграфе 3.2.1;
  3. подробное описание каждого элемента значения параметра;
  4. подробное описание предполагаемого использования этого типа параметра и возможности присутствия в одном блоке множества экземпляров данного параметра;
  5. каждый тип параметров должен быть уникальным для всех блоков.

15.4. Определяемые IETF дополнительные коды причин ошибок

Дополнительные значения кодов ошибок выделяются по процедуре Specification Required, определённой в [RFC8126]. Представляемая документация должна включать:

  1. имя ошибки;
  2. подробное описание условий, при которых конечной точке SCTP следует генерировать блок ERROR (или ABORT) с этим кодом ошибки;
  3. ожидаемые действия конечной точки SCTP при получении блока ERROR (или ABORT) с этим кодом ошибки;
  4. подробное описание структуры и содержимого полей данных, сопровождающих этот код.

Первое слово кода причина (32 бита) должно соответствовать формату, определённому в параграфе 3.3.10:

  • первые 2 байта содержат значение кода причины ошибки;
  • последние два байта указывают размер причины ошибки.

15.5. Идентификаторы протоколов (Payload)

Идентификаторы протокола выделяются по процедуре First Come First Served [RFC8126].

За исключением значения 0, зарезервированного в SCTP для индикации неуказанного протокола в блоке DATA, реализация SCTP не отвечает за стандартизацию или проверку идентификаторов протоколов. SCTP просто получает идентификатор от вышележащего уровня и передаёт его с соответствующими элементами данных.

Вышележащему уровню (пользователю SCTP) следует стандартизовать SHOULD идентификаторы конкретных протоколов через IANA, если такая стандартизация желательна. Использование каких-либо конкретных идентификаторов протоколов в элементах данных выходит за рамки спецификации.

15.6. Реестр номеров портов

Службы SCTP могут использовать контактные номера портов для предоставления услуг незнакомым абонентам, как это делается в TCP и UDP. Назначенные IESG эксперты поддерживают запрос в IANA на выделение портов SCTP в соответствии с процедурами, описанными в [RFC8126]. Детали процесса описаны в [RFC6335].

16. Предлагаемые параметры протокола SCTP

Рекомендуется использовать следующие значения параметров протокола:

RTO.Initial — 1 секунда

RTO.Min — 1 секунда

RTO.Max — 60 секунд

Max.Burst — 4

RTO.Alpha — 1/8

RTO.Beta — 1/4

Valid.Cookie.Life — 60 секунд

Association.Max.Retrans — 10 попыток

Path.Max.Retrans — 5 попыток (для каждого адреса получателя)

Max.Init.Retransmits — 8 попыток

HB.interval — 30 секунд

HB.Max.Burst — 1

SACK.Delay — 200 миллисекунд

Примечание для разработчиков. Реализация SCTP может разрешать ULP изменение некоторых параметров протокола (см. раздел 11).

Для RTO.Min следует использовать приведённое выше значение.

17. Литература

17.1. Нормативные документы

[ITU.V42.1994] International Telecommunications Union, «Error-correcting Procedures for DCEs Using Asynchronous-to-Synchronous Conversion», ITU-T Recommendation V.42, 1994.

[RFC1122] Braden, R., Ed., «Requirements for Internet Hosts — Communication Layers», STD 3, RFC 1122, DOI 10.17487/RFC1122, October 1989, <https://www.rfc-editor.org/info/rfc1122>.

[RFC1123] Braden, R., Ed., «Requirements for Internet Hosts — Application and Support», STD 3, RFC 1123, DOI 10.17487/RFC1123, October 1989, <https://www.rfc-editor.org/info/rfc1123>.

[RFC1191] Mogul, J. and S. Deering, «Path MTU discovery», RFC 1191, DOI 10.17487/RFC1191, November 1990, <https://www.rfc-editor.org/info/rfc1191>.

[RFC1982] Elz, R. and R. Bush, «Serial Number Arithmetic», RFC 1982, DOI 10.17487/RFC1982, August 1996, <https://www.rfc-editor.org/info/rfc1982>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC4291] Hinden, R. and S. Deering, «IP Version 6 Addressing Architecture», RFC 4291, DOI 10.17487/RFC4291, February 2006, <https://www.rfc-editor.org/info/rfc4291>.

[RFC4303] Kent, S., «IP Encapsulating Security Payload (ESP)», RFC 4303, DOI 10.17487/RFC4303, December 2005, <https://www.rfc-editor.org/info/rfc4303>.

[RFC4895] Tuexen, M., Stewart, R., Lei, P., and E. Rescorla, «Authenticated Chunks for the Stream Control Transmission Protocol (SCTP)», RFC 4895, DOI 10.17487/RFC4895, August 2007, <https://www.rfc-editor.org/info/rfc4895>.

[RFC5681] Allman, M., Paxson, V., and E. Blanton, «TCP Congestion Control», RFC 5681, DOI 10.17487/RFC5681, September 2009, <https://www.rfc-editor.org/info/rfc5681>.

[RFC6335] Cotton, M., Eggert, L., Touch, J., Westerlund, M., and S. Cheshire, «Internet Assigned Numbers Authority (IANA) Procedures for the Management of the Service Name and Transport Protocol Port Number Registry», BCP 165, RFC 6335, DOI 10.17487/RFC6335, August 2011, <https://www.rfc-editor.org/info/rfc6335>.

[RFC6083] Tuexen, M., Seggelmann, R., and E. Rescorla, «Datagram Transport Layer Security (DTLS) for Stream Control Transmission Protocol (SCTP)», RFC 6083, DOI 10.17487/RFC6083, January 2011, <https://www.rfc-editor.org/info/rfc6083>.

[RFC7296] Kaufman, C., Hoffman, P., Nir, Y., Eronen, P., and T. Kivinen, «Internet Key Exchange Protocol Version 2 (IKEv2)», STD 79, RFC 7296, DOI 10.17487/RFC7296, October 2014, <https://www.rfc-editor.org/info/rfc7296>.

[RFC8126] Cotton, M., Leiba, B., and T. Narten, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8200] Deering, S. and R. Hinden, «Internet Protocol, Version 6 (IPv6) Specification», STD 86, RFC 8200, DOI 10.17487/RFC8200, July 2017, <https://www.rfc-editor.org/info/rfc8200>.

[RFC8201] McCann, J., Deering, S., Mogul, J., and R. Hinden, Ed., «Path MTU Discovery for IP version 6», STD 87, RFC 8201, DOI 10.17487/RFC8201, July 2017, <https://www.rfc-editor.org/info/rfc8201>.

[RFC8899] Fairhurst, G., Jones, T., Tüxen, M., Rüngeler, I., and T. Völker, «Packetization Layer Path MTU Discovery for Datagram Transports», RFC 8899, DOI 10.17487/RFC8899, September 2020, <https://www.rfc-editor.org/info/rfc8899>.

17.2. Дополнительная литература

[FALL96] Fall, K. and S. Floyd, «Simulation-based Comparisons of Tahoe, Reno, and SACK TCP», SIGCOM 99, V. 26, N. 3, pp 5-21, July 1996.

[SAVAGE99] Savage, S., Cardwell, N., Wetherall, D., and T. Anderson, «TCP Congestion Control with a Misbehaving Receiver», ACM Computer Communications Review 29(5), October 1999.

[ALLMAN99] Allman, M. and V. Paxson, «On Estimating End-to-End Network Path Properties», SIGCOM 99, October 1999.

[WILLIAMS93] Williams, R., «A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS», SIGCOM 99, August 1993, <https://archive.org/stream/PainlessCRC/crc_v3.txt>.

[RFC0768] Postel, J., «User Datagram Protocol», STD 6, RFC 768, DOI 10.17487/RFC0768, August 1980, <https://www.rfc-editor.org/info/rfc768>.

[RFC0793] Postel, J., «Transmission Control Protocol», STD 7, RFC 793, DOI 10.17487/RFC0793, September 1981, <https://www.rfc-editor.org/info/rfc793>.

[RFC1858] Ziemba, G., Reed, D., and P. Traina, «Security Considerations for IP Fragment Filtering», RFC 1858, DOI 10.17487/RFC1858, October 1995, <https://www.rfc-editor.org/info/rfc1858>.

[RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, «HMAC: Keyed-Hashing for Message Authentication», RFC 2104, DOI 10.17487/RFC2104, February 1997, <https://www.rfc-editor.org/info/rfc2104>.

[RFC2196] Fraser, B., «Site Security Handbook», FYI 8, RFC 2196, DOI 10.17487/RFC2196, September 1997, <https://www.rfc-editor.org/info/rfc2196>.

[RFC2522] Karn, P. and W. Simpson, «Photuris: Session-Key Management Protocol», RFC 2522, DOI 10.17487/RFC2522, March 1999, <https://www.rfc-editor.org/info/rfc2522>.

[RFC2960] Stewart, R., Xie, Q., Morneault, K., Sharp, C., Schwarzbauer, H., Taylor, T., Rytina, I., Kalla, M., Zhang, L., and V. Paxson, «Stream Control Transmission Protocol», RFC 2960, DOI 10.17487/RFC2960, October 2000, <https://www.rfc-editor.org/info/rfc2960>.

[RFC3465] Allman, M., «TCP Congestion Control with Appropriate Byte Counting (ABC)», RFC 3465, DOI 10.17487/RFC3465, February 2003, <https://www.rfc-editor.org/info/rfc3465>.

[RFC3873] Pastor, J. and M. Belinchon, «Stream Control Transmission Protocol (SCTP) Management Information Base (MIB)», RFC 3873, DOI 10.17487/RFC3873, September 2004, <https://www.rfc-editor.org/info/rfc3873>.

[RFC4086] Eastlake 3rd, D., Schiller, J., and S. Crocker, «Randomness Requirements for Security», BCP 106, RFC 4086, DOI 10.17487/RFC4086, June 2005, <https://www.rfc-editor.org/info/rfc4086>.

[RFC4301] Kent, S. and K. Seo, «Security Architecture for the Internet Protocol», RFC 4301, DOI 10.17487/RFC4301, December 2005, <https://www.rfc-editor.org/info/rfc4301>.

[RFC4460] Stewart, R., Arias-Rodriguez, I., Poon, K., Caro, A., and M. Tuexen, «Stream Control Transmission Protocol (SCTP) Specification Errata and Issues», RFC 4460, DOI 10.17487/RFC4460, April 2006, <https://www.rfc-editor.org/info/rfc4460>.

[RFC4960] Stewart, R., Ed., «Stream Control Transmission Protocol», RFC 4960, DOI 10.17487/RFC4960, September 2007, <https://www.rfc-editor.org/info/rfc4960>.

[RFC6096] Tuexen, M. and R. Stewart, «Stream Control Transmission Protocol (SCTP) Chunk Flags Registration», RFC 6096, DOI 10.17487/RFC6096, January 2011, <https://www.rfc-editor.org/info/rfc6096>.

[RFC6458] Stewart, R., Tuexen, M., Poon, K., Lei, P., and V. Yasevich, «Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)», RFC 6458, DOI 10.17487/RFC6458, December 2011, <https://www.rfc-editor.org/info/rfc6458>.

[RFC6951] Tuexen, M. and R. Stewart, «UDP Encapsulation of Stream Control Transmission Protocol (SCTP) Packets for End-Host to End-Host Communication», RFC 6951, DOI 10.17487/RFC6951, May 2013, <https://www.rfc-editor.org/info/rfc6951>.

[RFC7053] Tuexen, M., Ruengeler, I., and R. Stewart, «SACK-IMMEDIATELY Extension for the Stream Control Transmission Protocol», RFC 7053, DOI 10.17487/RFC7053, November 2013, <https://www.rfc-editor.org/info/rfc7053>.

[RFC8260] Stewart, R., Tuexen, M., Loreto, S., and R. Seggelmann, «Stream Schedulers and User Message Interleaving for the Stream Control Transmission Protocol», RFC 8260, DOI 10.17487/RFC8260, November 2017, <https://www.rfc-editor.org/info/rfc8260>.

[RFC8261] Tuexen, M., Stewart, R., Jesup, R., and S. Loreto, «Datagram Transport Layer Security (DTLS) Encapsulation of SCTP Packets», RFC 8261, DOI 10.17487/RFC8261, November 2017, <https://www.rfc-editor.org/info/rfc8261>.

[RFC8540] Stewart, R., Tuexen, M., and M. Proshin, «Stream Control Transmission Protocol: Errata and Issues in RFC 4960», RFC 8540, DOI 10.17487/RFC8540, February 2019, <https://www.rfc-editor.org/info/rfc8540>.

Приложение A. Расчет контрольной суммы CRC32c

Мы определяем «отраженное значение», как значение с порядком битов, обратным по отношению к используемому в машине. 32-битовое значение CRC рассчитывается, как описано для CRC32c и использует полиномиальный код 0x11EDC6F41 (Castagnoli93) или x32+x28+x27+x26+x25+x23+x22+x20+x19+x18+x14+x13+x11+x10+x9+x8+x6+x0. Значение CRC рассчитывается с помощью процедуры, похожей на ETHERNET CRC [ITU32], которая изменена с учетом применения на транспортном уровне.

Расчёт CRC использует полиномиальное деление. Битовая строка сообщения (M) преобразуется в полином M(X) и значение CRC рассчитывается по M(X) с использованием полиномиальной арифметики.

При использовании CRC на канальном уровне полином строится с использованием естественного порядка битов — первый бит сигнала в линии является коэффициентов старшего порядка. Поскольку SCTP является протоколом транспортного уровня, он не может знать порядка передачи битов в физическую среду. Более того, на разных участках пути между конечными точками SCTP может на канальном уровне применяться разный порядок битов.

Следовательно, требуется соглашение для отображения транспортных сообщений SCTP на полиномы с целью расчёта CRC. При отображении сообщений SCTP на полиномы сначала берётся старший байт, но в каждом байте биты берутся, начиная с младшего. Первый байт сообщения обеспечивает восемь старших коэффициентов. В каждом байте младший бит SCTP дает самый старший коэффициент полинома в рамках данного байта, а старший бит SCTP — младший коэффициент в рамках байта (такой порядок иногда называют отраженным — mirrored или reflected [WILLIAMS93]). Полиномы CRC преобразуются обратно в значения байтов транспортного уровня SCTP с помощью соответствующего отображения.

Значение CRC для транспортного уровня SCTP следует рассчитывать в соответствии с приведённым ниже описанием.

  • Входными данными CRC является поток байтов с номерами 0 — N-1.
  • Байтовый поток транспортного уровня отображается на полиномиальное значение. PDU размером N байтов с номерами j от 0 до N-1 рассматривается, как коэффициенты полинома M(x) порядка 8N-1 и бит 0 байта j будет коэффициентом x(8(N-j)-8), а бит 7 этого байта — x(8(N-j)-1).
  • Оставшаяся часть регистра CRC заполняется единицами и рассчитывается значение CRC с помощью умножения на x32 и деления на полином CRC.
  • Полином умножается на x32 и делится на G(x), что порождает полином степени не более 31, образующий оставшуюся часть R(x).
  • Коэффициенты R(x) рассматриваются, как 32-битовая последовательность.
  • Последовательность битов дополняется и результат является полиномом CRC.
  • Полином CRC отображается обратно на байты транспортного уровня SCTP. Коэффициент x31 даёт значение биты 7 в байте SCTP 0, а коэффициент x24 даёт значение бита 0 в байте 0. Коэффициент x7 даёт значение бита 7 в байте 3, а коэффициент x0 — значение бита 0 в байте 3. Результирующая 4-байтовая последовательность является последовательностью транспортного уровня для 32-битовой контрольной суммы SCTP.

Примечание для разработчиков. В стандартах, книгах и литературе от производителей для CRC зачастую приводятся иные формулировки, где используется регистр для хранения остатка алгоритма деления long-division, инициализируемый нулями, а не 1 и первые 32 бита сообщения дополняются. Алгоритм long-division, используемый в нашей формулировке совмещает начальное умножение на 232 и «длинное деление» в одной операции. Для таких алгоритмов и сообщений, размер которых превышает 64 бита, две спецификации полностью эквивалентны. Обеспечение эквивалентности является одной из целей данного документа.

Следует предупредить разработчиков SCTP о том, что в литературе можно найти обе спецификации и иногда без ограничений для алгоритма long-division. Выбор формулировки в этом документе обусловлен возможностью применения не только для SCTP, когда тот же алгоритм CRC может применяться для сообщений меньше 64 битов.

Можно несколько снизить вычислительные издержки, проверяя ассоциацию по значению Verification Tag до расчета контрольной суммы, чтобы не рассчитывать контрольные суммы для пакетов с некорректными тегами. Исключением из этого правила являются блоки INIT и некоторые обмены SHUTDOWN-COMPLETE, а также устаревшие блоки COOKIE ECHO. Однако в этих случаях пакеты достаточно малы и расчет контрольных сумм не требует значительных ресурсов.

Ниже приведён (ненормативный) пример кода, заимствованный из генератора CRC с открытым кодом [WILLIAMS93], использующего метод «отражения» и таблицу для SCTP CRC32c с 256 записями по 32 бита в каждой. Этот метод не слишком быстрый и не слишком медленный по сравнению с поиском в таблицах CRC, но его преиуществом является возможность работы с процессами, использующими порядок big-endian и little-endian, при просмотре общих таблиц (с хост-порядком), а также использование лишь предопределенных операций ntohl() и htonl(). Код несколько отличается от [WILLIAMS93] для обеспечения переносимости между архитектурами big-endian и little-endian (отметим, что в тех случаях, когда известно, что целевая архитектура использует порядок little-endian, финальные операции bit-reversal и byte-reversal могут быть объединены).

<CODE BEGINS>
   /*************************************************************/
   /* Для генератора таблиц Ross Williams устанавливаются       */
   /* значения TB_WIDTH=4, TB_POLLY=0x1EDC6F41, TB_REVER=TRUE   */
   /* Для прямого расчета Mr. Williams используются значения    */
   /* cm_width=32, cm_poly=0x1EDC6F41, cm_init=0xFFFFFFFF,      */
   /* cm_refin=TRUE, cm_refot=TRUE, cm_xorort=0x00000000        */
   /*************************************************************/

   /* Пример файла с таблицей crc */
   #ifndef __crc32cr_table_h__
   #define __crc32cr_table_h__

   #define CRC32C_POLY 0x1EDC6F41
   #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])

   unsigned long  crc_c[256] =
   {
   0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
   0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
   0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
   0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
   0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
   0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
   0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
   0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
   0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
   0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
   0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
   0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
   0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
   0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
   0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
   0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
   0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
   0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
   0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
   0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
   0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
   0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
   0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
   0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
   0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
   0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
   0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
   0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
   0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
   0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
   0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
   0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
   0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
   0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
   0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
   0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
   0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
   0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
   0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
   0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
   0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
   0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
   0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
   0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
   0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
   0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
   0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
   0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
   0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
   0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
   0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
   0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
   0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
   0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
   0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
   0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
   0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
   0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
   0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
   0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
   0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
   0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
   0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
   0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
   };

   #endif

    /* Пример программы построения таблицы */
   #include <stdio.h>
   #include <stdlib.h>

   #define OUTPUT_FILE   "crc32cr.h"
   #define CRC32C_POLY    0x1EDC6F41L
   FILE *tf;
   unsigned long
   reflect_32 (unsigned long b)
   {
     int i;
     unsigned long rw = 0L;

     for (i = 0; i < 32; i++){
         if (b & 1)
           rw |= 1 << (31 - i);
         b >>= 1;
     }
     return (rw);
   }

   unsigned long
   build_crc_table (int index)
   {
     int i;
     unsigned long rb;

     rb = reflect_32 (index);

     for (i = 0; i < 8; i++){
         if (rb & 0x80000000L)
          rb = (rb << 1) ^ CRC32C_POLY;
         else
          rb <<= 1;
     }
     return (reflect_32 (rb));
   }

   main ()
   {
     int i;

     printf ("\nGenerating CRC-32c table file <%s>\n",
     OUTPUT_FILE);
     if ((tf = fopen (OUTPUT_FILE, "w")) == NULL){
         printf ("Unable to open %s\n", OUTPUT_FILE);
         exit (1);
     }
     fprintf (tf, "#ifndef __crc32cr_table_h__\n");
     fprintf (tf, "#define __crc32cr_table_h__\n\n");
     fprintf (tf, "#define CRC32C_POLY 0x%08lX\n",
     CRC32C_POLY);
     fprintf (tf,
     "#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])\n");
     fprintf (tf, "\nunsigned long  crc_c[256] =\n{\n");
     for (i = 0; i < 256; i++){
         fprintf (tf, "0x%08lXL, ", build_crc_table (i));
         if ((i & 3) == 3)
           fprintf (tf, "\n");
     }
     fprintf (tf, "};\n\n#endif\n");

     if (fclose (tf) != 0)
       printf ("Unable to close <%s>." OUTPUT_FILE);
     else
       printf ("\nThe CRC-32c table has been written to <%s>.\n",
         OUTPUT_FILE);
   }

   /* Пример вставки crc */
   #include "crc32cr.h"

   unsigned long
   generate_crc32c(unsigned char *buffer, unsigned int length)
   {
     unsigned int i;
     unsigned long crc32 = ~0L;
     unsigned long result;
     unsigned char byte0,byte1,byte2,byte3;

     for (i = 0; i < length; i++){
         CRC32C(crc32, buffer[i]);
     }

     result = ~crc32;

     /*  В result храниться «негативный» остаток полинома,
      *  поскольку таблица и алгоритм являются «зеркальными [williams95].
      *  Т. е., result имеет такое же значение, как будто мы отобразили сообщение
      *  на полином, рассчитали остаток полинома для хостового порядка битов
      *  выполнили финальную смену знака (negation) и сквозное обращение битов.
      *  Отметим, что 32-битовое обращение битов идентично 4 восьмибитовым обращениям 
      *  с последующим обращением порядка байтов. На машинах little-endian 
      *  такое обращение байтов и финальная операция ntohl cancel не нужны.
      */
     byte0 = result & 0xff;
     byte1 = (result>>8) & 0xff;
     byte2 = (result>>16) & 0xff;
     byte3 = (result>>24) & 0xff;
     crc32 = ((byte0 << 24) |
              (byte1 << 16) |
              (byte2 << 8)  |
              byte3);
     return ( crc32 );
   }

   int
   insert_crc32(unsigned char *buffer, unsigned int length)
   {
     SCTP_message *message;
     unsigned long crc32;
     message = (SCTP_message *) buffer;
     message->common_header.checksum = 0L;
     crc32 = generate_crc32c(buffer,length);
     /* and insert it into the message */
     message->common_header.checksum = htonl(crc32);
     return 1;
   }

   int
   validate_crc32(unsigned char *buffer, unsigned int length)
   {
     SCTP_message *message;
     unsigned int i;
     unsigned long original_crc32;
     unsigned long crc32 = ~0L;

     /* сохраним и обнулим контрольную сумму */
     message = (SCTP_message *) buffer;
     original_crc32 = ntohl(message->common_header.checksum);
     message->common_header.checksum = 0L;
     crc32 = generate_crc32c(buffer,length);
     return ((original_crc32 == crc32)? 1 : -1);
   }
<CODE ENDS>

Благодарности

Представленный в этом документе протокол является серьёзным достижением, основанным на результатах работы авторов исходного [RFC2960] — Q. Xie, K. Morneault, C. Sharp, H. Schwarzbauer, T. Taylor, I. Rytina, M. Kalla, L. Zhang, and V. Paxson.

Кроме того, следует отметить всех, кто внес вклад в создание исходного RFC — Mark Allman, R.J. Atkinson, Richard Band, Scott Bradner, Steve Bellovin, Peter Butler, Ram Dantu, R. Ezhirpavai, Mike Fisk, Sally Floyd, Atsushi Fukumoto, Matt Holdrege, Henry Houh, Christian Huitema, Gary Lehecka, Jonathan Lee, David Lehmann, John Loughney, Daniel Luan, Barry Nagelberg, Thomas Narten, Erik Nordmark, Lyndon Ong, Shyamal Prasad, Kelvin Porter, Heinz Prantner, Jarno Rajahalme, Raymond E. Reeves, Renee Revis, Ivan Arias Rodriguez, A. Sankar, Greg Sidebottom, Brian Wyld, La Monte Yarroll и многих других, кто дал свои значимые комментарии.

Добавим в этот список соавторов [RFC4460] — I. Arias-Rodriguez, K. Poon, A. Caro.

Отметим усилия участников всех семи проверок совместимости SCTP и тех, кто представил комментарии к [RFC4460], как отмечено здесь — Barry Zuckerman, La Monte Yarroll, Qiaobing Xie, Wang Xiaopeng, Jonathan Wood, Jeff Waskow, Mike Turner, John Townsend, Sabina Torrente, Cliff Thomas, Yuji Suzuki, Manoj Solanki, Sverre Slotte, Keyur Shah, Jan Rovins, Ben Robinson, Renee Revis, Ian Periam, RC Monee, Sanjay Rao, Sujith Radhakrishnan, Heinz Prantner, Biren Patel, Nathalie Mouellic, Mitch Miers, Bernward Meyknecht, Stan McClellan, Oliver Mayor, Tomas Orti Martin, Sandeep Mahajan, David Lehmann, Jonathan Lee, Philippe Langlois, Karl Knutson, Joe Keller, Gareth Keily, Andreas Jungmaier, Janardhan Iyengar, Mutsuya Irie, John Hebert, Kausar Hassan, Fred Hasle, Dan Harrison, Jon Grim, Laurent Glaude, Steven Furniss, Atsushi Fukumoto, Ken Fujita, Steve Dimig, Thomas Curran, Serkan Cil, Melissa Campbell, Peter Butler, Rob Brennan, Harsh Bhondwe, Brian Bidulock, Caitlin Bestler, Jon Berger, Robby Benedyk, Stephen Baucke, Sandeep Balani и Ronnie Sellar.

Отдельная благодарность Mark Allman, который реально должен был стать соавтором [RFC4460] по max-burst, но сумел уклониться по причине занятости. Благодарим также Lyndon Ong и Phil Conrad за их полезный вклад в работу.

Отметим также тех, кто подготовил [RFC4460] и комментировал его, включая Alfred Hoenes и Ronnie Sellars.

Добавим сюда соавтора [RFC8540]: Maksim Proshin и тех, кто представил замечания к [RFC8540]: Pontus Andersson, Eric W. Biederman, Cedric Bonnet, Spencer Dawkins, Gorry Fairhurst, Benjamin Kaduk, Mirja Kühlewind, Peter Lei, Gyula Marosi, Lionel Morand, Jeff Morriss, Tom Petch, Kacheong Poon, Julien Pourtet, Irene Rüngeler, Michael Welzl, Qiaobing Xie.

Наконец, добавим тех, кто представил комментарии к этому документу, включая Gorry Fairhurst, Martin Duke, Benjamin Kaduk, Tero Kivinen, Eliot Lear, Marcelo Ricardo Leitner, David Mandelberg, John Preuß Mattsson, Claudio Porfiri, Maksim Proshin, Ines Robles, Timo Völker, Magnus Westerlund, Zhouming.

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

Адреса авторов

Randall R. Stewart

Netflix, Inc.

2455 Heritage Green Ave

Davenport, FL 33837

United States of America

Email: randall@lakerest.net

Michael Tüxen

Münster University of Applied Sciences

Stegerwaldstrasse 39

48565 Steinfurt

Germany

Email: tuexen@fh-muenster.de

Karen E. E. Nielsen

Kamstrup A/S

Industrivej 28

DK-8660 Skanderborg

Denmark

Email: kee@kamstrup.com


Перевод на русский язык

Николай Малых

nmalykh@protokols.ru


1Public Switched Telephone Network — коммутируемая телефонная сеть общего пользования. Прим. перев.

2Максимальный размер передаваемых пакетов. Прим. перев.

3Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

4Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

5Имеющих несколько сетевых интерфейсов. Прим. перев.

6Denial of service attack.

7Connection-oriented.

8Соотношения между номерами потоков в противоположных направлениях сильно зависят от того, как приложения используют эти потоки. Ответственность за поддержку корреляции между порядковыми номерами (если она нужна) ложится на пользовательское приложение SCTP.

9Типы типы ECNE и CWR зарезервированы для использования в будущем явных уведомлений о перегрузке (ECN).

10Предполагается, что отказоустойчивые реализации будут воспринимать блоки даже в тех случаях, когда поле Chunk Length учитывает заполнение в конце блока.

11Type-Length-Value — Тип-Размер-Значение.

12Блоки INIT могут содержать множество адресов IPv4 и/или IPv6 в произвольных комбинациях.

13Поле ECN capable зарезервировано для будущего использования с ECN.

14Недопустимо включение в блок INIT параметра Host Name Address. Получатель блока INIT с Host Name Address должен передать блок ABORT и может включить в него причину ошибки Unresolvable Address.

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

16Здесь не используется согласование числа потоков — каждая сторона просто выбирает меньшее из двух значений — предложенного и запрашиваемого. Более подробное описание приводится в параграфе 5.1.1.

17Блоки INIT ACK могут содержать множество адресов IPv4 и/или IPv6 в произвольных комбинациях.

18Поле ECN capable зарезервировано для будущего использования с ECN.

19Недопустимо включение в блок INIT ACK параметра Host Name Address. Получатель блока INIT с Host Name Address должен передать блок ABORT и может включить в него причину ошибки Unresolvable Address.

20Здесь не используется согласование числа потоков — каждая сторона просто выбирает меньшее из двух значений — предложенного и запрашиваемого. Более подробное описание приводится в параграфе 5.1.1.

21Имена блоков указаны заглавными буквами, а в именах параметров только первая буква является заглавной (например, блок COOKIE ECHO и параметр State Cookie). Если смену состояния могут вызвать несколько событий или сообщений, они помечаются (A), (B) и т. д.

22off-path.

23Silly window syndrome — синдром неразумного окна.

24Advertised Receiver Window Credit — анонсированное окно приёма.

25Receiver advertised window size. Прим. перев.

26Congestion control window. Для краткости будем называть его просто окном перегрузки. Прим. перев.

27Slow-start threshold. Прим. перев.

28Highest TSN Newly Acknowledged — максимальный недавно подтверждённый номер.

29Максимальное число повторов передачи для ассоциации.

30Максимальное число повторов для пути.

31Heartbeat period.

32Out of the blue — совершенно неожиданный.

Рубрика: RFC | Оставить комментарий