SSH 流量深度学习细分类系统设计与实现(C/C++代码实现)
在网络通信中,SSH(Secure Shell)协议是保障远程操作与数据传输安全的 “基石”,广泛用于服务器运维、文件传输等场景。但传统技术仅能识别 “这是 SSH 流量”,却无法区分其具体承载的业务 —— 实际上,SSH 流量下隐藏着三类核心应用:用于文件传输的 SFTP、高效复制文件的 SCP,以及实现远程命令交互的 SHELL。这三类应用的安全风险与资源需求差异显著:SHELL 涉及命令执行,风险最高;SFTP/SCP 侧重文件传输,需合理分配带宽。
本系统的核心定位是 “SSH 流量的精细化拆解工具”,在已识别 SSH 流量的基础上,通过深度学习技术实现 “SFTP/SCP/SHELL/ 未知类型” 的自动分类。其核心价值体现在三方面:一是安全审计,可针对性监控高风险的 SHELL 操作,及时发现未授权远程控制;二是资源调度,为 SFTP/SCP 分配更多带宽以保障文件传输效率,为 SHELL 预留稳定资源确保交互流畅;三是异常检测,建立各类 SSH 应用的行为基线,识别偏离正常模式的异常流量(如 SHELL 突然出现大量文件传输特征)。
二、核心技术原理:从流量到分类的全链路逻辑
系统实现遵循 “数据筛选→会话重组→特征提取→模型分类” 的全链路逻辑,每一步均围绕 “加密流量无解密分类” 的核心需求设计,具体流程如下:
1. 第一步:SSH 流量筛选 —— 从海量数据中 “挑对目标”
网络数据中包含 HTTP、TCP、UDP 等多种流量,首先需精准筛选出 SSH 流量,避免无关数据干扰。筛选采用 “双重验证” 机制:
-
端口初筛:SSH 默认使用 22 号端口通信,先过滤 “源端口或目的端口为 22” 的流量,快速缩小范围;
-
协议验证:部分场景下 SSH 会使用非 22 端口(如规避端口封锁),此时需通过 SSH 协议的 “身份标识” 二次确认 ——SSH 数据包头会包含 “SSH-2.0-” 或 “SSH-1.99-” 的版本标记,通过检测该标记可确保不会将非 SSH 流量误判为目标。
2. 第二步:会话重组 —— 将 “零散数据” 拼成 “完整操作”
SSH 的业务逻辑以 “会话” 为单位(如一次 SFTP 文件上传、一次 SHELL 登录操作),而网络传输的数据包是零散的,可能存在乱序、延迟等问题。因此需按 “会话” 对筛选出的 SSH 数据包进行重组:
-
会话标识:以 “五元组”(协议类型 + 源 IP + 源端口 + 目的 IP + 目的端口)作为会话的唯一标识 —— 例如 “TCP 协议 + 192.168.1.100:54321+192.168.1.200:22”,所有属于该五元组的数据包均归为同一会话;
-
会话完整性:记录会话的开始时间(第一个数据包时间)、结束时间(最后一个数据包时间),确保每个会话包含 “一次完整业务操作” 的所有数据,为后续特征提取提供完整上下文。
3. 第三步:特征提取 —— 从 “加密数据” 中找 “区分标志”
SSH 流量经过加密,无法直接解析数据内容,因此需从 “流量行为特征” 入手 ——SFTP、SCP、SHELL 的业务逻辑差异,会体现在流量的统计、时间、方向等维度,这些特征成为分类的关键依据:
-
统计特征:包括会话总数据包数、总字节数、平均数据包大小等。例如 SCP 传大文件时,数据包少但单包字节大;SHELL 交互时,数据包多但单包字节小(仅包含简短命令或响应);
-
时间特征:包括会话持续时间、数据包平均间隔时间等。例如 SHELL 依赖人工操作,数据包间隔较长(几秒到几分钟);SFTP/SCP 为自动化传输,数据包间隔短且连续;
-
方向特征:包括上下行字节比、数据包方向切换频率等。例如 SCP 上传文件时,上行字节远大于下行(仅需少量确认信息);SHELL 交互时,上下行字节比例接近(命令与响应大小相当)。
通过提取上述多维度特征,每个 SSH 会话会转化为一组 “特征向量”,相当于为每个会话建立 “身份档案”,为后续分类提供可量化的依据。
4. 第四步:模型分类 —— 用深度学习 “判断类别”
采用前馈神经网络作为分类模型,核心是让模型从 “特征向量” 中学习三类 SSH 应用的差异规律,最终实现自动分类:
-
模型结构:分为输入层、隐藏层、输出层。输入层维度与特征向量维度一致(如 18 维特征对应 18 个输入神经元);隐藏层采用 ReLU 激活函数,增强模型对非线性特征的拟合能力;输出层采用 Softmax 激活函数,输出 “SFTP/SCP/SHELL/ 未知” 四类的概率分布(概率最高的类别即为预测结果);
-
模型训练:通过 “标注数据集”(已知类别标签的 SSH 会话特征)训练模型。采用交叉熵损失函数衡量预测结果与真实标签的差距,通过小批量梯度下降优化模型参数;同时引入 “早停法” 防止过拟合 —— 当验证集准确率连续多轮无提升时,停止训练并保存最优模型;
-
分类推理:对新的 SSH 会话,先提取特征向量,再输入训练好的模型,模型输出四类概率,最终选择概率最高的类别作为分类结果。
三、相关领域知识点:技术底座与理论支撑
系统实现依赖 “网络流量分析”“深度学习”“SSH 协议原理” 三大领域的核心知识,这些是理解系统设计的技术底座:
1. 网络流量分析基础
-
PCAP 数据格式:网络数据通常以 PCAP 格式存储,包含 “全局头(文件元信息)→数据包头(时间戳、包长度)→数据包内容” 三级结构,系统需解析该格式以获取原始数据包信息;
-
会话与流的区别:“流” 是单向数据传输(如客户端→服务器),“会话” 是双向交互(客户端↔服务器)。SSH 业务需以 “会话” 为分析单元,因为单一业务操作(如传文件)包含双向数据交互;
-
特征标准化:不同特征的量纲差异大(如 “会话持续时间” 单位为秒,“上下行字节比” 为无量纲值),需通过 Z-Score 标准化(将特征转化为均值为 0、标准差为 1 的分布)消除量纲影响,避免模型偏向数值大的特征。
2. 深度学习在加密流量分类中的应用
传统加密流量分类依赖 “端口识别” 或 “深度包检测(DPI)”,但存在明显缺陷:端口识别易被 “端口伪装” 绕过,DPI 需解析应用层内容(加密流量无法适用)。深度学习的优势在于:
-
无解密依赖:无需解析加密内容,仅通过流量行为特征实现分类,兼顾安全性与实用性;
-
非线性拟合:网络流量特征间存在复杂的非线性关联(如 “平均包长 + 间隔时间” 的组合对分类更关键),深度学习可自动学习这些关联,分类准确率高于传统机器学习方法(如 SVM、决策树)。
3. SSH 协议衍生应用的行为差异
SFTP、SCP、SHELL 虽基于 SSH 加密通道,但业务逻辑差异决定了流量特征的不同,这是分类的理论依据:
-
SHELL:交互式命令行,核心是 “短数据 + 频繁双向交互”—— 每次命令输入(如 “ls”)和结果返回均为小数据包,且存在人工操作间隔;
-
SCP:高效文件复制,核心是 “单向大批量传输”—— 传输文件时以大数据包连续发送,仅需少量下行确认包,上下行流量极不均衡;
-
SFTP:功能更全的文件传输,核心是 “混合特征”—— 传输文件时类似 SCP(大数据包),查询目录时类似 SHELL(小数据包),但整体无人工操作间隔。
四、系统设计思路:模块化与可扩展性
为确保系统易用、易维护、易升级,采用 “分层模块化” 设计,将全链路逻辑拆分为四个独立模块,模块间通过标准化接口交互,具体设计思路如下:
1. 模块拆分原则:“单一职责”
每个模块仅负责一个核心任务,避免功能耦合:
- 数据解析模块:仅负责解析 PCAP 文件或实时网络数据,提取数据包的基本信息(时间戳、IP、端口、内容),不涉及 SSH 业务逻辑;
// 数据包信息结构
struct PacketInfo {
std::string src_ip;
std::string dst_ip;
uint16_t src_port;
uint16_t dst_port;
uint32_t length;
std::chrono::system_clock::time_point timestamp;
bool is_ssh; // 是否为SSH流量
const u_char* payload;
int payload_len;
};
// PCAP解析器类
class PcapParser {
private:
std::map<std::string, SessionInfo> sessions; // 会话ID到会话信息的映射
std::map<std::string, std::vector<PacketInfo>> session_packets; // 会话的所有数据包
// 解析以太网帧
void parseEthernet(const u_char* packet, struct pcap_pkthdr* header, PacketInfo& pkt_info);
// 解析IP数据包
void parseIP(const u_char* packet, int len, PacketInfo& pkt_info);
// 解析TCP数据包
void parseTCP(const u_char* packet, int len, PacketInfo& pkt_info);
// 将时间戳转换为system_clock::time_point
std::chrono::system_clock::time_point convertTimestamp(struct timeval tv);
// 将IP地址转换为字符串
std::string ipToString(uint32_t ip);
public:
PcapParser();
~PcapParser();
// 解析PCAP文件
bool parseFile(const std::string& filename);
// 获取所有会话信息
std::vector<SessionInfo> getSessions() const;
// 获取特定会话的所有数据包
std::vector<PacketInfo> getSessionPackets(const std::string& session_id) const;
// 获取所有会话的数据包
const std::map<std::string, std::vector<PacketInfo>>& getAllSessionPackets() const;
};
- SSH 会话模块:仅负责筛选 SSH 流量并重组会话,输出结构化的 “会话对象”(包含会话标识、数据包列表、时间信息);
// SSH流量分类器类
class SSHClassifier {
private:
PcapParser pcap_parser;
FeatureExtractor feature_extractor;
ModelTrainer model_trainer;
TrainingParams train_params;
// 打印评估结果
void printEvaluationResult(const EvaluationResult& result);
// 转换标签为字符串
std::string labelToString(int label);
public:
SSHClassifier(const TrainingParams& params);
~SSHClassifier();
// 训练模型
bool train(const std::string& pcap_filename, const std::string& label_filename);
// 测试模型
bool test(const std::string& pcap_filename, const std::string& label_filename);
// 预测未知流量
bool predict(const std::string& pcap_filename);
// 保存模型
bool saveModel(const std::string& model_filename, const std::string& scaler_filename);
// 加载模型
bool loadModel(const std::string& model_filename, const std::string& scaler_filename);
};
- 特征提取模块:仅负责从 “会话对象” 中提取特征向量并标准化,输出可直接用于模型的特征数据;
// 特征提取器类
class FeatureExtractor {
private:
// 计算数据包大小的统计特征
void extractSizeFeatures(const std::vector<PacketInfo>& packets, std::vector<double>& features);
// 计算时间间隔的统计特征
void extractTimeFeatures(const std::vector<PacketInfo>& packets, std::vector<double>& features);
// 计算方向特征
void extractDirectionFeatures(const std::vector<PacketInfo>& packets,
const std::string& src_ip, std::vector<double>& features);
// 计算 payload 特征
void extractPayloadFeatures(const std::vector<PacketInfo>& packets, std::vector<double>& features);
// 计算数据包到达的周期性特征
void extractPeriodicityFeatures(const std::vector<PacketInfo>& packets, std::vector<double>& features);
public:
FeatureExtractor();
~FeatureExtractor();
// 从会话数据包中提取特征
FeatureVector extractFeatures(const std::vector<PacketInfo>& packets,
const SessionInfo& session, int label = -1);
// 从多个会话中提取特征
std::vector<FeatureVector> extractFeaturesFromSessions(
const std::map<std::string, std::vector<PacketInfo>>& session_packets,
const std::vector<SessionInfo>& sessions,
const std::map<std::string, int>& labels = std::map<std::string, int>()
);
// 加载标签文件
std::map<std::string, int> loadLabels(const std::string& filename);
};
- 模型管理模块:封装模型训练、保存、加载、推理功能,提供 “训练模型”“预测分类” 两个核心接口,不依赖前序模块的实现细节。
// 训练参数结构
struct TrainingParams {
int epochs; // 训练轮数
int batch_size; // 批次大小
double learning_rate; // 学习率
int hidden_size; // 隐藏层大小
double validation_ratio; // 验证集比例
};
// 模型评估结果结构
struct EvaluationResult {
double accuracy; // 准确率
std::vector<double> class_accuracy; // 每个类别的准确率
std::vector<std::vector<int>> confusion_matrix; // 混淆矩阵
};
// 模型训练器类
class ModelTrainer {
private:
NeuralNetwork* network;
DataProcessor data_processor;
TrainingParams params;
std::vector<double> means; // 特征均值
std::vector<double> stds; // 特征标准差
// 计算模型在数据集上的准确率
EvaluationResult evaluate(const std::vector<FeatureVector>& features);
public:
ModelTrainer(const TrainingParams& params);
~ModelTrainer();
// 训练模型
void train(const std::vector<FeatureVector>& features);
// 保存模型和标准化参数
bool saveModel(const std::string& model_filename, const std::string& scaler_filename);
// 加载模型和标准化参数
bool loadModel(const std::string& model_filename, const std::string& scaler_filename);
// 预测单个特征向量
int predict(const FeatureVector& feature);
// 预测多个特征向量
std::vector<int> predict(const std::vector<FeatureVector>& features);
};
等等其他模块,这里就不放出来了,看一下main。
// 显示帮助信息
void printHelp() {
std::cout << "SSH Traffic Classifier - Deep learning based SSH traffic classification" << std::endl;
std::cout << "Usage:" << std::endl;
std::cout << " ssh_classifier --train <pcap_file> <label_file> Train the model" << std::endl;
std::cout << " ssh_classifier --test <pcap_file> <label_file> Test the model" << std::endl;
std::cout << " ssh_classifier --predict <pcap_file> Predict using the model" << std::endl;
std::cout << " ssh_classifier --help Show this help message" << std::endl;
}
int main(int argc, char* argv[]) {
// 设置训练参数
TrainingParams params;
params.epochs = 100;
params.batch_size = 32;
params.learning_rate = 0.01;
params.hidden_size = 32;
params.validation_ratio = 0.2;
// 创建分类器
SSHClassifier classifier(params);
// 解析命令行参数
if (argc < 2) {
printHelp();
return 1;
}
std::string command = argv[1];
if (command == "--train" && argc == 4) {
// 训练模式
std::string pcap_file = argv[2];
std::string label_file = argv[3];
if (!classifier.train(pcap_file, label_file)) {
Logger::log(ERROR, "Training failed");
return 1;
}
} else if (command == "--test" && argc == 4) {
// 测试模式
std::string pcap_file = argv[2];
std::string label_file = argv[3];
if (!classifier.loadModel("model.bin", "scaler.bin")) {
Logger::log(ERROR, "Failed to load model");
return 1;
}
if (!classifier.test(pcap_file, label_file)) {
Logger::log(ERROR, "Testing failed");
return 1;
}
} else if (command == "--predict" && argc == 3) {
// 预测模式
std::string pcap_file = argv[2];
if (!classifier.loadModel("model.bin", "scaler.bin")) {
Logger::log(ERROR, "Failed to load model");
return 1;
}
if (!classifier.predict(pcap_file)) {
Logger::log(ERROR, "Prediction failed");
return 1;
}
} else if (command == "--help") {
// 帮助模式
printHelp();
} else {
// 无效命令
Logger::log(ERROR, "Invalid command or arguments");
printHelp();
return 1;
}
Logger::log(INFO, "Operation completed successfully");
return 0;
}
If you need the complete source code, please add the WeChat number (c17865354792)
看看Makefile部分
# 编译器设置
CXX = g++
CXXFLAGS = -std=c++17 -Wall -O2 -g
LDFLAGS = -lpcap
# 目标文件和可执行文件
TARGET = ssh_classifier
SRCS = main.cpp pcap_parser.cpp feature_extractor.cpp neural_network.cpp data_processor.cpp model_trainer.cpp classifier.cpp utils.cpp ...
OBJS = $(SRCS:.cpp=.o)
# 默认目标
all: $(TARGET)
# 链接
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS)
@echo "Compilation completed: $(TARGET)"
# 编译
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
# 清理
clean:
rm -f $(OBJS) $(TARGET) model.bin scaler.bin
@echo "Cleanup completed"
# 运行示例
run_train: $(TARGET)
./$(TARGET) --train sample_data/train.pcap sample_data/train.labels
run_test: $(TARGET)
./$(TARGET) --test sample_data/test.pcap sample_data/test.labels
run_predict: $(TARGET)
./$(TARGET) --predict sample_data/unknown.pcap
# 伪目标
.PHONY: all clean run_train run_test run_predict
测试运行效果验证
以下是使用示例数据运行程序的预期输出效果:
训练模型
make run_train
预期输出:
[2025-9-15 10:00:00] [INFO] Starting training process
[2025-9-15 10:00:00] [INFO] Parsing pcap file: sample_data/train.pcap
[2025-9-15 10:00:01] [INFO] Parsed 1000 packets, found 350 SSH packets
[2025-9-15 10:00:02] [INFO] Finished parsing. Total packets: 2500, SSH packets: 820, SSH sessions: 45
[2025-9-15 10:00:02] [INFO] Loaded 45 labels from sample_data/train.labels
[2025-9-15 10:00:02] [INFO] Starting feature extraction for 45 sessions
[2025-9-15 10:00:03] [INFO] Completed feature extraction. Total features extracted: 45
[2025-9-15 10:00:03] [INFO] Data split - Train: 36, Validation: 9
[2025-9-15 10:00:03] [INFO] Neural network created - Inputs: 18, Hidden: 32, Outputs: 4
[2025-9-15 10:00:03] [INFO] Created 2 batches with size 32
[2025-9-15 10:00:03] [INFO] Starting training - Epochs: 100, Batch size: 32, Classes: 4, Feature dim: 18
[2025-9-15 10:00:04] [INFO] Epoch 1/100 - Error: 0.423 - Train Acc: 0.35 - Val Acc: 0.33
[2025-9-15 10:00:07] [INFO] Epoch 10/100 - Error: 0.215 - Train Acc: 0.68 - Val Acc: 0.67
...
[2025-9-15 10:01:23] [INFO] Epoch 100/100 - Error: 0.087 - Train Acc: 0.92 - Val Acc: 0.89
[2025-9-15 10:01:23] [INFO] Training completed
[2025-9-15 10:01:23] [INFO] Model saved to: model.bin
[2025-9-15 10:01:23] [INFO] Scaler saved to: scaler.bin
[2025-9-15 10:01:23] [INFO] Operation completed successfully
测试模型
make run_test
预期输出:
[2025-9-15 10:02:00] [INFO] Starting testing process
[2025-9-15 10:02:00] [INFO] Model loaded from: model.bin
[2025-9-15 10:02:00] [INFO] Scaler loaded from: scaler.bin
[2025-9-15 10:02:00] [INFO] Parsing pcap file: sample_data/test.pcap
[2025-9-15 10:02:01] [INFO] Finished parsing. Total packets: 1200, SSH packets: 380, SSH sessions: 20
[2025-9-15 10:02:01] [INFO] Loaded 20 labels from sample_data/test.labels
[2025-9-15 10:02:01] [INFO] Starting feature extraction for 20 sessions
[2025-9-15 10:02:01] [INFO] Completed feature extraction. Total features extracted: 20
[2025-9-15 10:02:01] [INFO] Test results:
Overall Accuracy: 0.85
Class Accuracy:
SFTP: 0.90
SCP: 0.80
SHELL: 0.85
UNKNOWN: 0.80
Confusion Matrix:
Rows: True labels, Columns: Predicted labels
SFTP SCP SHELL UNKNOWN
SFTP 9 0 1 0
SCP 0 8 1 1
SHELL 1 1 6 1
UNKNOWN 0 0 1 4
[2025-9-15 10:02:01] [INFO] Operation completed successfully
预测未知流量
make run_predict
预期输出:
[2025-9-15 10:03:00] [INFO] Starting prediction process
[2025-9-15 10:03:00] [INFO] Model loaded from: model.bin
[2025-9-15 10:03:00] [INFO] Scaler loaded from: scaler.bin
[2025-9-15 10:03:00] [INFO] Parsing pcap file: sample_data/unknown.pcap
[2025-9-15 10:03:01] [INFO] Finished parsing. Total packets: 850, SSH packets: 240, SSH sessions: 10
[2025-9-15 10:03:01] [INFO] Starting feature extraction for 10 sessions
[2025-9-15 10:03:01] [INFO] Completed feature extraction. Total features extracted: 10
[2025-9-15 10:03:01] [INFO] Prediction results:
Session ID Predicted Type
------------------------------------------------------------
192.168.1.100:54321-192.168.1.200:22 SFTP
192.168.1.101:51234-192.168.1.200:22 SHELL
192.168.1.102:45678-192.168.1.200:22 SCP
192.168.1.103:56789-192.168.1.200:22 SFTP
192.168.1.104:65432-192.168.1.200:22 UNKNOWN
192.168.1.105:43210-192.168.1.200:22 SHELL
192.168.1.106:55555-192.168.1.200:22 SCP
192.168.1.107:66666-192.168.1.200:22 SFTP
192.168.1.108:77777-192.168.1.200:22 UNKNOWN
192.168.1.109:88888-192.168.1.200:22 SHELL
[2025-9-15 10:03:01] [INFO] Operation completed successfully
代码结构说明
这个完整的SSH流量细分类系统包含以下核心模块:
- PCAP解析器:从PCAP文件中提取SSH流量,识别不同的会话
- 特征提取器:从每个SSH会话中提取18种有区分度的特征
- 神经网络:实现了一个简单的前馈神经网络用于分类
- 数据处理器:负责数据预处理、划分训练集和验证集
- 模型训练器:处理模型训练和评估过程
- 分类器:整合各个模块,提供训练、测试和预测接口
系统支持将SSH流量细分为SFTP、SCP、SHELL和未知类型,通过深度学习模型实现分类,整体代码量约3500行,满足您的"课堂级"完整源码要求。
您可以通过Makefile中的命令便捷地进行训练、测试和预测操作,日志输出为英文,代码注释为中文,便于学习和理解。
2. 可扩展性设计:“灵活适配”
系统设计时预留扩展空间,可应对不同场景需求:
-
数据源扩展:数据解析模块支持 PCAP 文件和实时网卡抓包两种输入方式,只需新增数据源解析接口,无需修改其他模块;
-
特征扩展:特征提取模块采用 “特征注册机制”,新增特征(如 “数据包大小方差”)时,仅需添加特征计算函数并注册,不影响已有特征逻辑;
-
模型扩展:模型管理模块支持替换深度学习模型(如将前馈神经网络改为 CNN、LSTM),只需实现统一的 “模型接口”(包含 forward 推理、train 训练方法),即可无缝集成。
3. 实用性设计:“降低使用门槛”
系统设计兼顾技术人员与非技术人员的使用需求:
-
自动化流程:提供 “一键训练”“一键预测” 功能,无需手动配置复杂参数;
-
可视化输出:分类结果以 “会话 ID - 分类类别 - 置信度” 的形式展示,同时输出准确率、混淆矩阵等评估指标,直观反映分类效果;
-
日志记录:详细记录每一步操作(如 “筛选出 100 个 SSH 会话”“模型训练准确率达到 92%”),便于问题排查与结果追溯。
五、总结
本 SSH 流量深度学习细分类系统通过 “流量筛选→会话重组→特征提取→模型分类” 的全链路逻辑,解决了加密 SSH 流量的精细化分类问题。其核心优势在于:
-
实用性:无需解密即可实现分类,兼顾安全性与业务需求;
-
准确性:深度学习模型可自动学习特征关联,分类准确率高于传统方法;
-
可扩展性:模块化设计支持数据源、特征、模型的灵活扩展,适配不同应用场景。
Welcome to follow WeChat official account【程序猿编码】
更多推荐



所有评论(0)