Using markdown files to replace MAAT网络流处理配置统一描述框架.docx

This commit is contained in:
郑超
2023-05-04 06:16:42 +00:00
parent c88fd120dc
commit f087a4382d
18 changed files with 1133 additions and 3 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

3
.gitignore vendored
View File

@@ -3,3 +3,6 @@
# build
build/*
#Mac
.DS_Store

75
docs/history.md Normal file
View File

@@ -0,0 +1,75 @@
# 更新记录
| 版本 | 时间 | 说明 | 修订人 |
| ------- | ---------- | ------------------------------------------------------------ | ------------ |
| v4.0 | 2023-5-2 | Maat4.0使用Markdown重新组织文档 | 郑超、刘文坛 |
| V3.7.0 | 2022-8-23 | 增加Boolean Expression 回调表;修正分组于子分组中的描述。 | 郑超 |
| V3.2.3 | 2021-7-15 | 增加组合扫描一节 | 郑超 |
| V3.1.20 | 2021-4-28 | 增加加载gzip压缩后的JSON文件说明 | 郑超 |
| V3.1.5 | 2021-3-12 | 增加回调类FQDN表的匹配示例 | 郑超 |
| V3.1.4 | 2020-11-04 | 内容外键为“null”时表示空文件。 | 郑超 |
| V3.1.1 | 2020-9-27 | 增加虚拟表建立在多个不同类型物理表上的说明 | 郑超 |
| V3.1.0 | 2020-9-18 | 增加FQDN回调表 | 郑超 |
| v3.0.4 | 2020-8-17 | 增加扩展的数值类域配置interval_plus | 郑超 |
| v3.0 | 2020-6-29 | Maat 3.0, 支持子句,原分组表拆分为分组关系表和分组编译表 | 郑超 |
| v2.8 | 2020-3-13 | 支持组合表 | 郑超 |
| v2.8 | 2020-2-11 | 支持命中路径Hit Path | 郑超 |
| v2.8 | 2020-2-4 | 支持策略按照执行顺序Evaluation Order排序 | 郑超 |
| v2.8 | 2020-1-22 | Maat JSON文件支持加密参见17.3 | 郑超 |
| v2.8 | 2019-7-28 | 1、 不再兼容无分组表的情况 2、 支持虚拟表 | 郑超 |
| v2.7.2 | 2019-7-10 | 扩展类IP配置表支持CIDR格式。 | 郑超 |
| v2.7.1 | 2019-5-23 | 将富IP类配置表改名为扩展类IP配置表。 | 郑超 |
| v2.7.0 | 2019-5-12 | 1、 增加子分组关系说明 2、 增加富IP类配置的说明 | 郑超 |
| v2.6.0 | 2019-1-8 | 1、增加“非”运算的说明 2、文档和动态链接库版本号的前两位相同。 | 郑超 |
| v2.3.3 | 2018-12-24 | 增加Extra Data和read column函数的说明多命中情况下按照配置ID由大到小返回命中结果。 | 郑超 |
| v2.3.2 | 2018-12-03 | 支持运行态以全量通知的方式加载变化的json文件 | 郑超 |
| v2.3.1 | 2018-10-15 | 完善内容外键和配置生效标签的说明。 | 郑超 |
| v2.3.0 | 2018-9-26 | 增加内容外键和配置生效标签的说明。 | 郑超 |
| v2.2.5 | 2018-9-12 | 更正IP类域配置关于全0掩码表示任意说明全0掩码为精确匹配。 | 郑超 |
| v2.2.4 | 2018-08-09 | 在“配置表描述文件”一节中,说明编译配置表中用户自定义域转码的设置方法。 | 郑超 |
| v2.2.3 | 2018-07-27 | 1、完善“常见故障处理->扫描结果与预想不一致”一节。 2、整理“配置表描述方式”一节。 | 郑超 |
| v2.2.2 | 2018-07-05 | 支持超过128字节的用户自定义域 | 郑超 |
| v2.2.1 | 2018-05-25 | 更新Redis配置加载接口的事务机制。 | 郑超 |
| v2.1.2 | 2018-03-24 | 增加概述 | 郑超 |
| v2.1.1 | 2018-02-08 | 1、 maat_redis_tool支持写入json格式的配置到redis。 2、 增加Maat_read_state函数的使用说明。 | 郑超 |
| v2.1.0 | 2017-10-04 | 提供maat_redis_tool可以dump出redis中的maat配置。 | 郑超 |
| v2.0.1 | 2017-08-22 | 支持配置延迟初始化 | 郑超 |
| v2.0.0 | 2017-08-01 | 1. 支持从Redis加载配置 2. 提供配置增删函数接口即Maat Command API 3. 支持相似性字符串匹配; 4. 提供辅助工具digest_gen具备SFH摘要计算、编辑距离计算功能 | 郑超 |
| v1.9.1 | 2017-06-24 | 可以提示MAAT组合扫描中最后一个域可以提升与表达式运算性能。 | 郑超 |
| v1.9.0 | 2017-06-09 | 支持对个别配置表进行加密 | 郑超 |
| v1.8.4 | 2017-03-12 | 调整SNORT规则转换的目录结构 | 郑超 |
| v1.8.3 | 2016-12-30 | 1、增加设置实例名的功能2、更新运行状态数据说明。 | 郑超 |
| v1.8.2 | 2016-9-19 | JSON输入模式支持未命名分组可将group_name配置为"Untitled"以表示非分组复用由Maat自动生成group_id。 | 郑超 |
| v1.8.1 | 2016-9-14 | 在IP类域配置表中增加多层嵌套IP匹配的指导方案。 | 郑超 |
| v1.8.0 | 2016-09-02 | 增加配置表连接功能的说明 | 郑超 |
| v1.7.1 | 2016-06-17 | 1. 通过转义方式,支持空格作为关键字; 2. 增加快速字符串扫描开关; | 郑超 |
| v1.7.0 | 2016-04-03 | 单独设小节描述编码转换增加UNICODE到ASCII转码功能的说明 | 郑超 |
| v1.6.1 | 2016-03-24 | 完善配置分组表的字段说明。 | 郑超 |
| v1.6.0 | 2016-02-11 | 1. 增加状态统计和性能统计描述,以及相应的函数接口调整; 2. 增加扩展的字符串类域配置的函数接口描述。 | 郑超 |
| v1.5.0 | 2016-01-05 | 增加扩展的字符串类域配置完善IP类域配置关于IPv6掩码的描述。 | 郑超 |
| v1.4.4 | 2015-12-24 | 修改回调表的配置更新机制,以节约内存。 | 郑超 |
| v1.4.3 | 2015-12-02 | 完善数据库表间关系的描述,丰富界面设计要点。 | 郑超 |
| v1.4.2 | 2015-12-01 | 合并配置更新文件接口一章 | 郑超 |
| v1.4.1 | 2015-11-23 | 完善摘要类配置的说明 | 郑超 |
| v1.4.0 | 2015-11-06 | 增加文件摘要类域配置 | 郑超 |
| v1.3.9 | 2015-07-24 | 提供Maat_set_feather_opt接口Maat_20150724版本以上支持该功能。 | 郑超 |
| v1.3.8 | 2015-07-06 | 润色概述中对三类配置的说明,增加编码转换句柄复用的说明。 | 郑超 |
| v1.3.7 | 2015-06-16 | 增加常见故障处理的建议。 | 郑超 |
| v1.3.6 | 2015-06-10 | 1. 字符串域表增加相对位置的表达式类型; 2. 配置分组表支持非; 测试分支,暂不合并到主版本。 | 郑超 |
| v1.3.5 | 2015-06-08 | 添加数据库表描述示例 | 郑超 |
| v1.3.4 | 2015-05-22 | 可通过JSON加载回调类配置表 | 郑超 |
| v1.3.3 | 2015-05-13 | 增加对非组合域编译的快速处理路径,增加对命中结果返回条件的说明 | 郑超 |
| v1.3.2 | 2015-04-13 | 扫描空配置的返回值由-1改为0 | 郑超 |
| v1.3.1 | 2015-03-02 | 对于GBK到BIG5的转码将源编码改为GB2312 | 郑超 |
| v1.3 | 2015-02-20 | 增加JSON配置加载功能 | 郑超 |
| v1.2.2 | 2015-01-06 | 增加强制卸载机制 | 郑超 |
| v1.2.1 | 2015-01-05 | 扩展字符串类域配置的hexbin字段的定义 | 郑超 |
| v1.2.0 | 2014-12-20 | 增加配置更新机制的描述 | 郑超 |
| v1.1.0 | 2014-12-12 | 增加函数接口的说明,修改引用计数避免伪共享 | 郑超 |
| v1.0.3 | 2014-12-03 | 采用垃圾回收机制保证线程安全 | 郑超 |
| v1.0.2 | 2014-11-26 | 支持正则分组 | 郑超 |
| v1.0.1 | 2014-11-19 | IP类配置支持协议扫描 | 郑超 |
| v1.0 | 2014-08-19 | 第一个稳定版 | 郑超 |
| v0.1 | 2014-06-16 | 创建文档,包含表格式说明 | 郑超 |

BIN
docs/imgs/CNF.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
docs/imgs/exclude.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
docs/imgs/hitpath.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
docs/imgs/sub-exclude.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

101
docs/introduction.md Normal file
View File

@@ -0,0 +1,101 @@
# 概念
Item对网络属性的过滤条件某一字段的配置
- 例1指定HTTP协议中UserAgent包含子串“Chrome”和“11.8.1”
- 例2指定HTTP协议中域名以“.emodao.com”结尾
- 例3指定客户端IP地址属于202.118.101.*这个C段
- 例4指定HTTP协议中传输的文件摘要为” FsOmaK3utZafWYt/i[7203:46299992]”
Item的类型包括字符串过滤条件如关键词、正则表达式、IP过滤条件掩码、CIDR、范围、数值区间和内容摘要Stream Fuzzy Hash
分组配置Group又称Object是Item的集合
- 一个Item属于一个Group同一Group中的多个Item是“或”的关系
- 一个Group可以被其它Group包含Include或排除Exclude
- Group支持多层嵌套
- 一个Group可以被多个Compile引用
编译配置是由多个Group和虚拟表组成的合取范式
- 合取范式可以包含最多8个子句Clause同一个编译中的多个子句之间可以是“与”和“非”运算。
- 一个子句包含若干个LiteralLiteral虚拟表可选和Group组成之间是“或”运算。在配置加载过程中会按照同一个子句中的虚拟表+分组ID的组合生成唯一的Clause IDClause ID不会被不同的组合重用。
- 例如对于同时符合上面例1、例2、例3的访问进行重定向操作重定向策略ID=31(重定向地址为www.baidu.com黑名单5分钟),记录日志
![CNF](./imgs/CNF.jpg)
## Group/Object Nesting and Hierarchies
The objects and items are compared in the rule evaluation with **OR** operator. If a traffic attribute satisfies an item, the object it belongs to is satisfied.
### Exclude
An object defines a subset of an object type, such as network addresses or port numbers. The definition is made using items, which can be used to add to or exclude from the object definition. Objects can also have subordinate objects whose definitions are included in the superior object.
There are rules of precedence to take into account when defining objects:
- Excluding has precedence over including in the same object.
- Items in a superior object have precedence over items in a subordinate object.
- Items in a superior object are not taken into account in a subordinate object, if the subordinate object is used directly in a rule.
- Peer objects (different subordinate objects of the same superior object) do not affect each other.
In short, to determine the set defined by an object, perform the following calculation:
1. For each subordinate object (remember sibling objects do not affect each other):
1. Add included items.
2. Subtract excluded items.
2. Add included items in the object itself, overriding any excludes in the subordinate objects.
3. Subtract excluded items in the object itself.
The following figure shows an object with an included set and an excluded subset.
![exclude](./imgs/exclude.png)
Now, consider adding a subordinate object. The subordinate object also has an included set and an excluded subset. If the superior object is used, the result is shown in the following figure “A superior and subordinate object”.
![A superior and subordinate object](./imgs/hierarchy-and-exclude.png)
As can be seen, the excluded item in the subordinate object is overwritten since it is in the included set of the superior object. Also, the excluded item from the superior object excludes part of the included item in the subordinate.
If only the subordinate object is used in a rule condition, the superior object items are disregarded, leaving the set shown in the next figure, “The subordinate object”.
![The subordinate object](./imgs/sub-exclude.png)
Restrictions:
- An object can only include or exclude objects of the same type.
- An object should include at least one subordinate object. (Exclude only is not allowed)
- Traffic attribute using stream scan cannot allow use object with exclude, i.e., keywords object on HTTP Response Body, Email attachment.
Now, let's see a graph of hierarchy example, where the dotted line means exclude. The matched subordinate objects and activated superiors are listed in the following table.
![object-hierarchy-example](./imgs/object-hierarchy-example.png)
| **Matched subordinate objects** | **Activated superior Objects** |
| ------------------------------- | ------------------------------ |
| g1, g3 | g6, g9 |
| g3, g4 | none |
| g5 | g8, g10, g13 |
| g2, g3 | g9 |
| g3, g5 | none |
| g8, g11 | g10, g12 |
| g4, g11 | g7, g8, g9 |
| g1, g2 | g9 |
## 定义
| **名词** | **解释** |
| --------------------------- | ------------------------------------------------------------ |
| Instance | MAAT的句柄 |
| Item | 针对一个数据中某一域的配置如HTTP协议中的URL、DNS协议的IP地址等。 |
| Group/Object | 一条或多条域配置的集合,分组内的域配置之间是或的关系。 |
| Compile (编译配置) | 描述通过一条或多条分组配置“与”“非”运算,所执行的业务规则。 |
| Table配置表 | 在数据库表文件和规则扫描之间的抽象层,既可以是存储域配置、分组配置、编译配置的实体表,也可以是实体表的组合、虚拟和连接。 |
| Table Schema (配置表模式) | 定义配置表中存放的配置类型和字段格式 |
| Table Runtime | |
| Maat State | 用于记录扫描多个多流量属性的中间状态 |
| Maat Stream | 用于流式文本扫描的句柄 |
| Hit Path命中路径 | 从待扫描数据的角度描述其域ID->子分组ID->顶级分组ID含虚拟表名->编译配置的ID序列称为命中路径。 |
| Redis | 内存数据库参见https://redis.io/ ,通过其主从备份机制实现配置的多级同步。 |

112
docs/scan_api.md Normal file
View File

@@ -0,0 +1,112 @@
# Scan API
## 最大返回结果限制
多命中情况下按包含分组数由多到少返回分组数相同时按编译配置ID由大到小的顺序返回。
多命中扫描的最大命中次数受MAX_SCANNER_HIT_NUM宏控制当前为64条。
如果命中条数超出64则按照配置在IRIS库表文件出现的顺序返回。
## 流式跨包扫描
在配置表描述文件中如果指定某个字符串类域表设置的跨包缓存值且该值大于0则在为该表开启流式跨包扫描功能。
进行流式扫描中会对输入数据结束后缓存该值大小内容以便下次扫描时进行拼接。会增加一次内存拷贝并且该拷贝内存在下次扫描时复用。由此决定了下文中Maat_hit_detail_t结构体中命中位置指针的生存周期。
为了避免流式跨包扫描对带偏移量的字符串匹配的功能的干扰,流式扫描结构体中包含了一个当前已扫描长度的变量,用以显示表识输入数据的绝对偏移量。
## 结果缓存复用
另外为了提高系统的性能为每个scanner分配了一个region_rslt_buff用以缓存域扫描命中的中间结果。通过malloc分配长度为sizeof(scan_result_t)*MAX_SCANNER_HIT_NUM*scan_thread_num当外部调用扫描时根据thread_num参数分配region_rslt_buff+MAX_SCANNER_HIT_NUM*thread_num供当前线程保存域中间扫描结果。
### 命中结果返回条件
Maat_xx_scan函数输入的数据命中了某个域配置且满足某一编译配置就会返回该编译配置ID无论该编译配置是否已在之前扫描中命中。
### 命中结果执行顺序
多命中情况下,编译配置的按照如下顺序返回:
1. 两条编译配置的执行序号exec_seq都不为0执行序号较小的在前
2. 执行序号相同或者有任意一条编译配置的执行序号为0时依次按照以下顺序返回
1. 分组数量较多的在前
2. 编译配置ID较大的在前
## 命中路径
从待扫描数据的角度描述其域ID->子分组ID->顶级分组ID含虚拟表名->编译配置的ID序列称为命中路径。
一个待扫描数据在以下情况下有多个命中路径:
- 多规则命中输入同时命中多个region ID。如
- 输入URL: abc.com/index.html规则r1=”abc”r2=”index.html”输入有两个分别以r1和r2为起点的命中路径。
- 分组复用
- 分组间“与”运算
策略的结构是从compile到item的自顶向下而命中路径是从最底层的item到顶层的compile是自底向上的。它将网状和层次结构的object-policy图进行扁平化转换为图论中的路径。例如有如下策略
- 字符串object1包含 item1="abc"
- 字符串object2包含item2=".com"
- 字符串object3包含object2
- IP object4包含item3=192.168.0.1/24
- IP object5包含object4
- IP object6包含object5
- rule1=object1 & object6
- rule2=object1
输入url=abc.comua=chrome80IP=192.168.0.1的命中路径为
| 输入 | Region ID | Sub Group ID | Top Group ID | Virutal Table | Rule ID |
| ----------- | --------- | ----------------------- | ------------ | ------------- | ------- |
| abc.com | item1 | object1 | object1 | HTTP_URL | Rule1 |
| item2 | object2 | N/A因为没有最终命中 | N/A | N/A | |
| item1 | object1 | object1 | HTTP_URL | Rule2 | |
| 192.168.0.1 | item3 | object4 | object6 | IP | Rule2 |
| chrome80 | N/A | N/A | N/A | N/A | N/A |
命中关系还是一张图,采用邻接矩阵存储,而命中路径是邻接矩阵中的一行。
![Hit Path as a Graph](./imgs/hitpath.png)
## 组合扫描
同一网络传输单元的多个属性的扫描是通过scan_status* mid实现的其中缓存了已命中的子句id该ID在增量更新中不重用。
在一个mid的生存期内配置组合关系变化产生新的bool matcher。
- 如果是增量更新缓存的子句id会和新的bool matcher进行运算。由于子句ID在增量更新中不变化不会产生误命中。
- 如果是全量更新缓存的子句id不会和新的bool matcher进行运算。
## 常见故障处理
### 初始化失败
当出现Maat初始化失败、扫描不命中时首先查看Maat生成的日志文件FATAL级别的日志都会导致Maat不能正确加载、扫描配置。
日志提示“config file xxx,not full or inc config”请确认Maat_ feather/Maat_summon_feather/Maat_summon_feather_json初始化时传入的两个路径是否正确注意路径为IRIS配置线写入的index路径例如/home/ config/dest/index/,而不是/home /config/dest/。
该日志文件由Maat_summon_feather函数调用时传递的日志句柄所生成需要注意的是该句柄的日志级别过高会导致”INFO”级日志不可见。
### 扫描出现段错误
确认扫描传入的maat_state* state已在调用前创建。
确认输入的待扫描内容的内存可访问,长度参数正确。
### 扫描不命中
扫描不命中,首先查看初始化日志,判断加载的配置是否是你期待的路径。
然后判断配置加载是否有FATAL级别的错误日志。
接下来确认扫描时传入的table_id与期待的表名是否正确对应避免出现用表A的配置扫描表B的字段。
对于字符串扫描charset参数传递正确且包含在配置表描述文件通常为table_info.conf的”目的编码”中。如果不能确定可以暂时修改配置表描述文件中的do_merge列为”yes”。
在使用带有命中细节的函数扫描时一般detail_num应与rule_num相等。
IRIS文件模式下如待命中配置在增量索引中需要等待延迟加载日志中Postpone xx entries完成。调试时可将MAAT_OPT_SCANDIR_INTERVAL_MS 和MAAT_OPT_EFFECT_INVERVAL_MS设置为20毫秒。
另外JSON调试只能支持分组的模式下工作需要在配置表描述文件table_info.conf中增加分组表否则可能导致误命中或不命中。

486
docs/table_data.md Normal file
View File

@@ -0,0 +1,486 @@
# Table Data
输入必须使用UTF-8 without BOM编码例如MySQL使用utf8mb4而不是utf8参考永远不要在MySQL中使用UTF8编码
## 行列式文件格式IRIS
在Maat可以监听全量和增量目录下的文件来更新配置运行时变化下面对这种模式下的文件格式进行介绍。
配置是由一个索引文件和若干配置数据文件组成的。索引文件通过索引文件命名标识不同版本。
### 索引文件命名
全量索引文件名的格式为full_config_index.SEQ如full_config_index. 00000000000000055410增量索引文件名的格式为inc_config_index.SEQ分别存放在全量索引约定目录和增量索引约定目录下。
其中SEQ为配置线维护的自增序列,该序列保证:
1 当两个索引约定目录不为空时,新生成的索引文件比后生成的索引文件序号大;(建议使用数据库内的配置版本号或通过写入本地磁盘以保证一致性)
2 同一次下发产生全量索引文件与增量索引文件的的序列号相同;
3 序列号的格式为20位数字不满20位时用0补位取值范围不超过C语言中有符号长整型long long的上下界即0~2^63-1。
### 索引文件格式
如下表所示。列间以\t分割行间以\n分割。配置数据文件路径为绝对路径。
表 24索引文件格式/示例表
| **列名** | **table name** | **Config num** | **Table file path** | 加密算法(可为空) |
| -------- | -------------- | -------------- | ---------------------------------------------- | ---------------- |
| **示例** | PASS_WHITE_IP | 3 | /home/config/full/2014-04-24/PASS_WHITE_IP.123 | |
| | PASS_URL | 2 | /home/config/full/2014-04-24/PASS_URL.123 | aes-128-cbc |
### 配置数据文件格式
如下所示。列间用\t分割行之间用\n分割。首行为当前数据文件中包含的配置总数此值应以索引文件中对应的config_num一致。
表 25配置数据文件格式示例
```
3
45695 2 202.108.181.33 255.255.255.255 0 1
48697 2 202.108.181.33 255.255.255.255 0 1
66699 2 202.108.181.33 255.255.255.255 0 1
```
### 手工修改IRIS配置
通常**不建议**直接手工修改IRIS配置调试应使用JSON模式。
增加库表需要修改以下文件:
1. 在库表文件索引中增加新的库表路径及条目数
2. 在库表描述文件table_info.conf中增加库表的信息
3. 修改配置汇总表,使新增加配置生效,注意要保证第一行配置总数与实际的配置行数一致
手工增加已有库表配置需要修改以下文件
1. 在需要修改的库表文件中追加行region_id不能与已有所有域表中的冲突并修改文件第一行的行数
2. 在配置汇总表中增加该配置的汇总信息注意要和库表文件中的compile_id一致且不能与已有compile_id冲突修改文件第一行的行数
3. 在库表索引文件中修改配置汇总表和域表的行数
## Redis配置加载接口
Maat可以通过Redis的主从同步机制实现配置的分发。本节介绍MAAT加载Redis中配置时对存储结构的要求。和数据库一样Redis存储结构的设计上不需要考虑编译、分组和域的逻辑层次。由配置更新线程通过行列式配置重构各层次间的组合关系。
![Sync Rule with Redis](./imgs/data-sync-with-redis.png)
### Transactional Write
表 26 MAAT Redis中定义的数据结构
| Redis KEY | 名称 | 结构 | 用途 |
| ------------------------------------------------------- | ---------------- | ----------------------------------------------------------- | ------------------------------------------------------------ |
| MAAT_VERSION | 主版本号 | INTERGER | 标识Redis中配置的版本号。当redis中版本号大于MAAT中配置版本号时会去读取MAAT_UPDATE_STATUS。 |
| MAAT_PRE_VERSION | 预备版本号 | INTERGER | |
| MAAT_TRANSACTION_xx | 事务配置状态 | LIST | 用于临时存储事务中的配置状态xx为MAAT_PRE_VERSION其中的状态在事务结束后会被更新到MAAT_UPDATE_STATUS本身被删除。 |
| MAAT_UPDATE_STATUS | 配置状态 | sorted set, member是配置规则score 为版本号详见11.3 | MAAT会用ZRANGEBYSCORE命令读取。 |
| MAAT_RULE_TIMER | 主配置超时信息 | sorted set, member是配置规则score为超时间详见11.4 | MAAT配置更新线程会定时检查超时状况并设置超时状态。 |
| MAAT_VERSION_TIMER | 版本创建时间 | sorted Set | 存储了每个版本的创建时间score为版本创建时间member 为version用以将MAAT_UPDATE_STATUS维持在一个较小的规模。 |
| MAAT_LABEL_INDEX | 标签索引 | sorted set, element 是配置表名编译配置IDscore为label_id | |
| EFFECTIVE_RULE:TableName,ID OBSOLETE_RULE:TableName,ID | 主配置 | string | 生效中的配置结构与10.3中的行结构相同MAAT会逐条加载。 |
| SEQUENCE_ REGION | 域ID生成序列号 | INTERGER | 用于生产者生成不重复的region_id |
| SEQUENCE_ GROUP | 分组ID生成序列号 | INTERGER | 用于生产者生成不重复的group_id |
| EXPIRE_OP_LOCK | 分布式锁 | 字符串”locked” | 用于保证最多只有一个写者进行淘汰。 |
源码中reset_redis4maat.sh工具或Maat_cmd_flushDB函数可以对redis进行初始化。
#### 主版本号、预备版本号与Lua Script
生产者写入配置时先对预备版本号加1并作为写入配置状态的score待写入完成后再对主版本号加1。放弃WATCH MAAT_VERSION的事务。这一方法可以大幅提高写入性能除ID冲突外可确保写入成功。
当有多个生产者时可能存在配置状态与主版本号不一致的问题。主版本号为v某次更新时在配置状态中声明的版本号为u消费者增量更新时有以下情况
- 若v=u则版本号一致配置正常加载
- 若v>u该情况不存在。因为只有配置状态修改完成主版本号才会增加1。换句话说每次写入都是先增加预备版本号后增加主版本号所以主版本号必然小于或等于配置状态中的最大版本号。
- 错误:三个生产者情况下,有问题,如下表。
- 若v<u说明两个生产者中先启动写入的并没有先完成此时本次只更新到版本v留待下次轮询再更新至u
消费者全量更新时不看配置状态直接读取全部有效配置因为配置写入和主版本号增加1在同一个事务中执行读取到的全量配置版本必定与主版本一致
有多个生产者的情况下可能丢失配置更新消息状态
| **Time** | **Producer1** | **Producer2** | **Producer3** | **consmuer** |
| -------- | ------------------------ | ------------------------ | ------------------------ | ----------------------------------------------- |
| **0** | 准备更新mv=3924, tv=3925 | | | |
| **1** | | 准备更新mv=3924, tv=3926 | | |
| **2** | | | 准备更新mv=3924, tv=3927 | |
| **3** | | | 更新完毕mv=3925, tv=3927 | Get version 3925, zrangebyscore拿不到3925的状态 |
| **4** | | 更新完毕mv=3926, tv=3926 | | Maat版本号升到3926报错:noncontigous |
| **5** | 更新完毕mv=3927, tv=3925 | | | 3925被跳过 |
在事务结束部分采用lua script检查事务版本号transaction_version与主版本号maat_version
- tv==mv无需修正
- tv>mv本次更新的增量将在下一次
- tv<mv如何识别本次事务写入配置状态的规则呢然后才能将其score改为mv
为了解决事物结束时transaction version<maat_version的问题使用redis list MAAT_TRANSACTION_xx存储配置更新状态xx取自MAAT_PRE_VERSION事务结束时再用lua script同步MAAT_UPDATE_STATUS并删除MAAT_TRANSACTION_xx
![Add and Delete Operation](./imgs/add-del-rule-with-redis.png)
#### MAAT_UPDATE_STATUS
该结构中使用Sorted Set存储了主配置的变化状态score为版本号member为配置状态member的02字节描述了更新指令
1. ADD即配置增加结构为ADD,TableName,ID
2. DEL即配置删除结构为DEL,TableName,ID
MAAT在发现MAAT_VERSION变化后会用ZRANGEBYSCORE读取更新的配置状态按VERSION升序并检测第一个配置的Score如该Score>Maat版本+1则说明有遗漏的更新网络长时间中断启用全量更新流程。
对于DEL状态如果查询不到对应的主配置状态同样说明有遗漏更新网络中断时间超过OBSOLETE_RULE超时时间启用全量更新流程。
#### MAAT_EXPIRE_TIMER
该结构使用Sorted Set存储了主配置的超时信息score为绝对超时时间member的结构为TableName,ID。
删除配置时exec_serial_rule会关联删除该索引。
#### MAAT_VERSION_TIMER
该结构使用Sorted Set存储了每个版本的创建时间score为版本创建时间member为 版本号version即MAAT_UPDATE_STATUS的score用以将MAAT_UPDATE_STATUS维持在一个较小的规模。
#### 主配置结构
有两类配置命名方式:
1. EFFECTIVE_RULE:TableName,ID 表示正在生效的配置;
2. OBSOLETE_RULE:TableName,ID 表示已经删除的配置这些配置超时EXPIRE后会被Redis删除。
### Load From Redis
Maat实例的工作线程定时轮询Redis中MAAT_VERSION如果大于实例的MAAT_VERSION则进行更新。
![Load from Redis](./imgs/load-data-from-redis.png)
### 读写性能
为保证事物Redis需工作在单机+主从模式。带超时的配置写入5000条/秒无超时配置10000条/秒。
## JSON配置加载接口
使用Maat_summon_feather_jsonMaat_set_feather_opt函数通过选项MAAT_OPT_JSON_FILE_PATH设置进行JSON格式配置的加载。Maat在初始化后一旦检测到文件MD5值的变化则以全量更新的方式加载变化的json文件。
采用JSON文件进行描述纯文本可以使用JSON Viewer进行编辑和格式检查。
```json
{ //JSON语法不支持注释直接将以下内容拷贝后应删除注释后才符合JSON语法
//规定内容区分大小写,不可混用
"compile_table": "COMPILE",//编译表表名优先级高于配置表描述中的compile表
"group_table": "GROUP",//分组表表名优先级高于配置表描述中的group表
"rules": [
{
"compile_id": 123, //编译配置ID数值注意不要重复
"service": 1, //32位有符号整数
"action": 1, //8位有符号整数
"do_blacklist": 1, //8位有符号整数
"do_log": 1, //8位有符号整数
"effective_range": 0, //生效范围置0已被配置生效标签取代
"tags":"{\"tag_sets\":[[{\"tag\":\"location\",\"value\":[\"北京/朝阳/华严北里\",\"上海/浦东/陆家嘴\"]},{\"tag\":\"isp\",\"value\":[\"电信\",\"联通\"]}],[{\"tag\":\"location\",\"value\":[\"北京\"]},{\"tag\":\"isp\",\"value\":[\"联通\"]}]]}",
//tags为配置生效标签
"user_region": "anything",//用户自定义域不超过128字节的字符串不可//包含空格或制表符
"is_valid": "yes",//有效标志有效”yes”无效”no”
"evaluation_order": "100.2",//执行顺序,双精度浮点数,为了便于转换,用//字符串形式
"table_name": "COMPILE_ALIAS", //编译配置表名,可选,
//默认使用compile_table
"groups": [ //接下来描述配置包含的分组
{
"group_name": "IP_group",//分组名,用于辅助记忆,注意不要重复
//重复分组名表示分组内容复用。
//可以使用”Untitled”作为分组名表示无需 //复用此时由Maat自动生成group_id。
//无group_name时视为”Untitled” 。
"not_flag":0, //非运算标志位1表示不能包含该分组默认为0
“virtual_table”:”HTTP_RESPONSE_KEYWORDS”, //虚拟表名,可选
"regions": [ //对分组内配置域的描述
{
"table_name": "IP_CONFIG", //域表表名和类型,应与配置表
//描述文件一致
"table_type": "ip",//类型包括 ip, string, intval 三种
"table_content": {//以下是ip类配置表的格式
"addr_type": "ipv4",//地址类型可选ipv4和ipv6
"src_ip": "10.0.6.201",
"mask_src_ip": "255.255.255.255",
"src_port": "0",
"mask_src_port": "65535",
"dst_ip": "0.0.0.0",
"mask_dst_ip": "255.255.255.255",
"dst_port": "0",
"mask_dst_port": "65535",
"protocol": 6,
"direction": "double"//扫描方向single或double
}
},
{
"table_name": "IP_CONFIG",
"table_type": "ip",
"table_content": {
"addr_type": "ipv4",
"src_ip": "192.168.0.1",
"mask_src_ip": "255.255.255.255",
"src_port": "0",
"mask_src_port": "65535",
"dst_ip": "0.0.0.0",
"mask_dst_ip": "255.255.255.255",
"dst_port": "0",
"mask_dst_port": "65535",
"protocol": 6,
"direction": "double"
}
}
]
},
{
"group_name": "Untitled",//用”Untitled”作为分组名表示不需 //要复用
"regions": [
{
"table_name": "HTTP_URL",
"table_type": "string",
"table_content": {
"keywords": "abc&123",//格式遵循字符串类与配置一
//节的约定,”\”需要写作”\\”
"expr_type": "and",//表达式类型包括none, and,
// regex, offset
"match_method": "sub",//匹配模式,包括sub, right,
//left, complete
"format": "uncase plain"//格式类型包括uncase plain,
// hexbin, case plain
}
}
]
}
]
},
{
"compile_id": 124,
"service": 1,
"action": 1,
"do_blacklist": 1,
"do_log": 1,
"effective_range": 0,
"user_region": "anything",
"is_valid": "yes",
"groups": [
{
"group_name": "IP_group"//复用上一条编译配置的分组,仅列名字,
//重复分组名的域配置不会生效
},
{
"group_name": "Untitled",//Untitled表示该分组不会被复用
"regions": [
{
"table_name": "CONTENT_SIZE",
"table_type": "intval",
"table_content": {
"low_boundary": 100, //上下界的约定参照数值类域配
"up_boundary": 500 //置表定义
}
}
]
}
]
},
{
"compile_id": 125,
"service": 1,
"action": 1,
"do_blacklist": 1,
"do_log": 1,
"effective_range": 0,
"user_region": "anything",
"is_valid": "yes",
"groups": [
{
"group_name": "group_4",
"regions": [
{
"table_name": " TARGET_FILE_DIGEST ",
"table_type": "digest",
"table_content": {
" raw_len ": 20436318, //文件的原始长度
"digest": "VY2DfSUuQ5xkNQTnCN8iwd0VM5h3WVOunA/Jk87S3kfpukO84AL1qvmq2brnBt9sPvrfeaRip9Y+VhuEk0Sy4dvdKtk8DdSFOa7ZM[0:20436317]", //通过digest_gen工具生成的摘要
"cfds_level": 3 //摘要匹配置信度
}
}
]
}
]
},
{
"compile_id": 128,
"service": 1,
"action": 1,
"do_blacklist": 1,
"do_log": 1,
"effective_range": 0,
"user_region": "anything",
"is_valid": "yes",
"groups": [
{
"group_name": "group_8",
"regions": [
{
"table_name": "HTTP_REGION",
"table_type": "expr_plus", //扩展的字符串表
"table_content": {
"district": "URL", //keywords的匹配区域大小写敏感
"keywords": "abckkk&123",
"expr_type": "and",
"match_method": "sub",
"format": "uncase plain"
}
}
]
}
]
}
],
"plugin_table":[ //回调表,可不配置
{
"table_name":"QD_ENTRY_INFO",
"table_content":[
"1\t192.168.0.1\t101",//回调表行使用Tab键或\t分隔
"2\t192.168.0.2\t101",
"3\t192.168.1.1\t102" ]
},
{
"table_name":"TEST_PLUGIN_TABLE",
"table_content":[
"1\t3388\t99\t1",
"2\t3355\t66\t1",
"3\tcccc\t11\t1"
]
}
]
}
```
## 组合配置写入示例
已知IP类域配置表IP_TABLE、关键字类配置表KEYWORD、编译配置表COMPILE、分组表GROUP。
GRP为group_id的数据库sequenceREGION为region_id的数据库sequenceCOMPLIE为compile_id的数据库sequence
先要求写入规则(IP_TABLE:192.168.0.1|IP_TABLE:192.168.0.2)&(KEYWORD:abc)
写入顺序如下:
1、 从数据库中取 group_id1=GRP.next, region_id1=REGION.next, compile_id1=COMPILE.next;
2、 将"group_id1,compile_id1,1"写入GROUP表;
3、 将"group_id1,region_id1,abc"写入KEYWORD表;
4、 从数据库中取 group_id2=GRP.next
5、 将"group_id2,compile_id1,1"写入GROUP表;
6、 对于IP地址192.168.0.1从数据库获取region_id2=REGION.next
7、 将"group_id2,region_id2,192.168.0.1"写入IP_TABLE表
8、 对于IP地址192.168.0.2,从数据库中取 region_id3=REGION.next
9、 将"group_id2,region_id3,192.168.0.2"写入IP_TABLE表
10、 将"compile_id1,group_num=2"写入COMPILE表
此时各个表中的记录如下:
```
COMPILE表
c1,2;
GROUP表:
g1,c1
g2,c1
KEYWORD表:
g1,r1,abc
IP_TABLE表:
g2,r2,192.168.0.1
g2,r3,192.168.0.2
```
新增一个关键字"edf"也要使用IP组g2则增加三条记录
COMPILE:
c2;
GROUP:
g3,c2
g2,c2
KEYWORD:
g3,r5,edf
则当前库表记录状态为
```
COMPILE表
c1,2;
c2,2;
GROUP表:
g1,c1
g2,c1
g3,c2
g2,c2
KEYWORD表:
g1,r1,abc
g3,r5,edf
IP_TABLE表:
g2,r3,192.168.0.2
g2,r4,192.168.0.3
```
新增IP
- 如果用户在group_id2分组中增加IP则从数据库中取 region_id4=REGION.next将"group_id2,region_id4,192.168.0.3"写入KEYWORD表即可
删除IP
- 如果用户要删除group_id2分组中的IP192.168.0.1则将IP_TABLE表中g2,r2,192.168.0.1 该条记录置为失效
## 配置更新机制
### 最短加载间隔
Maat的配置管理线程会针对增量索引文件目录进行扫描在初始化后每隔1s默认扫描增量配置目录。同时为了避免自动机频繁更新耗尽内存自动机最短每隔60s默认创建一次如果两次**增量**配置更新间隔小于60s则会累积在更新队列中直到与上次更新自动机间隔60s才会批量加载。全量配置和回调类配置更新不受最短加载时间的限制。
文件扫描间隔和配置生效间隔可以通过Maat_set_feather_opt设置详见本文档“函数接口”一章。
### 引用计数
引用计数机制为了避免多个变量多线程读写因Cache一致性和伪共享问题导致速度降低采用为每个线程分配64字节对齐的引用计数变量。
### 延迟删除机制
Maat使用延时删除机制在不使用锁的前提下保证线程安全。
即配置管理线程在更新操作中:
a) 需要删除group_rule、compile_rule时将他们放入垃圾回收队列待超时后默认10后再进行释放。
b) 需要读取时,直接访问;
c) 需要修改时获得mutex后访问
扫描线程中:
a) 需要读取时获得mutex后访问
### 强制卸载机制
rulescan内部使用引用计数方式管理待删除的自动机其引用计数的加减周期是一次扫描函数的调用而不是一次流式扫描。满足MAAT实现强制卸载机制的条件。
所谓强制卸载机制,是指在一次流式扫描过程中,配置发生更新后,强制卸载该次扫描所引用的自动机,回收所占用内存。后续引用旧自动机的流式字符串扫描将不做任何命中,直接返回。
由于组合扫描为对MAAT的扫描器进行引用计数替换前后各自使用当前的bool matcher进行规则组合运算不受此影响。

288
docs/table_schema.md Normal file
View File

@@ -0,0 +1,288 @@
# Table Schema
自Maat 4.0Item ID、Group ID、Compile ID的取值范围为02^63即C语言long long类型。
## Item Table Schema
每个Item表必须包含
- Item ID唯一标识一个Item。在一个Maat实例中不同表的Item ID不得重复。
- Group ID表明该Item所属的Group一个Item属于且仅属于一个Group。
- 有效标志字段1表示生效在增量更新中表示添加0表示失效在增量更新中表示删除。
不同类型的表还根据各自需要定义了不同的字段。
### 字符串类域配置(含扩展后的)
用以描述针对字符串的匹配规则匹配类型由expr_type字段描述包括
- 非表达式匹配方式分为0子串匹配1右匹配2左匹配3完全匹配
- 与表达式最多支持8个子串或正则的与。
- 正则表达式
- 带偏移量的子串匹配,即规定某个字符串出现在某个位置的规则
- 偏移量从0开始计算为[offset_start, offset_end]的闭区间。
- 多个带偏移量的子串可以与
Maat4.0后仅支持UTF-8不再进行编码转换。对于二进制格式的配置其关键字格式为十六进制字符串例如“欢乐”表示成“bbb6c0d6”字母不区分大小写。关键字的内容不能包含空格、tab、回车等不可见字符即不能包含ASCII范围0x00至0x1F及0x7F如需要包含这些字符需要进行转义参见“关键字转义表”。该表以外使用反斜线引导的符号按普通字符串处理\t将按照字符串”\t”处理。
&符号在是MAAT中与表达式的连接运算符号关键字中出现的&符号,必须使用’\&’进行转义。
表 2关键字转义表
| **字符名称** | ANSII码 | 转义后的符号 |
| ------------ | ------- | ------------ |
| 反斜线,’\ | 0x5c | \\ |
| & | 0x26 | \& |
| 空格 | 0x20 | \b |
长度约束:
- 单个子串不小于3字节
- 与表达式中的单个子串不小于3字节
- 与表达式最多支持8个子串进行与运算即7个&
- 与表达式整体不超过1024字节包括&
表 3字符串类表格式
| **名称** | **字段名称** | **类型** | **空值** | **约束** |
| --------------------------------------------- | ------------ | -------------- | -------- | ------------------------------------------------------------ |
| **配置****ID** | region_id | INT | N | 由同一config_id的不同域拆分而成**主键**各表不重复以下各表中region_id/group_id/compile_id取值均为02^31。 |
| **分组ID** | group_id | INT | N | 分组关系表中的group_id |
| **关键字** | keywords | VARCHAR2(1024) | N | expr_type:1,2,3时 keywords中&’为与运算操作符,子表达式中的’&’符号用’\&’转义。 expr_type:3时格式为 offset_s1-offset_e1:keyword1& offset_s2-offset_e2:keyword2 expr_type:4时格式为 <offset_s1,offset_e1><,>:keyword1&<offset_s2,offset_e2><distance,within>:keyword2 |
| **表达式类型** | expr_type | INT | N | 0:无表达式,1:表示为与表达式,2:正则表达式,3:带偏移量的子串匹配,4:带偏移量和相对位置的子串匹配(暂未支持) |
| **匹配方式** | match_method | INT | N | expr_type:0时有意义其它情况必须置0。 0子串匹配1右匹配2左匹配3完全匹配 |
| **是否****HEX****格式二进制,大小写敏感匹配** | is_hexbin | INT | N | 默认为0:大小写不敏感且非HEX 1:HEX格式二进制大小写敏感 2:大小写敏感且非HEX 二进制格式是一种特殊的编码受table_info.conf文件中do_merge控制 |
| **有效标志** | is_valid | INT | N | 0无效1有效 |
### IP类域配置含扩展后的
用以描述IP地址的匹配规则地址和端口都用字符串表示其中IPv4为点分十进制IPv6为冒号分隔的16进制。
表 4 IP类表格式
| **名称** | **字段名称** | **类型** | **空值** | **约束** |
| ------------------ | ------------- | ------------ | -------- | ------------------------------------------------------------ |
| **域配置****ID** | region_id | INT | N | 由配置汇总表中统一id的不同域拆分而成**主键**,各表不重复 |
| **分组ID** | group_id | INT | N | 分组关系表中的group_id |
| **地址类型** | addr_type | INT | N | Ipv4=4,ipv6=6 |
| **源IP****地址** | src_ip | VARCHAR2(40) | N | 0.0.0.0值表示任意 |
| **源IP****掩码** | mask_src_ip | VARCHAR2(40) | N | IPv4:255.255.255.255和0.0.0.0表示无掩码即精确IP匹配 IPv6ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 和::两个半角冒号表示无掩码即精确匹配。非0掩码值必须是2的指数幂下同 |
| **源端口** | src_port | VARCHAR2(6) | N | 0值表示任意 |
| **源端口掩码** | mask_src_port | VARCHAR2(6) | N | 65535表示无掩码即精确端口匹配0表示任意 |
| **目的IP** | dst_ip | VARCHAR2(40) | N | 0.0.0.0值表示任意 |
| **目的IP****掩码** | mask_dst_ip | VARCHAR2(40) | N | 同源IP掩码 |
| **目的端口** | dst_port | VARCHAR2(6) | N | 0值表示任意 |
| **目的端口掩码** | mask_dst_port | VARCHAR2(6) | N | 同源端口掩码 |
| **协议(tcp/udp)** | protocol | INT | N | 6表示TCP17表示UDP无限制默认为0。可自解释取值范围为0~65535。 对于多层嵌套地址的匹配需求如第二层为UDP协议的某个IPv4地址可以用protocol的高8位表示嵌套层数低八位表示协议类型. |
| **方向** | direction | INT | N | 0无方向双向1有方向单向 |
| **有效标志** | is_valid | INT | N | 0无效1有效 |
### 数值类域配置
用以判断数值是否位于某个区间。
表 6数值类表格式
| **名称** | **字段名称** | **类型** | **空值** | **约束** |
| ---------------- | ------------ | -------- | -------- | ---------------------------------------------------------- |
| **域配置****ID** | region_id | INT | N | 由配置汇总表中统一id的不同域拆分而成**主键**,各表不重复 |
| **分组ID** | group_id | INT | N | 分组关系表中的group_id |
| **数值下界** | low_boundary | INT | N | 数据区间的下界包含lb取值范围0~2^32-1 lb<=ub |
| **数值上界** | up_boundary | INT | N | 数据区间的上界包含ub取值范围0~2^32-1 |
| **有效标志** | is_valid | INT | N | 0无效1有效 |
### 文件摘要类域配置Todo
用以描述需要使用摘要进行比对的规则。摘要生成digest_gen工具参见xx节。
表 8摘要类表格式
| **名称** | **字段名称** | **类型** | **空值** | **约束** |
| ---------------- | ------------ | ------------- | -------- | ---------------------------------------------------------- |
| **域配置****ID** | region_id | INT | N | 由配置汇总表中统一id的不同域拆分而成**主键**,各表不重复 |
| **分组ID** | group_id | INT | N | 分组关系表中的group_id |
| **原始长度** | raw_len | NUMBER | N | 生成摘要的原始文件长度 |
| **文件摘要** | digest | VARCHAR(4000) | N | 使用专用工具生成的摘要字符串 |
| **匹配置信度** | cfds_level | INT | N | 匹配置信度110 |
| **有效标志** | is_valid | INT | N | 0无效1有效 |
### Group To Group Relation 分组关系表
描述分组与分组间的关系。
表 12分组关系表格式
| 名称 | 字段名称 | 类型 | 空值 | **约束** |
| ---------- | ----------------- | ----- | ---- | ------------------------------ |
| 分组ID | group_id | INT64 | N | 引用自各域配置表的group_id字段 |
| 上级分组ID | superior_group_id | INT64 | N | |
| 排除标志位 | is_exlude | Bool | N | |
| 有效标志 | is_valid | Bool | N | 0无效1有效 |
## Compile Group Relation 分组编译表
描述分组与编译之间的关系。
Maat 2.8后不再兼容无分组模式。
\0. 表 13配置分组表格式
| **名称** | **字段名称** | **类型** | **空值** | **约束** |
| ------------------ | ------------- | ------------- | -------- | ------------------------------------------------------------ |
| **分组****ID** | group_id | INT | N | 引用自各域配置表的group_id字段 |
| **编译配置ID** | compile_id | INT | N | 编译配置ID |
| **有效标志** | is_valid | INT | N | 0无效1有效 |
| **非运算标志位** | not_flag | INT | N | “非关系”分组标识01是。当parent是编译配置parent_id=0时有效。 |
| **分组所属虚拟表** | virtual_table | VARCHAR2(256) | N | 默认为”null”。 |
| **子句序号** | Nth_clause | INT | N | group所属的合取范式编译配置中子句的编号从0到7相同子句ID的group在分组中是“或”关系。 |
注意若该表中某group_id不包含有效的域配置时必须标记为无效否则会导致包含该分组的编译配置无法命中。
析取与合取:[https://baike.baidu.com/item/%E6%9E%90%E5%8F%96](https://baike.baidu.com/item/析取)
## Compile 配置编译
描述每一条具体策略的业务信息一个Maat示例下可以有多个不同名称的编译配置表。
表 14配置编译表格式
| **名称** | **字段名称** | **类型** | **空值** | **约束** |
| ----------------------------- | ---------------- | -------------------- | -------- | ------------------------------------------------------------ |
| **编译配置****ID** | compile_id | INT | N | 通常有数据库中的SEQ类型生成主键本表不重复被配置分组表引用 |
| **业务****ID** | service | INT | N | 如URL关键字业务User Agent业务等 |
| **动作** | action | VARCHAR(1) | N | 推荐定义:0:阻断1监测2白名单 应用可自解释 |
| **是否黑名单** | do_blacklist | VARCHAR(1) | N | 0:不需要1:需要 应用可自解释 |
| **是否生成日志** | do_log | VARCHAR(1) | N | 0:不需要1:需要默认为1 应用可自解释 |
| **生效范围****/****配置标签** | tags | VARCHAR2(1024) | N | 默认值为0表示无标签分区域下发参见本文档“配置生效标签”一节。 |
| **用户自定义域** | user_region | VARCHAR2(8192) | N | 默认值为0 应用可自解释 |
| **有效标志** | is_valid | INT | N | 0无效1有效 |
| **包含子句数量** | clause_num | INT | N | 包含不超过8个子句用以克服多个表中域配置或分组配置不能原子下发的问题 |
| **执行顺序** | evaluation_order | DOUBLE[[1\]](#_ftn1) | N | 默认值为0执行顺序在最后非0时执行顺序号越大执行顺序越靠后详见6.7 |
[[1\]](#_ftnref1) 使用双精度浮点数而不是整数表示执行顺序可以保证一条编译配置执行顺序的修改不会影响其它配置。例如有顺序执行的4条编译配置a、b、c、d将d的执行顺序调整到b之前修改d.exec_seq = (a.exec_seq + b.exec_seq) /2。配置生成侧可以周期性的重置exec_seq为顺序整数以减少小数点位数。
## Plugin 回调类配置
这类配置没有固定格式由业务自己定义用于非扫描类配置或不需要做统一扫描的配置。注册回调函数后配置更新时Maat负责在会将表ID和表行作为参数回调注册的方式有两种
1. 回调表注册函数Maat_table_callback_register支持注册最多8组回调函数出于节省内存的考虑只有第一个注册的回调函数能够得到全量配置后继注册函数无法得到第一次注册到本次注册之间更新的内容。
2. 回调表Extra Data注册函数Maat_plugin_EX_register仅支持注册1组回调函数。
### Plain Plugin
使用字符串做为Key的简单KV更新、查询。
### IP Plugin
类似回调类配置其Key为IP范围。
### FQDN Plugin
按照域名层级“.”扫描输入的字符串。
返回结果顺序:
1、按照命中规则的长度递减排序
2、相同长度的规则即重复的规则后插入的规则先返回因为实现时后插入的规则放在在哈希桶的前面
例如对于如下4条规则假设均为后缀匹配
1. example.com.cn
2. com.cn
3. example.com.cn
4. cn
5. ample.com.cn
如果输入example.com.cn则返回结果顺序为3124。规则5中的ample不是域名层级的一部分不返回。
### Boolean Expression Plugin
按照布尔表达式扫描输入的整数数组,如[100,1000,2,3]。
布尔表达式规则为“&”分隔的数字例如“1&2&1000”。
## Foreign Files 内容外键
回调类配置中特定字段可以指向一个外部内容目前支持指向Redis中的一个key。
回调表的外键列必须具备”redis://”前缀。存放在Redis中的外键内容其Key必须具备”__FILE_”前缀。当Key为“null”时表示该文件为空。
例如,原始文件为./testdata/mesa_logo.jpg计算其MD5值后得到redis的外键__FILE_795700c2e31f7de71a01e8350cf18525写入回调表后的格式如下
```
14 ./testdata/digest_test.data redis://__FILE_795700c2e31f7de71a01e8350cf18525 1
```
回调表中的一行最多允许8个外键外键内容可以通过Maat_cmd_set_file函数设置。
Maat在通知回调表前会将外键拉取到本地文件并将外键列替换为本地文件路径。
内容外键的声明方法,参见本文档-配置表描述文件一节。
## 配置生效标签
通过将Maat接受标签与配置标签的匹配实现有选择的配置加载。其中配置标签是一个标签数组的集合记为”tag_sets”Maat接受标签是标签数组记为”tags”。
配置标签是指存放在编译配置或分组配置上的标签标识着该配置在那些Maat实例中生效。由多个tag_set构成1个set内的多个tag是与的关系1个tag的多个值是或的关系值内部用”/”表示层次结构。
格式为一个不含回车、空格的JSON结构为:
若干tag集合数组->tag集合数组->若干tag数组->{tag名称tag值数组}
例如:
```json
{"tag_sets":[[{"tag":"location","value":["北京/朝阳/华严北里","上海/浦东/陆家嘴"]},{"tag":"isp","value":["电信","移动"]}],[{"tag":"location","value":["北京"]},{"tag":"isp","value":["联通"]}]]}
```
上例有2个tag分组
- 分组1"北京/朝阳/华严北里""上海/浦东/陆家嘴")∧("电信""移动")
- 分组2"北京"∧"联通"
- 分组1分组2
Maat实例初始化时可以设置自身的标签信息称为接受标签。格式为同样要求的JSON内有多个标签加载配置时匹配实例标签和配置的生效范围标签。例如
```json
{"tags":[{"tag":"location","value":"北京/朝阳/华严北里/甲22号”},{"tag":"isp","value":"电信"}]}
```
该Maat实例在加载以下标签时
1. {"tag_sets":[[{"tag":"location","value":["北京/朝阳"]},{"tag":"isp","value":["联通","移动"]}]}不被接受因为isp tag不匹配。
2. {"tag_sets":[[{"tag":"location","value":["北京"]}]]}接受空tag在任意tag上生效。
对于Maat实例接受标签和配置标签name不匹配的异常情况Maat遵循不违背即接受的原则全部接受。
- Maat实例的接受标签是配置标签的真子集时即tags 属于tag_setMaat会接受该配置。
- 例如:接受标签为:{"tags":[{"tag":"location","value":"北京”}]} ,配置标签为:{"tags":[{"tag":"location","value":"北京/朝阳”},{"tag":"isp","value":"电信"}]} Maat会接受该配置因为实例仅要求”location”满足“北京”未对“isp”标签的值作出要求。
- 配置标签是Maat实例接受标签的真子集时即tag_sets属于tagsMaat会接受该配置。
- 例如:接受标签为:{"tags":[{"tag":"location","value":"北京/朝阳”},{"tag":"isp","value":"电信"}]},配置标签为:{"tags":[{"tag":"location","value":"北京”}]}Maat会接受该配置。配置没有“isp”标签并未违背Maat接受条件。
- Maat实例的接受标签和配置标签的交集为空时Maat会接受该配置。
当配置标签为“0”或“{}”时无论Maat实例的接受标签是什么都会接受这一特性用于向前兼容未设置标签的配置。
## Virtual Table 虚拟表
虚拟一个配置表其内容为特定物理域配置表的视图。实践中通常采用网络流量的属性作为虚拟表名如HTTP_HOST、SSL_SNI等。一个虚拟表可以建立在多个不同类型的物理表之上但不允许建立在其它虚拟表上。
虚拟表以分组为单位引用实体表中的域配置引用关系在分组关系表中描述。一个分组可被同一个编译配置的不同虚拟表引用。例如下表一个关键字的分组keyword_group_1被一条compile_1的Request Body和Response Body两个虚拟表引用。
| **分组ID** | **父ID** | **有效标志** | **非运算标志位** | **父节点类型** | **分组所属虚拟表** |
| ------------------- | --------- | ------------ | ---------------- | -------------- | ------------------ |
| **keyword_group_1** | compile_1 | 1 | 0 | 0 | REQUEST_BODY |
| **keyword_group_1** | compile_1 | 1 | 0 | 0 | RESPONSE_BODY |
## Conjunction Table 连接表
表名不同但table id相同的表。旨在数据库表文件和MAAT API之间提供一个虚拟层通过API调用一次扫描即可扫描多张同类配置表。
使用方法:
1. 在配置表描述文件中将需要连接的多个表共用一个table_id
2. 通过Maat_table_register注册被连接表中的任意一个表名使用该id进行扫描。
被连接的配置表的各项属性以在配置表描述文件table_info.conf中第一个出现的同ID描述行为准同一table_id下最多支持8个配置表。
支持所有类型表的连接,包括各类域配置、回调类配置。配置分组和配置编译的连接没有意义。

43
docs/tools.md Normal file
View File

@@ -0,0 +1,43 @@
# Tools
## maat_redis_tool工具
可以将redis中的生效配置dump为本地IRIS格式的配置文件即文件配置加载接口所描述的格式。
可以将json格式的配置写入redis。注意该模式下不支持分组复用。
具体用法,参照./maat_redis_tool -? 的输出。
## digest_gen工具
可以计算文件的SFH摘要比较两个SFH摘要的相似度比较普通字符串的相似度。
具体用法,参照./digest_gen ? 的输出。
## 使用gzip命令压缩JSON配置
Maat_set_feather_opt的MAAT_OPT_JSON_IS_GZIPPED参数可以压缩后的规则文件。
```shell
[zhengchao@GDNT-BJ-DEV1 ~]$ gzip -9 < maat_json.json > maat_json.json.gz
```
可以和下面的加密命令联合使用,应**先压缩后加密**。
## 使用openssl enc对配置加解密
Maat_set_feather_opt的MAAT_OPT_DECRYPT_KEY参数可以加载加密的规则文件文件可以通过命令行进行加解密openssl 版本小于 v1.1.0)。
加密:
```shell
[zhengchao@GDNT-BJ-DEV1 ~]$ openssl enc -e -aes-128-cbc -k 123456 -p -nosalt -in inputfile.txt -out encryptfile.txt
```
解密:
```
[zhengchao@GDNT-BJ-DEV1 ~]$ openssl enc -d -aes-128-cbc -k 123456 -p -nosalt -in encryptfile.txt -out tmp.txt
```
原理参见https://blog.csdn.net/littlefang/article/details/72972266

View File

@@ -1,13 +1,22 @@
# 简介
# MAAT网络流处理配置统一描述框架
## 简介
MAAT是古埃及神话中真理与正义女神她的羽毛feather能够判断离世之人能否前往天堂。
MAAT框架对网络流处理中的配置进行抽象并具有配置写入、多机同步基于Redis、加载、扫描的功能。
MAAT的输入可以选择三种输入源
* Redis数据库用于生产环境由其它程序写入数据源通常为关系数据库如Oracle、MySQL也可以通过Maat Command API写入。
* JSON文件用于生产环境和调试支持支持动态加载。
* Tab分割的文本文件IRIS故障诊断用。
maat.h中描述了初始化和配置扫描的API。
maat_command.h中描述了配置写入的API。
# 编译
## 编译
普通编译
` Make`
@@ -22,4 +31,17 @@ maat_command.h中描述了配置写入的API。
生成动态链接库 `./build/src/libmaat4.so`
生成静态链接库 `./build/src/libmaat4.a`
生成静态链接库 `./build/src/libmaat4.a`
## 更多资料
[Introduction](./docs/introduction.md) 概念和原理
[Table Schema](./docs/table_schema.md) 配置表的模式
[Table Data](./docs/table_data.md) 配置表中的数据
[Scan API](./docs/scan_api.md) 扫描接口
[Tools](./docs/tools.md) 工具