反连平台设计详解:DNSLog + HTTP 回调 + 异步关联,从零实现漏洞扫描 OOB 检测基础设施
目录背景介绍核心挑战解决方案完整实现测试策略最容易踩的5个坑面试高频考点总结与扩展背景介绍漏洞扫描中有一类问题无法只靠同步响应判断。比如目标服务器收到测试请求后会在后台访问一个外部地址目标应用触发了异步任务几秒后才产生网络访问目标环境没有把执行结果回显到 HTTP 响应里这种场景需要反连平台Reverse Connection Platform也常被称为 OOBOut-of-Band检测基础设施。它的核心思想是扫描器生成唯一回调地址 ↓ 检测插件把回调地址放入测试请求 ↓ 目标如果触发外联会访问该地址 ↓ 反连平台记录回调 ↓ 扫描器根据唯一ID关联检测结果xray 的 README 中也明确提到XXE、SSRF 等检测模块会使用反连平台能力。对扫描器来说反连平台不是单个插件而是所有“无回显检测”的公共基础设施。核心挑战挑战1如何生成唯一且可追踪的回调地址每一次检测都要有独立标识否则多个插件、多个目标、多个任务之间会串结果。扫描任务 A ├── 插件 ssrf │ └── token: a1b2c3 └── 插件 xxe └── token: d4e5f6 扫描任务 B └── 插件 ssrf └── token: g7h8i9反连平台必须知道token 属于哪个扫描任务token 属于哪个插件token 绑定哪个目标token 的有效期是什么挑战2HTTP 和 DNS 回调要同时支持不同漏洞触发的外联形式不同HTTP回调 ├── 能拿到完整路径 ├── 能拿到Header ├── 能记录User-Agent └── 适合验证Web访问类外联 DNS回调 ├── 更轻量 ├── 出网限制下更容易触发 ├── 只能拿到域名查询 └── 适合验证解析行为如果只支持 HTTP会漏掉只做 DNS 解析但不发 HTTP 请求的场景如果只支持 DNS又拿不到更丰富的访问证据。挑战3检测是异步的扫描器发出请求后回调可能在几十毫秒后出现也可能几秒后出现还可能永远不出现。所以不能写成sendPayload()ifcallbackExists(){reportVuln()}更合理的方式是发送测试请求 ↓ 注册等待器 ↓ 在超时时间内监听回调事件 ↓ 有事件则确认无事件则正常结束挑战4反连平台自身要安全反连平台暴露在公网天然会收到大量不可控流量。需要重点考虑token 猜测与伪造日志污染大请求体占用内存高并发打满连接数敏感信息落盘反连平台不是越“开放”越好而是要在可观测和可控之间取平衡。解决方案架构设计┌──────────────────────┐ │ Scanner │ │ plugin / task / url │ └──────────┬───────────┘ │ create token ▼ ┌──────────────────────┐ │ Reverse Client │ │ URL builder / wait │ └──────────┬───────────┘ │ ▼ ┌────────────────────────────────────┐ │ Reverse Platform │ │ │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ HTTP Server │ │ DNS Server │ │ │ └──────┬───────┘ └──────┬───────┘ │ │ └──────┬──────────┘ │ │ ▼ │ │ Event Store Matcher │ └────────────────┬───────────────────┘ │ callback event ▼ ┌──────────────────────┐ │ Result Joiner │ │ token - scan result │ └──────────────────────┘核心数据流1. 插件请求一个反连地址 2. 平台生成 token 与检测上下文 3. 插件把地址用于测试请求 4. HTTP/DNS 服务接收外部回调 5. 平台把回调写入事件存储 6. 扫描器等待 token 对应事件 7. 命中后生成漏洞结果和证据完整实现步骤1Token 与上下文设计pkg/reverse/token.gopackagereverseimport(crypto/randencoding/base32stringstime)typeTokenContextstruct{TokenstringTaskIDstringPluginstringTargetstringCreatedAt time.Time ExpiresAt time.Time}funcNewTokenContext(taskID,plugin,targetstring,ttl time.Duration)(TokenContext,error){token,err:randomToken(16)iferr!nil{returnTokenContext{},err}now:time.Now()returnTokenContext{Token:token,TaskID:taskID,Plugin:plugin,Target:target,CreatedAt:now,ExpiresAt:now.Add(ttl),},nil}funcrandomToken(sizeint)(string,error){buf:make([]byte,size)if_,err:rand.Read(buf);err!nil{return,err}encoded:base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(buf)returnstrings.ToLower(encoded),nil}Token 需要足够随机避免被猜测同时要适合作为子域名前缀所以使用小写字母和数字更方便。步骤2回调地址生成器pkg/reverse/client.gopackagereverseimport(fmttime)typeClientstruct{BaseDomainstringHTTPBasestringStore*Store}typeCallbackAddressstruct{TokenstringDNSNamestringHTTPURLstring}func(c*Client)NewCallback(taskID,plugin,targetstring)(CallbackAddress,error){ctx,err:NewTokenContext(taskID,plugin,target,5*time.Minute)iferr!nil{returnCallbackAddress{},err}c.Store.SaveContext(ctx)returnCallbackAddress{Token:ctx.Token,DNSName:fmt.Sprintf(%s.%s,ctx.Token,c.BaseDomain),HTTPURL:fmt.Sprintf(%s/%s,c.HTTPBase,ctx.Token),},nil}插件只需要拿到回调地址不应该关心反连平台内部如何记录事件。步骤3事件存储pkg/reverse/store.gopackagereverseimport(synctime)typeCallbackEventstruct{TokenstringProtocolstringRemoteIPstringHoststringPathstringUserAgentstringRawstringCreatedAt time.Time}typeStorestruct{mu sync.RWMutex contextsmap[string]TokenContext eventsmap[string][]CallbackEvent waitersmap[string][]chanCallbackEvent}funcNewStore()*Store{returnStore{contexts:map[string]TokenContext{},events:map[string][]CallbackEvent{},waiters:map[string][]chanCallbackEvent{},}}func(s*Store)SaveContext(ctx TokenContext){s.mu.Lock()defers.mu.Unlock()s.contexts[ctx.Token]ctx}func(s*Store)AddEvent(event CallbackEvent)bool{s.mu.Lock()defers.mu.Unlock()ctx,ok:s.contexts[event.Token]if!ok||time.Now().After(ctx.ExpiresAt){returnfalse}s.events[event.Token]append(s.events[event.Token],event)for_,waiter:ranges.waiters[event.Token]{select{casewaiter-event:default:}}returntrue}func(s*Store)Wait(tokenstring,timeout time.Duration)(CallbackEvent,bool){ch:make(chanCallbackEvent,1)s.mu.Lock()iflist:s.events[token];len(list)0{event:list[0]s.mu.Unlock()returnevent,true}s.waiters[token]append(s.waiters[token],ch)s.mu.Unlock()timer:time.NewTimer(timeout)defertimer.Stop()select{caseevent:-ch:returnevent,truecase-timer.C:returnCallbackEvent{},false}}这里的Wait支持两种情况回调已经到达直接返回回调尚未到达挂起等待直到超时步骤4HTTP回调服务pkg/reverse/http_server.gopackagereverseimport(ionetnet/httpstringstime)typeHTTPServerstruct{Store*Store}func(s*HTTPServer)ServeHTTP(w http.ResponseWriter,r*http.Request){token:strings.Trim(strings.Split(r.URL.Path,/)[1], )iftoken{http.NotFound(w,r)return}body,_:io.ReadAll(io.LimitReader(r.Body,4096))event:CallbackEvent{Token:token,Protocol:http,RemoteIP:clientIP(r),Host:r.Host,Path:r.URL.String(),UserAgent:r.UserAgent(),Raw:string(body),CreatedAt:time.Now(),}if!s.Store.AddEvent(event){http.NotFound(w,r)return}w.WriteHeader(http.StatusOK)_,_w.Write([]byte(ok))}funcclientIP(r*http.Request)string{host,_,err:net.SplitHostPort(r.RemoteAddr)iferr!nil{returnr.RemoteAddr}returnhost}注意点请求体必须限制大小未知 token 不返回详细错误只记录必要证据不把任意请求内容直接渲染到页面步骤5DNS回调服务pkg/reverse/dns_server.gopackagereverseimport(netstringstimegithub.com/miekg/dns)typeDNSServerstruct{BaseDomainstringStore*Store}func(s*DNSServer)HandleDNS(w dns.ResponseWriter,r*dns.Msg){msg:new(dns.Msg)msg.SetReply(r)for_,q:ranger.Question{token:s.extractToken(q.Name)iftoken{continue}s.Store.AddEvent(CallbackEvent{Token:token,Protocol:dns,RemoteIP:w.RemoteAddr().String(),Host:q.Name,Path:dns.TypeToString[q.Qtype],CreatedAt:time.Now(),})msg.Answerappend(msg.Answer,dns.A{Hdr:dns.RR_Header{Name:q.Name,Rrtype:dns.TypeA,Class:dns.ClassINET,Ttl:1,},A:net.ParseIP(127.0.0.1),})}_w.WriteMsg(msg)}func(s*DNSServer)extractToken(namestring)string{namestrings.TrimSuffix(strings.ToLower(name),.)base:strings.TrimSuffix(strings.ToLower(s.BaseDomain),.)if!strings.HasSuffix(name,base){return}left:strings.TrimSuffix(name[:len(name)-len(base)],.)parts:strings.Split(left,.)iflen(parts)0{return}returnparts[0]}真实实现中要补充DNS 服务器监听端口域名 NS 解析配置IPv6、CNAME 等记录处理上游解析兜底策略步骤6检测插件中的等待逻辑pkg/plugin/oob_check.gopackagepluginimport(contexttime)funcRunOOBCheck(ctx context.Context,reverse*reverse.Client,targetstring)(*VulnResult,error){callback,err:reverse.NewCallback(task-001,ssrf,target)iferr!nil{returnnil,err}iferr:sendSafeProbe(ctx,target,callback.HTTPURL);err!nil{returnnil,err}event,ok:reverse.Store.Wait(callback.Token,8*time.Second)if!ok{returnnil,nil}returnVulnResult{Target:target,Plugin:ssrf,Evidence:event.Protocol callback from event.RemoteIP,},nil}这里的sendSafeProbe代表插件发送的安全探测请求。文章重点是反连平台设计不展开具体漏洞利用细节。测试策略单元测试Token唯一性funcTestTokenUnique(t*testing.T){seen:map[string]struct{}{}fori:0;i10000;i{token,err:randomToken(16)require.NoError(t,err)_,exists:seen[token]assert.False(t,exists)seen[token]struct{}{}}}单元测试等待回调funcTestWaitCallback(t*testing.T){store:NewStore()ctx,_:NewTokenContext(task,plugin,target,time.Minute)store.SaveContext(ctx)gofunc(){time.Sleep(50*time.Millisecond)store.AddEvent(CallbackEvent{Token:ctx.Token,Protocol:http})}()event,ok:store.Wait(ctx.Token,time.Second)assert.True(t,ok)assert.Equal(t,http,event.Protocol)}安全测试未知Token不记录funcTestUnknownTokenIgnored(t*testing.T){store:NewStore()ok:store.AddEvent(CallbackEvent{Token:unknown})assert.False(t,ok)}最容易踩的5个坑坑1Token太短导致串结果错误示例token:strconv.Itoa(rand.Intn(10000))正确做法token,err:randomToken(16)Token 必须使用密码学安全随机数不能使用时间戳、自增 ID 或普通随机数。坑2等待逻辑阻塞扫描主流程错误示例time.Sleep(30*time.Second)checkCallback()正确做法event,ok:store.Wait(token,8*time.Second)等待必须有超时并且应以事件通知为主不要靠固定 sleep。坑3没有设置Token过期错误示例contexts[token]ctx正确做法ctx.ExpiresAttime.Now().Add(5*time.Minute)过期策略可以减少内存占用也可以降低旧回调污染新扫描的风险。坑4把回调内容直接展示在报告中错误示例pre{{ .RawCallback }}/pre正确做法safeEvidence:html.EscapeString(limit(event.Raw,1024))反连平台收到的数据不可信进入报告前必须转义和限长。坑5DNS服务没有部署验证错误示例// 本地启动DNS服务后直接认为可用正确做法digtoken.example-oob.com authoritative-dnsDNS 反连依赖域名 NS 配置代码正确不代表公网解析链路正确。面试高频考点考点1为什么反连平台能检测无回显漏洞回答要点同步响应看不到结果时观察目标是否产生外部网络行为每次检测生成唯一 token回调事件和扫描任务通过 token 关联HTTP 与 DNS 证据可以作为检测依据考点2HTTP回调和DNS回调有什么区别回答要点HTTP 证据更丰富可以记录路径、Header、User-AgentDNS 更轻量有些环境只会解析域名不发 HTTP 请求HTTP 依赖应用层访问DNS 依赖解析链路实际平台通常两者都支持考点3如何防止反连平台误报回答要点Token 必须唯一且不可猜测Token 绑定任务、插件和目标设置合理过期时间记录协议、来源 IP、时间等证据必要时结合二次确认逻辑总结与扩展核心经验总结反连平台是公共基础设施服务于 SSRF、XXE、无回显命令检测等场景插件只依赖回调地址和等待接口平台负责事件接收和关联唯一Token是核心绑定扫描上下文防止串任务便于证据追踪HTTP和DNS要同时覆盖HTTP 证据更完整DNS 触达率更高两者互补异步等待要可控事件通知优于固定 sleep每次等待必须有超时过期 token 要及时清理平台自身要做安全防护限制请求体大小未知 token 静默处理报告展示前转义清理过期数据

