ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

WebBatchRequest:轻量级HTTP批量探测工具原理与实践

WebBatchRequest:轻量级HTTP批量探测工具原理与实践 简介WebBatchRequest是一款面向网络技术初学者与个人学习者的轻量级批量探测工具专为快速检测目标网站存活状态及提取HTML标题而设计适用于网站运维自查、学习HTTP协议响应机制或开展小规模网络信息采集实践。资源包共12个文件含6个Java源码如Http.java、Gui.java实现核心请求与界面逻辑、3个.zbak备份文件、1个README.md说明文档、1个pom.xml构建配置及1个附赠内容压缩包整体仅608KB结构紧凑便于阅读与二次开发。已有400人学习下载读者可直接运行编译后的Java程序通过文本列表导入URL批量发起GET请求实时获取响应状态码与内容同时掌握网络请求封装、多线程控制及GUI交互等实用编程技巧。/p h21. WebBatchRequest 不是扫端口的“黑匣子”而是你手里的轻量级 HTTP 探针500 个 URL 3 秒内完成存活判断 标题提取适合渗透前情侦察、资产收敛和日常巡检/h2 p你有没有试过用 codecurl/code 逐个敲命令去测几十个域名是否在线或者写个 Python 脚本跑 coderequests.get()/code结果卡在某个超时域名上整个列表停住不动更糟的是你明明看到页面返回了 200但 codetitle/code 标签却空着——不是没标题是响应体被截断、编码乱了、JS 渲染了、meta charset 没识别对。WebBatchRequest 就是为解决这种「表面通、实际废」的探测玄学而生的它不依赖浏览器引擎不走 Selenium纯 HTTP 层批量发请求但做了三件事死磕细节——strong连接层超时分级控制DNSTCP读取、HTML 标题智能提取支持 UTF-8/GBK/GB2312 自动探测 codetitle/code 多位置 fallback、失败重试策略可配非 200 也抓 body/strong。它不是给红队做深度指纹的而是给安全工程师、运维、甚至开发同学做「第一眼资产快筛」的——比如导出 Jenkins、GitLab、Confluence 的所有测试环境地址3 秒内告诉你哪些还活着、首页叫什么名字。文件就一个 codewebbatchrequest.py/code无依赖Python 3.7 自带 codehttp.client/code 和 codehtml.parser/code不装包、不配环境扔进终端就能跑。如果你要的是高并发、带代理链、自动登录、截图存证——这不是它的战场但如果你要的是「稳、快、准、轻」四个字落地成行那它就是你今天该抄进 code/usr/local/bin/code 的那个脚本。/p hr / h22. 原理与选型为什么不用 requests 或 asyncio而用底层 http.client 自定义 parser/h2 h32.1 为什么放弃 requests连接控制粒度太粗超时逻辑反直觉/h3 pcoderequests/code 看似简单但它的 codetimeout(3, 5)/code 实际含义是「DNSTCP 连接 ≤3 秒首字节响应 ≤5 秒」且无法单独控制 DNS 解析超时。实测中当目标 DNS 服务器响应慢如某些内网 DNS 转发链路coderequests/code 会卡满 3 秒才报错而 codehttp.client/code 可以用 codesocket.create_connection(..., timeout1.0)/code 单独设 DNSTCP 连接上限。更关键的是coderequests/code 的 codestreamTrue/code 仍会缓冲整个响应头而 WebBatchRequest 需要在收到 codeContent-Length/code 后就决定是否读 body——因为有些 WAF 会故意返回大体积垃圾数据阻塞探测。我们翻过 coderequests/code 源码发现其底层 codeurllib3/code 的 codeHTTPConnection/code 类虽基于 codehttp.client/code但封装层把 socket 层参数全锁死了改起来成本高于重写。/p precode classlanguage-python# WebBatchRequest 中真实的连接建立逻辑简化版 def _connect_host(host, port, timeout_dns_tcp1.0): try: # 强制指定 AF_INET避免 IPv6 尝试拖慢 sock socket.create_connection( (host, port), timeouttimeout_dns_tcp, source_addressNone ) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) return sock except socket.timeout: raise ConnectionTimeout(DNS/TCP connect timeout) except socket.gaierror as e: raise DNSResolveError(fDNS resolve failed: {e}) /code/pre blockquote p提示codesocket.create_connection/code 是 codehttp.client/code 底层真正调用的函数WebBatchRequest 直接复用它省掉 coderequests/code 的中间层开销实测在 200 并发下延迟降低 37%对比 coderequests.Session()/code codethreading/code。/p /blockquote h32.2 为什么不用 asyncio小批量任务反而更慢且异常处理复杂/h3 pasyncio 在 1000 并发时优势明显但 WebBatchRequest 定位是「50–500 URL 批量探查」。我们实测了 codeaiohttp/code codeasyncio.gather/code 在 200 个 URL 下的表现CPU 占用率飙升至 95%大量协程在 codeawait response.text()/code 时因编码探测阻塞且 codeaiohttp.ClientSession/code 的 codeconnector.limit/code 参数对 DNS 并发无约束导致内网 DNS 服务器被打爆。而 codehttp.client/code codethreading/code 模型中每个线程独立 socketDNS 查询互不干扰codethreading.active_count()/code 可控内存占用稳定在 40MB 以内。更重要的是——strong异常堆栈清晰/strongcodehttp.client/code 报错直接指向 codesocket.timeout/code 或 codehttp.client.BadStatusLine/code而 codeaiohttp/code 的 codeClientConnectorError/code 常裹着 codeasyncio.TimeoutError/code 和 codeOSError/code 两层包装调试时得层层 unpack。/p h32.3 HTML 标题提取不用 BeautifulSoup靠 html.parser 编码嗅探双保险/h3 pcodeBeautifulSoup/code 功能强但启动慢导入耗时 80ms且默认 codehtml.parser/code 对 GBK 编码页面会乱码。WebBatchRequest 采用两级策略/p ol listrong先从 HTTP 响应头 codeContent-Type/code 提取 charset/strong如 codetext/html; charsetgbk/code/li listrong若未声明或声明无效则用 codechardet/code 轻量版内置 3KB 算法扫描前 1024 字节/strong/li listrong解析时用 codehtml.parser/code 子类只监听 codetitle/code 开始和结束标签不构建 DOM 树/strong内存占用 50KB/URL。/li /ol precode classlanguage-pythonclass TitleExtractor(HTMLParser): def __init__(self, encodingutf-8): super().__init__() self.encoding encoding self.in_title False self.title_content self._buffer bytearray() def handle_starttag(self, tag, attrs): if tag.lower() title: self.in_title True def handle_endtag(self, tag): if tag.lower() title: self.in_title False def handle_data(self, data): if self.in_title: # data 已按 self.encoding 解码此处只做清理 self.title_content data.strip() def feed(self, data: bytes): # data 是原始 bytes需先 decode try: text data.decode(self.encoding) except (UnicodeDecodeError, LookupError): # 回退到 utf-8 ignore text data.decode(utf-8, errorsignore) super().feed(text) /code/pre blockquote p注意codehandle_data/code 不做 HTML 实体解码如 codeamp;/code → code/code因为真实资产页标题极少含实体且解码需额外 import codehtml/code 模块违背「零依赖」原则。实测 99.2% 的存活页面标题可直接输出剩余 0.8%如含 codecopy;/code 的页人工核对即可。/p /blockquote hr / h23. 快速上手三步跑通第一个探测任务含命令行参数详解/h2 h33.1 准备输入文件URL 列表必须满足的三个硬性格式要求/h3 pWebBatchRequest 不做 URL 校验它假设你输入的是「已清洗过的、可直连的 HTTP/HTTPS 地址」。常见翻车点全在这里/p ul li✅ 正确格式每行一个协议必须显式写出precodehttps://example.com/ http://192.168.1.100:8080/admin https://test.company.internal/v2/api /code/pre /li li❌ 错误格式会导致 codesocket.gaierror/code 或 400 错误 ul licodeexample.com/code缺协议codehttp.client/code 无法解析 host/li licodehttps://example.com/code结尾无 code//code部分服务如 Nginx 默认配置会 301 重定向增加 RTT/li licodehttps://example.com/path?query1#hash/codecode#/code 后内容不发往服务端但 codehttp.client/code 会原样发送某些 WAF 拦截/li /ul /li /ul blockquote p提示建议用 codesed/code 预处理你的资产列表/p precode classlanguage-bashsed -E s/^([^:])\/?$/http:\/\/\1\//; s/^https?:\/\///; s/\/#.*$// urls.txt | grep -v ^$ clean_urls.txt /code/pre /blockquote h33.2 基础命令行执行code--threads/code 和 code--timeout/code 是性能命脉/h3 precode classlanguage-bashpython webbatchrequest.py --input clean_urls.txt --output result.csv --threads 50 --timeout 3 /code/pre ul licode--threads 50/code开 50 个线程并发探测。strong经验阈值内网环境可设 100公网建议 ≤30/strong。超过后 DNS 查询排队加剧整体耗时不降反升。/li licode--timeout 3/code等价于 code--timeout-dns-tcp 1 --timeout-read 2/code即 DNSTCP 连接 ≤1 秒读取响应头body ≤2 秒。这是平衡「漏报」和「耗时」的关键——设 5 秒可能卡住 10% 的不可达地址设 1 秒会漏掉部分高延迟但存活的 CDN 边缘节点。/li /ul blockquote p参数说明code--timeout/code 是总超时内部拆分为 codedns_tcptimeout*0.3/code向上取整 1 秒和 codereadtimeout*0.7/code向下取整。你也可以手动拆分/p precode classlanguage-bashpython webbatchrequest.py --input urls.txt --timeout-dns-tcp 1.2 --timeout-read 1.8 /code/pre /blockquote h33.3 输出结果解读CSV 里每一列的真实含义与可信度分级/h3 p生成的 coderesult.csv/code 共 7 列strong不是所有列都同等可靠/strong/p table thead tr th列名/th th示例值/th th可信度/th th说明/th /tr /thead tbody tr tdcodeurl/code/td tdcodehttps://example.com//code/td td★★★★★/td td输入原文无修改/td /tr tr tdcodestatus_code/code/td tdcode200/code/td td★★★★★/td tdHTTP 状态码codehttp.client/code 原始返回/td /tr tr tdcodetitle/code/td tdcodeExample Domain/code/td td★★★★☆/td td从 codetitle/code 提取经编码修复但可能被 JS 动态改写静态 HTML 页 100% 准/td /tr tr tdcodeserver/code/td tdcodenginx/1.18.0/code/td td★★★★☆/td tdcodeServer/code 响应头WAF 常伪造仅作参考/td /tr tr tdcodecontent_length/code/td tdcode1256/code/td td★★★★★/td tdcodeContent-Length/code 响应头或 codeTransfer-Encoding: chunked/code 时计算的实际字节数/td /tr tr tdcoderesponse_time_ms/code/td tdcode247/code/td td★★★★☆/td td从 codesocket.connect()/code 到 codehttp.client.HTTPResponse.read()/code 结束的毫秒数含 DNS 时间/td /tr tr tdcodeerror/code/td tdcodetimeout/code/td td★★★★★/td td错误类型codeNone/code 表示成功/td /tr /tbody /table blockquote p注意codetitle/code 列为空 ≠ 页面无标题可能是/p ul li响应体小于 1024 字节且不含 codetitle/code如纯 JSON API/li li编码探测失败codehtml.parser/code 未触发 codehandle_data/code/li li页面用 codemeta propertyog:title/code 替代 codetitle/codeWebBatchRequest 不解析 meta因非标准且易伪造。/li /ul /blockquote hr / h24. 避坑指南五个血泪经验总结的「必踩坑」与绕过方案/h2 h34.1 现象所有 HTTPS URL 都报 codessl.SSLError: [SSL: WRONG_VERSION_NUMBER]/code/h3 pstrong原因/strong目标服务开了 HTTP 服务却绑在 443 端口常见于 misconfigured Nginxcodehttp.client/code 尝试 TLS 握手失败。br / strong解决/strong加 code--force-http/code 参数强制走 HTTP 协议即使 URL 写 https://或预处理 URL/p precode classlanguage-bashawk -F:// /^https:\/\// /:443[^:]/ {sub(/^https/, http); print; next} {print} urls.txt fixed_urls.txt /code/pre h34.2 现象部分 URL 返回 codestatus_code200/code 但 codetitle/code用浏览器打开却有标题/h3 pstrong原因/strong页面 HTML 中 codetitle/code 标签写在 code/head/code 之后违反 HTML5 规范codehtml.parser/code 默认只在 codehead/code 内捕获。br / strong解决/strong启用 code--loose-title/code 模式让 codeTitleExtractor/code 忽略标签嵌套结构全文扫描 codetitle/code牺牲少量性能提升覆盖率/p precode classlanguage-bashpython webbatchrequest.py --input urls.txt --loose-title /code/pre h34.3 现象coderesult.csv/code 中 coderesponse_time_ms/code 普遍偏高2000ms但 codeping/code 延迟仅 20ms/h3 pstrong原因/strongDNS 解析慢。codehttp.client/code 每次都走系统 codegetaddrinfo()/code未缓存。br / strong解决/strong用 code--dns-cache/code 参数启用内存级 DNS 缓存首次解析后同 host 复用 IP/p precode classlanguage-bashpython webbatchrequest.py --input urls.txt --dns-cache /code/pre blockquote p补充若内网有自建 DNS可改 codesocket.getaddrinfo/code 为指定 DNS 服务器需 patch codehttp.client/code不推荐见第 6 章。/p /blockquote h34.4 现象探测结果中大量 codeerrorconnection refused/code但 codenmap -p80,443 target/code 显示端口开放/h3 pstrong原因/strong目标开了端口但 HTTP 服务未监听 code//code 路径如只监听 code/api/health/codecodehttp.client/code 发送 codeGET / HTTP/1.1/code 被拒绝。br / strong解决/strong用 code--path/code 指定探测路径支持变量 code%host%/code/p precode classlanguage-bashpython webbatchrequest.py --input urls.txt --path /api/health # 或针对不同 host 用不同 path需预处理 URL /code/pre h34.5 现象code--threads 100/code 时程序崩溃报 codeOSError: Cannot allocate memory/code/h3 pstrong原因/strongLinux 默认单进程线程数限制codeulimit -u/code通常为 1024每个线程至少占 1MB 栈空间100 线程 ≈ 100MB叠加其他开销触顶。br / strong解决/strong/p ol li查当前限制codeulimit -u/code/li li临时提高codeulimit -u 4096/code/li li永久修改编辑 code/etc/security/limits.conf/code加 code* soft nproc 4096/code/li /ol blockquote p注意不要盲目设 code--threads 200/code实测 50 线程在千兆网络下已达吞吐瓶颈再高只增上下文切换开销。/p /blockquote hr / h25. 进阶技巧定制化探测链——如何用 3 行代码实现「存活 → 标题 → 版本指纹」三级验证/h2 h35.1 为什么需要三级验证单一探测的局限性/h3 pcodestatus_code200/code 只代表 HTTP 服务响应了不代表应用存活可能是 Nginx 默认页codetitle/code 匹配 codeJenkins/code 也不代表 Jenkins 真在运行可能是历史快照或 WAF 伪装页。真正的资产确认需要strong行为验证/strong发一个已知能触发特定响应的请求。WebBatchRequest 本身不内置指纹库但它预留了 code--custom-check/code 钩子让你用 Python 函数注入自定义逻辑。/p h35.2 实战三步验证 Jenkins 实例存活 标题含 Jenkins code/api/json/code 返回 200/h3 p第一步准备自定义检查函数 codejenkins_check.py/code必须定义 codecheck(url: str, response: http.client.HTTPResponse) - str/code/p precode classlanguage-python# jenkins_check.py import json def check(url, response): # Step 1: 已通过基础探测确认 status_code 200 and title contains Jenkins if jenkins not in response.headers.get(X-Jenkins, ).lower(): # X-Jenkins header 是 Jenkins 独有比 title 更可靠 return not_jenkins_header # Step 2: 主动请求 /api/json 验证 API 可用性 from urllib.parse import urljoin import http.client import ssl api_url urljoin(url, /api/json) try: # 复用 WebBatchRequest 的连接逻辑简化版 context ssl.create_default_context() conn http.client.HTTPSConnection( hostapi_url.split(://)[1].split(/)[0], timeout3, contextcontext ) conn.request(GET, /api/json, headers{User-Agent: WebBatchRequest}) api_resp conn.getresponse() if api_resp.status 200: try: data json.loads(api_resp.read().decode()) if version in data: return fjenkins_{data[version]} except: pass return jenkins_api_unavailable except Exception as e: return fjenkins_api_error:{str(e)} /code/pre p第二步运行探测注入检查函数/p precode classlanguage-bashpython webbatchrequest.py \ --input jenkins_targets.txt \ --output jenkins_verified.csv \ --custom-check jenkins_check.py \ --filter title:jenkins # 先用 title 粗筛再精细验证 /code/pre p第三步coderesult.csv/code 新增一列 codecustom_check_result/code值为 codejenkins_2.387.1/code 或 codejenkins_api_unavailable/code。/p blockquote p关键设计code--filter/code 参数支持 codekey:value/code 语法codekey/code 是 CSV 列名codevalue/code 支持正则如 codetitle:/jenkins|ci/i/code。这避免了对全部 URL 执行昂贵的 API 请求只对 title 匹配的做二次验证效率提升 5 倍。/p /blockquote h35.3 扩展用 code--post-data/code 探测登录页是否存在 CSRF Token/h3 p某些系统如旧版 Confluence登录页会返回隐藏的 codeatl_token/code这是未登录状态下的可靠指纹。WebBatchRequest 支持 POST 请求/p precode classlanguage-bashpython webbatchrequest.py \ --input confluence_urls.txt \ --method POST \ --post-data os_destination%2F \ --header Content-Type: application/x-www-form-urlencoded \ --filter status_code:200 \ --output confluence_csrf.csv /code/pre p然后在 codecustom_check.py/code 中解析响应 body 是否含 codenameatl_token/code —— 这比检查 codetitleConfluence/code 更防伪。/p p从那以后我每次做资产普查都强制走一遍「基础探测 → filter 粗筛 → custom-check 精验」三步链宁可多花 2 秒也不让一个假存活混进报告。毕竟安全工程里最贵的不是时间是误报后人工复核的成本。希望帮到你。/p p a hrefhttps://download.csdn.net/download/2401_89793006/91402532 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p
返回列表