0

私はネットワークプログラミングの経験が比較的限られており、誰かがおそらくn00bishの質問で私を助けてくれることを望んでいました. :)

2 つの C++ プログラムを別々に実行しています。1 つは、特定のポートで受信したパケットのみをリッスンするようにフィルタリングする libpcap ライブラリで作成された単純なパケット スニファーです。次に、ペイロードの長さとペイロードの内容をバイナリ ファイルに書き出すようにパケットを解析します。

もう 1 つのプログラムは単純な bsd ソケット サーバー プログラムで、recv() 関数を使用して特定のポートでメッセージを受信するように設定されており、受信したメッセージの長さとメッセージの内容を同様にバイナリ ファイルに書き込みます。

すべてが正常に動作しているように見えるので、バイナリ出力ファイルを確認すると、内容は同じであると予想されます...しかし、残念ながら、それらは多少似ているだけです。パケット スニファーは、サーバーがキャッチしているのと同じデータをキャッチしているように見えますが、明らかにサーバー プログラムによって受信されていない、6 バイト長のペイロードを持つ余分なパケットも記録しています。

したがって、パケット スニファーがサーバーが認識していないパケットを検出しているか、サーバー プログラムが受信するはずのパケットを見逃しているかのいずれかです。ただし、サーバー プログラムが適切に機能し、適切なメッセージを受信して​​いることには多少の自信があるので、パケット スニファーによってこれらの余分なパケットが検出されるのは困惑させられます。これらの余分なパケットが何であるか、およびそれらをどのように除外するかを知っている人はいますか?

ノート:

私がリッスンしているポートにデータを送信しているクライアントは、小さなネットワーク内の古い Windows NT マシンであり、基本的にバイナリ データをサーバー プログラムに渡して処理しています。

残念ながら、職場のポリシーにより、コードをアップロードできません。ただし、私のコードの例は次の場所にあります: http://www.tcpdump.org/pcap.html http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html

再度、感謝します!

4

2 に答える 2

0

1 つは、特定のポートで受信したパケットのみをリッスンするようにフィルタリングする libpcap ライブラリで作成された単純なパケット スニファーです。次に、ペイロードの長さとペイロードの内容をバイナリ ファイルに書き出すようにパケットを解析します。

TCPポートまたはUDPポート?

TCP ポートの場合、プログラムは 3 ウェイ ハンドシェイク パケットと ACK のみのパケットを受信する可能性があります。

ペイロードの長さはどのように計算していますか? IP パケットの全長から IP ヘッダー長 (20 バイトではなく、バージョン/ヘッダー長フィールドからの長さ) を差し引いて、IP オプションを処理する必要があります。その長さが 5 未満の場合、つまり< 20 バイト、パケットを破棄するだけです。これは偽物です)、合計 TCP パケット長を取得し、そこからTCP ヘッダー長 (20 バイトではなく「データ オフセット」フィールド) を差し引くため、TCP オプションを処理しますその長さが < 5、つまり < 20 バイトの場合、パケットを破棄するだけです。これは偽物です)、TCP ペイロードの長さを取得します。

mfontanini が参照するオプションとIPオプションを処理する必要があります。

UDP ポートの場合でも、IP オプションを処理して、UDP パケットの合計長を取得する必要があります。

  • それが UDP ヘッダーの長さよりも短い場合は、パケットを破棄します。これは偽物です。
  • UDP ヘッダーの長さが 8 未満の場合、パケットを破棄します。これは偽物です。
  • それ以外の場合は、UDP ヘッダーの長さから 8 を引いた長さをペイロード長として使用します。

もう 1 つのプログラムは、recv() 関数を使用して特定のポートでメッセージを受信するように設定された単純な bsd ソケット サーバー プログラムであり、受信したメッセージの長さとメッセージの内容を同様にバイナリ ファイルに書き込みます。

最初のハンドシェイクや ACK のみのパケットは表示されません。

于 2013-06-18T18:19:50.950 に答える
0

私の魔法の玉は、これらの 6 バイト長のペイロードが単なる TCP オプションである可能性があることを示しています。ペイロードのみを操作する場合は、これらのオプションをスキップする必要があります。一部のパケットには、ペイロードと一部のオプションの両方が含まれる場合があることに注意してください。

TCP パケットのデータ オフセット フィールドは、ペイロードの開始点を示します。これについては、セクション 3.1で確認できます

とにかく、そのようなものを内部的に処理する高レベルのライブラリを使用することをお勧めします。libtinsを使用すると、次のような短いスニペットを使用してそのタスクを実行できます。

#include <tins/tins.h>

using namespace Tins;

bool callback(const PDU &pdu) {
    const RawPDU &raw = pdu.rfind_pdu<RawPDU>();
    // raw.payload() returns a std::vector<uint8_t>
    process_payload(raw.payload());
    return true;
}

int main() {
    Sniffer some_sniffer(
        "eth0", 
        Sniffer::NON_PROMISC,
        "some pcap filter"
    );
    some_sniffer.sniff_loop(callback);
}
于 2013-01-30T21:42:41.443 に答える