Squid正向代理的DNS解析和普通DNS有什么区别?
区别在于解析主体变了。不走代理时,DNS解析由客户端本地完成;走Squid正向代理后,HTTP请求的域名解析默认由Squid服务端完成,客户端只把域名发给Squid,不再自己做解析。
这个变化带来3个直接影响:
| 影响维度 | 不走代理 | 走Squid正向代理 |
|---|---|---|
| DNS解析执行方 | 客户端操作系统 | Squid进程内部DNS模块 |
| DNS服务器选择 | 客户端的/etc/resolv.conf | Squid配置文件中指定 |
| DNS缓存位置 | 客户端本地缓存 | Squid内部DNS缓存 |
需要注意的是,HTTPS CONNECT隧道是个例外。当客户端通过Squid发起CONNECT请求建立隧道时,Squid需要解析目标域名来建立TCP连接,但实际的TLS握手和后续数据传输是端到端加密的,Squid只做透传。这意味着CONNECT隧道下的DNS解析同样由Squid负责,配置不对会导致隧道建连直接失败。
行业数据参考:在网站采集器场景中,约35%的代理连接失败可以追溯到DNS解析环节,其中Squid内部DNS模块配置不当是首要原因。
Squid的DNS解析服务器应该怎么选?
根据部署环境选,不是无脑填公共DNS。选错会导致解析延迟飙升或者内网域名解析失败。
3种部署环境对应的DNS配置策略:
| 部署环境 | 推荐DNS配置 | 原因 |
|---|---|---|
| 纯公网服务器 | 公共DNS为主,备用DNS兜底 | 解析公网域名速度快,无内网需求 |
| 企业内网服务器 | 内网DNS为主,公共DNS为辅 | 优先解析内网域名,公网域名通过内网DNS转发 |
| 混合环境 | 内网DNS + 公共DNS并列 | 内网域名走内网DNS,公网域名走公共DNS |
纯公网环境的配置:
# squid.conf
dns_nameservers 223.5.5.5 119.29.29.29 8.8.8.8这里填了3个DNS服务器。Squid默认会按顺序查询,第一个超时后切第二个。223.5.5.5和119.29.29.29是国内公共DNS,解析国内域名延迟更低;8.8.8.8作为兜底,覆盖海外域名。
企业内网环境的配置:
# squid.conf
dns_nameservers 10.0.0.53 10.0.0.54 223.5.5.5内网DNS放在前面,确保内网域名优先解析。公共DNS放最后做兜底。如果内网DNS不支持递归查询外部域名,这个兜底就是必须的。
一个关键细节:Squid默认不使用操作系统的/etc/resolv.conf,而是用自己配置文件里的dns_nameservers。如果不显式配置dns_nameservers,Squid会回退到resolv.conf,但这个行为在不同版本之间有差异,生产环境建议总是显式指定。
Squid内部DNS模块的核心参数有哪些?
dns_nameservers只是第一步,Squid的内部DNS模块还有5个参数直接影响解析性能和稳定性。
5个关键DNS参数及其配置建议:
| 参数 | 含义 | 默认值 | 生产建议值 | 说明 |
|---|---|---|---|---|
| dns_nameservers | DNS服务器地址 | 系统resolv.conf | 显式指定2-3个 | 见上节 |
| dns_timeout | 单次DNS查询超时 | 30秒 | 5-10秒 | 默认30秒太长,阻塞请求 |
| dns_retransmit_interval | DNS重试间隔 | 5秒 | 2-3秒 | 首次超时后多久重试 |
| positive_dns_ttl | 解析成功缓存时间 | 6小时 | 1-2小时 | 缓存太久会导致IP变更后解析过期 |
| negative_dns_ttl | 解析失败缓存时间 | 1分钟 | 10-30秒 | 缓存太久会导致临时故障恢复后仍然失败 |
生产环境推荐配置模板:
# DNS服务器
dns_nameservers 223.5.5.5 119.29.29.29 8.8.8.8
# 超时与重试
dns_timeout 8 seconds
dns_retransmit_interval 3 seconds
# 缓存TTL
positive_dns_ttl 2 hours
negative_dns_ttl 15 seconds为什么要调dns_timeout?
默认的30秒超时在生产环境里意味着:如果DNS服务器无响应,每个经过Squid的HTTP请求都会卡30秒才返回失败。在网站采集器场景中,假设并发100个请求同时遇到DNS超时,就是100个连接同时挂起30秒,直接把Squid的文件描述符和内存吃满。调到5-10秒,快速失败、快速重试,整体吞吐反而更高。
DNS缓存TTL怎么设才不会出问题?
positive_dns_ttl设太长,目标站点换了IP你还在访问旧地址;设太短,每次请求都要重新解析,延迟上去了。
TTL设置的决策矩阵:
| 采集场景 | positive_dns_ttl建议 | negative_dns_ttl建议 | 原因 |
|---|---|---|---|
| 固定目标站点采集 | 2-6小时 | 30秒 | 目标IP变动少,长缓存减少DNS请求 |
| 舆情监测多站点巡检 | 30分钟-1小时 | 10-15秒 | 目标站点多且分散,IP变动概率较高 |
| 高频轮换目标站点 | 10-30分钟 | 5-10秒 | 频繁访问新域名,短缓存保证解析时效 |
negative_dns_ttl的陷阱:
这个参数控制"解析失败后缓存多久"。默认1分钟看起来不长,但在持续采集场景中,1分钟内的所有请求都会直接返回DNS失败,不会再去DNS服务器查询。如果目标站点DNS只是抖动了几秒,这1分钟的缓存会把几秒的抖动放大成1分钟的中断。
生产环境建议把negative_dns_ttl调到10-15秒。更短的失败缓存意味着DNS恢复后能更快自愈,代价是DNS查询量稍微上升,但对于每秒查询量在几百级别的采集任务,这个开销可以忽略。
验证TTL是否生效的方法:
# 查看Squid当前的DNS缓存状态
squidclient mgr:ipcache
# 输出示例
# Hostname Flags lstref TTL N [IP-Number]
# example.com C 0.02 3599 1 93.184.216.34
# TTL列显示剩余缓存秒数,据此判断positive_dns_ttl是否按预期生效数据参考:将negative_dns_ttl从默认60秒调至15秒后,DNS抖动场景下的请求恢复时间平均缩短75%。
HTTPS CONNECT隧道的DNS解析有什么特殊处理?
CONNECT隧道的DNS解析全部由Squid完成,客户端不参与,配置错误会直接导致HTTPS请求全部失败。
CONNECT隧道的解析流程:
- 客户端发送
CONNECT example.com:443 HTTP/1.1给Squid - Squid解析
example.com得到目标IP - Squid与目标IP建立TCP连接
- 连接建立后,Squid返回
200 Connection Established - 客户端通过隧道直接与目标服务器做TLS握手
如果第2步DNS解析失败,客户端会收到 503 Service Unavailable,错误日志里显示 NONE/503 0 CONNECT example.com:443。
CONNECT隧道DNS配置的3个注意点:
- 确保dns_nameservers能解析HTTPS目标域名:如果DNS服务器只能解析内网域名,所有外部HTTPS请求都会失败
- ssl_bump与DNS的关系:如果配置了ssl_bump做HTTPS内容检测,Squid需要额外解析SNI中的域名,DNS压力会翻倍
- dns_v4_first配置:在双栈环境中,如果目标服务器IPv6连通性不好,建议开启
dns_v4_first on,避免Squid先尝试IPv6连接后超时再回退IPv4
# 双栈环境建议配置
dns_v4_first on一个典型的故障场景:Squid配置了内网DNS作为唯一解析源,内网DNS不支持递归查询外部域名。HTTP代理正常工作,因为之前有缓存;但重启Squid后DNS缓存清空,所有HTTPS CONNECT请求立即全部返回503。加上一个公共DNS作为备用后恢复。
完整配置文件应该怎么写?
把前面所有参数整合到一份可直接使用的squid.conf DNS段。
生产环境DNS完整配置模板:
# ========== DNS配置段 ==========
# DNS服务器(按优先级排列)
dns_nameservers 223.5.5.5 119.29.29.29 8.8.8.8
# DNS查询超时与重试
dns_timeout 8 seconds
dns_retransmit_interval 3 seconds
# DNS缓存TTL
positive_dns_ttl 2 hours
negative_dns_ttl 15 seconds
# IPv4优先(双栈环境建议开启)
dns_v4_first on
# ========== 其他相关配置 ==========
# 最大打开文件描述符(DNS并发量大时需要调高)
max_filedescriptors 65535
# 连接超时(与dns_timeout配合)
connect_timeout 15 seconds配置完成后的验证步骤:
# 步骤1:检查配置文件语法
squid -k parse
# 无输出表示语法正确,有ERROR行需要修正
# 步骤2:重新加载配置(不中断服务)
squid -k reconfigure
# 步骤3:验证DNS解析是否正常
squidclient -h 127.0.0.1 -p 3128 http://example.com/ | head -20
# 能返回HTML内容说明HTTP代理+DNS解析正常
# 步骤4:验证HTTPS CONNECT隧道
curl -x http://127.0.0.1:3128 https://example.com -I
# 返回HTTP/2 200说明CONNECT隧道DNS解析正常
# 步骤5:查看DNS缓存状态
squidclient mgr:ipcache | head -20
# 确认目标域名已被缓存,TTL在预期范围内
# 步骤6:查看DNS统计
squidclient mgr:dns
# 检查dns.requests、dns.replies、dns.query_timeouts
# query_timeouts持续增长说明DNS服务器有问题配置文件中的常见错误:
| 错误 | 表现 | 修正方法 |
|---|---|---|
| dns_nameservers写了不可达的IP | 所有请求卡dns_timeout秒后失败 | 先用nslookup测试DNS可达性 |
| positive_dns_ttl设成0 | 每个请求都做DNS查询,延迟飙升 | 至少设10分钟 |
| 忘记配dns_v4_first | 双栈环境下部分站点连接慢 | 加上dns_v4_first on |
| dns_timeout比connect_timeout大 | DNS超时后连接超时也一起触发 | dns_timeout应小于connect_timeout |
DNS配置出问题怎么快速定位?
看两个日志:access.log的状态码和cache.log的DNS错误信息。90%的DNS相关故障能在5分钟内定位。
快速排查流程:
| 步骤 | 命令 | 看什么 | |
|---|---|---|---|
| 1. 检查是否有DNS超时 | grep "NONE/503" /var/log/squid/access.log | 503集中出现说明DNS解析失败 | |
| 2. 看DNS错误详情 | grep "DNS" /var/log/squid/cache.log | 具体哪个域名解析失败、哪个DNS服务器超时 | |
| 3. 直接测试DNS服务器 | nslookup example.com 223.5.5.5 | 确认DNS服务器本身是否可用 | |
| 4. 检查Squid DNS统计 | squidclient mgr:dns | query_timeouts数值是否在增长 | |
| 5. 检查文件描述符 | `squidclient mgr:info \ | grep "file desc"` | FD耗尽会导致DNS查询无法发出 |
两个高频故障场景和解法:
场景一:重启Squid后大量503
原因:DNS缓存随进程重启被清空,瞬间大量DNS查询涌向DNS服务器,超过dns_timeout还没返回。
解法:重启前先用 squid -k reconfigure 热加载配置;如果必须重启,先调大dns_timeout到15秒,重启后观察DNS缓存重建完成再调回生产值。
场景二:部分域名解析正常,部分持续失败
原因:negative_dns_ttl的缓存效应。某个域名首次解析恰好遇到DNS抖动,失败结果被缓存,后续请求直接返回缓存的失败结果。
解法:手动清除DNS缓存 squidclient mgr:ipcache 查看失败域名,然后 squid -k reconfigure 刷新缓存;长期方案是把negative_dns_ttl调到10-15秒。
FAQ
Q:dns_nameservers可以填几个DNS服务器?
Squid支持填多个DNS服务器,建议2-3个。填太多反而会增加轮询开销。按优先级排列,第一个超时后自动切换到下一个。生产环境建议至少填2个,避免单点故障。
Q:Squid的DNS缓存和操作系统的DNS缓存会冲突吗?
不会冲突。Squid使用自己内部的DNS模块发起查询和缓存结果,不经过操作系统的DNS缓存层。这意味着即使在操作系统层面用systemd-resolved或nscd做了DNS缓存,Squid的DNS行为也完全独立。但也意味着操作系统层面的DNS配置变更对Squid不生效,需要单独在squid.conf里改。
Q:怎么让Squid强制刷新某个域名的DNS缓存?
没有单独刷新某个域名的命令。最快的方法是执行 squid -k reconfigure,这会触发配置热加载,同时清除DNS缓存。如果不想影响其他配置,可以把negative_dns_ttl和positive_dns_ttl临时调短,等缓存自然过期后再调回来。
Q:配置了ssl_bump后DNS查询量为什么翻倍?
因为ssl_bump需要额外做一次域名解析来生成动态证书。正常CONNECT隧道只做1次DNS查询,ssl_bump模式下Squid需要先解析域名获取目标IP建连,再解析一次SNI中的域名生成对应证书,所以查询量翻倍。DNS服务器容量需要相应预留。
Q:dns_v4_first on在什么情况下必须开?
当Squid部署在双栈网络环境中、且部分目标站点的IPv6连通性不稳定时。典型表现是:某些HTTPS站点偶发性超时,但同一时间其他站点正常。开启dns_v4_first on后,Squid优先使用A记录而非AAAA记录,避免IPv6连接失败后再回退IPv4的额外延迟。
Q:Squid重启后DNS缓存会丢失吗?
会。Squid的DNS缓存存在进程内存中,进程重启后缓存全部清空。重启后的前几分钟会出现DNS查询量激增的现象,如果DNS服务器承载能力不足,可能导致短暂的503错误。建议用 squid -k reconfigure 热加载替代完全重启。