强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Squid 完全指南 / 04 - 正向代理

第四章:正向代理

4.1 正向代理概述

正向代理(Forward Proxy)是 Squid 最经典的应用场景。客户端将请求发送给代理,由代理代替客户端向目标服务器发起请求,并将响应返回给客户端。

┌──────────────┐       ┌─────────────────┐       ┌──────────────┐
│   客户端      │──────→│  Squid 正向代理  │──────→│  目标服务器    │
│  (浏览器)     │←──────│  3128 端口       │←──────│  (互联网)     │
│              │       │  ACL + 认证     │       │              │
│  代理设置:    │       │  缓存 + 日志    │       │              │
│  proxy:3128  │       │  内容过滤       │       │              │
└──────────────┘       └─────────────────┘       └──────────────┘

4.2 基础正向代理配置

4.2.1 最小配置

# /etc/squid/squid.conf — 基础正向代理

# 监听端口
http_port 3128

# 基础 ACL
acl localnet src 192.168.1.0/24
acl SSL_ports port 443
acl Safe_ports port 80 443 21 70 8080

# 访问控制
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost
http_access allow localnet
http_access deny all

# 日志
access_log /var/log/squid/access.log squid
cache_log /var/log/squid/cache.log

# 缓存
cache_dir ufs /var/spool/squid 1000 16 256
cache_mem 256 MB

# 主机名
visible_hostname proxy.example.com

4.2.2 多网段配置

# 定义多个内网段
acl office_net src 192.168.1.0/24
acl dev_net src 10.0.0.0/24
acl guest_net src 172.16.0.0/24
acl management src 192.168.100.10 192.168.100.11

# 分层访问控制
http_access allow management
http_access allow office_net
http_access allow dev_net
http_access deny guest_net !Safe_ports
http_access allow guest_net
http_access deny all

4.2.3 监听多个端口

# 标准 HTTP 代理
http_port 3128

# 透明代理端口(配合 iptables REDIRECT)
http_port 3129 intercept

# HTTPS 拦截端口(SSL Bump)
http_port 3130 ssl-bump \
    generate-host-certificates=on \
    dynamic_cert_mem_cache_size=20MB \
    cert=/etc/squid/ssl/myCA.pem \
    key=/etc/squid/ssl/myCA.key

4.3 客户端配置

4.3.1 浏览器手动配置

Firefox:

  1. 设置 → 网络设置 → 手动代理配置
  2. HTTP 代理: 192.168.1.1,端口: 3128
  3. 勾选「为所有协议使用相同代理」

Chrome(通过系统设置):

  1. 设置 → 网络 → 代理 → 手动设置代理
  2. HTTP 代理: 192.168.1.1,端口: 3128

4.3.2 通过 PAC 文件自动配置

创建 PAC (Proxy Auto-Config) 文件:

// /var/www/html/proxy.pac
function FindProxyForURL(url, host) {
    // 本地地址直连
    if (isPlainHostName(host) ||
        dnsDomainIs(host, ".local") ||
        isInNet(host, "192.168.0.0", "255.255.0.0") ||
        isInNet(host, "10.0.0.0", "255.0.0.0")) {
        return "DIRECT";
    }

    // 特定域名走特定代理
    if (dnsDomainIs(host, ".example.com")) {
        return "PROXY proxy1.example.com:3128; PROXY proxy2.example.com:3128";
    }

    // 其他流量走默认代理
    return "PROXY proxy.example.com:3128; DIRECT";
}

在 Squid 配置中提供 PAC 文件:

# 通过 Squid 自身提供 PAC 文件
# 将 proxy.pac 放在可访问的 Web 服务器上
# 浏览器配置自动代理 URL: http://proxy.example.com/proxy.pac

4.3.3 WPAD 自动发现

# WPAD (Web Proxy Auto-Discovery) 需要 DNS 或 DHCP 配置

# DNS 方式:创建 wpad.example.com 记录指向 Web 服务器
# 在 Web 服务器上提供 /wpad.dat 文件(内容同 PAC 文件)