相关新闻

游戏DLSS版本升级怎么做?DLSS Swapper一键替换教程让老游戏画质焕新

游戏DLSS版本升级怎么做?DLSS Swapper一键替换教程让老游戏画质焕新

游戏DLSS版本升级怎么做?DLSS Swapper一键替换教程让老游戏画质焕新 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper "我的显卡明明不差,为什么《赛博朋克2077》的远景还是糊成一片&#xf…

2026/8/15 15:13:27 阅读更多 →
3秒获取百度网盘提取码,baidupankey智能查询工具完整上手指南

3秒获取百度网盘提取码,baidupankey智能查询工具完整上手指南

3秒获取百度网盘提取码,baidupankey智能查询工具完整上手指南 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 还在为下载资料时找不到提取码而抓狂吗&am…

2026/8/15 15:13:27 阅读更多 →
BioGPT 未来演进路线图全解析:从医学文本生成到昇腾 NPU 落地的三级跳

BioGPT 未来演进路线图全解析:从医学文本生成到昇腾 NPU 落地的三级跳

BioGPT 未来演进路线图全解析:从医学文本生成到昇腾 NPU 落地的三级跳 【免费下载链接】biogpt 项目地址: https://ai.gitcode.com/hf_mirrors/FuJianAscend/biogpt 深夜十一点,某三甲医院科研中心的灯还亮着。一位医生盯着屏幕上密密麻麻的 37 …

