質問

問題の説明: 私のアプリケーションでは、データ パケットの内容を特定の形式で表現する必要があります。例:

パックされたバイナリ データ。例:4 バイトのヘッダー、4 バイトのタイプ (事前に定義された意味を持つタイプ コード)、送信元アドレス、宛先アドレスなどです。

以前は、バイナリ ファイル (固定レコード長により高速検索が可能) にデータを保存する自作の実装を作成しましたが、時間が経つにつれて、ある種のデータベースを発明していることに気づきました。たとえば、私は非常に大きなデータ ファイル用に独自の効率的なバイナリ ストレージ形式を実装しています。また、一部のフィールドで検索を迅速に実行するために、独自のインデックス作成も実装しています。実際の DB (単純な SQLite であっても) は、これを透過的に単純化できると思います。

質問1: DB はそのようなデータを保存するのに役立ちますか?また、どのように行うべきですか?ここには 1 対多、多対多のマッピングやその他の高度なものはないことに注意してください。これは、ユーザーに表示して操作してもらいたい、特定の内部構造を持つ単なるパケットのシーケンスです (つまり、特定のフィールドで検索します)。

質問2: ここで、ユーザー自身がパケットのフォーマットを指定できると仮定します。構成ファイル内:各フィールドの長さ、そのタイプ、その値の意味 (列挙型の場合) など。これに対して DB ベースの実装を拡張するにはどうすればよいですか?ユーザーが DB スキーマを定義する必要がありますか?構成ファイルをこのスキーマに自動変換する必要がありますか?ORM?

質問 #3: さらに進化した...ここで、データ パッケージの長さと内容が異なる可能性があると仮定します。つまり、タイプ #2 パッケージの場合はいくつかのフィールドがあり、タイプ #3 の場合はその他のフィールドなどがいくつかあります。しかし、それでもアプリでそれを処理して、すべてを適切に表示し、ユーザーが構成ファイルで形式を指定できるようにしたいと考えています。どのように行われるのでしょうか?

前もって感謝します。

役に立ちましたか?

解決

質問1:DBSはそのようなデータを保存するのに役立ちますか?また、どのように行う必要がありますか?

確かに、この用途にはデータベースが役立ちます。独自の特殊な目的のデータ ストアを実装することもできます。また、特定のアプリケーション向けに設計できるため、おそらくその方が効率的でしょう。リレーショナル データベースはより汎用的ですが、データベースを採用することで、数週間から数か月かかる開発時間を回避できます。

私は今日、拡張可能な型を処理する方法についての別の質問に答えました。拡張可能な型では、新しいサブタイプにはそれぞれ独自の属性セットがあります。

"製品テーブル、多くの種類の製品、各製品には多くのパラメータがあります."

あなたのアプリケーションでは、 具象テーブルの継承 デザイン。

質問2:これで、ユーザー自身がパケットの形式を指定できるとします。構成ファイル内:各フィールドの長さ、そのタイプ、その値の意味(列挙の場合)など。これのためにDBバックされた実装を拡張するにはどうすればよいですか?

パケット タイプの数が比較的少ないと考えられますが、多くのパケットがほぼ同じ構造で挿入されます。したがって、メタデータを管理するにはデータベースの機能を使用する必要があります。新しいパケット タイプごとに追加のテーブルを定義します。

また、パケットを「展開」して保存し、パケットの各フィールドが個別のデータベース列に保存されるようにします。そうすることで、各列に個別にインデックスを付けて、効率的な検索をサポートできます。

一部のフィールドが必須になるように制約を定義することもできます (NOT NULL)、またはその値はルックアップ テーブルによって制限されます。ここでも、データベースの機能を活用してメタデータを使用し、必要な場合に一貫した構造を強制します。

SQL は、データ型や制約などを使用してフィールドを指定するための標準の宣言型言語をすでにサポートしています。なぜ別の言語を開発し、それを SQL に変換する必要があるのでしょうか?

質問 #3:さらに進化した...これで、データパッケージの長さと内容が変化する可能性があるとします。

特定のパケット タイプでオプションのフィールドは許可する必要があります。 NULL 対応する列にあります。

他のヒント

簡単なルールは次のとおりです。データをクエリする場合は、DB 内のテーブル内の個別のフィールドである必要があります。そうでない場合は、BLOB を保存して作業を完了できます。

とはいえ、BLOB から「メタデータ」を取得し、そのデータにインデックスを付けたい場合は、それも簡単に行うことができます。

データ型がデータベースがサポートできるものと一致している (または正確に変換できる) 場合は、BLOB を DB 列に適切にマップするコンポーネント部分に展開する値がある可能性があります。

「実行中のテーブル」の定義 (これは簡単に実行できます) の問題は、テーブルの定義というよりも、テーブルが変更される可能性があることです。変更されているテーブル (つまり、列の追加、削除など)は、変更の間は使用できなくなる傾向があります。100 行の場合は問題ありません。何百万行にも及ぶ実際の問題。

データ定義がかなり静的な場合は、ユーザーが BLOB を記述できるようにするマッピング機能を作成し、その定義を使用して、準拠したテーブルを作成し、インポート中に BLOB を適切に変換します。

「異なるタイプの異なる行」については、そのデータを 1 つのテーブルに詰め込むことができます。一部の行には他の行と比較して「未使用」列があり、各行はタイプによって識別されます。行定義が多く、差異が多い場合、これを行うと多くの無駄なスペースが発生します。次に、行タイプごとにテーブルを作成し、行タイプと実際のテーブル内の実際の行への参照を保持するマスター テーブルを作成することになります。このマスター テーブルが必要になるのは、元のデータ パケットの相互関係を重視する場合のみです (その後、受信順に保存するなどのことが可能です)。