# DHCP 方式:在 DHCP 服务器中配置 option 252
# option 252 "http://wpad.example.com/wpad.dat"

4.3.4 系统级代理设置

# Linux 环境变量
export http_proxy=http://192.168.1.1:3128
export https_proxy=http://192.168.1.1:3128
export ftp_proxy=http://192.168.1.1:3128
export no_proxy=localhost,127.0.0.1,.local,.example.com

# 写入 ~/.bashrc 或 /etc/environment 持久化

# apt 代理配置
# /etc/apt/apt.conf.d/99proxy
# Acquire::http::Proxy "http://192.168.1.1:3128";
# Acquire::https::Proxy "http://192.168.1.1:3128";

# yum/dnf 代理配置
# /etc/dnf/dnf.conf
# proxy=http://192.168.1.1:3128
# proxy_username=user
# proxy_password=pass

4.4 透明代理 (Transparent Proxy)

4.4.1 配置透明代理端口

# 在 Squid 配置中添加 intercept 端口
http_port 3128         # 标准代理端口
http_port 3129 intercept  # 透明代理端口(旧写法 transparent)

4.4.2 iptables 流量重定向

# 方法一:REDIRECT(同机部署)
# 将本机发出的 HTTP 流量重定向到 Squid
iptables -t nat -A OUTPUT -p tcp --dport 80 \
    -m owner ! --uid-owner proxy \
    -j REDIRECT --to-port 3129

# 方法二:DNAT(网关部署)
# 将内网到外网的 HTTP 流量重定向到 Squid
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 \
    -j REDIRECT --to-port 3129

# 仅对特定子网生效
iptables -t nat -A PREROUTING -s 192.168.1.0/24 \
    -p tcp --dport 80 \
    -j REDIRECT --to-port 3129

# 保存规则
iptables-save > /etc/iptables.rules

4.4.3 nftables 流量重定向

# nftables 配置
nft add table inet squid_redirect
nft add chain inet squid_redirect prerouting \
    { type nat hook prerouting priority dstnat \; }
nft add rule inet squid_redirect prerouting \
    ip saddr 192.168.1.0/24 tcp dport 80 \
    redirect to :3129

# 持久化
nft list ruleset > /etc/nftables.conf

4.4.4 透明代理注意事项

问题 说明 解决方案
HTTPS 不可透明代理 加密流量无法中间人拦截 需要 SSL Bump 或使用 PAC
客户端绕过 修改 hosts 或使用 VPN 结合 DNS 和出口策略
绕过 Squid 自身流量 防止 Squid 代理自己 mangle 表排除 Squid 用户
流量回环 Squid 流量再次被重定向 排除 proxy 用户/进程

4.5 认证集成

4.5.1 Basic 认证

# NCSA 密码文件认证
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd
auth_param basic children 5 startup=2 idle=1
auth_param basic realm "Squid Proxy - Please enter your credentials"
auth_param basic credentialsttl 2 hours

# 创建密码文件
# htpasswd -c /etc/squid/passwd user1
# htpasswd /etc/squid/passwd user2

# 认证 ACL
acl authenticated proxy_auth REQUIRED

# 应用认证
http_access allow authenticated
http_access deny all

4.5.2 LDAP 认证

# LDAP 认证
auth_param basic program /usr/lib/squid/basic_ldap_auth \
    -b "dc=example,dc=com" \
    -D "cn=squid,ou=service,dc=example,dc=com" \
    -W /etc/squid/ldap_pass.txt \
    -f "(&(uid=%s)(objectClass=person))" \
    -H ldap://ldap.example.com:389 \
    -R

auth_param basic children 10 startup=3 idle=1
auth_param basic realm "Corporate Proxy"
auth_param basic credentialsttl 1 hour

acl ldap_auth proxy_auth REQUIRED
http_access allow ldap_auth
http_access deny all

4.5.3 基于用户组的 ACL