2026/8/15 15:13:27 阅读更多 →

最新新闻

零基础也能调出专业画质:MPV播放器懒人配置包的一站式体验

零基础也能调出专业画质:MPV播放器懒人配置包的一站式体验

零基础也能调出专业画质:MPV播放器懒人配置包的一站式体验 【免费下载链接】mpv_PlayKit 🔄 mpv player 播放器折腾记录 Windows conf | 中文注释配置 汉化文档 快速帮助入门 | mpv-lazy 懒人包 Win11 x64 config | 着色器 shader 滤镜 filter 整合方案 …

2026/8/15 15:52:41 阅读更多 →
下载老是断、速度上不去?3步把浏览器下载交给Motrix,多线程续传全搞定

下载老是断、速度上不去?3步把浏览器下载交给Motrix,多线程续传全搞定

下载老是断、速度上不去?3步把浏览器下载交给Motrix,多线程续传全搞定 【免费下载链接】motrix-webextension A browser extension for the Motrix Download Manager and its forks 项目地址: https://gitcode.com/gh_mirrors/mo/motrix-webextension …

2026/8/15 15:52:41 阅读更多 →
【Kubernetes从入门到精通】第47篇:NetworkPolicy——你的Pod之间需要“防火墙“,别让它们“裸奔“

【Kubernetes从入门到精通】第47篇:NetworkPolicy——你的Pod之间需要“防火墙“,别让它们“裸奔“

