深信服ACSG v12.0.41 DNS代理功能测试:转发、缓存与分流实战
发布时间:2026/9/30 8:52:17来源:尧图网络
简介深信服ACSG v12.0.41版本的DNS代理功能测试实施指导书是一份面向企业网络管理员与IT运维人员的专项部署手册主要解决多链路场景下DNS请求分配不均、非法域名访问难以管控等问题。文档按照重定向至DNS服务器、解析为指定IP、丢弃非法请求、重定向至指定线路四种代理方式展开每部分均包含测试条件、预期效果与详细配置步骤方便运维人员结合实际网络环境直接对照操作。资源为单个PDF文件大小约1.74MB内容精炼、目录结构完整适合正在部署或优化深信服上网行为管理设备DNS策略的中级运维人员参考学习。目前已有102人学习下载其中还涉及负载均衡原理与链路利用率优化思路能够帮助读者在完成功能配置的同时理解流量调度逻辑有效缩短排错与调优时间。1. 拿到《SANGFOR_ACSG_v12.0.41版本_DNS代理功能测试实施指导书》先别急着点用例很多运维拿到这类 PDF 的第一反应是照着步骤一条条点点完就算“测过了”。但 DNS 代理恰恰是 ACSG 上最容易被误判的功能内网上不了网、网页打开慢、部分系统解析到错误 IP客户第一反应都怪设备等你跑过去抓包才发现根本不是它的问题。这份指导书的核心不是教你“怎么点按钮”而是给你一套验证“DNS 代理行为是否符合预期”的方法——客户端请求有没有到设备、设备有没有正确转发到上游、缓存到底有没有生效、域名分流有没有按策略走。适合做版本升级回归、首次验收以及刚接手深信服设备、想自己搭环境跑一遍的网络工程师。2. DNS 代理在 ACSG v12.0.41 里的角色转发、缓存、分流三个测试维度2.1 为什么网关要替终端做 DNS 解析而不是让终端直连公共 DNS终端直连公共 DNS 表面上简单但对一台有上网行为管理诉求的网关来说等于把域名解析这块彻底放进黑匣子管理员看不到谁在解析什么没法按域名做封堵、审计也没法在某个上游 DNS 故障时统一切换。ACSG 做 DNS 代理以后客户端的 DNS 配置指向设备 LAN 口设备统一收包再按策略转发给预先设定的上游 DNS。这样一来域名解析路径上多了一个可以“插一脚”的位置日志、缓存、域名策略都在这层生效这层就是测试要盯住的对象。ACSG 上的 DNS 代理一般有两种收包方式。一种是显式代理客户端网卡里 DNS 直接填写设备 LAN 口地址请求本身就以设备为目的另一种是透明方式客户端 DNS 还填运营商的地址但设备在接口上拦截去往 53 端口的流量并交给本地模块处理。实施指导书里的测试通常默认前者因为行为可预期、排错简单。如果你在现场发现客户端请求根本没出现在设备上先确认是不是 DHCP 又把 DNS 推成了别的地址。这个细节我在第 5 章会单独展开。顺带说一句DNS 代理的日志功能经常被忽略。开启后设备能记录内部 IP 解析了哪些域名这对事后溯源很重要但日志会占存储。测试环境里如果磁盘紧张先把日志级别调低免得测试中途把盘写满那才是真的耽误事。被测对象不是协议本身而是“代理这个动作”所以测试要回答三件事请求是否真的到了 ACSGACSG 是否按配置转给了指定上游回包是否带着正确结果回来。抓包里同时看到客户端到设备、设备到上游的两段流量才算把链路看全。2.2 把功能测试拆成三条主链路转发、缓存、分流一份实施指导书的用例再多拆到底层也只有三条主链路。转发链路验证“解析正确性”缓存链路验证“性能与回源策略”分流链路验证“策略匹配与故障转移”。我习惯先列一张表把用例归档到这三列里再决定抓包的位置和预期结果。功能模块验证点关注指标转发返回记录类型与内容是否和上游一致结果一致性、响应耗时缓存二次查询是否回源、TTL 是否刷新缓存命中率、过期时间分流指定域名是否走指定上游或出口策略匹配率、切换耗时这张表最大的用处是防止“点完就忘”。比如有的用例表面在测“域名解析失败”实际是在验证故障转移那就要把重点从“解析结果”挪到“切换时间”上。v12.0.41 这种迭代版本功能测试的重点不在“能不能解析”而在“这些行为跟上一个版本比有没有变化”。所以在定通过标准时我会把每条用例的预期写得足够具体返回什么 IP、TTL 是多少、抓包能不能看到第二次回源。没有这些硬指标测试结论很容易变成“好像没问题”。三条链路对应的抓包位置也不一样。转发链路要看两段流量缓存链路要看上游侧的重复请求分流链路要看设备从哪个 WAN 口发出查询。同样一条 dig 命令配合不同的抓包位置验证的是完全不同的功能点。这也是为什么我不建议只拿客户端结果来判断设备行为——客户端看到的是一个合并后的结果中间发生了什么只有抓包和日志知道。2.3 版本差异与测试边界v12.0.41 回归要看哪些菜单ACSG 的控制台里DNS 相关配置一般集中在“网络配置”下有些小版本菜单叫“DNS 代理”有些叫“DNS 转发”菜单位置会随版本微调。测试前先到“系统状态-版本信息”页确认设备已经升到 v12.0.41再通过界面搜索 DNS 关键词定位入口这个顺序不能反。常见配置项包括DNS 代理总开关、上游 DNS 服务器列表、缓存开关、域名分流策略以及日志审计开关挨个过一遍能覆盖大部分回归点。测试边界要划清楚DNS 代理只处理域名到 IP 的映射不处理后面的 TCP 连接建立和网页加载。所以“网页打开慢”这种用例不能只测代理还要配合网页访问测试一起看而“部分域名解析错误”则可以完全限定在代理功能内排查。我一般在测试方案里明确写一句本批次只验证 v12.0.41 的 DNS 代理功能不覆盖同版本其他模块避免回归范围被无限扩大。如果是集中管理平台下发的设备还要多确认一步当前生效配置是本地配置还是平台模板下发的。有些测试环境里你刚改完上游 DNS几分钟后被平台策略刷新覆盖测试结果直接翻车。确认方法很简单改完配置后再回到界面刷新一次看配置是否还在。这个动作花不了十秒钟但能省掉后面一小时的排查。3. 搭一个最小可复现的 DNS 代理测试环境拓扑、域名数据与抓包基线3.1 测试拓扑与接口配置最小环境只需要四部分一台 ACSG、一台充当上游 DNS 的 Linux 服务器、一台客户端、一个能抓包的交换机镜像口。拓扑如下客户端接入 ACSG 的 LAN 口ACSG 的 WAN 口接到测试网络上游 DNS 服务器放在 WAN 侧管理口单独接出来用于登录控制台。客户端网卡 DNS 手动填写 ACSG LAN 口地址不要从 DHCP 获取避免环境干扰。角色接口/地址说明ACSGLAN 口 192.168.10.1客户端 DNS 指向这里ACSGWAN 口 10.0.0.2连接测试上游 DNS上游 DNS10.0.0.253dnsmasq 或 BIND 模拟现网 DNS客户端192.168.10.100Windows/Linux 均可为什么要用可控上游而不是现网公共 DNS因为缓存和分流用例需要你确切知道“上游返回了什么”。如果用公共 DNS你无法判断设备回的是缓存还是上游真实结果测试结论就站不住。上游 DNS 用 dnsmasq 最省事配置几行 address 记录就能模拟多种解析结果。另外建议准备一台带镜像口的交换机把 ACSG 的 LAN 口和 WAN 口流量都镜像到一台笔记本上抓包现场排查会方便很多。3.2 准备一套覆盖正常、异常、长尾的测试域名清单测试域名不要从生产环境里挑风险大且预期不明。我习惯在现场建一套专用测试域名全部挂在上游 DNS 服务器上。下面的清单可以覆盖大多数用例域名记录类型预期返回值用途a.test.localA10.10.10.1正常解析alias.test.localCNAMEa.test.localCNAME 跟随v6.test.localAAAAfd00::1AAAA 记录转发ttl5.test.localA10.10.10.2TTL 5缓存过期nx.test.local无记录NXDOMAIN异常解析split.test.localA10.20.0.5分流用例这里注意两点TTL 要特意设置成短值这样测缓存过期不用干等NXDOMAIN 一定要测很多代理实现会把上游的“不存在”结果也缓存下来第二次查询的表现会不一样。在 dnsmasq 配置里这类记录可以写成 address/a.test.local/10.10.10.1 这样的格式TTL 通过 dnsmasq 的 --max-ttl 或 local-ttl 控制具体看你的版本。3.3 先打基线不开 DNS 代理时上游的解析行为在改 ACSG 任何配置之前先直接在客户端用 dig 指向上游 DNS 打一轮基线。基线的意义是记录“上游本来就返回什么、耗时多少”后面所有对比都以这组数据为参照。Linux 客户端可以直接用 dig批量脚本如下#!/bin/bash # 基线测试客户端直连上游 DNS记录每个域名的答案与耗时 UPSTREAM10.0.0.253 for domain in a.test.local alias.test.local v6.test.local ttl5.test.local nx.test.local split.test.local; do start$(date %s%N) result$(dig $UPSTREAM $domain noall answer time3 tries1 21) end$(date %s%N) cost_ms$(( (end - start) / 1000000 )) echo $domain|$cost_ms|$result baseline.txt done脚本逻辑很简单对每个测试域名发起一次查询禁用额外尝试tries1把域名、耗时、答案一起写进 baseline.txt。date %s%N 拿到纳秒时间戳相减转成毫秒。time3 表示上游无响应时最多等 3 秒避免单个坏域名拖住整个测试。Windows 客户端可以换成 PowerShell 的 Resolve-DnsName -Server 10.0.0.253 -Name $domain效果一样。baseline.txt 建好后再在 ACSG 的 WAN 口和上游 DNS 服务器上各起一轮抓包命令如下# 上游 DNS 服务器上抓包抓满 20 个 DNS 报文就停 tcpdump -i eth0 -nn -c 20 port 53 -w upstream_baseline.pcap加上 -c 20 是为了控制抓包时长测试环境里 20 个请求足够看出规律。pcap 文件先留着后面验证缓存是否命中时要回放对比上游到底收到几次请求。基线做完设备配置才动这个顺序能保证后面所有异常都能回到基线对比定位。4. 按指导书执行功能测试正向转发、缓存命中、故障转移的用例与命令4.1 正向转发用例验证客户端解析请求确实经过 ACSG第一个用例不是看结果对不对而是看流量路径对不对。客户端执行# 客户端把 DNS 指向 ACSG LAN 口查询测试域名 nslookup a.test.local 192.168.10.1正常结果应返回 10.10.10.1跟基线上游返回值一致。如果结果不一致先别改 ACSG回到客户端确认 DNS 配置确实指向了 192.168.10.1再用抓包验证请求到底去了哪。在 ACSG 的 LAN 口和 WAN 口各开一路抓包LAN 口应该看到客户端 192.168.10.100 到 192.168.10.1 的 53 端口请求WAN 口应该看到设备 10.0.0.2 到 10.0.0.253 的转发请求。两段流量都出现才算“代理”成立。# 在 ACSG 上抓取 DNS 请求打印源和目的 IP tcpdump -i any -nn -c 10 port 53这里用 -i any 是因为不确定报文会出现在哪个接口实际测试中看到两条记录一条 src192.168.10.100 dst192.168.10.1一条 src10.0.0.2 dst10.0.0.253链路就通了。注意参数顺序-nn 表示不解析主机名和端口号-c 10 是抓满 10 个包退出适合现场快速验证。只看到 LAN 口那段说明设备可能直接回了缓存只看到 WAN 口那段说明客户端请求没走设备多半是 DHCP 又把 DNS 改回去了。4.2 缓存命中与 TTL用上游抓包区分“命中”和“碰巧”缓存用例最容易自欺欺人第二次查询快了一点就以为缓存生效其实只是网络抖动。最可靠的判断依据是看上游有没有再次收到请求。先在客户端连着查两次同一个域名同时在上游 DNS 服务器抓包# 上游 DNS 上抓包观察 ttl5.test.local 是否出现多次 tcpdump -i eth0 -nn port 53 -w cache_test.pcap然后客户端跑一个小循环记录每次查询耗时# 客户端循环查询 3 次间隔 1 秒打印耗时 for i in 1 2 3; do start$(date %s%N) dig 192.168.10.1 ttl5.test.local noall answer time3 tries1 /dev/null 21 end$(date %s%N) echo 第 ${i} 次查询耗时$(( (end - start) / 1000000 )) 毫秒 sleep 1 done如果第一次耗时几十毫秒、第二次变成一两毫秒并且 cache_test.pcap 里 ttl5.test.local 的请求只出现一次缓存就是真命中了。如果抓包里第二次请求又出现说明缓存没生效按顺序排查设备缓存开关是否打开、该域名的 TTL 是否被上游设成了 0、是不是命中了“不缓存 NXDOMAIN”的策略。这里有个血泪经验TTL 为 0 的域名永远不会被缓存测缓存用例前先 dig 一下确认上游 TTL 不是 0。我曾拿一个 TTL0 的接口域名测缓存折腾半天抓包才发现上游每次都不告诉设备“可以缓存”设备自然选择不缓存。4.3 域名分流与故障转移多上游、按域名走不同出口的验证方法分流用例的配置分两步。第一步在 ACSG 的上游 DNS 列表里配两个地址主用 10.0.0.253备用 10.0.0.254。第二步配置域名策略把 split.test.local 指定走主用其余域名走另一个上游。保存配置后客户端分别解析 split.test.local 和其他域名然后在设备会话列表或日志里确认这两类查询走了不同上游。注意ACSG 里访问控制策略的线路分流和 DNS 代理的域名分流是两套逻辑别在测试时把两者混为一个功能。故障转移测试的方法先确认 split.test.local 当前正常解析然后在主上游服务器上停掉 DNS 服务# 上游 DNS 服务器上停掉 dnsmasq制造故障 systemctl stop dnsmasq客户端立刻换一个新测试域名比如 failover.test.local再次解析。预期的行为是ACSG 发现主上游不可用后在下一个查询周期切到备用上游并正常返回。这里要记录两个时间故障注入时间、设备实际切换到备用上游的时间。有些版本每次查询都做健康探测切换是秒级的有些版本依赖定时探测切换可能要等下一个探测周期。这两个行为都算“符合设计”但指导书必须写明你的设备属于哪一种否则验收时容易被当成缺陷。故障恢复测试同理重启 dnsmasq 后再查一次确认解析可以回切。客户端本地 DNS 缓存会干扰结果每次切换验证都用新测试域名或者执行 ipconfig /flushdns 清掉缓存。4.4 并发与压测用脚本把代理压一压单条查询正常不代表经得起现网流量。v12.0.41 回归时我建议加一轮轻量并发测试不需要专业压测工具Python 标准库就能做。脚本逻辑是开多个线程每个线程从测试域名池里随机选域名持续查询统计成功率与耗时分布import concurrent.futures import random import subprocess import time # 参数区按测试设备性能调整 DNS_SERVER 192.168.10.1 # ACSG LAN 口地址 DOMAINS [a.test.local, alias.test.local, ttl5.test.local] THREADS 20 # 并发线程数 REQUESTS_PER_THREAD 50 # 每个线程查询次数 TIMEOUT 3 # 单次查询超时秒 def query_once(domain): start time.time() try: subprocess.run( [dig, DNS_SERVER, domain, time2, tries1], capture_outputTrue, timeoutTIMEOUT, checkFalse ) return time.time() - start, True except subprocess.TimeoutExpired: return TIMEOUT, False pool [] with concurrent.futures.ThreadPoolExecutor(max_workersTHREADS) as executor: for worker in range(THREADS): for _ in range(REQUESTS_PER_THREAD): pool.append(executor.submit(query_once, random.choice(DOMAINS))) elapsed [f.result() for f in concurrent.futures.as_completed(pool)] costs [e[0] for e in elapsed] ok sum(1 for e in elapsed if e[1]) costs.sort() p95 costs[int(len(costs) * 0.95)] print(f总请求数: {len(elapsed)} 成功率: {ok / len(elapsed):.2%} P95耗时: {p95:.3f}s)并发数我一般从 20 线程开始每线程 50 次总共 1000 个查询对多数 ACSG 硬件不至于造成压力。如果设备 CPU 高或日志丢失就降到 5 线程如果成功率低但单条查询正常优先怀疑设备会话表或安全策略把测试源 IP 当成了扫描攻击。脚本输出的 P95 耗时不要跟公共 DNS 比绝对数值要跟第 3 章打好的基线比——开启代理后的 P95 比基线多出的部分就是代理本身的开销。5. 功能测试避坑5 个常见问题与排查顺序DNS 代理测试的翻车现场多数不是设备坏了而是环境里存在一个比 ACSG 更隐蔽的 DNS 源。下面 5 条都按“现象 → 原因 → 解决”写命中现象就顺着原因往下查基本能定位到具体环节。5.1 现象客户端明明填了设备地址解析还是失败原因最常见的是 DHCP 又下发了一个 DNS 地址客户端网卡实际生效的不是 ACSG其次是 ACSG 对应接口的 DNS 代理开关没打开或者开关配置在另一个接口上。测试环境里 DHCP 和静态地址混用最容易踩这个坑因为客户端显示的是手动配置实际生效却是 DHCP 下发的优先级更高。解决第一步在客户端查生效地址Windows 用 ipconfig /allLinux 用 cat /etc/resolv.conf确认 DNS 是不是 192.168.10.1。第二步抓包看请求的目的 IP只有请求真到了设备才轮到查设备配置。抓包命令用 tcpdump -i any -nn host 192.168.10.1 and port 53。如果请求确实到了设备但没回应检查接口归属和 DNS 代理总开关。不要急着重启设备重启通常只掩盖问题不会暴露根因。5.2 现象改完上游 DNS解析结果纹丝不动原因设备缓存命中了。DNS 代理把上游结果按 TTL 缓存TTL 没到期前同一域名不会再向上游发查询。所以用旧域名验证配置变更看到的永远是旧结果。这个坑在版本升级回归里特别常见因为前面几轮测试已经把这些域名解析过一遍设备里全是缓存。解决变更验证必须换新域名。如果手头没有新域名可以在上游加一条刚创建的测试记录。不要用 TTL 大的生产域名做这类测试。反过来TTL0 的域名适合验证配置变更因为它每次都会回源结果即时可见。验证缓存是否命中时不要只看客户端计时要以上游抓包有没有再次出现请求为准这才是区分“碰巧快”和“真命中”的唯一证据。5.3 现象分流域名没按策略走全部落到默认上游原因通常三种策略写的是精确匹配而请求带子域更宽泛的策略排在前面抢先命中上游本身返回了结果设备认为不需要分流。前两种是策略配置问题第三种是测试数据设计问题。我在现场排查时发现大多数“分流不生效”根因不是设备坏了而是压根没有设计出可观察的差异。解决先在策略列表里核对匹配类型和顺序确认动作是“走指定 DNS”而不是“允许”。再到两个上游分别 dig 同一个域名确认两个上游返回的 IP 是否不同。如果两个上游返回一模一样分流从解析结果上根本看不出来测试就没有意义。建议给分流域名在两个上游配不同 IP让结果可观察。另外注意匹配范围带子域的场景要用后缀匹配否则 www.split.test.local 永远命不中策略。5.4 现象内网 OA 域名被解析到公网 IP 或者 NXDOMAIN原因ACSG 的 DNS 代理把内网域名也当成普通域名向上游转发上游没有这些记录自然返回不了内网 IP。设备内置域名库或全局代理策略会放大这个问题甚至把内网域名强行匹配到公网地址。很多第一次接触 ACSG 的同事都会在这上面耗掉半天看着日志里一串奇怪的公网 IP不知道从哪下手。解决在 DNS 代理的例外或分流策略里加入内网域名转发到内网 DNS 服务器。规划测试域名时把内网域名和公网域名分成两批互不混用。测试前还要确认内置域名库有没有把测试域名也截走很多“莫名失败”是库里预设的系统域名在起作用。如果设备有“域名识别库”这类开关测试期间可以考虑暂时关闭减少变量。5.5 现象测试机装了 SANGFOR 终端组件结果“莫名其妙失败”原因一些测试机之前装过 SANGFOR 的终端管理或 SSL 插件这类组件会接管本机 DNS 或劫持部分解析请求流量根本没到 ACSG。很多人第一次发现“sangfor 文件夹删不掉”问 sangfor 是什么软件、能不能卸载指的多半就是这类常驻组件。它不在设备日志里留痕所有异常都发生在客户端本地所以容易让人怀疑是 ACSG 的问题。解决测试前在服务列表和网络适配器属性里检查相关项能退出的退出能卸载的卸载不行就换一台干净测试机或者直接在虚拟机上做功能测试。这个坑最隐蔽因为它完全绕过了被测设备抓包也只能看到本机进程在自问自答。判断方法很简单把 ACSG 的 LAN 口网线拔掉如果客户端还能“正常解析”测试域名那解析一定发生在本地跟设备无关。6. 测试收尾的进阶做法把指导书变成可重复执行的自动回归脚本一次功能测试做完留下 pcap 和 baseline.txt 还不够。v12.0.41 不是终点下个版本还会回来。我现在拿到这类实施指导书会先抽出核心用例转成一个可重复执行的回归脚本跑完自动输出 CSV下次新版本回来直接对比差异。import csv import subprocess import time DNS_SERVER 192.168.10.1 CASES [ (a.test.local, 10.10.10.1), (alias.test.local, a.test.local), (v6.test.local, fd00::1), (nx.test.local, NXDOMAIN), ] rows [] for domain, expected in CASES: start time.time() result subprocess.run( [dig, DNS_SERVER, domain, noall, answer], capture_outputTrue, textTrue, timeout5 ) cost_ms int((time.time() - start) * 1000) passed str(expected) in result.stdout rows.append({domain: domain, expected: expected, cost_ms: cost_ms, passed: passed}) with open(regression.csv, w, newline) as f: writer csv.DictWriter(f, fieldnames[domain, expected, cost_ms, passed]) writer.writeheader() writer.writerows(rows)这里的预期结果来自第 3 章的基线自动化只做一件事把“实际结果 vs 基线预期”变成一行 CSV。下次升级版本重跑一遍用 diff 对比 CSV哪条用例行为变了一目了然。缓存的用例没办法完全自动化因为它依赖 TTL 的计时但转发和故障转移这类稳定行为非常适合做成回归项。我现在的习惯是拿到任何网络设备的功能测试 PDF先搭抓包基线再写回归脚本最后才点界面。DNS 这类功能太容易受环境干扰眼见为实数据说话希望这些方法能帮你在 v12.0.41 的测试上少走弯路。本文还有配套的精品资源点击获取
网站建设高端定制企业官网