news 2026/10/20 9:00:32

Squid缓存代理三种模式与配置实战:正向、反向、透明接管

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Squid缓存代理三种模式与配置实战:正向、反向、透明接管

作为一个在基础设施圈子里摸爬滚打了十来年的人,我始终觉得 squid 是个被严重低估的组件。它没有花哨的管理界面,没有热门的指标大盘,但靠着精简的配置和极高的吞吐能力,至今还在大量企业的网络出口、Web 入口和缓存卸载场景里扛着最核心的流量。今天想把这套东西掰开揉碎聊一聊:squid 的几种典型工作模式分别适合什么场景,配置上要注意哪些坑,以及上线后你会遇到哪些稀奇古怪的问题。

squid 本质上是一台内容缓存与转发服务,处在一端用户与另一端资源服务器之间。它能做缓存、能限定访问范围、能改写请求头、能对后端做负载分配。很多朋友一提到它就条件反射地想到正向出口缓存,但实际上它还能承担入口侧的流量接入与缓存卸载,甚至可以在用户完全无感知的情况下,在网络层把流量“接”进来再转发出去。这篇文章我会把三种主流模式从头到尾讲透:正向模式、反向接入模式、透明接管模式。适合刚接触网络中间层的运维新手,也适合想优化内网带宽、给 Web 集群减负的工程师参考。

1. 三种主流工作模式:先看清适用边界

1.1 正向模式:帮内网用户省流量

这是最传统的用法。当你把 squid 放在企业内网出口,客户端(浏览器、扫码设备、办公软件)把请求发给 squid,由 squid 代替客户端去访问目标站点,拿到资源后一方面返回给客户端,另一方面在本地磁盘或内存中留一份副本。下次有别的客户端请求相同资源,squid 直接从缓存返回,不再绕道外网。

我见过最典型的案例是某制造企业的办公网,几百号人每天都要重复访问同一批系统更新包、软件仓库、培训视频链接。原先这些流量全部穿透出口带宽,一条 500M 的链路被吃满,员工还抱怨网页卡顿。上了 squid 正向模式之后,重复资源的命中率能做到 40% 以上,出口链路压力立刻降了一个量级。这模式的核心价值就是“帮内网用户在重复请求中节省流量”,同时还能做访问名单控制,比如只允许特定网段访问特定域名,其他的一律拒绝。

1.2 反向接入模式:帮 Web 站点挡压力

反向接入模式的意思是 squid 站在 Web 服务器前面,对外接收用户请求,转发到后端的真实源站,并把源站返回的内容缓存下来。这里的用户一般来自公网,也可能来自内网。最常用的场景是Web集群:入口只有一个地址,后面挂多台应用服务器,squid 根据规则把不同请求分发到不同节点,同时对静态资源做缓存,减轻应用层压力。

反向接入和正向模式最大的区别在于服务对象:正向模式服务的是“发起请求的客户端”,反向接入服务的是“背后的源站”。我习惯用“前台接待”来理解——squid 是公司前台,访客只需要知道前台的位置,前台再引导你去找具体部门。后端服务器躲在接待台后面,不直接暴露给外部流量,这样既安全又方便做横向扩容。

1.3 透明接管模式:让客户端无感接入

透明接管模式就是把 squid 架设在网关路径上,通过网络层的引流规则(最常用的是 iptables 或路由器策略)把去往特定端口(比如 80)的流量悄无声息地交给 squid。客户端的浏览器不需要配置任何东西,用户完全感受不到中间多了一道关卡。

透明接管经常用在校园网、园区网这种无法逐台配置客户端的场景。它最大的优势就是“零客户端改动”,但对 squid 的配置要求更精细,因为请求的原始信息(比如源 IP、原始目标地址)需要在透明模式下被正确保留和还原,否则后端服务器看到的访问来源全变成 squid 自己的地址,日志和业务都会一团糟。后面我会详细演示这部分的配置要点。

我把三种模式的关键差异整理成了下表,方便你选型时对照。

模式服务对象客户端是否需要配置典型位置主要收益
正向模式内网用户需要内网出口节省带宽、访问控制
反向接入模式公网/内网访客不需要Web 入口隐藏源站、缓存加速
透明接管模式任意客户端无需感知网关路径免配置引流、集中管控

2. 配置文件与核心指令:先打好地基

2.1 主配置文件结构

squid 的所有行为都通过一个文本文件控制,通常位于 /etc/squid/squid.conf。这个文件看起来指令很多,但真正高频使用的不过二三十条。配置的核心哲学是“先定义资源,再定义权限,最后定义动作”:

  • 用http_port定义监听端口和模式
  • 用cache_dir定义缓存存放位置和大小
  • 用acl定义访问名单
  • 用http_access定义允许或拒绝的规则

