# ONVM-IPS / Hyperscan {%hackmd theme-dark %} ## DPDK * GitHub-[DPDK](https://github.com/DPDK/dpdk) * GitHub-[Pktgen-DPDK](https://github.com/pktgen/Pktgen-DPDK) ![](https://i.imgur.com/pmUdQ0l.png) ## OpenNetVM * GitHub-[openNetVM](https://github.com/sdnfv/openNetVM) ![](https://i.imgur.com/uKWxrJg.png) ## Hyperscan * GitHub-[hyperscan](https://github.com/intel/hyperscan) ![](https://i.imgur.com/hvR8Maj.png) **Figure 1:** Hyperscan compilation process ![](https://i.imgur.com/1nwg04R.png) **Figure 2:** Hyperscan run-time ![](https://i.imgur.com/PoERl5t.png) **Figure 3:** Data scattered in different units in time order ## Snort3 * GitHub-[snort3](https://github.com/snort3/snort3) ![](https://i.imgur.com/9LDmHVK.png) ## ONVM-IPS / Hyperscan ### 運行流程 ![](https://i.imgur.com/6ghECQa.png) * IPS運行架構如上圖所示 * 首先由 `onvm_nflib` 等 `function` 進行初始化,透過 `DPDK_init` 進行 `DPDK EAL` 環境的建構並執行 `onvm_signal` 與 `manager` 建立連線,這裡的連線指的是由 `manger` 指派的 `core`、`mempool` 等資源的共享。 ![](https://i.imgur.com/w23F1Xf.png) ### 規則解析 * 接著由 `databasesFromFile` 接手,讀取 `Snort Rules` 並將其解析、儲存於對應的結構體當中。 ![](https://i.imgur.com/UVVbNEC.png) * 如下圖所示,使用右側的 `unordered_map`,將原規則中的變數置換為實體 `IP` 位址,並於載入完成後進行規則的編譯,將 `protocol`、`srcAddr`、`srcPort`、`dstAddr`、`dstPort`,部分相同的規則編譯為對應的字元樹資料庫。 ![](https://i.imgur.com/oS0EOFQ.png) * 編譯完成後,所有 `Snort Rules` 與編譯完成的 `DB` 將會存在如下圖所示的全域變數結構體當中,並等待後續建構時的調用。 ![](https://i.imgur.com/ZddGzr5.png) :::info /* ACTION */ `ACTION_ALERT` 0x00 `ACTION_LOG` 0x01 `ACTION_DROP` 0x02 `ACTION_REJECT` 0x03 `ACTION_SDROP` 0x04 /* PROTOCOL */ `IP_PROTOCOL_ICMP` 0x01 `IP_PROTOCOL_OTHER` 0xFF ::: ### Flow建構(nf_setup) * 接著進入 `nf_setup` 的部分,因為這裡我們採用的 `scaling` 方法是 `Run-to-Completion`,因此每個 `child thread` 都必須根據 `parent` 儲存的全域變數 `RuleHashMap`,建構自己的 `Flow` 解析器。 ![](https://i.imgur.com/AOQKTDG.png) * 以 `Tcp_parser` 為例 1. 當 `tcp` 封包進入 `parser`,首先以封包內 `srcAddr`、`srcPort`、`dstAddr`、`dstPort`,建構 `FlowTuple` 結構,並檢查 `flow_map`。 2. 若 `key` 不存在則解析規則並記錄於 `flow_map` 中。 3. 將 `flow_map` 中 `value` 與 `steams` 內對應的狀態取出 4. 走訪對應的 `db` 並於匹配時呼叫對應的 `callback fucntion` :::info `ProtocolHashMp` *tcp_rules; `vector<unordered_map<FlowTuple, size_t, FlowTupleHash>>` stream_map; `hs_scratch_t` **scratch; `vector<vector<hs_stream_t *>>` streams; `unordered_map<FlowTuple, vector<int>, FlowTupleHash>` flow_map; ::: ![](https://i.imgur.com/2MGzjat.png) ```cpp const FlowTuple header(ipv4, tcp->src_port, tcp->dst_port); if (flow_map.find(header) == flow_map.end()) { int index = 0; for (it = tcp_rules->begin(); it != tcp_rules->end(); ++it, ++index) { if (parseRule(it->first, header)) { flow_map[header].push_back(index); } } } ``` --- ![](https://i.imgur.com/WrtbSm7.png) ```cpp for (auto &index : flow_map.at(header)) { it = next(tcp_rules->begin(), index); stream_map[index].insert(make_pair(header, stream_map[index].size())); err = hs_scan_stream(streams[index][stream_map[index].size()], payload, length, 0, *scratch, onMatch, this); if (err != HS_SUCCESS) { cerr << "ERROR: Unable to scan tcp packet. Exiting." << endl; exit(-1); } } ``` * 如下圖所示,偵測到對應特徵的封包時,於 log 檔內紀錄其狀態與輸出封包內容。 ![](https://i.imgur.com/zDGqVgV.png) ## Ref [NFA/DFA](https://www.itread01.com/exhkf.html)