TCP/IP は、同じパケットの複数のコピーが宛先に到達するのを防ぎますか? それとも、その上に冪等性ロジックをレイヤー化するのはエンドポイント次第ですか?
可能であれば、TCP/IP 仕様の特定の段落を参照してください。
TCP/IP は、同じパケットの複数のコピーが宛先に到達するのを防ぎますか? それとも、その上に冪等性ロジックをレイヤー化するのはエンドポイント次第ですか?
可能であれば、TCP/IP 仕様の特定の段落を参照してください。
重複したパケットから回復するのは、TCP スタックの仕事です。
TCP は、インターネット通信システムによって破損、紛失、複製、または順不同で配信されたデータから回復する必要があります。これは、送信される各オクテットにシーケンス番号を割り当て、受信 TCP からの肯定応答 (ACK) を要求することによって実現されます。ACK がタイムアウト間隔内に受信されない場合、データは再送信されます。受信側では、シーケンス番号を使用して、順不同で受信される可能性があるセグメントを正しく順序付けし、重複を排除します。損傷は、送信された各セグメントにチェックサムを追加し、受信側でチェックして、損傷したセグメントを破棄することで処理されます。
-- RFC 793 - 伝送制御プロトコル、セクション 1.5
ただし、それらが新しいシーケンス番号を持つ同じパケットである場合は、いいえ。
TCP は、再送信の場合に重複を検出するためにシーケンス番号を使用します。これにより、些細なリプレイ攻撃も防止されます。
RFC 793、セクション 3.3 - シーケンス番号から:
設計における基本的な概念は、TCP 接続を介して送信されるデータのすべてのオクテットにシーケンス番号があるということです。すべてのオクテットがシーケンス化されているため、それぞれを確認できます。使用される肯定応答メカニズムは累積的であるため、シーケンス番号 X の肯定応答は、X を含まないが X までのすべてのオクテットが受信されたことを示します。このメカニズムにより、再送信が発生した場合でも、単純な重複検出が可能になります。セグメント内のオクテットの番号付けは、ヘッダーの直後の最初のデータ オクテットが最も小さい番号であり、後続のオクテットは連続して番号付けされます。
重複検出により、同じパケットが自明に再送信できないことが保証されます。また、シーケンス番号は、データ ストリーム内のデータの挿入 (置換ではなく) が確実に認識されるようにします。これは、偽造されたパケットに続く正当なパケットに重複したシーケンス番号が含まれ、データ フローが中断されるためです。これにより、これらのパケットが重複としてドロップされる可能性が高く、使用されているプロトコルが壊れる可能性があります。
オリジナル (1981 年) の TCP/IP 仕様の詳細については、RFC 793と、TCP/IP プロトコルの拡張または変更を含む他の多くの RFC を参照してください。
はい、TCP レイヤーは重複したパケットを防ぎます。その下の IP 層にはありません。
詳細はRFC 1122にあります。
あなたは2つの異なることを心配しているようです:
1 への回答:
TCP は、バイト シーケンスの信頼できる順序どおりの配信を保証します。クライアントアプリケーションがTCPに送信するデータは、サーバーの呼び出しwrite()
中にまったく同じになります。read()
2 への回答:
すべての接続は、クライアントとサーバーがそれぞれ生成する 2 つのランダムな 32 ビット数に依存するため、リプレイ攻撃は TCP ではうまく機能しません。リプレイ攻撃が機能するためには、攻撃者は、開始しようとしている偽の接続に対してサーバーによって生成されたシーケンス番号を推測する必要があります (理論的には、攻撃者が正しく推測できる確率は 1 / 2**32 です)。攻撃者が推測を誤った場合、最悪の場合、OS でデータのバッファリングが発生します。
リプレイ攻撃が機能しないという理由だけで、攻撃者がサーバーとの正当な接続を形成し、必要なデータ ストリームをアプリケーションに送信することを妨げるものは何もないことに注意してください。これが、常に入力を検証することが重要な理由です。
TCP より下のレイヤーでは、複数のパケットまたはドロップされたパケットが発生する可能性があります。TCP より上位のレイヤーでは、パケットの繰り返しやドロップは発生しません。
実際には、データの受信方法によって異なります。技術的には、プロトコルで重複(つまり、同じtcpチェックサムを持つパケット)を取得することはできませんが、他の要因によって重複が発生する可能性があります。たとえば、使用しているネットワークハードウェアなどです。また、アプリケーションで開いているソケットを読み取るだけでなく、スニファを使用してtcpストリームを確認している場合は、監視している実際のtcpストリームにdupパケットがなくても、スニファから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));
}
}}
パケットの繰り返しについては知りませんが、TCP/IP を使用してこれに遭遇したことはありません。すべてのパケットが正しい順序で到着することが保証されていることは知っているので、なぜそうならないのか理解できません。
あなたは問題を完全には理解していません。このリンクを参照してください: http://en.wikipedia.org/wiki/Transmission_Control_Protocol
このページには次のように書かれています。
「RFC 1323 で定義されている TCP タイムスタンプは、TCP が送信者と受信者の間の往復時間を計算するのに役立ちます。タイムスタンプ オプションには、送信者がタイムスタンプ クロックの現在の値を挿入する 4 バイトのタイムスタンプ値と、4 バイトのタイムスタンプ値が含まれます。エコー応答タイムスタンプ値, 受信者は通常, 受信した最新のタイムスタンプ値を挿入する. 送信者は, 応答でエコー応答タイムスタンプを使用して, 応答セグメントが送信されてからの合計経過時間を計算する. [2]
TCP タイムスタンプは、TCP シーケンス番号が 2^32 境界に遭遇し、シーケンス番号空間を「ラップ アラウンド」する場合にも役立ちます。このスキームは、ラップされたシーケンス番号に対する保護、または PAWS として知られています (詳細については、RFC 1323 を参照してください)。
よろしく、共同(ポーランド)