尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

一次攻击请求的内部旅程:如何读懂 smsBomb 的调度引擎

一次攻击请求的内部旅程:如何读懂 smsBomb 的调度引擎 一次攻击请求的内部旅程如何读懂 smsBomb 的调度引擎【免费下载链接】smsBomb短信炸项目地址: https://gitcode.com/gh_mirrors/sms/smsBombsmsBomb 是 GitHub 加速计划下的一款短信轰炸工具Python 3多进程 插件化。本文不聊它能做什么而是顺着一次攻击请求从命令行到发送成功的完整链路拆解它的调度引擎加权随机选路、失败降权、进程池并发、进度回调。读完你就能回答三个问题——并发从哪来、服务商如何被选中、失败后发生了什么。出发前先看一张全景图运行python -m smsBomb -t 13800138000 -n 10之后程序内部的旅程大致是这样的主线就一条选节点 → 发请求 → 记结果 → 回调节点。下面逐站拆开看。第一站参数怎么变成攻击对象入口在 smsBomb/cli.py。它先扫出smsBomb/plugins/下所有插件模块名再读取config/sms.json可用-p过滤出单个服务商最后把配置、目标号码、进程数、次数打包成SmsBomb对象。容易被忽略的是日志初始化def setup_logger(name, use_colorsTrue, verbose_count0): level max(5 - verbose_count, 0) * 10 logger logging.getLogger(name) if use_colors: coloredlogs.install(loggerlogger, levellevel, ...) logging.getLogger(requests).setLevel(level) return logger关键在于level max(5 - verbose_count, 0) * 10这条换算。verbose_count来自-v参数的重复次数换算结果和大多数人以为的不一样参数换算级别你能看到什么不带 -vCRITICAL(50)几乎什么都不显示-vWARNING(40)节点失败、无此插件等警告-vvINFO(30)攻击开始/完毕、API 返回-vvvDEBUG(20)请求体、攻击进度百分比、requests 库细节也就是说-v只到 WARNING想看攻击进度得用-vvv进度信息是用logger.debug打的。这一步设计动机很实际默认静默、按需放量避免噪音淹没关键信息。另外注意它对requests库的日志也做了统一级别设置所以-vvv时连 HTTP 连接细节都会刷出来——这正是排查网络问题的入口。第二站每次攻击选中谁SmsBomb.start()里是一个 while 循环每次迭代先调_random_weight_select()挑一个配置节点def _random_weight_select(self): weight_lst [[k, v.copy()] for (k, v) in enumerate(self.config_lst) for _ in range(v.get(weight, 1))] if weight_lst: return random.choice(weight_lst) return None这段代码的思路是展开再随机把每个配置按weight值复制多份放进列表比如权重 3 就复制 3 份然后random.choice一次。权重越大被选中的概率越高。为什么用加权随机而不是轮询因为短信服务商质量参差不齐——某家的 app_key 可能随时被封或欠费。加权随机天然具备概率容错某个节点坏了只是它被选中的概率下降而不是整个调度卡住。观察点v.copy()是浅拷贝意味着后面对current_config的修改不会污染原列表但下面你会看到降权恰恰是写回原列表的。第三站并发从哪里来选好节点后程序不是直接发请求而是扔进进程池pool multiprocessing.Pool(processesself.process_num) ... success pool.apply(worker, args(cls, send, self.target), kwdspayloads)process_num默认 5cli.py 里还做了min(process_num, times)保护防止进程数超过攻击次数真正干活的worker是一个薄封装def worker(*args, **kwargs): obj, method_name args[:2] logging.debug({obj}-{method_name}({args},{kwargs}).format( objtype(obj).__name__, method_namemethod_name, argsargs[2:], kwargskwargs)) return getattr(obj, method_name)(*args[2:], **kwargs)它只做两件事打一条 debug 日志说明谁调用了谁然后getattr反射调用插件对象的send。这里有个容易忽略的点obj是插件实例但它是pool.apply的参数传进子进程的所以插件类必须能被 pickle 序列化——这正是 smsBomb/smsBomb.py 里LoggerMixin用属性动态获取 logger而不是在__init__里self.logger ...的原因logger 对象无法被 pickle注释里就引用了这个坑。多进程下每个子进程共享一份配置快照日志级别、格式一致所以你看到的输出是有序的。第四站失败之后节点被降权如果send返回了假值比如阿里云插件里resp[Code] ! OK就进入降权逻辑self.logger.warning(节点%s请求失败,尝试降低此配置的优先级..., current_config) self.config_lst[index][weight] max(current_config.get(weight, 1) - 1, 0) current_config[weight] 1 self.failed_config_lst.append(current_config) failed_cnt 1三步走把原列表里该节点的weight减 1最低到 00 就彻底退出选择把副本的权重重置为 1 后塞进failed_config_lst失败计数 1。这套失败降权是调度引擎的核心策略表现差的节点越选越少直到全部归零。那全部归零后呢循环开头有句if not cfg:此时会打 warning 并执行re_config(self.failed_config_lst)——把之前所有失败节点整体复活它们的权重都是 1同时失败计数 1 再继续。这个复活设计很务实没有可用节点时宁可从失败列表里重新试也不让任务干等。观察点re_config会清空failed_config_lst所以复活后如果再次全灭失败列表是从空列表重新累积的。第五站进度如何传出来每次迭代末尾都会调cb(success_cnt, failed_cnt, self.limit)cb是双通道的CLI 默认走progress_infoGUI 传入自己的回调。def progress_info(self, success_cnt, failed_cnt, limit, force_finishedFalse): if success_cnt limit or force_finished: self.logger.info(攻击完毕,成功: {0}次, 失败: {1}次.format(...)) return self.logger.debug(攻击进度(成功数/期望攻击次数): %d/%d %.2f%%, 实际攻击目标次数(含失败): %d(失败%d次, 失败率: %.2f%%), ...)对应到-vvv下的真实输出大致长这样[DEBUG 2018-05-31 11:29:17 smsBomb.smsBomb:168] 攻击进度(成功数/期望攻击次数): 1/10 10.00%, 实际攻击目标次数(含失败): 1(失败0次, 失败率: 0.00%) [INFO 2018-05-31 11:29:20 smsBomb.smsBomb:163] 攻击完毕,成功: 10次, 失败: 0次GUI 侧的回调在 smsBomb/gui.py 的refresh_progress_bar它把成功数写进 Kivy 的NumericProperty进度条就会自动刷新注意force_finished时它会用attack_cnt current_attacked_cnt把进度条停在当前值而不是强制拉满——这个小细节保证了提前失败时进度条是诚实的。实战用法与避坑清单调参看这里-n 50 --process 8把攻击次数和并发提上去权重写在config/sms.json每个节点的weight字段想让某家服务商多干活就调大它。想看调度细节用-vvv观察三样东西worker的调用日志、攻击进度的 debug 行、节点xxx请求失败的 warning 行。0.95 的最大失败率阈值max_allowed_failed_rate是硬编码在SmsBomb.__init__里的想改只能动源码。容易踩的坑-v≠ 详细日志。看到怎么什么日志都没有先数清楚-v的个数-vvv才是调试态。进程数不是越大越好cli.py 里min(process_num, times)会把它限制到不大于攻击次数-n 3 --process 10实际只开 3 个进程。插件实例要跨进程传递所以SmsPlugin子类别在__init__里持有不可 pickle 的对象比如直接存 logger这是LoggerMixin用属性动态取 logger 的原因。复活机制的代价全部节点失效后会重置所有权重可能导致大量失败 → 全部复活 → 再来一轮观察失败率日志判断是否该停。最后这套引擎能带给你什么剥掉短信轰炸的外壳smsBomb/smsBomb.py里这套加权随机 失败降权 进程池 进度回调的组合其实是一个约 100 行的通用调度器模板。写爬虫多代理轮换、对接多供应商 API、做多路请求负载均衡时都可以直接套用weight控制偏好、失败降权实现自愈、cb解耦进度展示。下次你写类似系统时不妨先照着这个骨架画一张链路图再决定每个环节怎么实现。【免费下载链接】smsBomb短信炸项目地址: https://gitcode.com/gh_mirrors/sms/smsBomb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表