首页 / 资讯中心 / 文章详情

异构DoS攻击下的预设时间控制仿真与MATLAB实现

异构DoS攻击下的预设时间控制仿真与MATLAB实现 ★ FEATURED ARTICLE
简介面向异构DoS攻击下预设时间控制的MATLAB仿真代码包主要为研究网络化控制、多智能体系统或安全控制方向的学者及研究生提供从典型工况到混合复杂情景的仿真验证工具。代码包按任务场景划分多个模块涵盖典型版本、预设时间触发、周期切换拓扑、PT与PWT组合、规避策略以及PT与规避协同控制等情景方便进行基准对照与多模块联合测试。压缩包共81个文件以36个m脚本为主体配合27张jpg静态结果图、12个gif动态演示以及3个fig图形文件直观展示状态轨迹、观测误差和输出误差变化另含md说明文档与def、prj工程配置整体约53.23MB目录结构清晰、便于按模块快速定位。目前已有51人学习下载。使用者可直接运行相应主程序与功能函数快速复现异构DoS攻击下的预设时间控制效果节省建模与调参时间适合做论文复现、课程设计或相关课题预研的参考。1. 异构DoS攻击下的预设时间控制仿真的目标与适用场景把异构DoS攻击、预设时间控制、MATLAB仿真代码这三个词放在一起通常是在做一个网络化控制系统方向的控制方案验证传感器把状态测量值发给控制器中间信道被攻击者用多种方式持续干扰——周期性阻塞让你收不到包随机丢包让你不确定哪个包可信欺骗注入直接把测量值换成攻击者编造的假数据。控制器的目标不是简单地稳住系统而是保证状态在一个预先指定的时间 T 内收敛到原点附近并且这个 T 与初始状态、与攻击时间序列都无关。这篇文章给出一套能在 MATLAB 里直接运行的预设时间控制仿真代码包含异构攻击生成器、时变增益控制律、绘图和排查记录。适合正在做安全控制、网络化控制方向的研究生和工程师也适合想快速评估预设时间控制这个方向是否值得投入的从业者。2. 异构DoS攻击建模与预设时间控制律参数先定明白再写代码动手写 MATLAB 代码之前最值得花时间的是把攻击模型和控制器形式定清楚。这一步不清后面跑出来的曲线只能“看起来像那么回事”换一组参数或换一台机器结论就变。我在仿真里把异构DoS攻击拆成三种可叠加的机制再配合一个带时变增益的预设时间控制律下面分别说清楚各自的数学形式和参数选择逻辑。2.1 三种攻击模式阻塞、欺骗、随机丢包的数学描述“异构”不是指攻击流量大而是指攻击机制不同源、时间尺度不同。我在仿真里最常用的三种 DoS 变体是周期性阻塞也就是狭义的 DoS。攻击者在某个时间窗口内按固定周期和占空比阻塞通信信道控制器侧表现为“收不到新数据包”只能使用上一次收到的值。数学上用一个开关信号 s(t) ∈ {0,1} 描述s0 表示信道被占。需要设置的参数是攻击窗口 [T_start, T_end]、阻塞周期 τ 和占空比 duty。欺骗注入。攻击者有能力覆盖数据包内容把真实测量 x 替换成自己构造的假值 x_fake。它不需要持续在线而是在时间窗内以概率 p_dec 随机出手很像真实场景里的中间人篡改。随机丢包。信道质量差或者攻击者附带制造丢包每个控制周期以概率 p_loss 丢失一个分组控制器侧同样用零阶保持补位。三种攻击同时存在时控制器收到的测量值 x_hat 不再是简单的 x_true而是被叠加处理过的信号。我常用的建模顺序是先做欺骗注入再做周期性阻塞最后叠加随机丢包。注意这个顺序不是随便定的欺骗产生的假值如果恰好赶在阻塞窗口之前到达会被控制器当成正常值存入保持寄存器接下来一个阻塞周期内控制器一直拿这个假值算控制量。这个耦合细节就是“异构”二字的真正含义也是很多初版仿真会漏掉的地方。攻击模式控制模型关键参数仿真取值周期阻塞x_hat x_hold当 s(t)0T_start/T_end、τ、duty0.3s~3.5s、0.25s、0.5欺骗注入x_hat x_fake窗口 [a,b]、概率 p_dec[0.8,1.8]、0.25随机丢包x_hat x_hold概率 p_loss0.08x_hold 表示控制器上一次成功收到的测量值也就是零阶保持器记住的那个值。这个值可能是正常值也可能是被欺骗攻击污染过的假值取决于攻击时序。仿真里我用 persistent 变量来保存它第 3 章的 hdos_attack.m 里会看到具体实现。2.2 预设时间控制律为什么 k0 k1/(T-t) 能给出确定收敛上界预设时间控制在文献里也叫 prescribed-time control和有限时间控制、固定时间控制的区别很关键有限时间稳定的收敛时间上界通常依赖初始状态 x(0)而预设时间控制要求收敛时刻 T 是纯设计参数——不管初始状态多大在有界范围内也不管攻击序列怎么变有界扰动下状态都必须在 tT 时进入指定残差集。对线性被控对象 dot{x} Ax Bu我采用的控制律形式是u(t) -[k0 k1/(T_p - t)] · K · x_hat(t)t T_p为什么这个形式能给出预设时间收敛看 Lyapunov 函数 V 0.5·x‘x。令 r(t) k0 k1/(T_p - t)闭环写成 dot{x} (A - r(t)·B·K)x。忽略有界扰动项时只要 k0 让 A - k0·B·K 稳定并且 k1 足够大就能让 V 的导数满足dot{V} ≤ -2V/(T_p - t)解这个微分不等式得到 V(t) ≤ V(0)·[(T_p - t)/T_p]²当 t 趋近 T_p 时 V 趋近于 0。收敛上界 T_p 出现在不等式右端与初始状态 V(0) 完全解耦这就是“预设时间”四个字的由来。参数选择逻辑我一般是这样k0 按常规极点配置或 LQR 来选保证 t0 时刻闭环至少是稳定的k1 决定把状态“压向零”的强度k1 太大会让 T_p 附近控制输入出现尖峰太小则收敛残差大T_p 是设计规格而不是调参对象——你希望系统几秒内完成收敛就直接把 T_p 写成几。需要说明的是以上推导对标称系统成立。存在有界测量攻击时控制律里的 x_hat 带误差扰动项会被 r(t) 在 T_p 附近放大所以仿真里看到的不是严格零而是小残差。这个特性是预设时间控制在攻击场景下的固有代价也是为什么后面要做多随机种子验证。2.3 仿真场景参数表系统、控制器与攻击的参数怎么定这一节的参数会直接写进第 3 章的代码先给一张完整的清单和选择依据。参数取值选择依据A[0 1; 3 1]开环有正实部特征值能明显看出控制必要性B[0; 1]单输入二阶系统时域曲线直观K[6 4]底稿反馈增益A-B·K 特征值约 -1.5±0.87ik02.0保证初始时刻闭环稳定k11.5与 T_p 搭配T 附近增益适中T_p2.0s预设收敛时间设计规格dt1e-3固定步长欧拉法的常用取值T_sim4.0s仿真总时长大于 T_p 以观察收敛后行为攻击窗口特意设成从 0.3s 一直持续到 3.5s覆盖 T_p 前后各一段这样既能看预设时间控制在攻击持续下是否仍在 2s 附近完成收敛又能看收敛之后继续攻击会不会把系统重新打散。欺骗窗口放在 [0.8, 1.8]原因是这段时间正好是控制器增益 r(t) 快速增长的阶段此时注入假值对收敛过程干扰最明显适合用来暴露问题。3. 从零搭 MATLAB 仿真主循环攻击生成器、时变增益控制器与绘图这一章进入可以抄作业的部分。完整仿真由四个文件组成初始化脚本、攻击生成器函数 hdos_attack.m、主循环、绘图代码。为了阅读方便我把初始化、主循环和绘图放在同一个主脚本里攻击生成器单独存成函数文件。所有代码在 MATLAB R2019a 及以上版本测试可用旧版本注意把 xline 换成 plot 竖线。3.1 初始化与存储分配先把系统、攻击参数和数组准备好% prescribed_time_doS_sim.m % 异构DoS攻击下的预设时间控制仿真 clear; close all; clc; rng(2024); % 固定随机种子保证结果可复现 %% 被控对象与控制器参数 A [0 1; 3 1]; % 开环不稳定二阶系统 B [0; 1]; K [6 4]; % 底稿状态反馈增益 k_base 2.0; % 时变增益中的固定部分 k0 k_beta 1.5; % 时变增益中的时变部分 k1 T_p 2.0; % 预设收敛时间秒 %% 异构DoS攻击参数 att.T_start 0.3; % 攻击窗口起点 att.T_end 3.5; % 攻击窗口终点 att.block_period 0.25; % 周期性阻塞的周期 att.block_duty 0.5; % 阻塞占空比 att.deception_win [0.8 1.8]; % 欺骗注入时间窗 att.p_deception 0.25; % 欺骗注入概率 att.p_loss 0.08; % 随机丢包概率 att.fake_value [0.6; 0.6]; % 欺骗攻击注入的虚假状态 %% 数值仿真参数 dt 1e-3; % 固定步长 T_sim 4.0; % 仿真总时长 t 0:dt:T_sim; N length(t); x0 [1.5; -0.8]; % 初始状态初始化部分的要点有三个。第一rng(2024) 必须放在所有随机过程之前否则攻击生成器里的 rand 每次调用结果都不一样仿真就没法复现。第二att 是一个结构体把攻击参数打包在一起这样后续蒙特卡洛验证时只需要循环修改 att 的字段不用改主循环。第三K 和 k_base 分开设置是有意的K 决定反馈方向k_base 决定初始控制强度调参时先动 k_base 再动 K定位问题更快。3.2 hdos_attack.m异构攻击生成器的持久化保持逻辑攻击生成器是整个仿真里最容易写错的文件。它要模拟“控制器收到的测量值”而不是真实状态。我单独建一个函数文件用 persistent 变量保存控制器侧的保持寄存器。function [x_valid, att_id] hdos_attack(x_true, t, att) % hdos_attack 异构DoS攻击生成器 % 攻击叠加顺序欺骗注入 - 周期阻塞 - 随机丢包 % x_valid: 控制器实际收到的测量值 % att_id: 最后生效的攻击类型标识 % 0正常, 1随机丢包, 2周期阻塞, 3欺骗注入 persistent x_hold if isempty(x_hold) x_hold x_true; % 首次调用用真实值初始化 end att_id 0; x_valid x_true; %% 1) 欺骗注入时间窗内以概率 p_deception 覆盖测量值 if t att.deception_win(1) t att.deception_win(2) if rand att.p_deception x_valid att.fake_value; att_id 3; end end %% 2) 周期阻塞信道被占控制器只能使用上一次的值 if t att.T_start t att.T_end if mod(t - att.T_start, att.block_period) att.block_period * att.block_duty x_valid x_hold; % 零阶保持 att_id 2; end end %% 3) 随机丢包伯努利丢包丢包时也保持上次值 if rand att.p_loss x_valid x_hold; if att_id 0 att_id 1; end end %% 更新保持寄存器阻塞时不更新其他情况把本次结果存入 if att_id ~ 2 x_hold x_valid; end end这个函数的逻辑说明值得细看。欺骗注入先执行但如果在同一个控制周期里阻塞也生效最终输出的是 x_hold 而不是假值——这符合物理直觉被篡改的数据包要能到达控制器才会产生危害。真正危险的场景是上一个周期欺骗成功假值已经写进 x_hold下一个周期进入阻塞窗口控制器拿出来的 x_hold 就是那个假值。参数说明上mod(t-att.T_start, att.block_period) duty·period 是方波发生器duty0.5 表示每个周期内前一半阻塞、后一半放行rand 每次调用都会消耗随机数序列这就是为什么 rng 必须固定。函数末尾“att_id ~ 2 才更新 x_hold”的规则也解释了阻塞发生时保持寄存器不会被本次欺骗结果覆盖。3.3 主循环欧拉更新、预设时间增益与增益饱和主循环是仿真引擎。我采用显式欧拉法做状态更新原因是系统里存在不连续的攻击切换和状态保持逻辑固定步长更容易控制攻击时序与积分步长的对齐如果换成 ode45反而要处理事件检测才能准确捕捉阻塞沿。%% 存储分配 x zeros(2, N); % 真实状态轨迹 x_hat zeros(2, N); % 控制器收到的测量值 u zeros(1, N); % 控制输入 att_flag zeros(1, N); % 攻击标识 x(:,1) x0; %% 主循环 for i 1:N-1 % 1) 攻击生成拿到控制器视角的测量值 [x_valid, flag] hdos_attack(x(:,i), t(i), att); x_hat(:,i) x_valid; att_flag(i) flag; % 2) 预设时间时变增益 if t(i) T_p k_t k_base k_beta / (T_p - t(i)); else k_t k_base k_beta / dt; % 等效为最后一步的增益 end k_t min(k_t, 500); % 增益饱和防止奇异 % 3) 控制律与状态更新 u(i) -k_t * (K * x_valid); x(:,i1) x(:,i) dt * (A * x(:,i) B * u(i)); end % 补齐最后一个采样点的历史记录 x_hat(:,N) x_hat(:,N-1); att_flag(N) att_flag(N-1); u(N) u(N-1);主循环有四个关键参数要解释。第一k_t 在 t 趋近 T_p 时趋于无穷这是预设时间控制的理论要求但计算机数值无法表示无穷大所以用 min(k_t, 500) 做饱和——只要 dt 足够小状态在增益达到 500 之前已经被压到接近机器精度饱和不会明显改变收敛性质。第二t T_p 之后我把 k_t 固定为 k_base k_beta/dt等价于“最后一步的有效增益”避免切换瞬间增益跳变再次激励系统。第三状态更新用的是真实状态 x(:,i)而控制律用的是 x_valid这两者的区别就是攻击引入的测量误差也是残差的来源。第四如果仿真中发现状态在 T_p 附近振荡优先检查 dt 是不是太大其次再检查 k_t 饱和上限是否过高。3.4 绘图状态、控制输入与攻击时间线三张子图%% 绘图 figure(Position, [100 100 700 800]); subplot(3,1,1); plot(t, x(1,:), b, LineWidth, 1.5); hold on; plot(t, x(2,:), r, LineWidth, 1.5); xline(T_p, --k, T_p, LineWidth, 1.2); legend(x_1, x_2, T_p, Location, best); grid on; ylabel(状态); title(预设时间控制下的状态轨迹); subplot(3,1,2); plot(t, u, LineWidth, 1); xline(T_p, --k, T_p); grid on; ylabel(控制输入 u); title(控制输入注意 T_p 附近的增益尖峰); subplot(3,1,3); stairs(t, att_flag, LineWidth, 1.2); ylim([-0.5 3.5]); grid on; ylabel(攻击标识); xlabel(时间 (s)); title(攻击时间线0正常 1丢包 2阻塞 3欺骗);读图时重点看三件事。第一T_p 竖线处 x_1、x_2 是否进入你预设的残差带比如 ±1e-3第二控制输入 u 在 t 接近 T_p 时是否出现尖峰尖峰高度是否超出执行器量程第三攻击标识是否为 2 的时间段内状态出现明显台阶如果是说明保持寄存器里存的是被污染的测量值。这三张图对应预设时间控制的三个验证维度收敛性、控制能量、攻击鲁棒性。xline 需要 MATLAB R2018b 以上旧版本用 plot([T_p T_p], ylim, --k) 代替。4. 仿真避坑指南增益爆炸、随机种子与欺骗攻击耦合排查这套仿真我前后改过很多版踩过的坑集中在四个方面。每一条都按“现象 → 原因 → 解决”来写方便你对照排查。4.1 状态在 T_p 附近跳 NaN增益奇异与步长不匹配现象状态曲线在接近 T_p 时突然变成 NaN图里出现断线控制输入直接飞到 1e308。原因k_t 的理论值是 k_base k_beta/(T_p - t)当 t 非常接近 T_p 时这个值超出 double 能表达的范围更隐蔽的原因是显式欧拉法在这种大增益下不再稳定增益越大闭环特征值越远欧拉的稳定步长上限 2/|λ_max| 越小dt1e-3 在大增益段可能不够小。解决给 k_t 加饱和上限 min(k_t, 500)这是第一道保险把 dt 从 1e-3 缩小到 1e-4 对比一次如果曲线明显变化说明步长仍在起作用再不行就在状态更新里改用半隐式欧拉把 A 矩阵的刚性部分隐式处理。我的经验是 500 的饱和配合 1e-3 步长对这类二阶系统已经足够但如果你把 k_beta 调到 10 以上就必须同时缩小步长。4.2 换台机器结果就变随机种子与 persistent 残留现象同一个脚本第一次运行状态在 2s 收敛第二次运行状态在 2s 后还有一个大的抖动或者脚本连续跑两次第二次的结果和第一次完全不同。原因攻击生成器里用了 rand而主脚本只调用了一次 rng(2024)为什么第二次还不一样问题出在 hdos_attack.m 开头的 persistent x_hold。第一次运行结束时 x_hold 保存的是第一次仿真最后几步的值第二次运行时 isempty(x_hold) 为 false保持寄存器带着上一次的残留数据直接开始工作。解决主脚本开头加 clear hdos_attack强制清掉 persistent 变量rng(2024) 放在 clear 之后。如果你做蒙特卡洛循环注意在每次更换种子之前都要 clear hdos_attack否则不同随机种子之间的攻击结果会被残留的 x_hold 串起来。这也是我最开始翻车的地方建议直接写进自己的仿真模板里。4.3 欺骗值混进保持寄存器异构攻击耦合导致状态被带偏现象攻击标识为 2阻塞的时间段里状态没有保持平稳反而朝着某个方向匀速漂移且漂移方向在每次仿真中一致。原因欺骗攻击在一个非阻塞周期成功注入假值x_hold 被更新为假值下一个阻塞周期控制器拿假值算控制量控制律把系统推向错误方向。因为 x_hold 是 persistent 的这个过程会持续到下一次成功接收到真实测量为止。这不是随机扰动而是异构攻击的确定性危害。解决从建模上给控制器加一道测量校验比如判断 x_valid 的范数是否超过物理上限超过则丢弃并保持上一值从仿真验证上做一个关掉欺骗攻击的对照实验如果残差显著变小说明欺骗-阻塞耦合确实是状态偏移的主因。我一般会同时做这两件事仿真里先确认机理再在控制算法侧加校验逻辑。4.4 预设时间 T_p 设太小执行器饱和与理论失效现象T_p 从 2.0 改成 0.5 之后收敛时间反而变长甚至系统在 T_p 附近剧烈振荡控制输入明显超出执行器量程。原因T_p 缩小意味着 k_beta/(T_p - t) 在更短时间内被放大到同样水平控制输入峰值几乎按 1/T_p 的比例增长。如果被控对象带执行器饱和实际系统在饱和区间运行等效增益下降预设时间性质不再成立。这是预设时间控制的物理边界不是仿真 bug。解决仿真中加入执行器饱和u_sat max(min(u, 10), -10)再观察收敛性质如果必须使用小的 T_p需要同时增大 k_base、减小 k_beta把“靠时变增益压收敛”改成“靠高基准增益压收敛”但这样做会牺牲 T_p 附近控制输入的形状。判断标准是看饱和段占比如果超过仿真总时长的 10%说明 T_p 定得不合理需要回退参数。5. 验证预设时间性质收敛时间测量与多初值蒙特卡洛检查仿真跑通之后不能只看一眼曲线就说“有效”。预设时间控制的核心承诺是“T 与初值无关”这个性质必须用量化手段验证。我习惯做三层检查单次收敛时间测量、固定增益对照、多初值多种子批量验证。5.1 量化收敛时间一个简单的阈值判定脚本%% 收敛时间测量状态二范数首次低于阈值的时间 threshold 1e-3; idx find(vecnorm(x, 2, 1) threshold, 1); if isempty(idx) t_conv inf; else t_conv t(idx); end fprintf(收敛时间: %.4f s (阈值 %.0e)\n, t_conv, threshold);vecnorm(x, 2, 1) 按列计算状态向量的二范数find 取第一个低于阈值的采样点。阈值取 1e-3 是经验值对应“工程上认为已收敛”的精度如果你的控制目标残差是 1e-4就把阈值改成 1e-4。注意阈值不能小于数值积分本身的精度否则 idx 可能为空t_conv 变成 inf这是正常的说明该组参数下没有在仿真时间内达到预期精度。5.2 对照组实验固定增益与预设时间控制的收敛时间对比把 k_t 改成固定值 k_base其他参数和攻击序列全部保持相同跑一次完整仿真用同一个测量脚本记录收敛时间。固定增益下闭环特征值约 -1.5±0.87i理论收敛时间在 2.5s 到 3s 之间预设时间控制应该在 T_p 附近完成收敛。这个对比能直观说明时变增益项 k1/(T_p - t) 的价值——它不是锦上添花而是把收敛时间从“由系统动态决定”变成“由设计参数决定”。我在实际验证时会把两组仿真的状态轨迹画在同一张图上并标注两条收敛时间竖线。如果固定增益组的收敛时间和预设时间组差距不明显说明 k_base 本身已经足够大时变项没有发挥应有作用此时应该减小 k_base 或增大 k1让两组结果拉开差距才有说服力。5.3 多初值与多攻击相位的批量验证预设时间性质的严格说法是“收敛时间上界 T 与初始状态无关”单组初值证明不了这一点。我通常在最后跑一组批量仿真初值取 [-3, -1] 到 [3, 1] 区域内的几个代表性点随机种子取 2024 到 2033 共 10 组逐一统计收敛时间和最终残差。%% 多初值多随机种子批量验证 x0_list [1.5 -0.8; -2.0 1.0; 0.5 0.5; 3.0 -1.0; -1.0 -1.5]; seed_list 2024:2033; t_conv_all zeros(length(x0_list), length(seed_list)); for i 1:length(x0_list) for j 1:length(seed_list) rng(seed_list(j)); clear hdos_attack; % 清除 persistent 残留 % 重新运行主循环建议把主循环封装成函数 % t_conv_all(i,j) measure_conv_time(...); end end fprintf(最大收敛时间: %.4f s\n, max(t_conv_all(:)));批量验证通过后可以下结论说这套预设时间控制方案在给定攻击模型下满足设计指标。如果最大收敛时间明显超出 T_p优先检查是不是增益饱和限制了大增益段的有效性或者欺骗攻击的假值在 T_p 前最后一个阻塞周期内把状态重新踢出残差带。我自己的习惯是每改一次攻击参数就跑一遍这组批量验证防止调出一套只在某一组随机种子下好看的仿真。希望这些方法能帮你少走我踩过的坑把验证精力花在真正影响结论的地方。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站