Предотвращает ли TCP / IP повторение пакетов?

StackOverflow https://stackoverflow.com/questions/141128

  •  02-07-2019
  •  | 
  •  

Вопрос

Предотвращает ли TCP / IP попадание нескольких копий одного и того же пакета в пункт назначения?Или конечная точка должна накладывать логику идемпотентности поверх нее?

Пожалуйста, по возможности, обратитесь к конкретным параграфам спецификации TCP / IP.

Это было полезно?

Решение

Это задача стека TCP восстанавливаться из дублирующихся пакетов:

TCP должен восстанавливаться из данных, которые повреждены, утеряны, дублируются или доставлены не в порядке системой интернет-связи.Это достигается путем присвоения порядкового номера каждому переданному октету и требования положительного подтверждения (ACK) от принимающего TCP.Если подтверждение не получено в течение тайм-аута , данные передаются повторно.На приемнике номера последовательности используются для правильного упорядочивания сегментов, которые могут быть получены не по порядку, и для устранения дубликатов.Устранение повреждений осуществляется путем добавления контрольной суммы к каждому переданному сегменту, проверки ее на получателе и удаления поврежденных сегментов.

-- RFC 793 - Протокол управления передачей, раздел 1.5

Однако, если это те же пакеты с новыми порядковыми номерами, то нет.

Другие советы

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

Из RFC 793, Раздел 3.3 - Порядковые номера:

Фундаментальное понятие в дизайне заключается в том, что каждый октет данных, отправляемых по TCP-соединению, имеет порядковый номер.Поскольку каждый октет упорядочен, каждый из них может быть подтвержден.Используемый механизм подтверждения является накопительным, так что подтверждение последовательности номер X указывает, что все октеты до , но не включая X, были получены.Этот механизм обеспечивает прямое обнаружение дубликатов при наличии повторной передачи.Нумерация октетов в сегменте заключается в том, что первый октет данных , следующий непосредственно за заголовком, имеет наименьший номер, а следующие октеты нумеруются последовательно.

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

Более подробную информацию об оригинальной спецификации TCP/IP (1981) можно найти в RFC 793, и многие другие RFC, включающие расширения или модификации протокола TCP / IP.

Да, уровень TCP предотвращает дублирование пакетов.Уровень IP под ним этого не делает.

Подробности в RFC 1122.

Похоже, вас беспокоят две разные вещи:

  1. Какие гарантии обеспечивает надежная доставка по протоколу TCP
  2. Может ли злоумышленник повлиять на процесс моего сервера с помощью повторной атаки

Ответ на вопрос 1:

Протокол TCP гарантирует надежную доставку последовательности байтов в определенном порядке.Какие бы данные клиентское приложение ни отправляло в TCP через write() выйдет точно так же во время работы сервера. read() позвони.

Ответ на вопрос 2:

Повторные атаки плохо работают с TCP, поскольку каждое соединение зависит от двух случайных 32-битных чисел, генерируемых клиентом и сервером соответственно.Чтобы повторная атака сработала, злоумышленник должен угадать порядковый номер, сгенерированный сервером для инициируемого им поддельного соединения (теоретически, у злоумышленника есть 1 / 2**32 шанс угадать правильно).Если злоумышленник угадает неправильно, в худшем случае это вызовет некоторую буферизацию данных в вашей операционной системе.

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

Уровни ниже TCP могут обрабатывать несколько пакетов или отброшенных пакетов.Уровни выше TCP не подвержены повторению или отбрасыванию пакетов.

Я не знаю о повторной отправке пакетов, но я никогда не сталкивался с этим при использовании TCP / IP, и я знаю, что это гарантирует, что все пакеты прибудут в правильном порядке, поэтому я не могу понять, почему этого не произойдет.

Это действительно зависит от того, как вы получаете свои данные - хотя технически протокол не должен выдавать вам дубликаты (т. е.пакеты с одинаковой контрольной суммой tcp), другие факторы могут привести к появлению дубликатов - например, используемое сетевое оборудование;кроме того, если вы используете снифферы для просмотра потоков tcp, а не просто для чтения открытого сокета в вашем приложении, можно получать пакеты dup от снифферов, даже если фактические потоки tcp, которые они отслеживали, не имели пакетов dup.

