← 返回

使用 Caddy + acme.sh 搭建带认证的 TLS 正向代理

为什么选择 Caddy

常见的代理方案(Squid、Nginx)配置繁琐,TLS 支持往往需要额外折腾。Caddy 通过 forwardproxy 插件原生支持 HTTPS 正向代理(CONNECT 隧道),配合 Basic Auth 认证,整套方案配置简洁、维护成本低。

选用 acme.sh 而非 Caddy 内置 ACME,是因为在某些场景下我们需要更灵活地控制证书签发流程——比如使用 DNS-01 验证、指定 CA(ZeroSSL / Let's Encrypt / Buypass)、或者在防火墙不开放 80/443 的机器上获取证书。

准备工作

  • 一台有公网 IP 的服务器(本文以 Debian/Ubuntu 为例)
  • 一个域名,且已将 A 记录解析到服务器 IP
  • 域名 DNS 服务商支持 API 操作(用于 DNS-01 验证)

一键脚本

如果你不想手动操作,可以直接使用自动化安装脚本

Bash
sudo DOMAIN=proxy.example.com \
     EMAIL=your@email.com \
     PROXY_USER=myuser \
     PROXY_PASS=mypassword \
     CF_Token=xxx \
     CF_Zone_ID=xxx \
     bash <(curl -fsSL https://gist.githubusercontent.com/madeye/9a578ad8c9b8166f999719aa7784aa6f/raw/setup-caddy-proxy.sh)

以下是手动步骤的详细说明。

1. 安装 acme.sh 并签发证书

Bash
# 安装 acme.sh
curl https://get.acme.sh | sh -s email=your@email.com

# 以 Cloudflare DNS 为例,设置 API Token
export CF_Token="your_cloudflare_api_token"
export CF_Zone_ID="your_zone_id"

# 签发证书(使用 DNS-01 验证)
~/.acme.sh/acme.sh --issue --dns dns_cf -d proxy.example.com

# 安装证书到指定目录
mkdir -p /etc/caddy/certs
~/.acme.sh/acme.sh --install-cert -d proxy.example.com \
  --cert-file /etc/caddy/certs/cert.pem \
  --key-file /etc/caddy/certs/key.pem \
  --fullchain-file /etc/caddy/certs/fullchain.pem \
  --reloadcmd "systemctl restart caddy"

如果你使用其他 DNS 服务商,acme.sh 支持数十种 DNS API,参考其 wiki 替换 dns_cf 及相关环境变量即可。

2. 编译带 forwardproxy 插件的 Caddy

官方发布的 Caddy 二进制不包含 forwardproxy 插件,需要使用 xcaddy 自行编译。

Bash
# 安装 Go(如果还没有)
sudo apt install -y golang

# 安装 xcaddy
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest

# 编译带 forwardproxy 的 Caddy
~/go/bin/xcaddy build --with github.com/caddyserver/forwardproxy=github.com/klzgrad/forwardproxy@naive

# 移动到系统路径
sudo mv caddy /usr/bin/caddy
sudo chmod +x /usr/bin/caddy

这里使用的是 klzgrad 维护的 forwardproxy 分支,它支持 naive 协议的流量混淆,抗探测能力更强。如果不需要此特性,可以直接使用官方 github.com/caddyserver/forwardproxy

3. 配置 Caddy

创建 Caddyfile:

Bash
sudo mkdir -p /etc/caddy

编辑 /etc/caddy/Caddyfile

CADDYFILE
{
  order forward_proxy before file_server
  admin off
}

:443, proxy.example.com {
  tls /etc/caddy/certs/fullchain.pem /etc/caddy/certs/key.pem

  forward_proxy {
    basic_auth user password123  # 替换为你自己的用户名和密码
    hide_ip
    hide_via
    probe_resistance secret.localhost  # 防主动探测
  }

  file_server {
    root * /var/www/html  # 伪装成普通网站
  }
}

几个关键配置说明:

  • basic_auth:设置代理认证的用户名和密码,阻止未授权访问
  • hide_ip / hide_via:隐藏客户端真实 IP 和代理标识
  • probe_resistance:当收到非代理请求时,伪装成普通网站返回内容,防止主动探测
  • file_server:配合 probe_resistance 使用,放一个普通网页作为伪装

4. 配置 systemd 服务

创建 /etc/systemd/system/caddy.service

INI
[Unit]
Description=Caddy
After=network.target network-online.target
Requires=network-online.target

[Service]
Type=notify
User=root
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512

[Install]
WantedBy=multi-user.target

启动服务:

Bash
sudo systemctl daemon-reload
sudo systemctl enable --now caddy

5. 客户端使用

配置完成后,在客户端使用 HTTPS 代理连接:

TEXT
https://user:password123@proxy.example.com:443

浏览器

大多数浏览器支持通过系统代理设置来配置 HTTPS 代理。也可以使用 SwitchyOmega 等扩展,协议选择 HTTPS,填入域名、端口、用户名和密码即可。

命令行

Bash
export https_proxy=https://user:password123@proxy.example.com:443
export http_proxy=https://user:password123@proxy.example.com:443
curl -I https://www.google.com

NaiveProxy 客户端

如果服务端编译时使用了 klzgrad 的 forwardproxy 分支,推荐使用 NaiveProxy 客户端以获得更好的流量混淆效果:

JSON
{
  "listen": "socks://127.0.0.1:1080",
  "proxy": "https://user:password123@proxy.example.com"
}

6. 验证与排查

Bash
# 查看 Caddy 运行状态
sudo systemctl status caddy

# 查看实时日志
sudo journalctl -u caddy -f

# 测试证书是否正常
openssl s_client -connect proxy.example.com:443 -servername proxy.example.com

# 测试代理是否工作
curl -x https://user:password123@proxy.example.com:443 https://httpbin.org/ip

证书自动续期

acme.sh 安装时会自动创建 cron job,证书到期前会自动续期并通过 --reloadcmd 重启 Caddy 加载新证书,无需手动干预。

可以手动检查 cron 是否生效:

Bash
crontab -l | grep acme

小结

整套方案的优势:

  1. 配置简单:Caddyfile 十几行搞定,远比 Nginx + Squid 方案省心
  2. TLS 加密:所有代理流量都走 HTTPS,中间人无法窥探
  3. 认证机制:Basic Auth 防止代理被滥用
  4. 抗探测probe_resistance + 伪装网站,非授权访问只能看到普通网页
  5. 自动续证:acme.sh 的 cron job 保证证书始终有效