上一篇【第46篇】K8s DNS——CoreDNS的"黄页"服务 下一篇【第48篇】Service的三种代理模式——userspace/iptables/IPVS 摘要 前面讲了网络连通(Flannel/Calico)、讲了名字解析(CoreDNS)。现在问你一个扎心的问题&…

2026/8/15 15:52:41 阅读更多 →
【Kubernetes从入门到精通】第48篇:Service的三种代理模式——userspace/iptables/IPVS的前世今生

【Kubernetes从入门到精通】第48篇:Service的三种代理模式——userspace/iptables/IPVS的前世今生

上一篇【第47篇】NetworkPolicy——你的Pod之间需要"防火墙" 下一篇【第49篇】Cilium——eBPF驱动的下一代K8s网络 摘要 前面我们一直在说"Service负责负载均衡",但Service自己不干活——真正把ClusterIP的流量转发到后端Pod的,是k…

2026/8/15 15:52:41 阅读更多 →
微信聊天记录如何永久保存?WeChatMsg 免费导出 HTML、Word、CSV 全攻略

微信聊天记录如何永久保存?WeChatMsg 免费导出 HTML、Word、CSV 全攻略

微信聊天记录如何永久保存?WeChatMsg 免费导出 HTML、Word、CSV 全攻略 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_T…

