加密流量恶意行为检测系统
SYSTEM PREMISE项目命题

看不见明文,依然看得见攻击

面向加密通信环境的端到端恶意行为检测技术体系设计与实现

HTTPSSSHDoH

深度学习负责学习信号组合而不是读取明文

输入 连续流量特征

时间 · 方向 · 包长 · 比例

学习 自动组合规律

从已标注样本中建立判断

输出 风险与行为
是否恶意行为类别

给出两项检测结果

关键理解模型学习的是一段通信的整体节奏

TCN 沿时间逐层扩大观察范围,同时捕捉短期重复与长期节奏

16 条连续 FLOW
近处dilation 1相邻变化
中程dilation 2周期节奏
远处dilation 4阶段切换
并行处理固定长度序列汇总为时序表征

加密隐藏了内容,时间、方向和包长仍然可见

CONTENT HIDDENBEHAVIOR VISIBLE
内容不可读取 URL / PATHGET /admin/loginGET /*********** CREDENTIALpassword=demo_accesspassword=*********** DNS QUERYdns-query=tunnel.exampledns-query=************** COMMANDcommand=powershell.execommand=************
时间
方向
包长
不破解加密读取通信留下的行为外观

重复、心跳、比例与阶段变化构成攻击识别信号

暴力破解重复连接
Botnet C2周期心跳
DoH 隧道比例异常
入侵后活动阶段变化

固定低误报后,恶意召回仍达到 99.9328%

TEST FPR0.9000%
RECALL99.9328%
PRECISION97.1745%
MACRO-F198.1644%
验证集确定阈值LOCKED测试集固定使用

一次推理同时判断是否恶意与具体行为

这段流量是否恶意?它属于哪一种行为?
共享表征192D
恶意概率MALICIOUS
行为类别DoH Tunnel

从原始 PCAP 到 Windows 告警,检测链路已经完整运行

不解密双任务端到端
捕获PCAP
组织双向 flow
表达116D
构造16 steps
学习多任务 TCN
原始证据
会话结构
流级特征
时序样本
风险 + 行为
产品动作

7 个来源被统一映射为5 类行为

75
HIKARIDoHBrwFriday BotThursdayTuesdayCTU-13HKD
统一语义层[16,116]
BENIGNbrute_forcebotnet_c2doh_tunnelinfiltration_post_compromise
数据边界HIKARI、DoHBrw、Friday、Thursday、Tuesday:包含正常与恶意背景CTU-13、HKD:恶意侧补强,仅做 Recall-only 审计

3,095,414 条候选序列中,3,087,563 条通过准入审计

ADMISSION可信准入
ADMITTED3,087,563
EXCLUDED7,851
TRAIN2,222,458 VALIDATION431,149 TEST433,956

标签只负责监督对齐,不进入 116 维模型输入

原始 PCAP自研 flow 与特征MODEL INPUT
官方标签 · 时间窗监督对齐STOP
LABEL FIREWALL
01先从原始 PCAP 构造 flow 02再对齐官方标签与攻击时间窗 03低置信对齐进入 unknown / excluded / 审计 04CTU-13 / HKD:仅做 Recall-only

PCAP 先归并为双向 flow,再计算 116 维行为特征

特征名禁用字段命中0
输入封装Ethernet / raw IP / Linux SLL 协议范围IPv4 / IPv6 · TCP / UDP flow timeout120 秒 active / idle gap1 秒 bulk 规则至少 4 包 · 相邻间隔 ≤ 1 秒 非 TCP 流TCP flag 特征统一置 0
FEATURE CONTRACT116 / 116禁用字段 0
规模
0–12
IAT
13–26
包长
27–31
Flags
32–39
Active / Idle
40–47
速率与比例
48–85
TCP / Bulk
86–108
Flow Delta
109–115
真实源码 · 双向 flow 归并214_rawpcap_direct_efb_v2c_extractor.py · L434–449
key = canonical_key(src, sport, dst, dport, proto)
flow = active.get(key)
if flow is not None and (ts - flow.last_ts > FLOW_TIMEOUT_S or flow.saw_fin_rst):
    flows.append(flow)
    flow = None
    active.pop(key, None)
if flow is None:
    flow = FlowAgg(first_ts=ts, last_ts=ts, fwd=(src, sport), bwd=(dst, dport), proto=proto)
    active[key] = flow
flow.add(ts, (src, sport), l3_len, header_len, payload_len, flags, win)
flows.extend(active.values())
flow_vecs = [f.vector() | {"_first_ts": f.first_ts, "_last_ts": f.last_ts} for f in flows]
01canonical_key02active / timeout03FlowAgg.vector()

单条 flow 难以充分识别攻击,连续 16 条更能呈现行为模式

单条连接
局部外观相似
连续 16 条 flow
重复 · 周期 · 阶段变化
CONTEXT REVEALS BEHAVIOR行为存在于过程,而不是一个快照

16 条 flow 如何变成一个带标签的 [16,116] 行为窗口

16 FLOWS
STRIDE 8
SAMPLE 01SAMPLE 02
统一张量[16,116]
sequence length16 条 flow stride8 · 相邻窗口重叠一半 padding不足 16 条时零填充 flow_present区分真实 flow 与 padding
任一恶意 flowsequence → malicious 恶意行为多数类sequence behavior 全部正常behavior → BENIGN
真实源码 · 差分与窗口张量214 extractor · L475–500
d["delta_prev_total_packets"] = d["total_packets"] - prev["total_packets"]
starts = list(range(0, max(len(base) - seq_len + 1, 1), stride))
if len(base) > seq_len and starts[-1] != len(base) - seq_len:
    starts.append(len(base) - seq_len)
chunk = base[st: st + seq_len]
mat = np.zeros((seq_len, len(FEATURE_NAMES_EFB_V2C)), dtype=np.float32)
for r, d in enumerate(chunk):
    mat[r, :] = np.array([d[n] for n in FEATURE_NAMES_EFB_V2C], dtype=np.float32)
真实源码 · sequence 标签233b label extractor · L205–225
flow_labels = [f["_behavior_label"] for _, f in chunk]
malicious = [f for _, f in chunk if int(f["_y"]) == 1]
if malicious:
    y = 1
    behavior = Counter(f["_behavior_label"] for f in malicious).most_common(1)[0][0]
    binary = "malicious"
else:
    y = 0
    behavior = "BENIGN" if all(lbl == "BENIGN" for lbl in flow_labels) else Counter(flow_labels).most_common(1)[0][0]

每个 TCN block 都是两层卷积 + 残差连接

dilation 1
连续局部
dilation 2
中段重复
dilation 4
长程阶段
kernel = 3BatchNormGELUDropout 0.15Residual
真实源码 · TCNBlockscripts_236b_train_deep_multitask_v1.py · L114–130
class TCNBlock(nn.Module):
    def __init__(self, channels: int, dilation: int, dropout: float):
        super().__init__()
        pad = dilation
        self.net = nn.Sequential(
            nn.Conv1d(channels, channels, kernel_size=3, padding=pad, dilation=dilation),
            nn.BatchNorm1d(channels),
            nn.GELU(),
            nn.Dropout(dropout),
            nn.Conv1d(channels, channels, kernel_size=3, padding=pad, dilation=dilation),
            nn.BatchNorm1d(channels),
            nn.GELU(),
        )
        self.drop = nn.Dropout(dropout)
    def forward(self, x):
        return x + self.drop(self.net(x))
为什么用三种 dilation?在不增加序列长度的前提下,同时观察相邻 flow、周期重复和更长阶段变化。

共享表征经 mean + max 汇聚,再分成 1 维与 5 维输出

764,934parameters
INPUT[B,16,116]Linear 116 → 192
TCN × 3dilation 1 · 2 · 4
MEANMAX384 → 192
BINARY HEADLinear(192,1)恶意概率
BEHAVIOR HEADLinear(192,5)五类行为
真实源码 · MultiTaskTCNscripts_236b_train_deep_multitask_v1.py · L133–160
self.inp = nn.Sequential(
    nn.Linear(feature_dim, hidden),
    nn.LayerNorm(hidden),
    nn.GELU(),
    nn.Dropout(dropout),
)
self.blocks = nn.Sequential(
    TCNBlock(hidden, 1, dropout),
    TCNBlock(hidden, 2, dropout),
    TCNBlock(hidden, 4, dropout),
)
self.post = nn.Sequential(nn.Linear(hidden * 2, hidden), nn.GELU(), nn.Dropout(dropout))
self.bin_head = nn.Linear(hidden, 1)
self.beh_head = nn.Linear(hidden, n_beh)

h = self.inp(x)  # B,T,H
h = self.blocks(h.transpose(1, 2)).transpose(1, 2)
pooled = torch.cat([h.mean(dim=1), h.amax(dim=1)], dim=1)
z = self.post(pooled)
return self.bin_head(z).squeeze(1), self.beh_head(z)

最终路线把数据选择、训练器与模型定义分层复用并逐轮验证

175.654sCUDA 总耗时
244e wrapper选择最终 HKD 增强 manifest 243a trainer均衡采样 · 训练 · 验证 · 选模 236b modelMultiTaskTCN 结构定义
DATA

数据与采样

Normalization500,000 序列 · 8,000,000 flowSamplingfamily|behavior 反频率Random seed24320260702
OPTIMIZE

优化与联合损失

Batch / Eval4096 / 8192OptimizerAdamW · CosineAnnealingLRLR / decay0.001 / 2e-4Lossbinary + 0.8 × behaviorClip / Dropout3.0 / 0.15
SELECT

验证与选模

Epochs8Best epoch4DeviceCUDA
真实源码 · 优化器与联合损失243a trainer · L229–246 / L268–284
opt = torch.optim.AdamW(model.parameters(), lr=args.lr, weight_decay=2e-4)
sched = torch.optim.lr_scheduler.CosineAnnealingLR(opt, T_max=max(args.epochs, 1))

blogit, hlogit = model(x)
loss = loss_bin(blogit, yb) + 0.8 * loss_beh(hlogit, yh)
scaler.scale(loss).backward()
scaler.unscale_(opt)
              torch.nn.utils.clip_grad_norm_(model.parameters(), 3.0)
真实源码 · Validation-only 选模243a trainer · L290–318
val_pred = base.predict(model, val_loader, device)
val_metrics = base.eval_metrics(val_pred, beh_to_id)
thr = float(val_metrics["binary"]["at_1pct_fpr"]["threshold"])
val_groups = group_eval(val, val_pred["y_bin"], val_pred["bin_score"], val_pred["beh_pred"], beh_to_id, thr)
score = score_for_selection(val_metrics, val_groups)
if score > best_score:
    best_score = float(score)
Train-only归一化参数只由训练样本估计 Validation-only每轮计算 1% FPR Recall、Macro-F1 与分 family 指标
第 4 轮best_model.pt

跨 split 的 sample_id 精确重复为 0证明边界也明确写出

INPUT字段隔离标签、IP、端口不进入模型
NORMTrain-only归一化统计量只来自训练集
THRESHOLDValidation-only工作阈值只在验证集选择
SPLITSample ID 审计跨集合 exact duplicate = 0

已验证边界

EXACT DUPLICATE
0跨 split 的 sample_id 精确重复

3,087,563条准入序列纳入审计

证明边界

NOT CLAIMED
01文件级交叉02五元组级交叉03相邻滑窗级交叉

未声明为已形式化证明

默认采用 1% 工作点避免多出 6,963 个正常误报

VAL 1% → TESTFPR 0.9000%FP 2,982 · FN 69
VAL 3% → TESTFPR 3.0015%FP 9,945 · FN 51
LOCKED
少漏检 18增加正常误报 6,963 个

102,626 个恶意序列中,102,557 个被检出

漏检69Precision97.1745%
恶意序列检出率99.9328%102,557 / 102,626
331,330 个正常序列误报 2,982

五类行为 Macro-F1 达到 98.1644%主要短板是入侵后活动

OVERALL ACCURACY99.8350%
类别PrecisionRecallF1Support
BENIGN99.9486%99.8609%99.9047%331,330
brute_force99.9647%99.8588%99.9117%73,642
botnet_c299.3324%99.3385%99.3355%16,327
doh_tunnel99.3876%99.9807%99.6833%10,389
infiltration_post_compromise86.5190%98.1922%91.9868%2,268
主要混淆边界BENIGN ↔ infiltration_post_compromisePrecision 86.5190%仍需补强真实入侵后活动背景

16 步 TCN 把漏检从 32,117 降至 72,完整模型进一步降至 69

RECALL (%)TEST FPR 0.9000%–0.9667%
单 flow + MLP68.7048%FPR 0.9667% · FN 32,117
16 步 + TCN,无 delta99.9298%FPR 0.9477% · FN 72
8 步 + TCN99.5235%FPR 0.9166% · FN 489
最终 16 步 + TCN,全 116 维99.9328%FPR 0.9000% · FN 69
主要增益来自连续 16 条 flow

跨源泛化审计:HKD 提升了 DoHBrw 迁移能力Recall 22.48% → 74.29%,仍未达部署水平

Holdout 来源训练条件 / 代表行为RecallFPR结论
Thursday Infiltration不含 Thursday · infiltration92.36%0.79%较稳
Friday Bot不含 Friday · botnet_c288.38%1.09%接近可用
DoHBrw不含 DoHBrw,加入 HKD · doh_tunnel74.29%9.41%22.48% → 74.29%,仍未达部署水平
CTU-13无完整 benign · botnet_c272.93%Recall-only
HKD DoH Tunnel无完整 benign · doh_tunnel100.00%Recall-only
HIKARIbrute_force / 混合恶意2.84%7.97%跨源迁移失败
Tuesdaybrute_force11.27%20.91%跨源迁移失败
能力边界混合测试集高指标不等于任意未知网络都能保持同等表现

真实 CPU 运行把 31,295 个包转换为 7 个检测窗口

PACKETS31,295
BIDIRECTIONAL FLOWS60
[16,116] WINDOWS7
116 维禁用字段命中 0NaN / Inf 0真实 detector.exe CPU 结果

从抓包文件到源文件级结论,Windows 工具直接完成检测

Windows x64 CPU 推理无需 Python / PyTorch / CUDAPCAP / PCAPNG / zip 内 PCAPmanifest 批处理窗口级 / 源文件级 / 总结.txt
ENCRYPTED TRAFFIC DETECTOR样例 · 界面重构示意
INPUT SAMPLEHKD dnstt PCAP 样例
DETECTION RESULTMALICIOUS
BEHAVIORdoh_tunnel
WINDOWS7 / 7 maliciousthreshold 0.0018279440

模型、源码、manifest、审计与 Windows 工具组成完整交付

RAW PCAP自研抽取源码
MODEL权重与归一化
MANIFEST统一数据入口
AUDIT正式指标与边界
WINDOWSx64 一键工具
请旋转手机 横屏后可完整观看,并左右滑动翻页