Skip to content
Go back

使用 Caddy (layer4) 和 GOST 搭建 HTTPS 代理

| 0 Views Edit page

前言

HTTP 代理对于防火墙来说是明文的,容易被识别和封锁,因此我选择使用 Caddy 来自动申请和续签 TLS 证书,并将 GOST 配置为使用这些证书来提供 HTTPS 代理服务。


方案概述

  1. 安装 Caddy 并获取 TLS 证书
  2. 使用 Docker 启动 GOST 以创建 HTTPS 代理
  3. 配置 systemd.path 来监控 TLS 证书的变化并重启 GOST 服务
  4. 配置 Caddy 进行 443 端口的分流

详细步骤

一、安装 Caddy 并获取 TLS 证书

首先去域名注册商处将你的域名解析到服务器的 IP 地址上,并确保服务器的 80 和 443 端口对外开放,以便 Caddy 能够成功申请 TLS 证书。
安装 Caddy 的话,可以参考官方文档:安装 Caddy

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

然后在 /etc/caddy/Caddyfile 中添加以下配置:

nano /etc/caddy/Caddyfile
# 替换为你的域名
yourdomain.com {
    respond "ok" 200
}

保存后,重启 Caddy 服务:

sudo systemctl reload caddy
sudo systemctl restart caddy

此时访问 https://yourdomain.com 应该能看到 “ok” 的响应,并且 Caddy 已经成功申请了 TLS 证书。
而证书则在 /var/lib/caddy/.local/share/caddy/certificates 目录下,文件名通常是 yourdomain.com.crtyourdomain.com.key

ls /var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/yourdomain.com/*

二、使用 Docker 启动 GOST 以创建 HTTPS 代理

安装 Docker 参考:Ubuntu 20.04 从官方源安装最新的 Docker
启动 GOST 容器的话就简单一些,不用 docker compose,直接用 docker run 了:

# 拉取镜像并检查版本
docker run --rm gogost/gost -V
# 启动容器
docker run -d \
  --name gost \
  --restart unless-stopped \
  -p 8443:8443 \
  -v /var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/yourdomain.com/:/certs \
  gogost/gost \
  -L 'http+tls://username:password@0.0.0.0:8443?certFile=/certs/yourdomain.com.crt&keyFile=/certs/yourdomain.com.key&probeResist=host:httpforever.com:80'

启动完成后,在本地运行以下命令测试 HTTPS 代理是否可用:

curl --resolve yourdomain.com:8443:127.0.0.1 \
  -x https://username:password@yourdomain.com:8443 \
  ipinfo.io

三、配置 systemd.path 来监控 TLS 证书的变化并重启 GOST 服务

关于 systemd.path:提供了监控文件、目录变化并触发执行指定操作的功能。
它支持 PathExistsPathChangedPathModified 等事件,可以监控文件的创建、修改、删除等操作。

我们会创建两个 systemd 单元文件:

  • gost-cert-watch.path:监控 TLS 证书文件的变化
  • gost-restart.service:当证书变化时重启 GOST 服务

首先创建 gost-cert-watch.path

sudo nano /etc/systemd/system/gost-cert-watch.path
[Unit]
Description=Watch GOST certificate changes

[Path]
PathChanged=/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/yourdomain.com
Unit=gost-restart.service

[Install]
WantedBy=multi-user.target

然后创建 gost-restart.service

sudo nano /etc/systemd/system/gost-restart.service
[Unit]
Description=Restart GOST container
Wants=docker.service
After=docker.service

[Service]
Type=oneshot
ExecStartPre=/bin/sleep 2
ExecStart=/usr/bin/docker restart gost

保存后,启用并启动 gost-cert-watch.path

sudo systemctl daemon-reload
sudo systemctl enable --now gost-cert-watch.path

这样当 Caddy 自动续签 TLS 证书时,gost-cert-watch.path 会检测到证书文件的变化并触发 gost-restart.service 来重启 GOST 容器,从而确保 HTTPS 代理始终使用最新的 TLS 证书。

四、配置 Caddy 进行 443 端口的分流

Caddy 原生并不支持直接对 TCP 流量进行操作,但我们可以通过安装 caddy-l4 插件来实现 TCP 分流功能:

# 直接使用 caddy add-package 命令安装插件
sudo caddy add-package github.com/mholt/caddy-l4
# 安装完重启 Caddy 服务
sudo systemctl restart caddy

然后在 /etc/caddy/Caddyfile 中添加以下配置来实现分流:

{
    # 全局配置,指定 ACME 证书颁发机构为 Let's Encrypt
    cert_issuer acme {
        dir https://acme-v02.api.letsencrypt.org/directory
    }

    servers :443 {
        listener_wrappers {
            layer4 {
                # 匹配 SNI 为 yourdomain.com 的流量,转发到 GOST 监听的 8443 端口
                @gost tls sni yourdomain.com
                route @gost {
                    proxy tcp/127.0.0.1:8443
                }

                route {
                }
            }
            tls
        }
    }
}

修改完后,验证文件有效性:

sudo caddy validate --config /etc/caddy/Caddyfile

没问题的话就重载配置:

sudo caddy reload --config /etc/caddy/Caddyfile

需要注意的是,这么设置后 Caddy 会根据 SNI 域名将 TLS 连接原样转发到 GOST,真正的 HTTPS/TLS 终止将只发生在 GOST 上。
造成的结果就是,再次尝试在浏览器上访问 https://yourdomain.com 时,不会得到 Caddy 的 “ok” 响应,而是会直接被转发到 GOST,而又因为我指定了 probeResist=host:httpforever.com:80,所以会显示 httpforever.com 的页面。 当然 HTTPS 代理肯定是可用的,在任意机器上测试一下:

curl -x https://username:password@yourdomain.com ipinfo.io

最后就目前的情况进行总结:

  • Caddy 用 Let’s Encrypt 管理 TLS 证书,并自动续签
  • GOST 使用 Caddy 管理的 TLS 证书来提供 HTTPS 代理服务
  • systemd.path 监控 TLS 证书的变化并自动重启 GOST 服务
  • Caddy 通过 caddy-l4 插件实现 TCP 分流,将 yourdomain.com 的 HTTPS 流量(443 端口)转发到 GOST 上(8443 端口)

结束。


Edit page