资讯动态

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

发布时间:2026/10/20 9:00:36 来源:尧图企业网站定制
作为一个在基础设施圈子里摸爬滚打了十来年的人我始终觉得 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 all2.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 all3.3 客户端配置与验证浏览器或操作系统把 HTTP 出口指向192.168.10.10:3128后浏览器发往目标站点的请求就会先到 squid。验证是否生效最直接的方法是查看 access.logtail -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 nameweb1 cache_peer 192.168.30.12 parent 8080 0 no-query originserver nameweb2 # 将 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-limit2 allow-missconnect-fail-limit2表示连续两次连接失败就标记该源站为不可用后续请求自动转移到其他源站。这里的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 端口。如果还想接管 HTTPS443 端口情况要复杂得多因为 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 的日志字段非常丰富接上开源日志采集工具后完全可以做出企业内部出口流量的可视化分析看板。希望这篇配置解析能帮你在实际业务里少踩几个坑把这台经典服务真正用起来。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