http_access的匹配是自上而下的,匹配到第一条就停止,所以一定要把严格的拒绝规则放在宽松规则前面。由于这个顺序问题,我见过多次误操作导致整网断流的案例,后面会专门讲排查方法。

下面是一段最基础、能在大多数环境跑起来的配置骨架:

# 定义工作模式与监听端口 http_port 3128 # 缓存目录:分配 10GB 空间,一级目录16个,二级目录256个 cache_dir ufs /var/spool/squid 10240 16 256 # 定义内部网段 acl localnet src 192.168.10.0/24 acl localnet src 10.10.0.0/16 # 定义允许访问的域名 acl allowed_domains dstdomain .example.com acl allowed_domains dstdomain .software-update.example.net # 只要来自内网,就允许访问 http_access allow localnet # 其他情况一律拒绝 http_access deny all

2.2 三个容易忽略的细节

第一,cache_dir中的 16 和 256 分别代表第一级和第二级子目录数量。这两个值直接影响磁盘上大量小文件时的查找效率,不建议随意调大。如果缓存文件数量非常大,可以适当增加一级目录数量,但不要超过 32,否则目录遍历反而变慢。

第二,visible_hostname建议显式配置。很多发行版把 squid 编译时的默认主机名写进配置,但如果你改了系统主机名,squid 启动时可能会因为无法解析主机名而报错。我习惯直接写一行:

visible_hostname squid-node-01

第三,缓存目录必须在启动前手工初始化。squid 在运行过程中会动态创建子目录,但首次建立顶层缓存目录结构通常需要执行squid -z。否则首次启动可能会报“Failed to verify one of the cache_dirs”之类的错误。

2.3 日志与统计

squid 的日志格式非常稳定,默认访问日志在 /var/log/squid/access.log。每一行都记录着时间戳、客户端 IP、请求方式、请求 URL、响应码、命中状态等关键信息。排查问题时一定要看日志,而不是瞎猜。我常用的三条命令:

# 查看实时访问情况 tail -f /var/log/squid/access.log # 统计最热门的请求目标 awk '{print $7}' /var/log/squid/access.log | sort | uniq -c | sort -rn | head -20 # 统计命中率 grep -c "TCP_HIT" /var/log/squid/access.log

日志里的TCP_HIT、TCP_MISS、TCP_MEM_HIT这些状态码能直接告诉你缓存是否生效,绝大部分命中率问题都能从这些字段里找出答案。

3. 正向模式配置实操:从零跑通出口缓存

3.1 规划与准备

在动手之前,先想清楚三件事:监听端口、缓存空间、允许名单。监听端口建议用 3128,这是 squid 的传统端口,不会与 Web 服务冲突。缓存空间根据出口流量来定,我一般建议至少给到磁盘剩余空间的 20%。允许名单则要梳理出内网哪些网段允许使用,以及是否有必须放行的域名。

准备好一台双网卡服务器:一块网卡接内网交换机,另一块接出口网关。squid 本身不需要开启路由转发,因为它只是接收内网客户端发来的请求,再作为客户端去访问外网资源。

3.2 正向模式核心配置

下面是经过我反复验证的正向模式配置,直接拿去改改就能用:

# 监听内网网卡地址,仅允许内网访问 http_port 192.168.10.10:3128 # 缓存目录 20GB cache_dir ufs /data/squid/cache 20480 16 256 # 内存缓存上限,别设太大,避免占用过多业务内存 cache_mem 512 MB # 日志 access_log /var/log/squid/access.log squid cache_log /var/log/squid/cache.log # 定义内网网段 acl boss_net src 192.168.10.0/24 acl office_net src 192.168.20.0/24 # 禁止访问的目标 acl blocked_sites dstdomain .p2p.example.net acl blocked_sites dstdomain .ads.example.com # 规则顺序:先允许内网,再拒绝特殊域名 http_access allow boss_net http_access allow office_net http_access deny blocked_sites http_access deny all

3.3 客户端配置与验证

浏览器或操作系统把 HTTP 出口指向192.168.10.10:3128后,浏览器发往目标站点的请求就会先到 squid。验证是否生效,最直接的方法是查看 access.log:

tail -f /var/log/squid/access.log

当你在浏览器里打开一个网页,日志中会多出类似这样的记录:

1690000000.000 123 192.168.10.5 TCP_MISS/200 1024 GET http://www.example.com/

