- 渗透测试
- 网络安全
- 应用安全
【免费下载链接】reconftw
reconFTW is a tool designed to perform automated recon on a target domain by running the best set of tools to perform scanning and finding out vulnerabilities
reconFTW 是面向 bug bounty、渗透测试与安全研究场景的 Bash 侦察编排框架,其 Phase 1(Resilient Resume & Timeout Safety)集中解决长时间扫描面临的四类可靠性问题:中断后无法续跑、磁盘中途写满、并行批处理被卡死作业拖垮、DNS 枚举无限期挂起。本文基于 01-CONTEXT.md 的完整设计决策(D-01~D-17),结合 modules/core.sh、lib/parallel.sh、modules/utils.sh、modules/modes.sh 与 reconftw.cfg 的实际实现,讲清每个机制的触发链路、配置方法与源码级依据。读完你既能掌握PRESERVE=true续跑、PARALLEL_JOB_TIMEOUT_SECONDS限时等实战配置,也能理解这套设计为何选"哨兵文件 + EXIT trap"而非 PID/时间戳方案。
一、Phase 1 的边界与目标:四项 v1 需求
Phase 1 要解决的核心问题:长时间扫描在遭遇中断、磁盘压力或卡死工具时,不能静默产出截断结果,也不能在续跑时浪费数小时重复劳动。按 ROADMAP.md 的定义,Phase 1 覆盖 REQUIREMENTS.md 中的四项 v1 需求,拆分为三个计划:
| 计划 | 机制 | 对应需求 |
|---|---|---|
| 01-01 | .inprogress哨兵生命周期 + 续跑检测 | RESIL-01 |
| 01-02 | 函数边界处周期性df检查(磁盘满中途防护) | RESIL-02 |
| 01-03 | lib/parallel.sh中PARALLEL_JOB_TIMEOUT_SECONDS强制执行 +reconftw.cfgDNS 超时默认值 | RESIL-03、PERF-02 |
范围内改动面:生命周期包装位于 modules/core.sh 的start_func/end_func,并行作业机制位于 lib/parallel.sh,磁盘辅助函数位于 modules/utils.sh,四项配置默认值位于 reconftw.cfg。
明确不在范围内(推迟到其他阶段):MIN_DISK_SPACE_GB的 2-vs-5 不一致问题(DOCS-02,Phase 5)、逐工具线程上限(PERF-01,Phase 3)、针对新超时/心跳路径的并行覆盖测试(TEST-01,Phase 4)。
从 PROJECT.md 可以看到,Phase 1 的五项成果(RESIL-01/02/03、PERF-02 及 01-04/01-05 两个缺口修复)均已标记为 Validated,说明下述设计与实现已经落地为仓库中的真实代码。
二、.inprogress哨兵生命周期与续跑检测(RESIL-01)
2.1 哨兵文件的形态:纯空文件(D-01)
设计决策 D-01 规定:哨兵文件是一个纯空文件${called_fn_dir}/.inprogress_<fn>。start_func负责touch创建它;end_func负责在touch既有的.<fn>成功检查点之前删除它。不携带任何 JSON 元数据、PID 或时间戳。
源码印证(modules/core.shstart_func,L1441-L1469):
function start_func() { # Mid-run disk-full guard (D-07/D-09): abort BEFORE any state write _check_disk_mid_run || _abort_disk_full ... # Resume sentinel (RESIL-01 / D-01): touch .inprogress_<fn> as a crash-leftover marker if [[ -n "${called_fn_dir:-}" ]]; then touch "$called_fn_dir/.inprogress_${1}" 2>/dev/null || true fi log_json "INFO" "${1}" "Function started" "description=${2}" ... }对应 modules/core.shend_func(L1471-L1507):
# Resume sentinel (RESIL-01 / D-01): remove .inprogress_<fn> BEFORE touching # the .<fn> success checkpoint. A crash between the rm and the touch leaves # .<fn> absent — the existing checkpoint guard re-enters the function on the # next run. .<fn> is the source of truth; .inprogress_<fn> is a surface # indicator only. if [[ -n "${called_fn_dir:-}" ]]; then rm -f "$called_fn_dir/.inprogress_${fn}" 2>/dev/null || true touch "$called_fn_dir/.${fn}" 2>/dev/null || true fi关键语义:.<fn>是事实来源(决定是否重跑),.inprogress_<fn>只是表面指示器(用于"发生了什么"的报告),不参与控制流。若函数在rm与touch之间崩溃,.<fn>缺失,下次运行的检查点守卫会自然重入该函数——这正是透明续跑得以成立的原因(见 2.5)。
2.2 过时检测:clean-exit-gated trap(D-02)
D-02 规定过时检测采用以干净退出为门槛的 trap 清理机制:
- modules/modes.sh 的
start()(L13 起)初始化模块级标志_RECON_CLEAN_EXIT=false(实际在 L16),并安装一个独立的 EXIT-only trap调用_cleanup_inprogress; - trap 清扫以
_RECON_CLEAN_EXIT=true为门槛,该值由end()(工作流收尾函数)的最后一条可执行语句设置; - 因此干净遍历不会残留任何
.inprogress_*文件; - 而 SIGINT/SIGTERM(经由
cleanup_on_exittrap 调用exit 130)不会翻转该标志,EXIT trap 以_RECON_CLEAN_EXIT=false触发,哨兵得以保留——下次运行看到哨兵并发出 WARN 续跑横幅。
trap 安装源码(modules/modes.sh L122-L123):
trap 'cleanup_on_exit' INT TERM trap '_cleanup_inprogress' EXIT # silent EXIT-only sentinel sweep (D-02)标志翻转源码(modules/modes.sh L526-L532,end()收尾):
# Mark clean traversal so the EXIT trap's _cleanup_inprogress sweeps # ... (bypasses end() — SIGINT/SIGTERM via cleanup_on_exit, an # internal abort like _abort_disk_full's exit 1, or an unhandled error) _RECON_CLEAN_EXIT=trueEXIT trap 实现(modules/utils.sh_cleanup_inprogress,L153-L157):
function _cleanup_inprogress() { [[ "${_RECON_CLEAN_EXIT:-false}" == "true" ]] || return 0 [[ -n "${called_fn_dir:-}" ]] && rm -f "${called_fn_dir}"/.inprogress_* 2>/dev/null return 0 }注意,start()中还已存在一个 ERR trap(modules/modes.sh L140 附近),新增的 EXIT trap 必须与它组合而非替换——可通过单个注册字符串链式挂多个 handler,或重构为同时调用两者的单一_recon_exit_hook。
2.3 为何弃用 PID / 时间戳方案(D-03)
D-03 解释了选型的理由:项目是单操作员、单目标约束(见 PROJECT.md Constraints 与 CLAUDE.md),同一called_fn_dir永远不会被并发运行竞争。这一约束使得"目录里还留着哨兵 = 之前崩溃过"成为安全推断,从而完全不需要 PID 存活探测或时间戳过时窗口。PID 方案在长时运行机器上还会因PID 回收而失效(旧进程的 PID 可能被新进程复用,导致误判存活)。
因此规划阶段明确要求:不要出于"保险"重新引入 PID/时间戳元数据——在单操作员约束下,更简单的设计才是正确的设计(见原文档 Specific Ideas 小节)。
2.4 续跑报告:单行横幅而非逐函数徽章(D-04)
D-04 规定:当start()时发现一个或多个.inprogress_*文件,在 recon 横幅顶部输出一行汇总:
WARN resume: N functions re-running after interruption (fn_a, fn_b)之后静默继续——不做逐函数RESUME徽章,不在模块区内部增加额外噪声。JSONL 日志同步输出level=WARN func=resume reason=inprogress_leftover funcs=fn_a,fn_b。
该设计刻意保持OK/WARN/FAIL/SKIP徽章词汇不变(徽章词汇表锁定于 CONVENTIONS.md),汇总行是唯一的续跑专属 UI。横幅渲染方式(用现有_print_msg WARN还是新_print_resume_banner辅助函数)属于规划层渲染选择;由于它是 WARN 级别,在默认OUTPUT_VERBOSITY=1下即可见,而_print_error路径的磁盘满错误则始终可见。
2.5PRESERVE=false清理与透明重执行(D-05 / D-06)
- D-05:
PRESERVE=false(默认)在运行开始前就会清空.<fn>检查点;同一个循环也必须清理任何孤儿.inprogress_*文件,保证PRESERVE=false的运行永不报告续跑。而PRESERVE=true时,trap 清理 + 残留检测逻辑正是续跑得以工作的机制。 - D-06:函数重执行是透明的。既有检查点守卫
[[ ! -f "$called_fn_dir/.${FUNCNAME[0]}" ]] || [[ $DIFF == true ]]本就会重跑.<fn>不存在的函数——崩溃的函数从未到达end_func,其.<fn>必然缺失,守卫自然重入。哨兵文件纯粹服务于"发生了什么"的表面报告,不驱动控制流。
这与 ROADMAP.md 的成功标准 1 完全一致:"中断sub_brute后以PRESERVE=true重跑,产生清晰的.inprogress_sub_brute指示,且仅重执行该函数——已完成的函数保留.<func>检查点并被跳过"。
三、磁盘满中途防护(RESIL-02)
3.1 检查节奏:每个函数边界(D-07)
D-07 规定检查节奏为每次start_func/end_func边界:
- 新增辅助函数
_check_disk_mid_run,位于 modules/utils.sh(紧挨既有check_disk_space()); start_func在既有函数体之前调用它;end_func在 touch 检查点之后调用它。
源码印证:start_func第一行即_check_disk_mid_run || _abort_disk_full(modules/core.sh L1444),end_func在持久化.status_<fn>之后、收尾之前再次执行_check_disk_mid_run || _abort_disk_full(modules/core.sh L1575),注释明确说明"在.<fn>与.status_<fn>可靠写入之后执行,让已完成的函数留下完整成功记录;在此中止可保护下一个函数不在无余量状态下运行"。
成本评估:每次调用约 1ms,一个扫描约 100 次函数边界,总开销可忽略;不引入后台监视进程。
3.2 阈值单一来源:复用MIN_DISK_SPACE_GB(D-08)
D-08 规定阈值就是 pre-flight 检查所用的同一个MIN_DISK_SPACE_GB(单一事实来源),实现如下(modules/utils.sh L449-L453):
# Mid-run disk-full check: thin wrapper around check_disk_space using MIN_DISK_SPACE_GB (D-07/D-08). function _check_disk_mid_run() { check_disk_space "${MIN_DISK_SPACE_GB:-5}" "${dir:-.}" return $? }底层的check_disk_space()(modules/utils.sh L432-L447)用df -Pk计算可用 GB,跨 macOS/Linux 可移植,返回 0/1 并填充DISK_SPACE_INFO。Phase 5(DOCS-02)将解决reconftw.cfg中MIN_DISK_SPACE_GB=2(reconftw.cfg L49)与 modules/modes.shstart()中${MIN_DISK_SPACE_GB:-5}回退默认值 5 之间的差异;Phase 1 刻意不碰这两处,运行期读到哪个值就用哪个值,也不引入独立的中途旋钮。
3.3 中止策略:整轮硬中止(D-09)
D-09 规定磁盘满时硬中止整个运行:_check_disk_mid_run返回非零 → 调用_abort_disk_full。实现(modules/utils.sh L455-L460):
function _abort_disk_full() { _print_error "disk_full: aborting (${DISK_SPACE_INFO:-disk space exhausted})" log_json "ERROR" "${FUNCNAME[1]:-main}" "Disk space exhausted" "reason=disk_full" "info=${DISK_SPACE_INFO:-unknown}" exit 1 }它输出disk_full: aborting (avail=XGB, req=YGB at dir)形式的错误、记录log_json ERROR disk_full abort_run,然后exit 1。此时 D-02 的 Bash EXIT trap 会在退出路上触发,清空所有.inprogress_*——后续运行不会看到虚假的续跑条件。软中止与暂停等待方案均被否决:单操作员项目,快速失败(fail-fast)才是正确选择。
3.4 ENOSPC 检测机制:仅边界df(D-10)
D-10 明确检测机制只有边界df:不做run_command的 stderr 扫描(No space left on device),不做每个重定向的失败 trap。这是有意识接受的权衡:某个工具在单个函数内部耗尽磁盘(如gotator写出 2GB 词表)时,该函数可能产生截断输出,但下一次start_func会在造成进一步破坏前中止整个运行。pre-flight 5GB 余量 + Phase 5 的 DOCS-02 对齐让这种情况成为罕见边缘场景;对 v1 而言,全量逐写 trap 属于过度设计。
四、PARALLEL_JOB_TIMEOUT_SECONDS强制执行(RESIL-03)
4.1 默认值:0(禁用、显式启用)(D-11)
D-11 规定默认值PARALLEL_JOB_TIMEOUT_SECONDS=0(禁用、opt-in),随 reconftw.cfg 发布,并附文档注释明确建议:长扫描用3600,CI 运行用600。这样在运行的扫描零风险被过度激进的默认值杀死,且向后兼容。
实际配置(reconftw.cfg L330-L331):
PARALLEL_JOB_TIMEOUT_SECONDS=0 # 0 disables; e.g. 3600 for long scans, 600 for CI PARALLEL_KILL_GRACE_SECONDS=10 # Seconds between TERM and KILL when enforcing PARALLEL_JOB_TIMEOUT_SECONDS规划层面特意强调:不要提议非零默认值(见原文档 Specific Ideas)。
4.2 执行点:既有 batch-flush 心跳循环(D-12)
D-12 规定执行点位于既有的batch-flush 心跳循环(lib/parallel.sh,parallel_funcs的 batch 等待区)。该循环原本每PARALLEL_HEARTBEAT_SECONDS(默认 20s)用kill -0 ${batch_pids[$idx]}轮询存活 PID;扩展后为每个存活 PID 计算now - batch_starts[$idx],若超过PARALLEL_JOB_TIMEOUT_SECONDS(且变量> 0)则调用_timeout_kill_job。
实际源码(lib/parallel.sh L516-L524,batch flush 心跳内):
for idx in "${!batch_pids[@]}"; do if kill -0 "${batch_pids[$idx]}" 2>/dev/null; then alive=1 job_dur=$((now - batch_starts[$idx])) # Timeout enforcement (RESIL-03 / D-11..D-14): fires regardless of # verbosity (CR-02 fix). Uses hoisted _to from outer scope. if (( _to > 0 )) && (( job_dur > _to )); then _timeout_kill_job "${batch_pids[$idx]}" "${batch_funcs[$idx]}" "$job_dur" fi ...CR-02 缺口修复使超时执行与--quiet无关(心跳循环在"超时启用或verbose 进度开启"时即运行,见 L508 与 L629 的循环条件),保证 CI 场景(--quiet)下超时依然生效。注意 lib/parallel.sh 的注释还记录了一个已知细节:PARALLEL_HEARTBEAT_SECONDS=0会完全禁用该循环,从而也禁用超时执行(WR-05,计划在 Phase 5 DOCS-01 处理)。
4.3 杀进程行为:TERM 后 KILL(D-13)
D-13 规定先 TERM 再 KILL:新旋钮PARALLEL_KILL_GRACE_SECONDS=10(默认)。_timeout_kill_job先发kill -TERM $pid,随后以 1 秒间隔轮询kill -0 $pid直至宽限期结束,若仍存活则kill -KILL $pid。这符合 Unix 关停语义,并能对付无视 TERM 的工具。
实现(lib/parallel.sh_timeout_kill_job,L77-L105):
function _timeout_kill_job() { local pid="$1" func_name="$2" duration_sec="$3" local grace="${PARALLEL_KILL_GRACE_SECONDS:-10}" [[ "$grace" =~ ^[0-9]+$ ]] || grace=10 _kill_tree "$pid" TERM local i for ((i=0; i<grace; i++)); do kill -0 "$pid" 2>/dev/null || break sleep 1 done _kill_tree "$pid" KILL ...CR-03 修复让_timeout_kill_job切换为进程树击杀:_kill_tree(lib/parallel.sh L55-L66)通过pgrep -P递归遍历先信号化叶子节点再信号化父节点,确保真正的底层外部工具(puredns、dnsx、ffuf、axiom-scan 等)被终止,而不只是包装子 shell——修复前的行为是只杀包装 PID,导致工具被孤儿化到 PID 1 后继续超时运行。若宿主机缺pgrep,则优雅退化为仅杀包装(与补丁前行为一致),运行不失败。进程组击杀方案(kill -- -<pgid>)被否决,因为 modules/modes.sh L17 显式set +m禁用了作业控制,包装子 shell 没有独立 pgid。
4.4 超时报告:FAIL + reason=timeout(D-14)
D-14 规定被击杀作业的徽章为FAIL,原因timeout:持久化到.status_<fn>(FAIL)与.status_reason_<fn>(timeout),复用 modules/core.sh 既有的状态持久化模式(原文档引用 L1505-L1509,当前实现位于end_func的 L1547-L1552)。批计数器failed++,于是RECON_PARTIAL_RUN=true由既有聚合器自动跟随。控制台徽章输出FAIL func_name 600s (timeout)。
_timeout_kill_job中的持久化与结构化日志(lib/parallel.sh L96-L104):
if [[ -n "${called_fn_dir:-}" ]]; then printf "FAIL\n" >"${called_fn_dir}/.status_${func_name}" 2>/dev/null || true printf "timeout\n" >"${called_fn_dir}/.status_reason_${func_name}" 2>/dev/null || true fi if declare -F log_json >/dev/null 2>&1; then log_json "ERROR" "${func_name}" "Job timed out" "reason=timeout" "duration_sec=${duration_sec}" fi下游_parallel_emit_job_output(lib/parallel.sh L235-L363)读取这两个文件并在 FAIL 徽章上渲染reason: timeout,无需任何 schema 扩展。实际杀延迟 = 阈值 + 约 1s(心跳轮询节奏)+PARALLEL_KILL_GRACE_SECONDS(此计算已写进 reconftw.cfg L328-L329 的注释)。
4.5 本地与 Axiom 通用(D-15)
D-15 强调超时对本地与 axiom 分布式作业同样适用——两者的并行批处理包装是同一代码路径,无特例。Axiom 无需改动:超时击杀发生在父 shell 的parallel_funcs心跳层、每个作业子 shell 之前;从并行批处理内部发起的 axiom 分布式作业在本地子 shell 层被击杀(axiom-scan命令被终止,其本身会向远端节点发信号,这已足够)。
五、DNS 超时默认值(PERF-02)
5.1 默认值从0改为非零(D-16)
D-16 规定 reconftw.cfg 中两个 DNS 超时默认值从0改为:
DNS_BRUTE_TIMEOUT=6h # timeout/gtimeout duration for DNS bruteforce (0 disables hard-timeout). Default protects against hung resolvers. DNS_RESOLVE_TIMEOUT=4h # timeout/gtimeout duration for DNS resolve (0 disables hard-timeout). Default protects against hung resolvers.(当前实现位于 reconftw.cfg L414-L415;规划文档中的原始引用行号为 L387-L388,随阶段推进行号有位移。)
这两个值都经由_run_dns_with_heartbeat(modules/utils.sh L1434 附近)透传,该辅助函数尊重0(禁用)——非零的h后缀时长被timeout/gtimeout原样接受。辅助函数本身零代码改动,只改 cfg 默认值加内联文档注释。
5.2 超时触发后的呈现(D-17)
D-17 规定:硬超时触发时,既有的_run_dns_with_heartbeat已经返回非零并输出清晰的日志行,无需新增呈现逻辑——既有的徽章路径(end_func的WARN)已足够。JSONL 日志条目应携带reason=dns_hard_timeout,让下游工具(Phase 4 测试、AI 报告)能够区分该原因。
这与 ROADMAP.md 成功标准 4 一致:"新装reconftw.cfg出厂即带非零DNS_BRUTE_TIMEOUT=6h与DNS_RESOLVE_TIMEOUT=4h默认值,卡死的 DNS 运行以日志化超时中止,而不是无限期阻塞"。它修复了 CONCERNS.md 中"两个硬超时守卫默认0(禁用),大词表上的长 DNS 爆破可能无限期运行"的性能隐患。
六、可复用资产与集成点速查
6.1 既有可复用资产
| 资产 | 位置 | 在 Phase 1 中的作用 |
|---|---|---|
check_disk_space() | modules/utils.sh L432 | 已返回 0/1 并填充DISK_SPACE_INFO;_check_disk_mid_run包装它,无需重实现df解析 |
start_func/end_func | modules/core.sh L1441 / L1471 | 并行安全的逐函数开始时间戳与record_func_timing保留;哨兵操作插入指定位置 |
_run_dns_with_heartbeat | modules/utils.sh L1434 | 已尊重0=disabled并接受timeout/gtimeout风格时长;DNS 硬超时只改 cfg |
| 心跳循环 | lib/parallel.sh L508-L544 / L629-L665 | 已迭代存活 PID;超时击杀检查插入其中 |
| 状态持久化模式 | modules/core.sh L1547-L1552 | .status_<fn>与.status_reason_<fn>模式已存在;超时报告(D-14)直接复用 |
log_json辅助函数 | 各模块 | D-09、D-14、D-17 复用同一调用形态log_json LEVEL func msg key=val ... |
6.2 集成点清单
start()(modules/modes.sh L13):安装_cleanup_inprogress的 EXIT/INT/TERM trap(D-02)、在首个模块开始前输出续跑汇总横幅(D-04)、承载PRESERVE=false孤儿清理循环(D-05)。- 既有 ERR trap(modules/modes.sh L140 附近):新 EXIT trap 必须与之组合而非替换。
reconftw.cfg:本阶段四处配置——PARALLEL_JOB_TIMEOUT_SECONDS=0、PARALLEL_KILL_GRACE_SECONDS=10(并行旋钮应紧邻PARALLEL_HEARTBEAT_SECONDS文档区,实际位于 reconftw.cfg L328-L331),以及DNS_BRUTE_TIMEOUT=6h、DNS_RESOLVE_TIMEOUT=4h两处取值变更(reconftw.cfg L414-L415)。- Axiom 无改动:见 4.5 节。
6.3 既有模式约束
- 徽章词汇表锁定:
OK/WARN/FAIL/SKIP/CACHE/INFO/RUN(CONVENTIONS.md)。超时击杀 =FAIL(D-14),磁盘满中止 =FAIL(D-09),续跑提示 =WARN(D-04),不引入任何新徽章值。 - verbosity 门控:
OUTPUT_VERBOSITY=0/1/2已管控哪些_print_msg/notification调用可见。续跑汇总行是 WARN 级别,默认 verbosity 1 下可见;磁盘满错误走_print_error,始终可见。 - CLI-over-config 重应用:本阶段新增旋钮(如
PARALLEL_KILL_GRACE_SECONDS)不需要 CLI 标志,env-var/cfg 覆盖已足够;若日后加标志,遵循reconftw.sh的CLI_*重应用模式。 - Source guards:本阶段不新增 lib 文件,全部改动进既有 lib/parallel.sh、modules/core.sh、modules/utils.sh、modules/modes.sh、reconftw.cfg,通过编辑既有文件保持 source-guard 模式。
6.4 命名约定
D-01 之外的私有辅助函数名(_check_disk_mid_run、_abort_disk_full、_timeout_kill_job、_cleanup_inprogress)遵循 CONVENTIONS.md 的下划线前缀私有约定(当前源码均以function关键字声明,符合函数命名规则)。JSONL 日志的 key/value 拼写(reason=inprogress_leftover、reason=timeout、reason=dns_hard_timeout)沿用 modules/core.sh 既有模式。
七、推迟项与边界(明确不做的内容)
原文档 Deferred 小节列出的刻意推迟项,理解它们有助于避免在后续使用中误以为存在缺失功能:
- 逐工具超时覆盖(如
PARALLEL_TIMEOUT_DNS_BRUTE_SECONDS):v1 讨论后否决;用户可上调PARALLEL_JOB_TIMEOUT_SECONDS以容纳最慢工具。仅在真实调优需求出现后重新评估。 - 函数中段的磁盘后台心跳监视器:能在下一个边界前捕获单个函数烧盘,但鉴于 5GB pre-flight 余量被否决为过度设计;若遥测显示截断事件,可在未来"可观测性"里程碑考虑。
- 逐重定向 ENOSPC trap包裹每个
>/>>:最彻底但侵入全代码库,v1 不在范围内。 MIN_DISK_SPACE_GB2-vs-5 对齐:明确归 Phase 5(DOCS-02);Phase 1 刻意不碰 reconftw.cfg 与 modules/modes.sh 的取值。- 新代码路径的测试:Phase 4(TEST-01)覆盖
parallel_funcs超时击杀路径;哨兵生命周期与磁盘满处理测试可并入该阶段——Phase 1 交付行为,Phase 4 交付覆盖率。从 ROADMAP.md 可以看到,Phase 1 还额外完成了 01-04(_RECON_CLEAN_EXIT门控,对应 RESIL-01/CR-01)与 01-05(超时执行脱离--quiet门控 +_kill_tree进程树击杀,对应 RESIL-03/CR-02、CR-03)两个缺口闭合计划。
八、实战配置速查
将以下配置应用于 reconftw.cfg 即可启用 Phase 1 的三大实战能力:
# --- 续跑(RESIL-01)--- # PRESERVE=true 时,中断后重跑会检测 .inprogress_* 哨兵并只重执行崩溃函数 PRESERVE=true # --- 磁盘满中途防护(RESIL-02)--- # 阈值沿用 pre-flight 的 MIN_DISK_SPACE_GB(注意 cfg 写 2、modes.sh 回退 5 的差异归 Phase 5) MIN_DISK_SPACE_GB=5 # --- 并行作业超时(RESIL-03)--- # 0 禁用;长扫描建议 3600,CI 建议 600 PARALLEL_JOB_TIMEOUT_SECONDS=600 # 先 TERM、宽限期后仍存活再 KILL 的间隔秒数 PARALLEL_KILL_GRACE_SECONDS=10 # --- DNS 硬超时(PERF-02)--- # 0 禁用硬超时;默认值已保护免受挂死 resolver 阻塞 DNS_BRUTE_TIMEOUT=6h DNS_RESOLVE_TIMEOUT=4h典型场景与预期行为:
- 中断续跑:
sub_brute执行中被 Ctrl-C → 重跑(PRESERVE=true)→ 横幅输出WARN resume: 1 functions re-running after interruption (sub_brute),其余已完函数因.<fn>存在被跳过。 - 磁盘写满:运行中途可用空间跌破
MIN_DISK_SPACE_GB→ 下一函数边界_check_disk_mid_run失败 →_abort_disk_full输出disk_full: aborting (...)并exit 1,EXIT trap 顺带清理哨兵,后续运行不误报续跑。 - 卡死工具:某并行作业超过
PARALLEL_JOB_TIMEOUT_SECONDS→_kill_tree TERM(宽限 10s)→_kill_tree KILL→ 徽章FAIL func_name 600s (timeout),failed++使RECON_PARTIAL_RUN=true,批次继续而非整体停摆。 - DNS 挂起:resolver 卡死导致 DNS 爆破超过
6h/ 解析超过4h→_run_dns_with_heartbeat经timeout/gtimeout终止并返回非零,日志携带reason=dns_hard_timeout,end_func以WARN徽章呈现。
九、总结
Phase 1 以"哨兵文件 + 干净退出门控 trap"替代 PID/时间戳方案,把续跑检测收敛为纯表面指示,让控制流继续由.<fn>检查点驱动;以边界df检查 + 硬中止拦截磁盘写满,避免截断输出污染后续管线;以heartbeat 循环内的 TERM→KILL 进程树击杀为并行批处理提供每作业时限;并以6h/4h的 DNS 硬超时默认值堵住无限阻塞。四者共用既有徽章词汇、log_json形态与状态持久化模式,未新增任何配置之外的运行面——整套设计在"单操作员、fail-fast、向后兼容"三大约束下,用最小的机制面换取确定性的恢复与中止语义。对希望在长时侦察中保住已投入计算、又能防止环境故障静默劣化输出的使用者而言,这四项配置与行为是优先理解的可靠性基座。
- 渗透测试
- 网络安全
- 应用安全
【免费下载链接】reconftw
reconFTW is a tool designed to perform automated recon on a target domain by running the best set of tools to perform scanning and finding out vulnerabilities
相关推荐
ESPHome 完整指南:4 步让 ESP8266 说出温湿度数据
ESPHome 完整指南:4 步让 ESP8266 说出温湿度数据 抽屉里那块吃灰的 NodeMCU,加上不到 50 行的 YAML,几分钟之后它的温湿度读数就
渗透测试网络安全应用安全如何购买第一台云服务器用于个人知识库网站?
如何购买第一台云服务器用于个人知识库网站? 《toBeBetterJavaer》(二哥的Java进阶之路)在「知识库搭建」章节完整记录了它的知识库网站从码云 P
渗透测试网络安全应用安全Grist:如何用关系型表格管理复杂数据
Grist:如何用关系型表格管理复杂数据 客户表、订单表、跟进记录,三张表各放各的。改一个客户名,十几处要手动同步。Grist 是一种关系型表格工具,每列有固定
渗透测试网络安全应用安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考