実際のところ、すべては、どれだけのデータを持っているか、どれだけの量を期待しているか、どれだけの作業を実行したいのか、どれだけの作業をすでに実行しているのか、などによって決まります。

検討すべきもう 1 つのオプションは、 バークレーDB またはそのクローンの 1 つ。BDB はかなり低レベルであり、SQL はありません。これは、非常に小さく、非常に高速なファイルベースのハッシュ テーブルです。これは永遠に存在しており、スピードとシンプルさが最優先される多くの場所で使用されています。ただし、目的を達成するには、上にいくつかの機能を追加する必要があります。

1 対多の関係は存在しないと述べたという事実にもかかわらず、存在します:)

パケットストレージ用に 2 つのテーブルを作成することをお勧めします。1 つは「ヘッダー」または「スカラー」情報を保存するもので、これはパケットに共通であり、どのようなデータが存在するかを定義することはできますが、パケットに保存されている実際のデータではありません。

2 番目のテーブルには、各フィールドと値の組み合わせがこのテーブルの行を表す、各パケットのデータが格納されます。たとえば、次の 2 つのテーブル:

create table packet
(
    packet_id int identity(1, 1) primary key,
    destination varchar(50),
    sender varchar(50),
    packet_type_id int not null
)

create table packet_field
(
    packet_field_id int identity(1, 1) primary key,
    packet_id int not null references packet (packet_id),
    field_id int not null,
    data varbinary(500)
)

明らかに、これら 2 つのテーブルは保存されるデータのタイプとサイズについての仮定を行っており、保存する必要があるデータを網羅しているわけではありません。ただし、この基本的な構造により、動的に定義されたパケット形式が可能になり、簡単にインデックスを作成できるスキーマになります (たとえば、 packet_id+field_idpacket_field それは簡単なことでしょう)。

アプリケーションが行うべきことは、パケットを解凍してこのスキーマの DB に保存し、(必要に応じて) 再パックすることだけです。

もちろん、この時点から、パケットの実際の形式を保存するテーブルが必要になります。何かのようなもの...

create table packet_type
(
    packet_type_id int identity(1, 1) primary key,
    name varchar(200) not null
)

create table packet_type_field
(
    field_id int identity(1, 1) primary key,
    packet_type_id int not null references packet_type (packet_type_id)
    field_offset int not null,
    name varchar(200) not null
)

繰り返しますが、明らかに単純化されていますが、基本的な考え方を示しています。レコードは 1 つだけになります。 packet_type 各パケット形式のテーブルと、 packet_type_field 指定されたパケットの各フィールドに対して。これにより、バイナリ データの任意のチャンクを処理して前述のパケット ストレージ スキーマに入れるために必要な情報のほとんどが得られます。

3つの方法が思い浮かびます。

sFlow と IPFlow は、限られたパケット コンテンツのセットを送信できます。これは、いくつかの異なるデータベースに直接ログインできます。

よりターゲットを絞った別の方法は、送信元アドレスや宛先アドレスなどの非常に単純な Snort ルールを書き込むことです。次に、Snort にパケットのペイロードをキャプチャさせます。そうすれば、必要な実際のデータのみを取得できます。たとえば、パケット内のデータのフィールドだけを取得することができます。例えばパスワードなど

ngrep は、選択したデータをネットワークから直接取得することもできます。

もちろん、サーバー/ワークステーション自体でキャプチャを実行していない場合は、それぞれのポートでタップまたはモニター セッションが必要になる可能性があります。

私はこの実装の大ファンではありませんが、一部の通話リストに対して基本的にこれを行うソフトウェアがいくつかあります。基本的に、彼らがやることは次のとおりです。

  1. 列定義を含むテーブル - tblColumnDefs と呼びます。このテーブルには、「名前」、「タイプ」、「長さ」、「説明」などの列が含まれています。
  2. インスタンス マスター テーブル (tblPacketNames)。基本的に、定義している各パケット タイプの「PacketTypeID」、「PacketName」、「Description」だけです。
  3. インスタンス定義テーブル (これは tblPacketColumns になります)。このテーブルは、事前定義された列を集めて、保存するデータ構造を形成します。たとえば、「PacketTypeID」、「ColumnNumber」、「ColumnID」を保持する場合があります。データベースの正規化で言えば、これは多対多のテーブルです。列を使用するパケットにマップするからです。
  4. 2 番目のデータベースでは (このステップの動的 SQL/インジェクションの影響のため)、実際のデータを保持するテーブルが動的に作成されます。たとえば、(ステップ 2/3 で) 「PING」というパケット タイプを定義した場合、データベース内にそのデータを保持する「PING」というテーブルが存在する可能性があります。tblColumnDefs にリンクされた tblPacketColumns を使用して、作成するフィールドの種類とそのサイズを決定します。最終的に、ステップ 1 の列を使用して、ステップ 3 のパケット タイプ定義に一致するテーブルのコレクションが作成されます。

注記:私はステップ 4 の SQL インジェクションの影響があまり好きではありません。テーブルを動的に作成すると、セキュリティが適切に設計されておらず、アプリケーション内のユーザー入力フィールドからの入力が適切にクレンジングされていない場合、特にこのアプリケーションに信頼できない呼び出し元 (インターネットなど) が利用できるインターフェイスがある場合、何らかの結果が生じる可能性があります。 )。

これを使用すると、テーブルの作成時に必要に応じてインデックスを作成できます (手順 1 で特定の列に「インデックス可能」のフラグを設定すると、テーブルの作成時にその列の上にインデックスが作成される場合があります)。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top