米线不如面条宽
煎饼倒比油条圆
凉皮有酸也有辣
馒头米饭堆成山
大家好,数字证书的重要性不说了。我将用一系列文章演示如何在自己家的IT实验室(homelab)搭建CA——证书颁发机构。
阅读并完成实验需要您:
- 知晓一点点PKI知识,比如:什么是私钥什么是CRL
- 有DNS记录管理能力
- 会使用Linux命令行
- 有至少一台闲置的Linux或macOS机器(虚拟可)
- 有域名
您将得到:
一个自动化的数字证书环境,web服务/app自动获取证书、续期、安装。
C 为什么我要搭建自己的CA?
这里是水词凑字数的,不用点开
优点
- 安全性提升:通过自签名CA,可以为实验环境的服务提供加密连接,避免数据在传输过程中被窃听。
- 成本低:无需支付商业CA的证书费用,非常适合个人或小型团队的非生产环境。
- 学习机会:搭建和管理CA的过程可以帮助我理解更多PKI(Public Key Infrastructure)体系以及SSL/TLS协议的工作原理。
- 灵活性高:我可以根据自己的需要随时生成、吊销证书,而不受第三方限制。
- 内网应用:对于内部使用的服务,自签名证书足以满足验证和加密的需求。
缺点
- 信任问题:自签名证书不会被浏览器和操作系统默认信任,需要手动将根证书添加到受信任的证书存储中。
- 管理复杂性:需要自己管理证书的生命周期,包括生成、更新、吊销等,这对于初学者来说可能较为复杂。
- 有限的适用范围:由于不被公共信任,很难用于生产环境中的公共服务。
- 安全隐患:如果私钥管理不当,可能会导致证书被滥用,从而引发安全问题。
对于个人用户,https://zerossl.com/ 和https://letsencrypt.org/ 等免费的CA已经足够用来对外提供服务(hosting)了,比如您家里的群晖就是用的Let’s Encrypt的证书。但是要是像我一样经常把玩IT实验室的话,使用免费CA就有点烦人,每次创建新的服务都要验证我对域名的控制权,而我又不想用通配符证书。 而上述缺点1可以用chef或者ansible或者组策略什么的来解决,缺点2则可以用Hashicorp Vault(下称Vault)缓解,比起OpenSSL简直容易了10个Smallstep😇。
Vault本意不是干这个用的,人家是用来管理用于程序的身份验证的(比如服务账号的访问凭据)。本文就只拿它当CA用。费用是免费的,比收费版本少一些功能,家用足够了。
注意:本文的初心是在自己家里玩赛博过家家,不要将本文中用到的配置套用在生产环境!
安装Vault
我用的x64 Linux虚拟机运行Debian 12(bookworm),诸位可以选择自己家里的闲置机器或者租一个VPS什么的。我的虚拟机运行在家里,私有DNS域名为vault-dev-01.lab.miyunda.com
,另外有CNAME解析为vault-dev.miyunda.com
。
安装使用系统自带的包管理,先引入厂家官方的源然后安装:
1
2
3
4
5
| sudo apt update && sudo apt install lsb-release gpg curl wget -y
wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install vault
vault
|
它的服务文件应该也安装好了:
1
| cat /lib/systemd/system/vault.service
|
数据的存储可以有很多选择。比如etcd或者Consul什么的,既然是家用就随便存在本地磁盘文件即可。
编辑配置文件:
1
2
| sudo cp /etc/vault.d/vault.hcl /etc/vault.d/vault.hcl.stock
sudo nano /etc/vault.d/vault.hcl
|
其内容为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| ui = true #开启web界面
disable_mlock = true
storage "file" {
path = "/opt/vault/data"
}
listener "tcp" {
address = "127.0.0.1:8200"
tls_disable = "false"
tls_cert_file = "/opt/vault/tls/tls.crt" #它生成自签名证书,以后可以换成您自己的自签名证书
tls_key_file = "/opt/vault/tls/tls.key"
}
api_addr = "http://127.0.0.1:8200"
cluster_addr = "https://127.0.0.1:8201"
|
保存后就可以启动服务了:
1
2
3
4
| sudo systemctl start vault
systemctl status vault
sudo journalctl -xeu vault
sudo systemctl enable vault
|
可以尝试查询它的状态:
1
| curl -k -X 'GET' 'https://localhost:8200/v1/sys/health'
|
回应应该是:
1
2
3
4
5
6
| {
"initialized": false,
"sealed": true,
"standby": true,
...
}
|
D 反向代理服务器
上面的vault.hcl
指定了Vault服务监听在回环地址的TCP 8200端口,从其它机器访问的话就得通过代理服务器,要不就得修改监听地址为网卡实际绑定地址。代理服务器我选择Caddy,强大不强大我不知道,反正简单好用。
我将用Caddy监听TCP 443和80,并对外(家里)提供web服务,将来自外部(家里)的http请求转发给Vault服务。
安装
使用系统自带的包管理器即可:
1
2
| sudo apt update
sudo apt install caddy
|
然后编辑配置文件:
1
| sudo nano /etc/caddy/Caddyfile
|
内容为:
1
2
3
4
5
6
7
8
9
10
11
| <FQDN,比如vault-dev.miyunda.com> {
log {
output file /var/log/caddy/vault-dev.log
format console
}
reverse_proxy https://127.0.0.1:8200 {
transport http {
tls_insecure_skip_verify # 不检查Vault的自签名证书
}
}
}
|
数字证书
Caddy提供https服务,当然需要给它安装数字证书,不过它自己会装——前提是您得证明这FQDN由您控制。Caddy内置的ACME(Automatic Certificate Management Environment)客户端会去ACME服务端验证域名,方法是在Caddy机器上开启TCP80服务任由ACME服务端访问。所以上面配置在外面租VPS是可以的,家用就不行了——TCP 80端口开不了。Caddy也支持DNS验证,它会去DNS添加一条TXT record,然后能从公网解析到这条记录的话一样认可我们对域名的控制权。
租赁公网VPS的可以忽略下面两小节,打算在代理服务器使用自签名的也可以忽略。
DNS
ACME支持多家DNS服务商,国内大厂也有。我用的是Cloudflare。 为了Caddy能有写入DNS记录的权限,先得给它弄个访问凭据
Cloudflare那里是 API token:
This API token will affect the below accounts and zones, along with their respective permissions
Caddy的模块
去这里下载包含Cloudflare模块并且放在Caddy/Vault机器上,改名字为caddy
然后替换掉包管理器安装的版本:
1
2
3
4
5
| sudo dpkg-divert --divert /usr/bin/caddy.default --rename /usr/bin/caddy
sudo mv ./caddy /usr/bin/caddy.custom
sudo update-alternatives --install /usr/bin/caddy caddy /usr/bin/caddy.default 10
sudo update-alternatives --install /usr/bin/caddy caddy /usr/bin/caddy.custom 50
/usr/bin/caddy.custom build-info
|
Caddyfile也需要更多设置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| {
acme_ca https://acme.zerossl.com/v2/DV90
email <邮件地址> #最好与您在zerossl.com的注册的一样
}
vault-dev.miyunda.com {
log {
output file /var/log/caddy/vault-dev.log
format console
}
reverse_proxy https://127.0.0.1:8200 {
transport http {
tls_insecure_skip_verify
}
}
tls {
dns cloudflare <CF的访问凭据> #讲究点的放到环境变量里稍微隐藏下
resolvers 1.1.1.1 #由于复制延迟,假如它解析不到新添加的TXT记录就用这个DNS服务器
}
}
|
之后就可以启动Caddy了:
1
2
3
4
| sudo systemctl start caddy
systemctl status caddy
sudo journalctl -xeu caddy | less
sudo systemctl enable caddy
|
Caddy自签名证书:
没有域名的或者有域名但不爱折腾的可以暂时使用Caddy自签名证书,以后可以换成我们这次的CA签发的证书。
1
2
3
4
5
6
7
8
9
10
11
12
| <FQDN,比如foobar.local> {
log {
output file /var/log/caddy/vault-dev.log
format console
}
tls internal
reverse_proxy https://127.0.0.1:8200 {
transport http {
tls_insecure_skip_verify # 认可Vault的自签名证书
}
}
}
|
可以用浏览器试试:
也可以从其它机器上用命令行试试:
1
2
3
| export VAULT_ADDR='https://<FQDN>'
curl $VAULT_ADDR/v1/sys/init
{"initialized":false}
|
E Vault初始化
Vault安装好之后需要初始化,这个过程它将生成5个解封用的密钥(key),1个管理员(root)的令牌(token),必须将这些密钥分发给贵司高管,每人最多1个。Vault服务解封时需要5个密钥中的任意3个。
我们过家家就不需要,也没有“5个高管”。
首先我们需要在日常操作用机上面运行Vault的命令行,这样就不用SSH到Vault服务器上了。
比如macOS:
1
2
3
| brew tap hashicorp/tap
brew install hashicorp/tap/vault #之后更新版本可以用update替换install
vault --version
|
Linux和WSL的安装请自行往上翻。
然后我们初始化:
1
2
3
4
| export VAULT_ADDR='https://<FQDN>' # 喜欢到服务器上贴脸操作的话就是:VAULT_ADDR='https://127.0.0.1:8200'
vault operator init \
-key-shares=1 \
-key-threshold=1 # 假如需要忽略自签名证书:-tls-skip-verify
|
这样我们就得到了1个高管密钥。以及一个管理员令牌,找个稳妥的地方记下来。
解封它:
1
2
| vault operator unseal
vault status
|
好了,我们Vault可以用了。看过就是会了,下次我们学习创建CA。