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

Squid 完全指南 / 09 - HTTPS 拦截 (SSL Bump)

第九章:HTTPS 拦截 (SSL Bump)

9.1 SSL Bump 概述

SSL Bump(SSL 拦截)是 Squid 实现 HTTPS 流量中间人(Man-in-the-Middle, MitM)解密的技术。它允许代理检查、过滤和缓存加密的 HTTPS 流量。

┌──────────┐     ┌───────────────────┐     ┌──────────────┐
│  客户端   │────→│   Squid SSL Bump  │────→│  目标服务器   │
│          │←────│                    │←────│              │
│          │     │  1. 拦截 ClientHello│     │              │
│          │     │  2. 动态生成证书    │     │              │
│          │     │  3. 解密流量        │     │              │
│          │     │  4. 检查/过滤       │     │              │
│          │     │  5. 重新加密        │     │              │
└──────────┘     └───────────────────┘     └──────────────┘
       TLS 1.3         SSL Bump              TLS 1.3
       (动态证书)       (解密+检查)           (真实证书)

⚠️ 法律与合规警告:SSL Bump 拦截加密流量涉及隐私和法律问题。在企业环境中使用前,务必确认:

  1. 有明确的公司政策授权
  2. 员工已被告知(通常在入职协议中)
  3. 不拦截银行、医疗、政府等敏感网站
  4. 遵守当地法律法规(如 GDPR)

9.2 SSL Bump 工作模式

9.2.1 Splice 模式(透传)

客户端 ←──TLS──→ Squid(仅转发)←──TLS──→ 服务器

Squid 不解密流量,仅做 TCP 转发。可以记录连接元数据(域名、IP),但不能检查内容。

9.2.2 Bump 模式(解密)

客户端 ←──TLS──→ Squid(解密+重新加密)←──TLS──→ 服务器

Squid 完全解密流量,检查明文内容后重新加密发给客户端。

9.2.3 Peek 模式(窥探)

客户端 ←──TLS──→ Squid(查看 SNI/证书)←──TLS──→ 服务器

Squid 仅查看 ClientHello 中的 SNI 和服务器证书信息,不解密数据。

9.2.4 模式对比

模式 解密内容 可见信息 性能影响 法律风险
Splice IP、端口 极低
Peek SNI、证书
Bump 全部内容
Stare SNI

9.3 编译支持

SSL Bump 需要 Squid 编译时启用 SSL 支持:

# 检查当前 Squid 是否支持 SSL
squid -v 2>&1 | grep -o "enable-ssl"
# 如果没有输出,需要重新编译

# 源码编译时添加 SSL 选项
./configure \
    --prefix=/usr/local/squid \
    --enable-ssl \
    --with-openssl \
    --enable-ssl-crtd \
    ...

# Ubuntu/Debian 安装支持 SSL 的 Squid
sudo apt install -y squid
# 大多数发行版默认编译了 SSL 支持
squid -v | grep ssl

9.4 生成 CA 证书

9.4.1 创建自签名 CA

#!/bin/bash
# generate_ca.sh — 生成 SSL Bump CA 证书

SSL_DIR="/etc/squid/ssl"
mkdir -p "$SSL_DIR"
cd "$SSL_DIR"

# 生成 CA 私钥
openssl genrsa -out ca.key 4096

# 生成 CA 证书(10年有效期)
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
    -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/OU=IT/CN=Squid SSL Bump CA"

# 合并为 PEM 格式(Squid 需要)
cat ca.crt ca.key > myCA.pem

# 设置权限
chmod 600 ca.key myCA.pem
chmod 644 ca.crt
chown -R proxy:proxy "$SSL_DIR"

echo "CA certificate generated at: $SSL_DIR/myCA.pem"
echo "CA certificate fingerprint:"
openssl x509 -in ca.crt -noout -fingerprint -sha256

9.4.2 创建 SSL 证书数据库

# 初始化 SSL 证书数据库
# 需要 Squid 6.x 或编译了 --enable-ssl-crtd 的版本
/usr/lib/squid/security_file_certgen -c -s /var/lib/squid/ssl_db -M 20MB

# 设置权限
chown -R proxy:proxy /var/lib/squid/ssl_db

9.4.3 分发 CA 证书到客户端

CA 证书需要导入到所有客户端的信任证书存储中:

Windows(域控推送)

# 通过 GPO 推送 CA 证书
certutil -addstore "Root" "ca.crt"

# 或手动导入
# 双击 ca.crt → 安装证书 → 受信任的根证书颁发机构

macOS

sudo security add-trusted-cert -d -r trustRoot \
    -k /Library/Keychains/System.keychain ca.crt

