用Hashicorp Vault搭建自己的CA——安装及初始化

米线不如面条宽

煎饼倒比油条圆

凉皮有酸也有辣

馒头米饭堆成山

大家好,数字证书的重要性不说了。我将用一系列文章演示如何在自己家的IT实验室(homelab)搭建CA——证书颁发机构。

阅读并完成实验需要您:

  • 知晓一点点PKI知识,比如:什么是私钥什么是CRL
  • 有DNS记录管理能力
  • 会使用Linux命令行
  • 有至少一台闲置的Linux或macOS机器(虚拟可)
  • 有域名

您将得到:

一个自动化的数字证书环境,web服务/app自动获取证书、续期、安装。

C 为什么我要搭建自己的CA?

这里是水词凑字数的,不用点开

优点

  1. 安全性提升:通过自签名CA,可以为实验环境的服务提供加密连接,避免数据在传输过程中被窃听。
  2. 成本低:无需支付商业CA的证书费用,非常适合个人或小型团队的非生产环境。
  3. 学习机会:搭建和管理CA的过程可以帮助我理解更多PKI(Public Key Infrastructure)体系以及SSL/TLS协议的工作原理。
  4. 灵活性高:我可以根据自己的需要随时生成、吊销证书,而不受第三方限制。
  5. 内网应用:对于内部使用的服务,自签名证书足以满足验证和加密的需求。

缺点

  1. 信任问题:自签名证书不会被浏览器和操作系统默认信任,需要手动将根证书添加到受信任的证书存储中。
  2. 管理复杂性:需要自己管理证书的生命周期,包括生成、更新、吊销等,这对于初学者来说可能较为复杂。
  3. 有限的适用范围:由于不被公共信任,很难用于生产环境中的公共服务。
  4. 安全隐患:如果私钥管理不当,可能会导致证书被滥用,从而引发安全问题。

对于个人用户,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
mkdir /opt/vault/data

编辑配置文件:

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

  • All zones - DNS:Edit

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的自签名证书
        }
    }
}

可以用浏览器试试:

Image.png

也可以从其它机器上用命令行试试:

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。

0%