Caddy2 与 Cloudflare 不完美结合方案

  |   0 评论   |   0 浏览

  

  本文的大多数信息来源于社区的 lizhongyue248 帮助以及官方文档,我这边只是将相关内容整理出来。

  感谢 lizhongyue248!🙏🙏🙏

01. cloudflare 相关设置

  1.环境变量设置的方式无效了,需要在配置文件里面设置 token

  2.不需要设置邮箱,不能使用全局 token,要单独创建一个具有如下权限的 token

1Zone / Zone / Read
1Zone / DNS / Edit

  进入 cloudflare 管理端,点击右下角的“获取您的 API 令牌“

  image.png

  进入编辑页面

  image.png

  修改如下配置,区域资源那边选择自己的网站。

  image.png

  全部处理完成之后,会出现一个 api_token,值得注意的一点是这个 token 和大多数网站一样,只显示一次,注意 ⚠️找个地方记录下。

02. 编译 caddy 添加 tls.dns.cloudflare 模块

  可以使用 golang 的 docker 镜像来构建,你运行的环境是什么 os,你就选择什么环境的 golang

1$ mkdir -p caddy && cd caddy
2$ wget https://raw.githubusercontent.com/caddyserver/caddy/v2/cmd/caddy/main.go

  然后编辑 main.go,在 import 代码块里面添加你需要的模块:

 1
 2
 3package main
 4
 5import (
 6	caddycmd "github.com/caddyserver/caddy/v2/cmd"
 7
 8	// plug in Caddy modules here
 9	_ "github.com/caddyserver/caddy/v2/modules/standard"
10	_ "github.com/caddyserver/tls.dns/providers/cloudflare"
11)
12
13func main() {
14	caddycmd.Main()
15}

  然后构建就可以了,我当时构建的是 beta.15 版本

1$ go mod init caddy
2$ go get github.com/caddyserver/caddy/[email protected]
3$ go build

  构建完成用会在当前目录生成一个 caddy 二进制文件

1./caddy list-modules

  结果会包含 tls.dns.cloudflare,我之前用 caddy 的 caddy-builder 镜像一直没改成功

