Files
tianxuan/.omo/drafts/tianxiu-v6.md
T

14 KiB
Raw Blame History

Draft: 天璇 v6 — 基于真实TLS特征的恶意流量分析

Intent

  • intent: CLEAR
  • review_required: true
  • status: awaiting-approval

自我审查发现的问题

  1. Phase 0 依赖用户给真实数据——应基于 TLS 1.3 协议推导
  2. 21x2 hex 列我不知道是哪个,回避了问题
  3. "TlsS"/"TlsC" 列我不知道是哪个,回避了问题
  4. 归一化步骤没说明如何集成到现有 data_loader 中
  5. 特征间有冗余(port_category vs is_standard_port
  6. 时域特征 inter_arrival_time_std 在单流级别不可计算
  7. 缺少 JA3 指纹近似、SNI 长度熵等关键特征
  8. lat/lon 覆盖方案没说具体怎么做
  9. 空白语义只说了 4 列,其他几十列没说
  10. 聚类流程图漏了"归一化"步骤

Phase 0: 基于 TLS 1.3 协议的列类型推导(不需要用户数据)

基础事实

  • 数据来源:TLS 1.3 握手报文字段抽取
  • 每条流 = 一个 TLS 连接握手 + 数据传输的摘要
  • 大量空白是预期的——TLS 握手中很多字段是可选 extension,不是每条流都有

每列精确类型定义

TLS协议来源 存放格式 空白语义
:ips 捕获点记录的源IP IPv4字符串 从不空白
:ipd 捕获点记录的目标IP IPv4字符串 从不空白
:prs TCP源端口 整数 缺失
:prd TCP目标端口 整数 缺失
scnt GeoIP从:ipd推断 2字母大写代码 缺失(GeoIP无法解析时)
dcnt GeoIP从:ipd推断 2字母大写代码 缺失
server-ip 服务器IP(可能与:ipd同) IPv4 缺失
client-ip 客户端IP(可能与:ips同) IPv4 缺失
0ver ServerHello.protocol_version 2x2 hex: 03 04 TLS连接都必有,极少空白
snam ClientHello.extensions.server_name UTF8域名 缺失(ClientHello中无SNI扩展 → 可疑)
cnam Certificate.certificate.subject.CN UTF8字符串 缺失(无证书或未知证书)
4dur 流持续时间(纳秒/毫秒? 整数 常见空白(40%+
8ses 会话起始偏移 整数 常见空白
2tmo 超时偏移 整数 常见空白
4ksz 证书公钥大小 整数(256/384/521/1024/2048) 空白(无证书)
cnrs SessionTicket.can_resume +/空白 空白≠缺失 +=可恢复 ""=不可恢复
isrs SessionTicket.was_resumed +/空白 空白≠缺失 +=已恢复 ""=未恢复
8ack 反向方向字节数 整数 缺失
8ppk 有效载荷包数 整数 缺失
8dbd 数据库日志记录时间 时间戳字符串 缺失
1ipp IP协议号 整数(6/17) 缺失
4dbn 数据库编号 整数 缺失
tabl 数据库表名 字符串 缺失
name 捕获链路名称 字符串 缺失
source-node 捕获节点名 字符串 缺失
cipher-suite 密码套件名(IANA格式) 大小写混合字符串 缺失(无密码协商时)
ecdhe-named-curve 椭圆曲线名 大小写混合字符串 缺失(非ECDHE密钥交换时)
0cph ServerHello.cipher_suite 2x2 hex: 13 01 缺失
0crv ServerHello.KeyShare 2x2 hex: 00 1d 缺失(非ECDHE时)
0rnd ServerHello/ClientHello.random 32x2 hex(也可能是21x2 TLS必有,但可能截断存储
0rnt Random.gmt_unix_time 整数或4x2 hex 常见空白(现代TLS用随机值替代时间)
row 行号 整数 从不空白
time 时间 字符串 缺失
timestamp 时间戳 字符串 从不空白
:ips.latd/lond GeoIP推断,过时 浮点数 不可靠,覆盖
:ipd.latd/lond GeoIP推断,过时 浮点数 不可靠,覆盖
:ips.ispn/.orgn/.city GeoIP推断 字符串 大部分空白
:ipd.ispn/.orgn/.city GeoIP推断 字符串 大部分空白

待识别项目

  • 21x2 hex 列: 不在我已知的任何标准 TLS 结构中。0rnd(32x2)、0cph(2x2)、0crv(2x2)、0ver(2x2)。21x2 可能是一个额外的截断/编码字段。将用 column_survey 自动发现 hex_pairs_count==21 的列。
  • TlsS/TlsC: 可能是 tablsource-node 列的两个值。含义接近 "TLS Server" / "TLS Client"。待 column_survey 确认。

Phase 0.5: 值归一化模块 analysis/value_normalizer.py

架构

新增独立的归一化模块,在 data_loader.pyload_csv_directory() 中作为最后一个清理步骤执行(类型分类之后、返回 LazyFrame 之前)。

归一化方式

每列生成 {col}_norm 保留原始列,供下游特征工程使用。

TLS Version → Enum (0ver)

TLS_VERSION_MAP = {
    # hex wire format
    '03 04': 'tls_1_3', '03 03': 'tls_1_2',
    '03 02': 'tls_1_1', '03 01': 'tls_1_0',
    '02 00': 'ssl_2_0', '03 00': 'ssl_3_0',
    # display formats (case-insensitive)
    'tlsv1.3': 'tls_1_3', 'tls 1.3': 'tls_1_3', '1.3': 'tls_1_3',
    'tlsv1.2': 'tls_1_2', 'tls 1.2': 'tls_1_2', '1.2': 'tls_1_2',
}
# 未知值 → 'unknown_version'

Cipher Suite → Enum (0cph, cipher-suite)

CIPHER_MAP = {
    # hex → IANA name (TLS 1.3 + common TLS 1.2)
    '13 01': 'tls_aes_128_gcm_sha256',
    '13 02': 'tls_aes_256_gcm_sha384',
    '13 03': 'tls_chacha20_poly1305_sha256',
    'c0 2b': 'tls_ecdhe_ecdsa_aes_128_gcm_sha256',
    'c0 2f': 'tls_ecdhe_rsa_aes_128_gcm_sha256',
    'c0 30': 'tls_ecdhe_rsa_aes_256_gcm_sha384',
    'cc a9': 'tls_ecdhe_ecdsa_chacha20_poly1305_sha256',
    'cc ac': 'tls_ecdhe_rsa_chacha20_poly1305_sha256',
    '00 9c': 'tls_rsa_aes_128_gcm_sha256',
    '00 9d': 'tls_rsa_aes_256_gcm_sha384',
    'c0 09': 'tls_ecdhe_ecdsa_aes_128_cbc_sha256',
    'c0 13': 'tls_ecdhe_rsa_aes_128_cbc_sha256',
    # display → IANA (normalize: lowercase, ' '→'_', '-'→'_')
    'tls_aes_128_gcm_sha256': 'tls_aes_128_gcm_sha256',
    'aes 128 gcm': 'tls_aes_128_gcm_sha256',
    'aes-128-gcm': 'tls_aes_128_gcm_sha256',
    'tls 1.3 aes 128 gcm': 'tls_aes_128_gcm_sha256',
}
# 未知hex → 'unknown_cipher_0x{hex}'
# 未知显示名 → 标准化后保留

Named Curve → Enum (0crv, ecdhe-named-curve)

CURVE_MAP = {
    # hex wire format
    '00 1d': 'x25519', '00 17': 'secp256r1',
    '00 18': 'secp384r1', '00 19': 'secp521r1',
    '00 1e': 'x448',
    # display (case-insensitive)
    'x25519': 'x25519', 'curve25519': 'x25519',
    'secp256r1': 'secp256r1', 'prime256v1': 'secp256r1',
    'p-256': 'secp256r1', 'p256': 'secp256r1',
    'secp384r1': 'secp384r1', 'p-384': 'secp384r1',
}
# 未知 → 'unknown_curve_0x{hex}'

CNRS/ISRS → Enum (cnrs, isrs)

'+' → 'yes'  (never missing)
''  → 'no'   (never missing)

纯字符串(不操作)

snam, cnam, name, source-node, tabl → 不归一化,保持原始字符串

归一化与现有 data_loader 的集成

现有 data_loader 清理流水线:
  BOOL_ENUM → LAT_LON → HEX → [新增: VALUE_NORMALIZATION] → GenericNumCoerce

value_normalizer.normalize(lf, type_map) → pl.LazyFrame (带 _norm 列)

Phase 1: 特征工程(每条流级别 → 实体聚合级别)

第一步:单流特征(在 entity_aggregator 聚合前计算)

特征 来源列 计算方式
has_sni snam 有SNI? 1/0
sni_length snam SNI域名长度(长域名可疑)
sni_entropy snam 域名Shannon熵(高熵域名=算法生成=DGA)
sni_vs_cnam snam, cnam SNI与CN一致? 1/0
tls_version_risk 0ver_norm <tls_1_2=3, tls_1_2=1, tls_1_3=0
cipher_suite_category 0cph_norm aead=0, cbc=1, rc4=2, null=3
key_exchange 0cph_norm ecdhe=0, dhe=1, static=2
is_modern_cipher 0cph_norm tls 1.3 only cipher? 1/0
curve_type 0crv_norm x25519=0, secp256r1=1, other=2
curve_bit_strength 0crv_norm/4ksz 128/192/256 bits
port_type :prd 443=0, 80-1023=1, >1024=2
bytes_per_packet 8ack, 8ppk avg bytes/packet
is_recoverable cnrs_norm yes=1, no=0
was_resumed isrs_norm yes=1, no=0
has_cert_key 4ksz 有密钥大小? 1/0

第二步:实体聚合特征(在 entity_aggregator 中计算,按 :ips 分组)

聚合特征 聚合方式 意义
flow_count count 总流数
unique_dst_ips n_unique 目标多样性
unique_dst_ports n_unique 端口多样性
unique_tls_versions n_unique(0ver_norm) TLS版本跨度
unique_ciphers n_unique(0cph_norm) 密码套件跨度
unique_curves n_unique(0crv_norm) 曲线跨度
unique_snis n_unique(snam) SNI多样性
tls_13_ratio mean(is_modern_cipher) TLS 1.3密码比例
ecdhe_ratio mean(key_exchange==0) 前向保密比例
avg_bytes_per_packet mean(bytes_per_packet) 平均包大小
std_bytes_per_packet std(bytes_per_packet) 包大小标准差(小=beaconing
avg_duration mean(4dur) 平均持续时长
std_duration std(4dur) 时长标准差
port_443_ratio mean(port_type==0) 标准端口比例
non_standard_port_ratio mean(port_type==2) 非标准端口比例(可疑)
sni_missing_ratio mean(1-has_sni) 无SNI比例(可疑)
sni_cn_mismatch_ratio mean(1-sni_vs_cnam) SNI/CN不匹配比例
sni_avg_entropy mean(sni_entropy) SNI平均熵(高=DGA
recoverable_ratio mean(is_recoverable) 会话可恢复比例
resumed_ratio mean(was_resumed) 会话恢复比例
has_any_cert mean(has_cert_key) 有证书比例
countries_visited n_unique(dcnt) 跨国多样性
unique_hours n_unique(hour_of_day) 活跃时段
inter_arrival_std std(timestamp_diff) Beaconing检测: 到达间隔标准差
night_ratio mean(is_night_hour) 夜间流量比例

总计:约 30+ 聚合特征


Phase 2: 空白语义精确处理

空白语义 聚合前处理 聚合中处理
cnrs, isrs 非缺失 (+=yes, blank=no) 归一化为 yes/no 直接聚合
snam, cnam 缺失(无SNI/证书) 保留空白 has_sni=0, sni_cn_mismatch=null
0ver 极少空白 空白→unknown_version tls_version_risk=null
0cph, 0crv 缺失(无协商) 空白→unknown 相应特征为null
4dur, 8ack, 8ppk 缺失(40%+ 保留空白 mean/std跳过null
:prs, :prd 缺失 保留空白 port_type=null
scnt, dcnt 缺失(GeoIP失败) 保留空白 countries_visited排除null
lat/lon 基于过时库 全部替换 见Phase 2.5
ispn/orgn/city 大部分空白 不参与分析 排除

Phase 2.5: 经纬度覆盖方案

lat/lon 基于过时 IP 地理库,不可靠。处理方式:

  • 不使用原始 lat/lon 值
  • 对于 globe 可视化:用随机生成的地理位置模拟
  • 对于分析特征:移除所有基于 lat/lon 的特征
  • 保留 dcnt(目标国家代码)作为地理特征——国家代码更可靠且更有分析价值

Phase 3: 完整聚类流程

原始CSV
  → data_loader加载
      → 类型分类 (type_classifier.py)
      → BOOL_ENUM清洗
      → HEX预处理 (hex_pairs_count)
      → 值归一化 (value_normalizer.py) ← Phase 0.5 新增
      → 通用数值清洗
  → 单流特征计算 (data_loader.py 扩展) ← Phase 1 新增
  → 实体聚合 (entity_aggregator.py 扩展) ← Phase 1 新增
  → 通用数值清洗 (已有)
  → 方差过滤 ← Phase 1 新增
  → 相关过滤
  → StandardScaler → PCA(20-50维)
  → HDBSCAN聚类
  → 簇画像生成

簇画像输出

每个簇的完整描述:

簇标签: 3
大小: 42实体 (14%)
簇类型: 🚨 高度可疑
特征画像:
  - sni_missing_ratio: 0.85  (+2.1σ 高于均值)
  - non_standard_port_ratio: 0.72  (+1.8σ)
  - tls_13_ratio: 0.15  (-2.3σ)
  - avg_bytes_per_packet: 45  (-1.9σ, 小包=beaconing)
  - inter_arrival_std: 2.3s  (-2.1σ, 固定间隔)
  - countries_visited: 12  (+1.5σ, 跨国)
判定: 疑似代理/隧道流量
建议操作: 深度包检测, IP列入观察名单

Phase 4: 测试数据生成 (gen_test_data.py)

测试数据也使用归一化格式输出,确保端到端可验证。

3 类流量画像

1. 正常浏览 (60%示例数据)

  • TLS 1.3 (03 04) + AEAD cipher
  • Curve: x25519 (00 1d)
  • SNI: www.google.com, api.github.com 等合法域名
  • 端口 443
  • 多样的目标IP
  • 短连接 (0.5-5s), 中等包大小
  • cnrs/isrs: 随机 yes/no

2. 代理/VPN 隧道 (20%)

  • TLS 1.2 (03 03) + ECDHE cipher
  • Curve: secp256r1 (00 17)
  • SNI: 可能缺失或单一代理解析域名
  • 端口 443 但可能也在非标准端口
  • 少目标高流量
  • 长连接, 大字节量
  • cnrs: 高恢复率 (keep-alive)

3. 恶意/可疑 (20%)

  • TLS 1.0/1.1 或奇怪版本
  • 弱密码 (CBC/RC4)
  • SNI/CN 不匹配或无 SNI
  • Beaconing: 固定间隔小包 (30-40 bytes)
  • 高重连率 (大量 cnrs=yes → isrs=yes)
  • 非标准端口
  • 低熵 TLS random
  • 多国目标分布
  • 低包大小标准差

Phase 5: 端到端验证

  1. 生成3类测试数据
  2. 跑完整管道
  3. 验证归一化正确性(每列hex→enum映射)
  4. 验证聚类结果的自然分簇(正常/代理/恶意)
  5. 验证簇画像的可解读性
  6. 单元测试: 120+ passed

前置依赖

  • Phase 0-5 都不需要用户真实数据,全部基于 TLS 1.3 协议推导

意外预案

意外 后备
21x2 hex 列不在已知列中 column_survey 自动发现后添加合适映射
TlsS/TlsC 列无法确认含义 保留为原始字符串枚举,不做归一化
聚类仍不理想 增加规则引擎层(if sni_missing>0.5 → flag
特征数量不足 从 hex 列提取字节分布统计作为补充特征
归一化映射表不全 未知hex→unknown_{type}_0x{hex} 兜底