如何將實時流量解析并存入數據庫
Suricata介紹
Suricata
是一個開源的網絡入侵檢測和防護系統(IDS/IPS
),由Open Information Security Foundation(OISF)
開發和維護。該系統可以利用多線程設計在硬件上實現高性能數據處理,并且能夠深入檢查并解析多種網絡和應用層協議。通過高級的流量處理和還原能力,Suricata
能夠實時識別并處理網絡威脅,為分析人員提供原始且詳盡的網絡通信數據,助其深入洞察網絡行為,預防潛在的安全隱患。
流量還原技術的原理
Suricata
流量還原技術主要基于網絡流量來重構原始數據,為深入分析和研究數據提供基礎。一旦Suricata
捕獲到網絡流量,就能靈活解析多種協議,并從中提取文件、會話內容等關鍵數據。流量還原技術的核心在于,它將這些提取的數據按照原始的順序和結構重新排序,確保還原出的數據與原始傳輸狀態一致。這種技術賦予了分析人員直觀理解攻擊內容、方法和目的的能力,并為后續的高級分析(如文件的惡意性檢測)提供了有力支持。
(1)數據包捕獲
首先,Suricata
通過監聽指定的網絡接口,利用如PCAP
這樣的工具庫,實時捕獲并臨時存儲數據包。為了保障數據的完整性以及檢測的準確性,Suricata
通過特定的內存和緩沖區策略,確保即使在高流量環境下也能有效捕獲數據。同時,通過動態的負載均衡技術,Suricata
使得每個處理線程都能有效處理其分配到的數據,從而提高處理效率,防止性能瓶頸出現。
(2)會話跟蹤
會話跟蹤是確保網絡流量上下文完整性的關鍵環節。一旦Suricata
識別到一系列相關聯的數據包,它會依據源、目標地址及端口信息快速創建會話記錄。這些記錄不僅用于分類,更是為了全面理解通信的完整性。為了高效管理這些會話,Suricata
維護了一個動態的會話表,能夠迅速識別并更新現有會話或創建新會話。此外,通過對會話內的數據包進行深度分析,Suricata
能夠捕捉更為復雜的通信模式(如多階段攻擊或數據傳輸),從而為后續的安全分析和響應提供詳盡且豐富的上下文信息。
(3)數據包排序
數據包在傳輸過程中可能會遭遇亂序,因此排序成為流量重組的重要環節。在TCP
通信中,Suricata
精準利用TCP
頭部的序列號來確定數據包的正確順序,確保每個數據包都能各歸其位。
數據包排序關乎流量的連貫性、數據的完整性和準確性,而網絡擁塞、路由變動或其他外部因素都可能導致數據包順序混亂,進而影響數據流的完整性和分析結果的準確性。為此,Suricata
通過持續跟蹤每個會話的狀態和預期的數據包序列號,對這些數據包進行排序。此外,為了確保不會因為失序而丟失重要的通信內容,Suricata
會暫時存儲那些尚未找到正確位置的數據包。這一策略在保障數據流完整性的同時,也確保了Suricata
在處理高速、高流量網絡時,能夠捕獲并正確解析所有關鍵信息,為網絡安全分析提供強有力的支持。
(4)重組數據流
當數據包經過精確的排序后,Suricata
便開始著手將這些分散的碎片重新拼湊成原始的形態。像拼圖一樣,每個數據包都被放在其應有的位置,形成一個流暢且連貫的數據流。這一過程不僅還原了通信的真實情境,也為后續深入的安全分析構建了穩固的基石。
(5)處理重組的數據
數據流一經Suricata
恢復與重組,便開啟了對數據的深入挖掘之旅。這一過程不僅僅是簡單的內容瀏覽,而是涵蓋了多層次、多角度的細致分析,包括但不限于協議分析、應用行為識別,以及潛在安全威脅檢測等。
(6)協議解析
協議解析是流量重組后的首要任務。Suricata
憑借內置的協議解析器,能夠輕松解碼網絡中遵循的多種協議,如HTTP、FTP、SMTP
等。這一解碼過程不僅有助于識別數據流的類型,也有助于進一步的數據提取。
(7)數據提取
在協議解析的基礎上,Suricata
能夠進一步從數據流中提取關鍵信息和內容,涵蓋特定字符串、用戶憑據、URL
乃至完整的文件內容。這些提取出的數據元素可用于進一步的分析,例如與惡意軟件簽名匹配或進行行為分析,并為數據重組工作提供支持。
如何使用
安裝過程略過,網上教程也有很多,這里不再贅述
配置suricata
編輯配置文件/etc/suricata/suricata.yaml
# 指定監聽的網卡(如 eth0)
af-packet:
- interface: eth0
# 啟用HTTP協議解析
app-layer:
protocols:
http:
enabled: yes
# 配置EVE日志輸出(JSON格式)
outputs:
- eve-log:
enabled: yes
filetype: regular
filename: eve.json
types:
- http:
extended: yes # 啟用擴展字段
request-body: yes # 記錄請求體(可選)
response-body: yes # 記錄響應體(可選)
配置完成以后,我們在eth0
制造一些流量,就可以看到suricata
對實時流量進行了解析:
UDP
{
"timestamp": "2025-04-25T11:20:45.678901+0800",
"flow_id": 987654321098765,
"event_type": "flow",
"src_ip": "172.16.0.20",
"src_port": 33333,
"dest_ip": "192.168.2.200",
"dest_port": 53,
"proto": "UDP",
"app_proto": "dns",
"flow": {
"pkts_to_server": 2,
"pkts_to_client": 2,
"bytes_to_server": 100,
"bytes_to_client": 100
},
"start": "2025-04-25T11:20:00.000000+0800",
"end": "2025-04-25T11:20:50.000000+0800",
"age": 50,
"state": "established",
"reason": "timeout",
"alerted": false
}
TCP
{
"timestamp": "2025-04-25T12:30:10.345678+0800",
"flow_id": 567890123456789,
"event_type": "flow",
"src_ip": "192.168.3.15",
"src_port": 8888,
"dest_ip": "10.1.1.10",
"dest_port": 22,
"proto": "TCP",
"app_proto": "ssh",
"flow": {
"pkts_to_server": 10,
"pkts_to_client": 8,
"bytes_to_server": 500,
"bytes_to_client": 400
},
"start": "2025-04-25T12:29:30.000000+0800",
"end": "2025-04-25T12:30:20.000000+0800",
"age": 50,
"state": "established",
"reason": "user_logout",
"alerted": false
}
HTTP
{
"timestamp": "2025-05-01T10:15:40.789012+0800",
"flow_id": 864209753108624,
"event_type": "http",
"src_ip": "192.168.20.30",
"src_port": 53002,
"dest_ip": "172.67.147.133",
"dest_port": 8080,
"proto": "TCP",
"app_proto": "http",
"http": {
"http_method": "POST",
"url": "/api/login",
"protocol": "HTTP/1.1",
"status": 200,
"length": 567,
"http_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_3_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Safari/605.1.15",
"post_data": "username=testuser&password=testpass"
},
"start": "2025-05-01T10:15:20.000000+0800",
"end": "2025-05-01T10:15:50.000000+0800",
"age": 30,
"state": "completed",
"reason": "normal",
"alerted": false
}
解析入庫
以HTTP
為例,創建表結構
-- 創建存儲 HTTP 流量解析信息的表
CREATE TABLE http_traffic_analysis (
-- 流量記錄的唯一 ID,自增主鍵
id INT AUTO_INCREMENT PRIMARY KEY,
-- 事件發生的時間戳
timestamp DATETIME NOT NULL,
-- 流量的唯一標識符
flow_id BIGINT NOT NULL,
-- 事件類型,固定為 'http'
event_type VARCHAR(20) NOT NULL DEFAULT 'http',
-- 源 IP 地址
src_ip VARCHAR(45) NOT NULL,
-- 源端口號
src_port INT NOT NULL,
-- 目的 IP 地址
dest_ip VARCHAR(45) NOT NULL,
-- 目的端口號
dest_port INT NOT NULL,
-- 傳輸層協議,如 TCP、UDP
proto VARCHAR(10) NOT NULL,
-- 應用層協議,固定為 'http'
app_proto VARCHAR(20) NOT NULL DEFAULT 'http',
-- HTTP 請求方法,如 GET、POST
http_method VARCHAR(10) NOT NULL,
-- HTTP 請求的 URL
http_url VARCHAR(2048) NOT NULL,
-- HTTP 協議版本,如 HTTP/1.1
http_version VARCHAR(10) NOT NULL,
-- HTTP 響應狀態碼,如 200、404
http_status_code INT NOT NULL,
-- HTTP 響應的長度
http_response_length INT,
-- 客戶端的用戶代理信息
http_user_agent VARCHAR(255),
-- HTTP POST 請求的數據
http_post_data TEXT,
-- 連接開始時間
start_time DATETIME NOT NULL,
-- 連接結束時間
end_time DATETIME NOT NULL,
-- 連接持續時間
age INT NOT NULL,
-- 連接狀態,如 completed
state VARCHAR(20) NOT NULL,
-- 事件原因,如 normal、page_not_found
reason VARCHAR(50),
-- 是否觸發警報
alerted BOOLEAN NOT NULL DEFAULT FALSE
);
讀取Suricata
的EVE
日志文件,并將數據存儲到MySQL
數據庫中
public class SuricataDataStorage {
private static final String DB_URL = "jdbc:mysql://localhost:3306/suricata_data";
private static final String DB_USER = "your_username";
private static final String DB_PASSWORD = "your_password";
public static void main(String[] args) {
try (Connection connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
BufferedReader reader = new BufferedReader(new FileReader("/var/log/suricata/eve.json"))) {
String line;
while ((line = reader.readLine()) != null) {
try {
JSONObject event = new JSONObject(line);
//TODO 寫入數據庫
} catch (Exception e) {
System.err.println("Error parsing JSON line: " + e.getMessage());
}
}
} catch (SQLException e) {
System.err.println("Database connection error: " + e.getMessage());
} catch (IOException e) {
System.err.println("File reading error: " + e.getMessage());
}
}
}
以上代碼只是一個簡單的示例,實際應用中可能需要根據具體需求進行修改和擴展。