Linux(Firefox)

# 使用 certutil
certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n "Squid CA" -i ca.crt

# 或在 Firefox 设置中手动导入
# 设置 → 隐私与安全 → 证书 → 查看证书 → 导入

Linux(系统级)

# Ubuntu/Debian
sudo cp ca.crt /usr/local/share/ca-certificates/squid-ca.crt
sudo update-ca-certificates

# CentOS/RHEL
sudo cp ca.crt /etc/pki/ca-trust/source/anchors/squid-ca.crt
sudo update-ca-trust

9.5 SSL Bump 配置

9.5.1 基础 SSL Bump 配置

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

# SSL Bump 策略
ssl_bump stare all          # 先窥探所有连接
ssl_bump bump all           # 然后解密所有

# SSL 代理设置
sslproxy_cert_error allow all  # 允许后端证书错误(生产环境不建议)
sslproxy_flags DONT_VERIFY_PEER  # 不验证后端证书(仅测试用)

9.5.2 分级 SSL Bump 策略

# 配置 SSL Bump 拦截端口
http_port 3129 ssl-bump \
    cert=/etc/squid/ssl/myCA.pem \
    generate-host-certificates=on \
    dynamic_cert_mem_cache_size=20MB

# SSL 证书数据库
sslcrtd_program /usr/lib/squid/security_file_certgen -s /var/lib/squid/ssl_db -M 20MB
sslcrtd_children 5

# ============ SSL Bump ACL ============

# 不解密的域名(银行、医疗、政府等敏感站点)
acl nobump_ssl ssl::server_name_regex -i "/etc/squid/nobump_domains.txt"

# 解密的域名(一般网站)
acl bump_ssl ssl::server_name_regex -i "/etc/squid/bump_domains.txt"

# 不解密的 IP
acl nobump_ip dst "/etc/squid/nobump_ips.txt"

# ============ SSL Bump 规则 ============

# 1. 先窥探(获取 SNI)
ssl_bump peek all

# 2. 白名单域名不解密
ssl_bump splice nobump_ssl

# 3. 白名单 IP 不解密
ssl_bump splice nobump_ip

# 4. 其他流量解密
ssl_bump bump all

nobump_domains.txt(不解密的域名)

# 银行
.bank.example.com
.alipay.com
.wechat.com
.paypal.com

# 医疗
.hospital.example.com

# 政府
.gov.cn

# 其他敏感站点
.google.com  # 如果需要保留隐私

9.5.3 基于端口的 SSL Bump

# 仅对 443 端口做 SSL Bump
acl https_port port 443
ssl_bump peek all
ssl_bump bump https_port
ssl_bump splice !https_port

9.6 SSL 证书管理

9.6.1 使用通配符证书

# 使用自己的通配符证书
# 合并证书链
cat wildcard.crt intermediate.crt > combined.pem
cat combined.pem wildcard.key > /etc/squid/ssl/site.pem

# 配置
https_port 443 cert=/etc/squid/ssl/site.pem

9.6.2 证书错误处理

# 策略一:拒绝证书错误(安全,推荐生产环境)
sslproxy_cert_error deny all

# 策略二:允许证书错误(仅测试环境)
# sslproxy_cert_error allow all

# 策略三:根据 ACL 选择性允许
acl trusted_domain ssl::server_name .trusted.com
sslproxy_cert_error allow trusted_domain
sslproxy_cert_error deny all

# 不验证后端证书(仅测试,生产环境不要使用)
# sslproxy_flags DONT_VERIFY_PEER

# 证书错误日志
sslproxy_cert_sign hash all
sslproxy_cert_adapt setCommonName all

9.6.3 证书缓存管理

# 动态证书内存缓存
dynamic_cert_mem_cache_size 20MB

# 证书数据库位置
sslcrtd_program /usr/lib/squid/security_file_certgen \
    -s /var/lib/squid/ssl_db -M 20MB

# 证书生成子进程数
sslcrtd_children 10 startup=3 idle=1

9.7 透明 SSL Bump

9.7.1 配置透明 SSL Bump

# 透明 SSL Bump 端口
http_port 3130 intercept ssl-bump \
    cert=/etc/squid/ssl/myCA.pem \
    generate-host-certificates=on \
    dynamic_cert_mem_cache_size=20MB

# SSL Bump 规则
ssl_bump peek all
ssl_bump bump all
# iptables 配置
# 将 HTTPS 流量重定向到 Squid 的 SSL Bump 端口
iptables -t nat -A PREROUTING -s 192.168.1.0/24 \
    -p tcp --dport 443 \
    -j REDIRECT --to-port 3130