看到TCP_MISS表示首次访问,还没命中缓存;再刷新一次浏览器,日志里会变成TCP_HIT,说明本地缓存已经建立。连续刷三次同样的页面,只有第一条是 MISS,后面都应该是 HIT,这就是缓存生效的铁证。

3.4 我踩过的一个坑:缓存目录权限

有一次配置完以后,squid 进程正常启动,但日志疯狂报警,提示缓存目录无法写入。排查了半天发现是因为我用了/data/squid/cache这个自定义目录,但没把该目录的所有者改成运行 squid 的系统用户。解决方式很简单:

chown -R squid:squid /data/squid/cache

养成习惯:创建完缓存目录后立刻检查属主,再执行squid -z初始化,最后再启动服务。

4. 反向接入模式配置实操:给 Web 集群加一层入口守护

4.1 反向接入的整体思路

反向接入模式下,squid 对外表现为一个普通 Web 入口,监听 80 或 443 端口。它接收所有访问请求,然后按照规则把请求转发给内网的真实业务服务器。整个过程对用户透明,用户只会认为 squid 的地址就是网站地址。

这里需要重点理解的是cache_peer指令。它用来定义后端源站,可以指定多个源站,squid 会按照轮询方式把请求分发下去。同时配合cache_peer_domain或cache_peer_access可以把不同域名转发到不同的后端组,实现简单的分流。

4.2 反向接入模式核心配置

# 监听 80 端口,工作在加速模式 http_port 80 accel vhost # 关闭转发功能,不向外网直接抓取 # 这里通过 never_direct 强制所有请求都走 cache_peer never_direct allow all # 定义后端源站 cache_peer 192.168.30.11 parent 8080 0 no-query originserver name=web1 cache_peer 192.168.30.12 parent 8080 0 no-query originserver name=web2 # 将 www.example.com 的请求转发给这两个后端 cache_peer_domain web1 web2 .example.com www.example.com # 缓存规则:静态资源缓存 24 小时 acl static_assets urlpath_regex -i \.(css|js|png|jpg|jpeg|gif|webp|svg|woff2?)$ http_access allow static_assets # 动态请求不缓存 acl dynamic_urls urlpath_regex -i \.(php|do|action)$ http_access deny dynamic_urls

注意accel vhost这两个参数是反向接入模式的关键。accel让 squid 进入加速模式,不再要求请求里必须有完整的转发链;vhost允许 squid 根据请求中的 Host 头来决定后端目标,而不是把配置写死成单台服务器。如果你只加了一个后端,可以省掉vhost,但做多站点托管时一定要保留。

4.3 缓存规则制定的经验

反向接入中最容易犯的错误是把所有页面全都缓存。动态接口一旦被缓存,用户会看到过期的订单状态、陈旧的库存信息,甚至登录失败。我的经验是:把缓存优先级放在静态资源上,动态 URL 一律透传。

squid 判断动态请求通常靠 URL 后缀或规则匹配。上面配置里dynamic_urls那一行已经拒绝了动态后缀,但有些网站的路由是伪静态的,比如/product/id/123,这时候再用后缀匹配就不明智。可以考虑用acl dynamic_urls urlpath_regex -i /api/这样的关键字匹配,或者干脆依赖后端返回的Cache-Control响应头。

更好的做法是让后端在响应头里显式声明缓存策略,然后 squid 通过refresh_pattern配合响应头来决定缓存时长。这样前后端职责分明,缓存策略不容易出错。

4.4 后端健康检查与宕机转移

cache_peer自身带有简单的存活检测,但默认并不频繁。我建议在配置里加上监测周期和连续失败次数:

cache_peer 192.168.30.11 parent 8080 0 no-query originserver monitorurl=/healthz connect-fail-limit=2 allow-miss

connect-fail-limit=2表示连续两次连接失败就标记该源站为不可用,后续请求自动转移到其他源站。这里的allow-miss也很重要,它允许 squid 在上游异常时依然返回本地缓存副本。否则一旦源站挂了,所有本来能命中缓存的静态资源也会变得不可用。

5. 透明接管模式配置实操:网络层引流与免配置接入

5.1 为什么需要透明接管

正向模式要求每台客户端手动指定出口地址,这在小型办公室还能接受,但在几百人的教室、宿舍、园区网里几乎是不可行的。透明接管模式让 squid 成为路径上的一个“隐形关卡”,客户端不需要任何修改。

它依赖网络层的重定向,最常见的做法是用 iptables 把发往 80 端口的 TCP 包重定向到 squid 的一个监听端口。当然,iptables 重定向的能力通常是本机范围内的,如果是跨设备引流,则需要路由器或交换机上配合策略路由。本文以内网单机部署为例,讲解最常见的 iptables 方案。

