4

问题描述: 在我的应用程序中,我必须以某种格式呈现数据包的内容。一个例子:

示例 任何打包的二进制数据,例如:4 字节头、4 字节类型(类型代码具有预先定义的含义),然后是源地址、目标地址等。

以前,我制作了将数据存储在二进制文件中的自制实现(固定记录长度允许快速查找),但随着时间的推移,我意识到我正在发明某种数据库。例如,我正在为非常大的数据文件实现我自己的高效二进制存储格式。我还实现了自己的索引以在某些字段上快速运行搜索。我认为一个真正的数据库(甚至是简单的 SQLite)可以使这些东西变得透明简单。

问题#1:数据库对存储此类数据有用吗?应该如何做?请注意,这里没有一对多、多对多的映射和其他高级的东西,它只是一个简单的数据包序列,具有一定的内部结构,我想向用户显示并让他与之交互(即搜索由某个领域)。

问题#2:现在假设用户自己可以指定他的数据包的格式,即在配置文件中:每个字段的长度、它的类型、它的值的含义(在枚举的情况下)等等。如何为此扩展由数据库支持的实现?用户应该定义数据库模式吗?配置文件是否应该自动翻译成这个模式?奥姆?

问题#3:更高级……现在假设数据包的长度和内容可以不同。即,对于类型#2 的包,有一些字段,对于类型#3,还有一些其他字段,等等。但我仍然希望我的应用程序能够处理它,很好地显示所有内容并允许用户在配置文件中指定格式。它是如何完成的?

提前致谢。

4

6 回答 6

1

一个简单的规则是:如果您要查询数据,那么它应该是数据库中表中的离散字段。如果没有,您可以存储 BLOB 并完成它。

也就是说,如果您想从 BLOB 中获取“元数据”并对其进行索引,那么您也可以轻松地做到这一点。

如果您的数据类型与数据库可以支持(或可以准确转换)的数据类型一致,那么将 BLOB 分解为可以很好地映射到 DB 列的组件部分可能会有一些价值。

定义“动态表格”(这很容易完成)的问题不在于表格的定义,而在于表格的潜在变化。正在更改的表(即添加或删除的列等)在更改期间往往无法使用。100 行不是问题。数百万行的真正问题。

如果数据定义是相当静态的,则创建一个映射工具,让您的用户描述 BLOB,然后您使用该定义来创建兼容表并在导入期间适当地转换 BLOB。

至于“不同类型的不同行”,您仍然可以将该数据填充到单个表中。与其他行相比,某些行具有“未使用”列,每行都按类型标识。如果您有很多行定义和大量差异,那么这样做会浪费大量空间。然后,您可能希望为每种行类型创建一个表,以及一个包含行类型和对实际表中实际行的引用的主表。如果您关心原始数据包之间的关系,则仅需要此主表(然后您可以按接收顺序存储它们,例如等)。

真的,这一切都归结为您拥有多少数据,您期望多少,您想要做多少工作与您已经完成了多少,等等。

于 2009-03-31T00:31:44.880 回答
1

问题#1:数据库对存储此类数据有用吗?应该如何做?

当然,数据库对于此应用程序很有用。您可以实现自己的专用数据存储,也许它对您的特定应用程序更有效,因为您可以针对该专业进行设计。关系数据库更通用,但您可以通过使用数据库来避免数周或数月的开发时间。

我今天早些时候回答了另一个关于如何处理可扩展类型的问题,其中每个新的子类型都有自己独特的一组属性。

产品表,多种产品,每个产品都有很多参数。”

对于您的应用程序,我会选择Concrete Table Inheritance设计。

问题#2:现在假设用户自己可以指定他的数据包的格式,即在配置文件中:每个字段的长度、它的类型、它的值的含义(在枚举的情况下)等等。如何为此扩展由数据库支持的实现?

我假设数据包类型的数量相对较少,然后以几乎相同的结构插入许多数据包。所以你应该使用数据库管理元数据的能力。我将为每种新的数据包类型定义一个附加表。

我还将存储“爆炸”的数据包,因此数据包的每个字段都存储在单独的数据库列中。这样,您可以单独索引每一列,以支持高效搜索。

您还可以定义约束,以便某些字段是必需的 ( NOT NULL) 或其值受查找表约束。同样,利用数据库的功能使用元数据在需要的地方实施一致的结构。

