The keyword “IP rule engine” should be integrated as follows:
In fact, the matching process of rules in an IP rule engine is strongly linked to the loading process. The way you organize the rules determines the data structure used for matching. For example, if you use a radix tree to organize a large number of IP rules, the matching process involves a bit test to identify the prefix node, followed by querying the left and right subtrees. Suricata functions in a similar manner. Here’s a brief overview of this matching process.
1. Run the IP-only engine
Run the pure IP rule engine for matching. Since it involves only IP rules, as long as the destination IP and source IP match, it can be considered a hit. We add the matched rule’s SID to the alert array as output.
2. Get our rule group
This step involves obtaining the rule group to which the packet belongs. During rule loading, we group the incoming and outgoing ports of the rules, for example:
alert ip 1.1.1.1 80 -> 1.1.1.2 80:90(sid:1;)
alert ip 1.1.1.1 80 -> 1.1.1.2 80:85(sid:2;)
These two rules will form a new group using 80:85, including SIDs 1 and 2. A new group for 86:90 includes SID 1. The function then matches the current packet’s destination or source port to find the rule group based on these incoming and outgoing ports.
3. Run the prefilters for packets
This step involves prefilter rule filtering. In step 2, we obtain the group SGH, which contains several prefilter engine lists such as the content prefilter. This organizes the content of rules in the same group into a multi-pattern database using hyperscan, allowing content prefilter to quickly identify candidates during execution.
SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf, strlen(buf));
4. Inspect the rules against the packet
After the series of prefiltering in step 3, very few candidate SIDs remain. Now, we need to individually examine these rules to determine if they truly match. At first, the five tuples and protocol are checked, followed by matching rule options like PCRE, threshold, etc. If all these options match, it is considered that this packet hit the rule, leading to the generation of relevant alerts and logs.
/* if prefilter didn't already run, we need to consider transformations */
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
//->
const InspectionBuffer *buffer = engine->v2.GetData(det_ctx, transforms,f, flags, txv, list_id);
/* Inspect all the uricontents fetched on each
* transaction at the app layer */
int r = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd,NULL, f,
(uint8_t *)data, data_len, offset, ci_flags,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
//->
(void)sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx);
5. Append a signature match to a packet
Record the rule match results