03. caddy 相关配置

  Caddy1 可以直接从 get caddy 里面选择插件进行下载

  目前 caddy2 只有手动编译,get caddy 相关页面还在开发过程中

  Caddyfile 里面没有配置 dns 选项,由于 go 不是很熟悉

  https://github.com/caddyserver/dnsproviders/blob/master/cloudflare/cloudflare.go

  这个仓库中有一个 credentials,不知道如何配置

 1// Package cloudflare adapts the lego Cloudflare DNS
 2// provider for Caddy. Importing this package plugs it in.
 3package cloudflare
 4
 5import (
 6	"errors"
 7
 8	"github.com/caddyserver/caddy/caddytls"
 9	"github.com/go-acme/lego/v3/providers/dns/cloudflare"
10)
11
12func init() {
13	caddytls.RegisterDNSProvider("cloudflare", NewDNSProvider)
14}
15
16// NewDNSProvider returns a new Cloudflare DNS challenge provider.
17// The credentials are interpreted as follows:
18//
19// len(0): use credentials from environment
20// len(2): credentials[0] = Email address
21//         credentials[1] = API key
22func NewDNSProvider(credentials ...string) (caddytls.ChallengeProvider, error) {
23	switch len(credentials) {
24	case 0:
25		return cloudflare.NewDNSProvider()
26	case 2:
27		config := cloudflare.NewDefaultConfig()
28		config.AuthEmail = credentials[0]
29		config.AuthKey = credentials[1]
30		return cloudflare.NewDNSProviderConfig(config)
31	default:
32		return nil, errors.New("invalid credentials length")
33	}
34}

  代码的大概意思是可以通过环境变量获取 apikey 和 mail,也可以通过 credentials 这个来获取对应的值

  熟悉 go 的小伙伴可以去深入的研究下,原先是想 caddy1 的 Caddyfile 中配完 tls,然后用 caddy2 的 adapt 来自适应,目前发现不可行

  caddy2 的那部分代码发生变化,可以看出来完全使用的 JSON 中 key

 1package cloudflare
 2
 3import (
 4	"time"
 5
 6	"github.com/caddyserver/caddy/v2"
 7	"github.com/caddyserver/caddy/v2/modules/caddytls"
 8	tlsdns "github.com/caddyserver/tls.dns"
 9	"github.com/go-acme/lego/v3/challenge"
10	"github.com/go-acme/lego/v3/providers/dns/cloudflare"
11)
12
13func init() {
14	caddy.RegisterModule(Cloudflare{})
15}
16
17// CaddyModule returns the Caddy module information.
18func (Cloudflare) CaddyModule() caddy.ModuleInfo {
19	return caddy.ModuleInfo{
20		ID:  "tls.dns.cloudflare",
21		New: func() caddy.Module { return new(Cloudflare) },
22	}
23}
24
25// Cloudflare configures a solver for the ACME DNS challenge.
26//
27// Please see the following documentation about which credentials
28// to supply: https://go-acme.github.io/lego/dns/cloudflare/#api-tokens.
29type Cloudflare struct {
30	// An API token with the scoped to all applicable domains with the
31	// following permissions:
32	//
33	// - Zone / Zone / Read
34	// - Zone / DNS / Edit
35	//
36	// Or, if you prefer a more strict set of privileges: give this token
37	// only the `Zone / DNS / Edit` permission, scoped only to the domains
38	// you want to manage certificates for, then provide a ZoneAPIToken
39	// scoped to all your zones with the `Zone / Zone / Read` permission.
40	APIToken string `json:"api_token,omitempty"`
41
42	// An optional API token used in conjunction with APIToken, only
43	// needed if you prefer a stricter set of privileges. If used, this
44	// API token must have the `Zone / Zone / Read` for all zones.
45	ZoneAPIToken string `json:"zone_api_token,omitempty"`
46
47	tlsdns.CommonConfig
48}
49
50// NewDNSProvider returns a DNS challenge solver.
51func (wrapper Cloudflare) NewDNSProvider() (challenge.Provider, error) {
52	cfg := cloudflare.NewDefaultConfig()
53	if wrapper.APIToken != "" {
54		cfg.AuthToken = wrapper.APIToken
55	}
56	if wrapper.ZoneAPIToken != "" {
57		cfg.ZoneToken = wrapper.ZoneAPIToken
58	}
59	if wrapper.CommonConfig.TTL != 0 {
60		cfg.TTL = wrapper.CommonConfig.TTL
61	}
62	if wrapper.CommonConfig.PropagationTimeout != 0 {
63		cfg.PropagationTimeout = time.Duration(wrapper.CommonConfig.PropagationTimeout)
64	}
65	if wrapper.CommonConfig.PollingInterval != 0 {
66		cfg.PollingInterval = time.Duration(wrapper.CommonConfig.PollingInterval)
67	}
68	if wrapper.CommonConfig.HTTPClient != nil {
69		cfg.HTTPClient = wrapper.CommonConfig.HTTPClient.HTTPClient()
70	}
71	return cloudflare.NewDNSProviderConfig(cfg)
72}
73
74// Interface guard
75var _ caddytls.DNSProviderMaker = (*Cloudflare)(nil)

  我的 caddyfile 转成 JSON,tls 部分如下

 1"tls": {
 2      "automation": {
 3        "policies": [{
 4          "hosts": ["solo.mufengs.com"],
 5          "management": {
 6            "challenges": {
 7              "dns": {
 8                "provider": "cloudflare",
 9                "api_token": "pSSnFQj",
10                "base_url": "mufengs.com"
11              }
12            },
13            "module": "acme"
14          }
15        }]
16      }
17    }

  可以将上面部分直接拷到你的 josn 中 apps 那一层中

  启动 caddy

1caddy run --config /path/to/caddy.json

  搞定收工,再次感谢 lizhongyue248

---------------------------------------------------------------
>> 博客地址:https://blog.mufengs.com
>> 邮箱地址:[email protected]
>> 微信帐号:Do8080
>> Github : https://github.com/mufengcoding
---------------------------------------------------------------