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

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 模式对比

模式解密内容可见信息性能影响法律风险
SpliceIP、端口极低
PeekSNI、证书
Bump全部内容
StareSNI

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)可能无法正常工作。务必在部署前充分测试。

扩展阅读