# 排除 Squid 自身流量
iptables -t nat -A OUTPUT -p tcp --dport 443 \
    -m owner --uid-owner proxy \
    -j RETURN

9.8 TLS 1.3 支持

# Squid 6.x 支持 TLS 1.3
# 配置 TLS 版本
http_port 3129 ssl-bump \
    cert=/etc/squid/ssl/myCA.pem \
    generate-host-certificates=on \
    tls-min-version=1.2

# 配置加密套件
https_port 443 \
    cert=/etc/squid/ssl/site.pem \
    options=NO_SSLv3,NO_TLSv1,NO_TLSv1_1 \
    cipher=ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384 \
    tls-min-version=1.2

9.9 SSL Bump 日志分析

# 启用 SSL 相关日志
access_log /var/log/squid/access.log squid

# 自定义日志格式包含 SSL 信息
logformat ssl_log %ts.%03tu %6tr %>a %Ss/%03>Hs %<st %rm %ru %[un %Sh/%<a %ssl::>sni %ssl::>cert_subject %mt
access_log /var/log/squid/ssl_access.log ssl_log
# 查看 SSL Bump 日志
tail -f /var/log/squid/access.log | grep SSL

# 查看拦截的域名
awk '{print $11}' /var/log/squid/ssl_access.log | sort | uniq -c | sort -rn

# 查看证书错误
grep "CERT_ERROR" /var/log/squid/cache.log

9.10 SSL Bump 排除列表

# 推荐排除的网站类别

# 1. 金融类
acl nobump_finance ssl::server_name_regex -i \
    "\.bank\." "\.paypal\." "\.alipay\." "\.wechat\."

# 2. 医疗健康
acl nobump_health ssl::server_name_regex -i \
    "\.hospital\." "\.medical\." "\.health\."

# 3. 政府网站
acl nobump_gov ssl::server_name .gov .gov.cn .mil

# 4. 个人隐私
acl nobump_personal ssl::server_name_regex -i \
    "\.health\." "\.therapy\." "\.lawyer\."

# 5. 证书钉扎的站点(SSL Bump 会破坏证书钉扎)
acl nobump_pinning ssl::server_name_regex -i \
    "\.google\." "\.facebook\." "\.twitter\."

# 应用排除
ssl_bump splice nobump_finance
ssl_bump splice nobump_health
ssl_bump splice nobump_gov
ssl_bump splice nobump_personal
ssl_bump splice nobump_pinning
ssl_bump bump all

9.11 完整 SSL Bump 配置示例

# /etc/squid/squid.conf — SSL Bump 生产配置

# ============ 端口 ============
http_port 3128
http_port 3129 ssl-bump \
    cert=/etc/squid/ssl/myCA.pem \
    generate-host-certificates=on \
    dynamic_cert_mem_cache_size=20MB

# ============ SSL ============
sslcrtd_program /usr/lib/squid/security_file_certgen -s /var/lib/squid/ssl_db -M 20MB
sslcrtd_children 10 startup=3 idle=1

# ============ ACL ============
acl localnet src 192.168.0.0/16
acl SSL_ports port 443
acl Safe_ports port 80 443
acl CONNECT method CONNECT

# SSL Bump ACL
acl nobump ssl::server_name_regex -i "/etc/squid/nobump.txt"
acl nopeek ssl::server_name_regex -i "/etc/squid/nopeek.txt"

# 认证
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd
auth_param basic children 10
auth_param basic realm Proxy
acl auth proxy_auth REQUIRED

# ============ SSL Bump 规则 ============
ssl_bump peek all
ssl_bump splice nobump
ssl_bump splice nopeek
ssl_bump bump all

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

# ============ 证书策略 ============
sslproxy_cert_error deny all
sslproxy_cert_sign hash setCommonName all

# ============ 缓存 ============
cache_dir ufs /var/spool/squid 20000 256 4096
cache_mem 2048 MB

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

# ============ 安全 ============
via off
forwarded_for delete
httpd_suppress_version_string on
visible_hostname proxy.example.com

9.12 本章小结

功能 关键配置
SSL Bump 端口 http_port ... ssl-bump
CA 证书 cert=/etc/squid/ssl/myCA.pem
证书数据库 sslcrtd_program + security_file_certgen
Bump 策略 ssl_bump peek/splice/bump/stare
排除域名 ssl::server_name ACL
证书错误 sslproxy_cert_error

⚠️ 重要提示:SSL Bump 会影响 TLS 证书链验证,某些应用(如证书钉扎的 App)可能无法正常工作。务必在部署前充分测试。

扩展阅读