Приведу реальный пример - в данный момент я работаю над некоторым анализом tcp внутренних сетей для крупной фондовой биржи, и данные, которые я просматриваю, поступают от нескольких анализаторов и объединяются обратно.Итак, собирая данные, я обнаружил, что мне нужно выполнить ряд шагов предварительной обработки, включая поиск и удаление дубликатов.Например, в потоке, который я только что прочитал, из примерно 60 000 пакетов данных я обнаружил и удалил 95 дублирующихся пакетов.

Стратегия, которую я использую здесь, заключается в том, чтобы сохранить скользящее окно с 10 самыми последними контрольными суммами tcp и игнорировать пакеты, которые соответствуют этим контрольным суммам.Обратите внимание, что это хорошо работает для пакетов PSH, но не так хорошо для пакетов ACK - но в любом случае меня это меньше беспокоит.

Я написал специальную коллекцию с целью отслеживания этого скользящего окна контрольных сумм tcp, которое может быть полезно другим:

/// <summary>
/// Combination of a double-linked-list and a hashset with a max bound; 
/// Works like a bounded queue where new incoming items force old items to be dequeued; 
/// Re-uses item containers to avoid GC'ing;
/// Public Add() and Contains() methods are fully thread safe through a ReaderWriterLockSlim;
/// </summary>
public class BoundedHashQueue<T>
{
    private readonly int _maxSize = 100;
    private readonly HashSet<T> _hashSet = new HashSet<T>();
    private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
    private readonly Item _head;
    private readonly Item _tail;
    private int _currentCount = 0;

    public BoundedHashQueue(int maxSize)
    {
        _maxSize = maxSize;
        _head = _tail = new Item();
    }

    private class Item
    {
        internal T Value;
        internal Item Next;
        internal Item Previous;
    }

    public void Add(T value)
    {
        _lock.Write(() =>
            {
                if (_currentCount == 0)
                {
                    Item item = new Item();
                    item.Value = value;
                    _head.Next = item;
                    item.Previous = _head;
                    item.Next = _tail;
                    _tail.Previous = item;
                    _currentCount++;
                }
                else
                {
                    Item item;
                    if (_currentCount >= _maxSize)
                    {
                        item = _tail.Previous;
                        _tail.Previous = item.Previous;
                        _tail.Previous.Next = _tail;
                        _hashSet.Remove(item.Value);
                    }
                    else
                    {
                        item = new Item();
                        _currentCount++;
                    }
                    item.Value = value;
                    item.Next = _head.Next;
                    item.Next.Previous = item;
                    item.Previous = _head;
                    _head.Next = item;
                    _hashSet.Add(value);
                }
            });
    }

    public bool Contains(T value)
    {
        return _lock.Read(() => _hashSet.Contains(value));
    }
}}

Вы не до конца понимаете проблему.Смотрите эту ссылку:http://en.wikipedia.org/wiki/Transmission_Control_Protocol

На этой странице есть запись:

"Временные метки TCP, определенные в RFC 1323, помогают TCP вычислять время прохождения туда и обратно между отправителем и получателем.Параметры временной метки включают 4-байтовое значение временной метки, куда отправитель вставляет текущее значение своей временной метки clock, и 4-байтовое значение временной метки эхо-ответа, куда получатель обычно вставляет самое последнее значение временной метки, которое он получил.Отправитель использует временную метку эхо-ответа в подтверждении для вычисления общего времени, прошедшего с момента отправки подтвержденного сегмента.[2]

Временные метки TCP также используются, чтобы помочь в случае, когда порядковые номера TCP сталкиваются со своей привязкой 2 ^ 32 и "обтекают" пространство порядковых номеров.Эта схема известна как Защита от обернутых порядковых номеров, или PAWS (подробности см. в RFC 1323)."

С уважением, Джойнт (Польша)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top