SQL 已经支持一种标准的声明性语言,用于指定具有数据类型、约束等的字段。为什么要开发一种不同的语言,然后必须将其翻译成 SQL?

问题#3:更高级……现在假设数据包的长度和内容可以不同。

给定数据包类型中的可选字段应NULL在相应列中允许。

于 2009-03-31T00:42:02.983 回答
1

您可能希望考虑的另一个选择是Berkeley DB或其克隆之一。BDB 级别很低,没有 SQL。它几乎是一个非常小、非常快的文件支持哈希表。它一直存在,并被用于许多速度和简单性至关重要的地方。不过,您需要在顶部添加一些功能才能完成您想要完成的工作。

于 2009-03-31T01:17:30.357 回答
1

尽管您说没有一对多的关系,但还是有:)

我建议为数据包存储创建两个表。一种用于存储“标头”或“标量”信息,这是数据包共有的,虽然它可以定义存在什么数据,但它不是数据包中存储的实际数据。

您的第二个表将存储每个数据包的数据,每个字段值组合代表此表中的一行。例如以下两个表:

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)
)

显然,这两个表对所存储数据的类型和大小进行了假设,并且并未详尽说明它们需要存储的内容。但是,这种基本结构将允许动态定义的数据包格式,并且是一种易于索引的模式(例如,在packet_id+field_idin上添加索引packet_field将是不费吹灰之力)。

然后,您的所有应用程序负责解包数据包并将其存储在此模式中的数据库中,然后重新打包(如有必要)。

当然,从这一点开始,您将需要存储数据包实际格式的表。就像是...

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
)

同样,显然简化了,但它显示了基本思想。对于每种数据包格式,您的表中将有一条记录,在给定数据包中的每个字段中都有packet_type一行。packet_type_field这应该为您提供将任意二进制数据块处理到上述数据包存储模式所需的大部分信息。

于 2009-04-02T13:23:10.363 回答
1

想到了三种方法。

sFlow 和 IPFlow 可以传输一组有限的数据包内容。这可以直接记录到几个不同的数据库中。

另一种更有针对性的方法是编写一个非常简单的 snort 规则,例如源地址或目标地址。然后让 snort 捕获数据包的有效负载。这样你只会得到你需要的实际数据。例如,您可以只获取数据包内的数据字段。例如密码等。

ngrep 还可以立即获取选择性数据。

当然,如果您不在服务器/工作站本身上进行捕获,则其中每一个都可能需要在端口上进行点击或监视会话。

于 2010-08-12T13:01:31.117 回答
0

虽然我不是这个实现的忠实拥护者,但我们有一些软件基本上可以为某些呼叫列表执行此操作。本质上,这就是他们所做的:

  1. 具有列定义的表 - 称之为 tblColumnDefs。此表包含“名称”、“类型”、“长度”和“描述”等列
  2. 实例主表 (tblPacketNames)。本质上,您定义的每种数据包类型只有“PacketTypeID”、“PacketName”和“描述”
  3. 一个实例定义表(对您来说,这将是 tblPacketColumns)。此表将预定义的列收集在一起以形成您要存储的数据结构。例如,它可能包含“PacketTypeID”、“ColumnNumber”、“ColumnID”。在数据库规范化中,这是一个多对多表,因为它将列映射到使用它们的数据包。
  4. 在第二个数据库中(由于此步骤的动态 SQL/注入影响),动态创建表以保存实际数据。例如,如果您已定义(在步骤 2/3 中)名为“PING”的数据包类型,则您的数据库中可能有一个名为“PING”的表来保存该数据。您将使用链接到 tblColumnDefs 的 tblPacketColumns 来确定要创建的字段类型以及它们应该有多大。使用步骤 1 中的列,您最终会得到一组与步骤 3 中的数据包类型定义匹配的表。

注意:我并不特别喜欢第 4 步的 SQL 注入影响。如果安全性设计不当并且应用程序中任何用户输入字段的输入未正确清除,动态创建表可能会导致一些后果,特别是如果此应用程序有一个可供不受信任的调用者使用的接口(即 Internet)。

使用它,您可以在创建表时创建所需的索引(也许您在步骤 1 中有一个列,您将某些列标记为“可索引”,并在创建表时在它们之上创建索引。

于 2009-03-30T16:53:50.177 回答