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

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

扩展阅读