Возможность организации работы SCTP поверх UDP (известная ещё как инкапсуляция SCTP-пакетов в UDP-пакеты) определена в RFC 6951 и реализована в пространстве ядра Linux начиная с версии ядра 5.11.0. Поддержку этой возможности планируется включить в Red Hat Enterprise Linux (RHEL) 8.5.0 и 9.0.



В этом материале даётся краткий обзор организации работы SCTP поверх UDP в ядре Linux.

Зачем нужна организация работы SCTP поверх UDP?


В вышеупомянутом RFC 6951 выделены две основные причины необходимости организации работы SCTP поверх UDP:

  • Это нужно для того чтобы позволить SCTP-трафику проходить через устаревшие NAT-системы, не имеющие встроенной поддержки SCTP, как указано в этом и этом документах.
  • Это нужно для того чтобы открыть возможность реализации SCTP на хостах, которые не предоставляют прямого доступа к уровню IP. В частности, речь идёт о том, чтобы у приложений была бы возможность использовать собственную реализацию SCTP в том случае, если операционная система не предоставляет им своей реализации SCTP.

Первая причина связана с решением «проблем промежуточных устройств». Эти проблемы доставили тем, кто пользуется SCTP, много неприятностей и встали на пути у широкого использования SCTP. В основе второй причины лежит потребность в наличии механизма, который позволяет разработчикам приложений пользовательского уровня создавать собственные реализации SCTP, основанные на UDP.

Как работает инкапсуляция SCTP-пакетов в UDP-пакеты?


Если в нашем распоряжении имеется возможность организации работы SCTP поверх UDP, то оказывается, что SCTP-пакеты инкапсулируются в UDP-пакеты. Реализация этого механизма создана с использованием набора API для работы с UDP-туннелями. Эти API уже использовались для организации работы протоколов VXLAN, GENEVE и TIPC.

Ядро, для того чтобы иметь возможность получать инкапсулированные пакеты, прослушивает особый UDP-порт на всех локальных интерфейсах. По умолчанию используется порт 9899. Этот порт, кроме того, играет роль порта src для UDP-пакетов, отправляемых хостом. Вполне логично то, что порт dest системы, с которой ведётся обмен данными, должен быть портом, который прослушивает эта система. В качестве его номера тоже, по умолчанию, используется 9899. Адреса портов src и dest, связанные с SCTP-механизмами, используются и в IP-заголовках:

    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |    IP(v6)-заголовок  (адреса, связанные с SCTP) |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |    UDP-заголовок      (src: 9899, dest: 9899)   |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |    Общий заголовок SCTP (SCTP-порты)            |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |    Блок SCTP #1                                 |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |    ...                                          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |    Блок SCTP #n                                 |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Обратите внимание на то, что протокол SCTP принимает во внимание UDP-заголовок при нахождении точки фрагментации данных.

Как пользоваться реализацией SCTP поверх UDP?


С точки зрения использования описываемого здесь механизма в программах, можно сказать, что тут нет никакой разницы с тем, что было раньше. А именно, можно применять все стандартные возможности SCTP, в новых условиях доступны и все прежние API. Старые приложения будут работать правильно без необходимости внесения в них изменений или их перекомпиляции. Единственно — нужно правильно настроить UDP-порт (локальный порт, который прослушивает система, или порт src) и точку инкапсуляции (порт, который прослушивает удалённая система, или порт dest). Для конкретного сетевого пространства имён сделать это можно с помощью утилиты sysctl:

    # sysctl -w net.sctp.encap_port=9899
    # sysctl -w net.sctp.udp_port=9899

Можно, в качестве альтернативы, использовать команду setsockopt и настроить порт инкапсуляции для отдельного сокета (socket), для того, что в SCTP принято называть «ассоциацией» (association), или для транспортного механизма (transport):

setsockopt(SCTP_REMOTE_UDP_ENCAPS_PORT, port);

На стороне сервера обычно нет нужды специально настраивать порт инкапсуляции. Подробнее об этом мы поговорим в следующем разделе.

Порт инкапсуляции UDP


Концепция порта инкапсуляции UDP отличается большой гибкостью. На стороне отправителя данных глобальный порт инкапсуляции демонстрирует лишь значение, задаваемое по умолчанию:

  • Порт инкапсуляции, заданный для отдельного сокета (per-socket) может быть использован тогда, когда другой сокет на одном хосте соединён с другим хостом, на котором используется другой UDP-порт.
  • Порт инкапсуляции, заданный для отдельной ассоциации (per-association) может быть использован тогда, когда тот же самый сокет соединён с другим хостом, на котором используется другой UDP-порт.
  • Порт инкапсуляции, задаваемый для отдельного транспортного механизма (per-transport), может быть использован тогда, когда в рамках одной и той же ассоциации нужно отправлять SCTP-пакеты, инкапсулированные в UDP-пакеты, пользуясь заданным транспортом.

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

  • Порт инкапсуляции каждой ассоциации можно выяснить, проанализировав первый пакет INIT. Другие такие пакеты, в которых указан другой UDP-порт src, после этого будут отбрасываться.
  • Порт инкапсуляции для каждого транспортного механизма можно узнать из входящих пакетов соответствующего пути, номер порта может быть обновлён в любое время.
  • Обычные SCTP-пакеты могут обрабатываться даже тогда, когда заданы порты инкапсуляции ассоциации и её транспортных механизмов.

Итоги


Если вы пользуетесь SCTP, если вам нравятся возможности этого протокола, вроде поддержки множественной адресации (Multihoming), многопоточности (Multi-streaming) и разрешения на потерю некоторых пакетов (Partial Reliability), но вы сталкиваетесь с «проблемами промежуточных устройств», теперь вы можете прибегнуть к возможностям ядра Linux, которые дают нам самый простой способ эти проблемы обойти.

Применяете ли вы SCTP?

Комментарии (6)


  1. edo1h
    05.09.2021 17:17
    +2

    у меня есть ощущение, что эпоха sctp заканчивается так и не начавшись, возможно, «убийцей» стал mptcp, максимально совместимый с обычным tcp.


    1. wlr398
      05.09.2021 19:21
      +1

      SCTP, насколько знаю, давно обосновался в телефонии фиксированной и сотовой для SIGTRAN и закончиться он там в обозримое время врядли сможет.


      1. edo1h
        06.09.2021 14:10

        Ну это свой мир. Я про «дикий» интернет, в котором по mptcp бегает трафик от openmptcprouter, устройств apple и т.п.
        Случаи подобного применения sctp мне неизвестны, хотя ниже yaguarundi написал о применении, наверное, у него опыт есть.


  1. yaguarundi
    06.09.2021 08:15

    SCTP используем, но первый раз слышу о проблеме "промежуточных устройств".


    1. wlr398
      06.09.2021 09:27

      Для чего, если не секрет ?
      Если SIGTRAN, то там по пути следования трафика не предполагается наличие устаревших NAT-систем.


      1. yaguarundi
        07.09.2021 11:00

        SIGTRAN и Diameter (в сетях сотовых операторов).