# LDAP 组验证
external_acl_type ldap_group %LOGIN /usr/lib/squid/ext_ldap_group_acl \
    -b "ou=groups,dc=example,dc=com" \
    -D "cn=squid,ou=service,dc=example,dc=com" \
    -W /etc/squid/ldap_pass.txt \
    -f "(&(memberUid=%u)(cn=%g))" \
    -H ldap://ldap.example.com

acl proxy_users external ldap_group proxy_users
acl admins external ldap_group admins

# 允许 proxy_users 使用基本代理
http_access allow proxy_users

# 允许 admins 访问所有站点
http_access allow admins

http_access deny all

4.6 ACL 高级控制

4.6.1 按目标域名控制

# 禁止访问特定域名
acl blocked_domains dstdomain "/etc/squid/blocked_domains.txt"
http_access deny blocked_domains

# /etc/squid/blocked_domains.txt 内容:
# .facebook.com
# .twitter.com
# .tiktok.com
# .gambling-site.com

# 仅允许访问白名单域名(白名单模式)
acl allowed_domains dstdomain "/etc/squid/allowed_domains.txt"
http_access deny !allowed_domains

4.6.2 按 URL 路径控制

# 禁止访问特定 URL 路径
acl blocked_urls url_regex "/etc/squid/blocked_urls.txt"
http_access deny blocked_urls

# /etc/squid/blocked_urls.txt 内容:
# ^https?://.*\.exe$
# ^https?://.*\.torrent$
# ^https?://.*download.*\.zip$

# 限制下载文件大小
reply_body_max_size 50 MB allow all

4.6.3 按时间控制

# 工作时间(周一至周五 8:00-18:00)
acl work_hours time MTWHF 08:00-18:00

# 限制非工作时间的访问
http_access allow work_hours
http_access deny all

# 允许特定用户在任何时间访问
acl vip_user proxy_auth "admin"
http_access allow vip_user
http_access deny !work_hours

4.6.4 带宽控制 (Delay Pools)

# 定义延迟池
delay_pools 2

# 延迟池 1:限制普通用户的带宽(每秒 1MB)
delay_class 1 2
delay_parameters 1 1000000/500000 250000/125000

# 延迟池 2:VIP 用户不限速
delay_class 2 1
delay_parameters 2 -1/-1

# ACL 匹配
acl normal_users proxy_auth "/etc/squid/normal_users.txt"
acl vip_users proxy_auth "/etc/squid/vip_users.txt"

delay_access 1 allow normal_users
delay_access 2 allow vip_users
delay_access 1 deny all
delay_access 2 deny all

4.7 CONNECT 隧道(HTTPS 代理)

4.7.1 CONNECT 基础

# CONNECT 方法用于代理 HTTPS 和其他 SSL/TLS 连接
# 客户端发送: CONNECT www.google.com:443 HTTP/1.1
# Squid 建立到目标的 TCP 连接
# 之后客户端和目标直接通过隧道通信

# 允许 CONNECT 到标准 HTTPS 端口
acl SSL_ports port 443
acl CONNECT method CONNECT
http_access deny CONNECT !SSL_ports

4.7.2 限制 CONNECT 隧道

# 限制 CONNECT 仅允许认证用户
acl authenticated proxy_auth REQUIRED
http_access deny CONNECT !authenticated

# 限制 CONNECT 到特定域名
acl allowed_https dstdomain "/etc/squid/allowed_https.txt"
http_access deny CONNECT !allowed_https

# 限制 CONNECT 隧道的保持时间
connect_timeout 30 seconds

4.8 转发策略

4.8.1 直连与父代理

# 始终通过父代理转发(不做直连)
never_direct allow all

# 始终直连(不使用父代理)
always_direct allow all

# 基于目标域名选择转发策略
acl cdn_domains dstdomain .cdn.example.com
always_direct allow cdn_domains
never_direct allow all

# 定义父代理
cache_peer parent.proxy.example.com parent 3128 0 no-query default

4.8.2 多父代理故障转移

# 定义多个父代理
cache_peer parent1.example.com parent 3128 0 \
    no-query default weight=10
cache_peer parent2.example.com parent 3128 0 \
    no-query default weight=5