5.2 透明接管模式核心配置

squid 侧的配置和正向模式类似,但要加上transparent关键字:

# 监听 3128,以透明模式工作 http_port 3128 transparent # 缓存目录和日志 cache_dir ufs /data/squid/cache 10240 16 256 access_log /var/log/squid/access.log squid # 允许内网所有网段 acl all_net src 0.0.0.0/0 http_access allow all_net http_access deny all

网络侧的 iptables 规则一般放在 nat 表的 PREROUTING 链:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3128

这条规则的意思是:从内网网卡 eth0 进入、目标端口是 80 的 TCP 包,全部重定向到本机 3128 端口。squid 通过透明模式识别出原始目标地址,主动发起连接,再把响应返回给客户端。用户在浏览器里输入网址时,地址栏不变,请求先经过 squid,但客户端自己完全没有感知。

注意,这里只重定向了 HTTP 的 80 端口。如果还想接管 HTTPS(443 端口),情况要复杂得多,因为 TLS 握手阶段 squid 必须知道目标域名,需要用 SSL 拦截或显式配置,我不建议新手直接在生产环境开干,可以先从 HTTP 场景入手。

5.3 透明接管模式的路由环回坑

透明接管最常见的故障是“路由环回”。如果不加任何额外规则,重定向后的数据包可能又被 squid 本身的网络栈重新判断为发往外部的流量,从而再次进入 PREROUTING,产生死循环。

解决办法是在重定向之前排除由 squid 自己发出的流量:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3128 iptables -t nat -A OUTPUT -o eth1 -p tcp --dport 80 -j REDIRECT --to-port 3128

其实还有更稳妥的做法:在 squid 所在机器上关闭对 80 端口的内核转发,并把http_port监听地址绑定到内网 IP,这样避免对外转发路径和透明入口路径互相干扰。我这边的经验是,先把规则拆成最小验证,确认日志中出现请求后,再逐步放开其他链路。

5.4 与正向模式同时部署的思路

有些网络环境需要同时提供“主动配置型”和“透明接管型”两种接入方式。squid 允许在一个进程里监听多个端口,每个端口可以有不同的模式,比如:

http_port 3128 transparent http_port 3129

这样一来,走网络层引流到 3128 的请求是透明的,而愿意手动配置的客户端可以使用 3129。这种混合部署在过渡期非常实用,不用担心切换窗口期客户端全都无法上网。

6. 常见故障与调优经验:手把手排查实录

6.1 访问被拒绝:多半是规则顺序问题

症状是客户端访问任意地址都返回 403,日志里出现TCP_DENIED。这时候先去检查http_access规则的顺序。squid 从上往下匹配,匹配即生效。如果deny all写在allow前面,所有请求都会被拒绝。

还有一种隐蔽情况:客户端 IP 不在任何acl src网段内。比如内网实际是 172.16.0.0/16,但你在 acl 里只写了 192.168.10.0/24,那当然匹配不上。建议先用print或日志里记录的源 IP 反向确认,别想当然。

6.2 缓存命中率低:检查对象尺寸和 refresh_pattern

有时候日志里全是TCP_MISS,命中率不到 10%。原因通常是默认的minimum_object_size或maximum_object_size设置过小。小于 0KB 的对象不会被缓存,如果站点大量图片都是 5KB 以内,而最小值被设成 8KB,那这些图片永远不会进缓存。

另外refresh_pattern也要关注。不同后缀的资源刷新周期差别很大,图片、CSS、JS 可以给 24 小时甚至 7 天,但 HTML 页面最好用较短时间。我常用的模板如下:

refresh_pattern -i \.(css|js|png|jpg|jpeg|gif|webp|svg|ico)$ 1440 80% 2880 refresh_pattern -i \.(html|htm|php|asp|aspx)$ 0 50% 60 refresh_pattern -i . 5 40% 4320

最后一行默认规则很重要,它会兜住所有没有匹配上的 URL,防止因规则遗漏导致缓存策略混乱。

6.3 高并发时文件描述符不足

当并发请求数超过系统默认限制,squid 会在 cache.log 中报too many open files。处理办法是提高进程可打开的文件数限制:

ulimit -n 65535

同时检查/etc/security/limits.conf,给运行 squid 的系统用户设置更高的软硬限制。如果设备内存充足,还可以适当调大cache_mem,把热门对象留在内存里,减少磁盘读取,这是提升并发响应速度最直接的手段。

6.4 DNS 解析导致首次访问极慢