2026/8/15 15:52:41 阅读更多 →
告别慢查询熬夜排查:三步用 SQLAdvisor 生成 MySQL 索引优化建议

告别慢查询熬夜排查:三步用 SQLAdvisor 生成 MySQL 索引优化建议

告别慢查询熬夜排查:三步用 SQLAdvisor 生成 MySQL 索引优化建议 【免费下载链接】SQLAdvisor 输入SQL,输出索引优化建议 项目地址: https://gitcode.com/gh_mirrors/sq/SQLAdvisor 深夜两点,你的手机突然被监控告警震醒——某个核心接…

2026/8/15 15:51:38 阅读更多 →

日新闻

内景 空间站内部 中国空间站 太空 内仓

内景 空间站内部 中国空间站 太空 内仓

本项目为前几天收费帮学妹做的一个项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 空间站内部 中国空间站 太空 内仓 地址:本地PC端运行(或Web…

2026/8/15 0:00:30 阅读更多 →
重新定义数据接口:3个突破性场景让通达信数据读取更智能

重新定义数据接口:3个突破性场景让通达信数据读取更智能

重新定义数据接口:3个突破性场景让通达信数据读取更智能 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx 当我们面对海量金融数据时,传统的数据获取方式往往让我们陷入困境—…

2026/8/15 0:00:30 阅读更多 →
一文读懂快消WMS怎么选?2026年国内外10大主流WMS品牌盘点

一文读懂快消WMS怎么选?2026年国内外10大主流WMS品牌盘点

快消品(FMCG)是流通速度较快、竞争较为激烈的行业之一。一瓶饮料从出厂到消费者手中,往往只有几十天甚至几天的周转窗口。这决定了快消行业的仓储管理系统(WMS)与制造业、电商行业存在明显区别:它不仅需要管…

2026/8/15 0:02:30 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/13 2:38:34 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/15 12:59:14 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/13 10:41:51 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/14 13:40:53 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/14 14:06:45 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/15 2:35:29 阅读更多 →