# 故障检测
cache_peer_access parent1 allow all
cache_peer_access parent2 allow all

# 连接超时和重试
connect_timeout 10 seconds
peer_connect_timeout 5 seconds

4.9 企业正向代理完整示例

# /etc/squid/squid.conf — 企业正向代理配置

# ============ 网络端口 ============
http_port 3128

# ============ ACL 定义 ============
# 网络段
acl office_net src 192.168.1.0/24
acl dev_net src 10.10.0.0/24
acl mgmt_net src 192.168.100.0/24

# 端口
acl SSL_ports port 443 8443
acl Safe_ports port 80 443 21 70 8080 8443

# 时间
acl work_hours time MTWHF 08:30-18:00
acl lunch_time time MTWHF 12:00-13:30

# 认证
auth_param basic program /usr/lib/squid/basic_ldap_auth \
    -b "dc=example,dc=com" \
    -D "cn=squid,ou=service,dc=example,dc=com" \
    -W /etc/squid/ldap_pass.txt \
    -f "(uid=%s)" \
    -H ldap://192.168.1.10
auth_param basic children 10
auth_param basic realm "Company Proxy"
auth_param basic credentialsttl 2 hours
acl authenticated proxy_auth REQUIRED

# URL 过滤
acl blocked_sites dstdomain "/etc/squid/blocked_sites.txt"
acl blocked_urls url_regex "/etc/squid/blocked_urls.txt"
acl streaming_sites dstdomain .youtube.com .netflix.com .bilibili.com

# 文件类型
acl download_ext url_regex -i "\.(exe|msi|bat|ps1|vbs|scr)$"

# ============ 访问控制 ============
# 基础安全
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports

# 允许管理网段免认证
http_access allow mgmt_net

# 要求认证
http_access deny !authenticated

# 内容过滤
http_access deny blocked_sites
http_access deny blocked_urls
http_access deny download_ext

# 流量限制(工作时间限制流媒体)
http_access deny streaming_sites !lunch_time

# 允许所有已认证流量
http_access allow office_net
http_access allow dev_net

# 默认拒绝
http_access deny all

# ============ 带宽控制 ============
delay_pools 2
delay_class 1 2
delay_parameters 1 1000000/500000 500000/250000
delay_class 2 1
delay_parameters 2 -1/-1

acl normal_users proxy_auth "/etc/squid/normal_users.txt"
acl vip_users proxy_auth "/etc/squid/vip_users.txt"
delay_access 1 allow normal_users
delay_access 2 allow vip_users

# ============ 缓存配置 ============
cache_dir ufs /var/spool/squid 10000 16 256
cache_mem 1024 MB
maximum_object_size 128 MB
maximum_object_size_in_memory 512 KB
cache_replacement_policy heap GDSF
memory_replacement_policy heap GDSF

# ============ 日志配置 ============
access_log /var/log/squid/access.log squid
cache_log /var/log/squid/cache.log
cache_store_log stdio:/var/log/squid/store.log
log_fqdn on
log_mime_hdrs on

# ============ 性能参数 ============
forwarded_for delete
via off
httpd_suppress_version_string on
client_db off
pipeline_prefetch on

# ============ 错误页面 ============
error_directory /usr/share/squid/errors/zh-cn
visible_hostname proxy.example.com

4.10 故障排查

# 检查配置语法
sudo squid -k parse

# 查看活跃连接
squidclient -h localhost mgr:active_requests

# 查看缓存信息
squidclient -h localhost mgr:info

# 查看客户端连接
squidclient -h localhost mgr:client_list

# 实时监控日志
tail -f /var/log/squid/access.log

# 查看连接数统计
squidclient -h localhost mgr:5min

4.11 本章小结

功能 配置要点
基础代理 http_port + http_access
透明代理 http_port intercept + iptables
PAC 自动配置 JavaScript PAC 文件 + 浏览器设置
认证 auth_param basic + proxy_auth
ACL 控制 域名/URL/时间/用户组
带宽限制 delay_pools + delay_parameters
转发策略 never_direct / always_direct + cache_peer

扩展阅读