内网环境或NAT环境下Caddy基于DNSPOD签发证书
本文最后更新于 169 天前, 如有失效请评论区留言.
纯个人喜好,Docker环境下比较喜欢Caddy,k8s环境下比较喜欢Traefik
前提条件
- 域名托管在DNSPOD(腾讯云DNS)
- 内网环境或者NAT环境(即没有办法使用
HTTP-01
方式签发证书)
通常来说(不负责任), 内网环境没必要使用证书。
本文演示环境为鸡仔云NAT,端口映射方式暴露Caddy HTTP(S)端口,使用非标准协议端口,故而只能使用DNS-01
方式
简单科普
HTTP-01
适合简单、快速的验证,通常访问http://yourdomain.com/.well-known/....
这个目录下的文件并验证其内容是否正确,然后签发证书,依赖80端口可被公网访问
DNS-01
添加TXT记录来验证域名
其他
如果域名托管在CF,还可以选择CF的15年证书
腾讯云DNS配置
创建普通用户
通常情况下,选择新建一个普通用户,只给编程访问权限
, 其他默认即可
创建自定义策略
出于某些考虑,限制我这个API使用,只允许白名单IP(合法IP,示例可以理解为马赛克)可访问,不需要去掉即可
{
"statement": [
{
"action": [
"dnspod:DescribeDomainDigResult",
"dnspod:DescribeDomainExistRecordList",
"dnspod:DescribeRecord",
"dnspod:DescribeRecordImpactInfo",
"dnspod:CreateRecord",
"dnspod:DeleteRecord"
],
"condition": {
"ip_equal": {
"qcs:ip": [
"2409:...",
"183..."
]
}
},
"effect": "allow",
"resource": [
"qcs::dnspod::uin/账号ID:domain/DomainID"
]
}
],
"version": "2.0"
}
- 账号ID: 点击右上角
主账号
就可以看到了, 也可以通过账号中心/账号信息 - DomainID: 云解析-域名设置中可看
关联策略
用户列表-关联策略,效果如下
完成之后,获取API密钥备用
构建Caddy镜像
目前情况下Caddy是不支持DNSPOD方式签发证书的。这里我提供一下我构建好的镜像
ccr.ccs.tencentyun.com/k7scn/caddy:2024
我还是推荐自行构建好,因为我会经常调整
我的镜像,增删插件
。
构建Dockerfile如下
FROM ccr.ccs.tencentyun.com/k7scn/god AS builder
RUN go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
WORKDIR /go/src/
RUN xcaddy build \
--with github.com/caddy-dns/cloudflare \
--with github.com/caddy-dns/tencentcloud \
--with github.com/caddy-dns/alidns \
--with github.com/caddy-dns/dnspod
RUN /go/src/caddy list-modules
FROM ccr.ccs.tencentyun.com/k7scn/debian
COPY --from=builder /go/src/caddy /usr/bin/caddy
RUN chmod +x /usr/bin/caddy && \
mkdir -p \
/config/caddy \
/etc/caddy \
/data/caddy \
/var/log/caddy
ENV XDG_CONFIG_HOME /config
ENV XDG_DATA_HOME /data
EXPOSE 80
EXPOSE 443
EXPOSE 443/udp
VOLUME /config
VOLUME /data
VOLUME /var/log/caddy
CMD caddy run --config /etc/caddy/Caddyfile --adapter caddyfile
结构还是比较清晰的
部署Caddy
使用compose方式部署镜像
services:
caddy:
image: ccr.ccs.tencentyun.com/k7scn/caddy:2024
container_name: caddy
volumes:
- /etc/caddy:/etc/caddy
- /var/log/caddy:/var/log/caddy
- /data/caddy/data:/data
- /data/caddy/config:/config
ports:
- "38080:38080"
- "38443:38443"
restart: always
network_mode: "host"
给大家看下/etc/caddy
目录结构
.
├── Caddyfile # 全局配置
├── site # 域名配置
│ ├── default.caddy
│ ├── tea.caddy
│ └── tts.caddy
└── ssl # CF15证书、自签证书或其他证书
└── ysicing.eu.org
├── ysicing.key
└── ysicing.pem
全局配置Caddyfile
主要定义了3个全局模块,方式域名里单独引用
(LOG) {
log {
output file "{args[0]}" {
roll_size 50M
roll_uncompressed
roll_local_time
roll_keep 3
roll_keep_for 7d
}
format json
}
}
(TLS) {
tls {
load /etc/caddy/ssl
}
}
(CFIP) {
@ip_whitelist {
not remote_ip 2400:cb00::/32 2606:4700::/32 2803:f800::/32 2405:b500::/32 2405:8100::/32 2a06:98c0::/29 2c0f:f248::/32 fd7a:115c:a1e0::/96 173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/13 104.24.0.0/14 172.64.0.0/13 131.0.72.0/22
}
route @ip_whitelist {
respond 451
}
}
{
debug
admin off
http_port 38080
https_port 38443
email 邮箱(建议写上)
acme_dns tencentcloud {
secret_id "腾讯云AK"
secret_key "腾讯云Key"
}
}
import /etc/caddy/site/*.caddy
独立站点示例
这里以/etc/caddy/site/default.caddy
简单说下,主要是对接CF的,设置了日志和IP访问策略
:38080 {
import CFIP
import LOG "/var/log/caddy/default-http.log"
respond "http, cf: {remote_host}, ip: {http.request.header.CF-Connecting-IP}"
}
:38443 {
import CFIP
import LOG "/var/log/caddy/default-https.log"
import TLS
respond "tls, cf: {remote_host}, ip: {http.request.header.CF-Connecting-IP}"
}
验证我的想法可以访问ysicing.eu.org
其他站点按照Caddy的规则写就可以了,随便编个大概示例如下
nat.ysicing.net {
import CFIP
import LOG "/var/log/caddy/nat-ysicing-net.log"
import TLS
reverse_proxy http://127.0.0.1:3333
}
其他问题
由于使用非标准端口,默认配置是没办法实现http自动跳转https。