squid 自己需要一个运行良好的 DNS 解析环境。如果上游 DNS 延迟高或者不稳定,首次访问新域名时会出现长时间卡住,而后台日志里没有任何异常。这种情况可以在配置里增加dns_nameservers指定更快的 DNS 地址:

dns_nameservers 223.5.5.5 8.8.8.8

这里注意别同时把太多 DNS 写上,两个就够。另外可以开启positive_dns_ttl,对解析结果做一段时间的缓存,减少重复解析带来的等待。

6.5 磁盘空间增长过快

有些环境里缓存目录蹭蹭涨,很快把磁盘填满。这不一定是 bug,而是没有设好cache_dir的上限以及maximum_object_size上限。如果站点里存在超大视频文件,squid 默认也可能去缓存,很快就会吃掉大量空间。我建议把超过 64MB 的对象直接跳过缓存:

maximum_object_size 64 MB minimum_object_size 0 KB

同时写一个磁盘空间监控脚本,当缓存目录超过总大小 80% 时自动清理最老的缓存文件,防止业务磁盘被写满。

6.6 上线前必做的四件事

这里是我每次部署 squid 都会走一遍的检查清单,直接用即可:

  • 执行squid -k parse验证配置文件语法,有错误会直接指出行号
  • 执行squid -z初始化缓存目录,确认没有权限错误
  • 启动后看/var/log/squid/cache.log,确保没有 FATAL 级别日志
  • 从客户端发起一次真实请求,核对 access.log 中的响应码和命中状态

做完这四步,一个可用的转发缓存服务就已经跑起来了。后续再逐步叠加访问控制、多后端接入、透明引流这些高级特性。

写在最后的一点个人心得

squid 这玩意儿,虽然老,但它的配置模型非常经典。很多人一开始被各种 ACL、refresh_pattern 绕得晕头转向,其实只要记住“先定义对象、再定义规则、最后控制动作”这条主线,后面所有配置都是往这个框架里填内容。我在实际项目里观察下来,真正容易出问题的地方往往不在 squid 本身,而是周边配套——防火墙规则、路由策略、DNS 解析、磁盘空间。把这些环境因素管好,squid 能跑得非常扎实。

如果后续你想继续扩展,可以试试在反向接入模式下给不同域名配置不同的后端节点组,或者把透明接管模式扩展到 IPv6 场景。另外,squid 的日志字段非常丰富,接上开源日志采集工具后,完全可以做出企业内部出口流量的可视化分析看板。希望这篇配置解析能帮你在实际业务里少踩几个坑,把这台经典服务真正用起来。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 9:00:09

自动包装Wrapper实战:统一Dubbo消费方调用,告别散乱RPC代码

先说结论:Dubbo高级特性里的“自动包装Wrapper”,并不是官方文档里某个开箱即用的类,而是一套把消费方调用过程收敛到统一封装层的设计思想。它解决的核心问题很现实:不用再手动new ReferenceConfig、不用每个接口都写一遍超时重试…

作者头像 李华
网站建设 2026/10/20 8:59:46

EVM误差矢量幅度详解:定义、计算与测试方法

简介:EVM(误差矢量幅度)是通信系统中衡量调制信号质量的关键指标,尤其对QPSK等非恒包络调制具有重要意义。这份中文图解文档围绕EVM的定义展开,系统讲解其计算公式、星座图误差矢量示意,并延伸至IQ信号幅度…

作者头像 李华
网站建设 2026/10/20 8:59:44

OpenOCD源码编译指南:Windows与Linux平台完整流程

1. 为什么要放着现成的安装包不用,非要自己编译我刚接触OpenOCD那会儿,和大家一样,习惯性找了个现成的发行包装上就完事。Windows上有打包好的exe,Linux上用apt直接装,确实零成本起步。直到有一次我在一块比较冷门的开…

作者头像 李华
网站建设 2026/10/20 8:59:30

AI插件安全审核系统:三级漏斗架构与eBPF沙箱实践

1. 项目概述:一个被低估的“安全门禁系统”正在成型最近在几个技术社区刷到一条消息:“Claude插件目录开源,第三方提交需过安全审核”。初看像一句平平无奇的公告,但作为连续三年深度参与多个AI工具链安全治理项目的从业者&#x…

作者头像 李华
网站建设 2026/10/20 8:59:03

Go短信验证码接口封装:签名、错误码与防刷实践

平时写Go后端时,接到短信验证码需求往往是“看着简单、做起来全是暗坑”。发送要调第三方,验证要自己存,前端还要倒计时,稍微哪个环节没接好,线上就是一连串“验证码收不到”“验证码一直报错”“接口被刷爆”的投诉。…

作者头像 李华