TCP / IP是否会阻止数据包重放?

时间:2008-09-26 18:27:02

标签: tcp

TCP / IP是否阻止同一数据包的多个副本到达目的地?或者由端点将幂等性逻辑分层到它之上?

如果可能,请参考TCP / IP规范中的特定段落。

8 个答案:

答案 0 :(得分:7)

从重复数据包恢复是TCP堆栈的工作:

  

TCP必须从数据中恢复   损坏,丢失,重复或       由互联网通信系统发出故障。这个       通过为每个八位字节分配序列号来实现       发送,并要求来自的肯定确认(ACK)       接收TCP。如果在超时内未收到ACK       interval,重传数据。在接收器,   序列       数字用于正确排序可能收到的细分       乱序,消除重复。损坏由处理       为每个传输的段添加一个校验和,检查它       接收器,并丢弃损坏的段。

- RFC 793 - 传输控制协议,第1.5节

但是,如果它们是具有新序列号的相同数据包,则为no。

答案 1 :(得分:5)

TCP使用序列号来检测重传时的重复,这也可以防止琐碎的重放攻击。

来自RFC 793,第3.3节 - 序列号:

  

设计中的基本概念   是每个八位字节的数据发送   通过TCP连接有一个序列   数。因为每个八位字节都是   按顺序排列,每个都可以   确认。确认   所采用的机制是累积的   确认序列   数字X表示所有八位字节都向上   到了但不包括X了   接收。这种机制允许   直接重复检测   在重传的情况下。   段内八位字节的编号   是第一个数据八位字节   紧接着标题是   最低编号,以及以下   八位字节连续编号。

重复检测将确保不能轻易地重传相同的数据包。序列号还将确保注意到数据流中数据的插入(而不是替换),因为伪造数据包之后的其他合法数据包将具有重复的序列号,这将破坏数据流。这可能会导致这些数据包被丢弃为重复数据包,这可能会破坏正在使用的协议。

有关原始(1981)TCP / IP规范的更多信息可以在RFC 793以及涉及TCP / IP协议扩展或修改的许多其他RFC中找到。

答案 2 :(得分:4)

是的,TCP层可以防止重复的数据包。它下面的IP层没有。

RFC 1122中的详细信息。

答案 3 :(得分:3)

你似乎关心两件事:

  1. TCP可靠传送提供什么保证
  2. 攻击者可以通过重播攻击影响我的服务器进程
  3. 回答1:

    TCP保证可靠,按顺序传递字节序列。客户端应用程序通过write()发送给TCP的数据在服务器read()调用期间将完全相同。

    回答2:

    重播攻击不能很好地与TCP配合使用,因为每个连接都依赖于客户端和服务器分别生成的两个随机32位数。为了使重放攻击起作用,攻击者必须猜测服务器为其启动的虚假连接生成的序列号(理论上,攻击者有一个1/2 ** 32的机会正确猜测)。如果攻击者猜错了,她最好会在你的操作系统中导致一些缓冲数据。

    请注意,仅仅因为重放攻击不起作用,没有什么能阻止攻击者与您的服务器形成合法连接并将所需的任何数据流传输到您的应用程序。这就是为什么始终验证输入非常重要。

答案 4 :(得分:2)

TCP下面的层可能会遇到多个数据包或丢弃数据包。 TCP上的层不会出现重复或丢弃的数据包。

答案 5 :(得分:1)

我不知道数据包重复,但我从来没有遇到过使用TCP / IP,我知道它确实保证数据包都以正确的顺序到达,所以我无法理解为什么它不会“T

答案 6 :(得分:1)

这实际上取决于您接收数据的方式 - 虽然从技术上讲协议不应该给您重复(即具有相同tcp校验和的数据包),但其他因素可能会导致您看到重复数据 - 例如,您是网络硬件使用;另外,如果你使用嗅探器来查看tcp流,而不是只是在应用程序中读取一个打开的套接字,即使他们监控的实际tcp流没有重复数据包,也可以从嗅探器获取重包。

举一个现实世界的例子 - 目前我正在为一个主要的证券交易所进行内部网络的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));
    }
}}

答案 7 :(得分:0)

您还没有完全理解这个问题。 看到这个链接: http://en.wikipedia.org/wiki/Transmission_Control_Protocol

在此页面上写道:

“RFC时间戳,在RFC 1323中定义,帮助TCP计算发送方和接收方之间的往返时间。时间戳选项包括4字节时间戳值,其中发送方插入其时间戳时钟的当前值,以及4字节回送应答时间戳值,其中接收器通常插入它收到的最新时间戳值。发送器在确认中使用回应应答时间戳来计算自确认段发送以来经过的总时间。[2] < / p>

TCP时间戳也用于帮助TCP序列号遇到其2 ^ 32绑定并“环绕”序列号空间的情况。此方案称为“防止包裹序列号”或PAWS(详见RFC 1323)。“

此致 联合(波兰)