为您的家庭实验室建立一个微小的证书颁发机构

2020-12-24 21:40:02

TL; DR在本教程中,我们将构建一个小型的独立在线证书颁发机构(CA),该证书颁发机构将生成TLS证书并使用YubiKey进行保护。它将是我们本地网络上的内部ACME服务器(ACME与Let's Encrypt使用的协议相同)。 YubiKey将安全地存储CA私钥和签名证书,作为硬件安全模块(HSM)的廉价替代品。我们还将使用开源的True Random Number Generator(称为无限噪声TRNG)来为Linux熵池增光添彩。

由于端到端TLS很棒,因此您应该可以轻松地在需要的任何地方运行TLS。特别是在您的家庭实验室中。内部网络不再被视为可以进行未加密流量的安全区域。但是您需要证书。

由于TLS客户端身份验证在各种服务中得到越来越广泛的支持,并且比密码要好得多。但是您需要证书。

由于ACME协议(由Let's Encrypt使用)可以轻松地在内部部署,因此您可以自动进行续订,而不必考虑证书。

因为也许您已经用OpenSSL完成了“自签名证书”操作十多次。可能还要使事情正规化,并使您的设备信任可以在任何需要的地方使用的CA。

支持CA签名操作的支持个人身份验证(PIV)应用程序的任何YubiKey。我使用的是YubiKey 5 NFC。

USB拇指驱动器(或第二个YubiKey),用于存储我们CA的脱机备份

在笔记本电脑上,使用Raspberry Pi Imager将Ubuntu 20.10 Server 64位ARM预安装服务器映像刻录到microSD卡上。

启动Raspberry Pi,将其插入网络并找到其初始IP地址。您可以运行arp -na | grep -e" b8:27:eb" -e" dc:a6:32" -e&#34:5f:01"在本地网络上发现Raspberry Pi设备。

使用timedatectl set-timezone America / Los_Angeles设置时区(或任何时区; timedatectl list-timezone将列出所有时区)

确保NTP工作正常。使用timedatectl检查状态-确保“ NTP服务”为“活动”。如果没有,您可以将一些NTP服务器添加到/etc/systemd/timesyncd.conf并运行systemctl restart systemd-timesyncd。

您需要在计算机上使用DNS名称(对我来说是tinyca.internal)和/或网络上的静态IP。

现在,插入您的YubiKey。让我们安装yubico-piv-tool,并确保您可以连接到YubiKey:

$ sudo apt-add-repository ppa:yubico / stable $ sudo apt update $ sudo apt install -y yubico-piv-tool $ yubico-piv-tool --action =" status"版本:5.2.7串行数字:... CHUID:3019 ..... 0fe00CCC:无可用数据PIN尝试左移:3

$ cd $ curl -LO https://golang.org/dl/go1.15.6.linux-arm64.tar.gz$ sudo tar -C / usr / local -xzf go1.15.6.linux-arm64.tar.gz $ cat<< EOF>> .profile>导出PATH = $ PATH:/ usr / local / go / bin> EOF $源.profile $ go版本go版本go1.15.6 linux / arm64

您需要同时安装step-ca(CA服务器软件)和step(用于配置和控制step-ca的命令)。

$ curl -LO https://github.com/smallstep/certificates/archive/v0.15.5.tar.gz$ tar xvzf v0.15.5.tar.gz $ cd certificate-0.15.5 /#step-ca说明从此处开始:$ sudo apt-get install -y libpcsclite-dev $ make bootstrap $ make build GOFLAGS ="" .... Build Complete!$ sudo cp bin / step-ca / usr / local / bin $ sudo setcap CAP_NET_BIND_SERVICE = + eip / usr / local / bin / step-ca $ step-ca versionSmallstep CA / 0.15.5(linux / arm64)发布日期:2020-12-08 19:49 UTC

$ curl -LO https://github.com/smallstep/cli/releases/download/v0.15.3/step_linux_0.15.3_arm64.tar.gz$ tar xvzf step_linux_0.15.3_arm64.tar.gz $ sudo cp step_0.15.3 / bin / step / usr / local / bin $步骤版本Smallstep CLI / 0.15.3(linux / arm64)发布日期:2020-10-21 23:46 UTC

无限噪声TRNG是一种开源USB真随机数发生器。它使用“模块化熵乘法器”架构来快速生成大量随机数据。对于此设置,守护程序将通过写入/ dev / random来将熵连续地馈入Linux的系统熵池中。

但是CA会实际使用这个可爱的新熵生成器吗?我需要在这里回答两个问题:

CA如何生成随机数?我不得不仔细研究一下以确认这一点。 step-ca使用Go的crypto / rand生成所有密钥,而cyrpto / rand使用/ dev / urandom作为Linux系统上的随机数据源。

通过写入/ dev / random创建的熵是否实际上会影响从/ dev / urandom读取的内容?这样做是因为Linux只有一个熵池,由/ dev / random和/ dev / urandom共享。

我们还需要确认舷外TRNG实际上正在产生高质量的噪声。我们将在一分钟内完成。

您需要从源代码编译驱动程序,因为没有可用的预构建arm64软件包。

$ curl -LO https://github.com/13-37-org/infnoise/archive/0.3.1.tar.gz$ tar xvzf 0.3.1.tar.gz $ cd infnoise-0.3.1 / $ sudo apt -get install -y libftdi-dev libusb-dev $ make -f Makefile.linux $ sudo make -f Makefile.linux installinstall -d / usr / local / sbininstall -m 0755 infnoise / usr / local / sbin / install -d / usr / local / lib / udev / rules.d / install -m 0644 init_scripts / 75-infnoise.rules /usr/local/lib/udev/rules.d/install -d / usr / local / lib / systemd / systeminstall- m 0644 init_scripts / infnoise.service / usr / local / lib / systemd / system

重新启动后,您应该看到驱动程序已启动。它会根据是否存在TRNG来启动和停止。

$ systemctl status infnoise●infnoise.service-Wayward Geek InfNoise TRNG驱动程序已加载:已加载(/usr/local/lib/systemd/system/infnoise.service;已禁用;供应商预设:已启用)活动:自2020年2月以来处于活动状态12-08 12:52:51 PST; 2分钟0之前进程:1652 ExecStart = / usr / local / sbin / infnoise --dev-random --daemon --pidfile /var/run/infnoise.pid(代码=已退出,status = 0>主PID:1657(infnoise )任务:1(限制:2099)CGroup:/system.slice/infnoise.service└─1657/ usr / local / sbin / infnoise --dev-random --daemon --pidfile /var/run/infnoise.pidDec 08 12:52:51 tinyca systemd [1]:启动Wayward Geek InfNoise TRNG驱动程序...十二月08 12:52:51 tinyca systemd [1]:启动Wayward Geek InfNoise TRNG驱动程序。

最后,让我们进行运行状况检查,以确保可以使用TRNG:

$ infnoise --debug --no-output生成1048576位。 **可以使用数据。**估计的每位熵:0.877159,估计的K:1.836755num1s:50.514668%,偶数失火:0.111168%,奇数失火:0.152342%^ C

每秒infnoise.service将熵写入/ dev / random。一切都取决于随机性!现在,您已经拥有了足够多的熵,现在可以生成CA密钥了。

现在,您将创建根CA证书和中间CA证书和密钥,并将它们安全地存储在YubiKey上。

理想情况下,此部分应使您的Raspberry Pi保持脱机状态。断开以太网电缆,然后通过HDMI和键盘直接连接到设备。

您不能仅让CA私钥仅存在于YubiKey上。万一YubiKey坏了,您至少要备份一份!

插入USB拇指驱动器。您将直接在此驱动器上生成密钥,这样它们就永远不会碰到Pi的microSD卡。首先,找到您的USB驱动器的设备名称:

$ sudo fdisk -l ...磁盘/ dev / sda:14.91 GiB,16005464064字节,31260672扇区磁盘模型:Cruzer FitUnits:1 * 512 = 512字节的扇区扇区大小(逻辑/物理):512字节/ 512字节...

在这种情况下,驱动器为/ dev / sda。让我们使用一个ext4分区对其进行初始化:

$ sudo fdisk / dev / sda欢迎使用fdisk(util-linux 2.36)。更改将仅保留在内存中,直到您决定将其写入为止。在使用write命令之前请小心。命令(m寻求帮助):nPartition类型p primary( 0个主要,0个扩展,4个免费)e扩展(逻辑分区的容器)选择(默认p):p分区号(1-4,默认1):第一个扇区(2048-31260671,默认2048):最后一个扇区,+ / -sectors或+/- size {K,M,G,T,P}(2048-31260671,默认值为31260671):创建了类型为' Linux'的新分区1。大小为14.9 GiB.Command(m为帮助):w分区表已更改。调用ioctl()重新读取分区表。同步磁盘。$ sudo mkfs.ext4 / dev / sda1 -vmke2fs 1.45.6(20 -2020年3月)用于mke2fs.conf的fs_types解析度:' ext4'文件系统标签=操作系统类型:Linux ...创建日志(16384块):done编写超级块和文件系统记帐信息:done $ sudo mount / dev / sda1 / mnt

太好了,现在您可以创建您的公钥基础结构(PKI)。具体来说,您将创建CA密钥和证书。

Tiny CA具有根CA密钥和证书,以及中间CA密钥和证书。

默认情况下,step-ca颁发具有24小时寿命的证书。我希望此默认设置将迫使您在客户端上设置自动续订。如果您希望更轻松一些,可以随时在CA配置中增加TLS证书的持续时间。

如果设备配置为信任您的根CA,它将信任您使用step-ca创建的证书。

需要X.509证书复习吗?请参阅我们的帖子,有关证书和PKI的所有知识,但又害怕问。

出现提示时,请使用强密码,并离线保存密码,超级安全。

$ cd / mnt $ sudo mkdir ca $ sudo chown ubuntu:ubuntu ca $ export STEPPATH = / mnt / ca $ step ca init --pki --name =" Tiny"✔您想输入什么密码是? [留空,我们将生成一个]:...正在生成根证书...已完成!正在生成中间证书...已完成!✔根证书:/mnt/ca/certs/root_ca.crt✔根私钥:/ mnt / ca /​​ secrets /root_ca_key✔根指纹:d6b3b9ef79a42aeeabcd5580b2b516458ddb25d1af4ea7ff0845e624ec1bb609✔中级证书:/mnt/ca/certs/intermediate_ca.crt✔中级私用密钥/ ret /ret_sec😍/ BACK检测使用情况统计信息。它不给家打电话。但是您的反馈意见非常宝贵。您可以提供的有关您如何使用“步骤”的任何信息都会有所帮助。请给我们发送一两个句子,无论好坏:[email protected]或加入https://github.com/smallstep/certificates/discussions。

别忘了给您的CA取个可爱的名字!它会出现在您所有的证书上。还要抓紧您的根指纹;您将需要它来稍后引导您的客户。

$ yubico-piv-tool --action =" import-certificate" --slot =" 9a" --touch-policy =&never" < /mnt/ca/certs/root_ca.crt成功导入了新证书。$ yubico-piv-tool --action =" import-key" --slot =" 9a" --touch-policy =&never" < / mnt / ca /​​ secrets / root_ca_key输入PEM密码:...已成功导入新的私钥。$ yubico-piv-tool --action =" import-certificate" --slot =" 9c" --touch-policy =&never" < /mnt/ca/certs/intermediate_ca.crt成功导入了新证书。$ yubico-piv-tool --action =" import-key" --slot =" 9c" --touch-policy =&never" < / mnt / ca /​​ secrets / intermediate_ca_key输入PEM密码:...已成功导入新的私钥。 :没有可用数据槽位9a:算法:ECCP256主题DN:CN =微小的根CA颁发者DN:CN =微小的根CA指纹:d6b3b9ef79a42aeeabcd5580b2b516458ddb25d1af4ea7ff0845e624ec1bb609不早于:Dec 8 20:12:15 2020 GMT Not After: 2030 GMTSlot 9c:算法:ECCP256主题DN:CN =微小的中级CA颁发者DN:CN =微小的根CA指纹:fa21279c114ef44be899cb41e830b920faa6ce2c0ec5bc4f1c9310194e5837d2不早于:Dec 8 20:12:15 2020 GMT Not After向左尝试:3

好!现在,您将复制CA证书文件,将私钥留在USB记忆棒上,然后继续创建CA。

您现在要重新运行步骤ca init,但是您将不使用它生成的证书或密钥。这样做只是为了创建配置文件。在出现提示时选择的密码将是管理员提供者密码。拥有该密码的任何人都可以使用step ca certificate子命令从您的CA获取任何证书。

不要将您的根CA密码用于配置者,而要选择坚固的东西并将其存储在安全的地方。

$ sudo useradd step $ sudo passwd -l step $ sudo mkdir / etc / step-ca $ export STEPPATH = / etc / step-ca $ sudo --preserve-env step ca init --name =" Tiny CA&# 34; \ --dns =" tinyca.internal,10.20.30.42" --address =":443" \ --provisioner =" [email protected]"✔您希望密码是什么? [留空,我们将生成一个]:正在生成根证书...已完成!正在生成中间证书...已完成!✔根证书:/etc/step-ca/certs/root_ca.crt✔根私有密钥:/ etc / step-ca / secrets /root_ca_key✔根指纹:d52aa8dc57114fb28aafe0a4fa2795d3afe​​eb3a024bf6e6291077d99ff0cebc6✔中级证书:/ etc / step-ca / certs / intermediate_ca。文件夹:/ etc / step-ca /db✔默认配置:/etc/step-ca/config/defaults.json✔证书颁发机构配置:/etc/step-ca/config/ca.json您的PKI已准备就绪。要为单个服务生成证书,请参见“步骤帮助ca..FEEDBACK”。步骤实用程序未安装使用情况统计信息。它不给家打电话。但是您的反馈意见非常宝贵。您可以提供的有关您如何使用“步骤”的任何信息都会有所帮助。请给我们发送一两个句子,无论好坏:[email protected]或加入https://github.com/smallstep/certificates/discussions。

现在,您将添加一个ACME配置器,它将您的Tiny CA变成一个很小的Let's Encrypt。

$ step ca Provisioner添加acme --type acme成功!您的`step-ca`配置已更新。为了获得新的配置SIGHUP(kill -1< pid>)或重新开始step-ca过程。

最后,您需要使用YubiKey上的中间键,将step-ca配置为使用YubiKey签署证书。请注意,此处也显示了默认的YubiKey PIN(123456)。编辑文件/etc/step-ca/config/ca.json。您希望文件的顶部看起来像这样:

{" root&#34 ;:" /etc/step-ca/certs/root_ca.crt" ;," federatedRoots&#34 ;: []," crt" :" /etc/step-ca/certs/intermediate_ca.crt" ;," key&#34 ;:" yubikey:slot-id = 9c&#34 ;," kms& #34 ;: {" type&#34 ;:" yubikey&#34 ;," pin&#34 ;:" 123456" }," address&#34 ;:":443&#34 ;, ...

现在,您将启动CA并确保其正常运行:

$ sudo chown -R step:step / etc / step-ca $ sudo -u step step-ca /etc/step-ca/config/ca.json2020/12/08 14:17:06在:443上提供HTTPS .. 。

在这里,您需要使用初始密钥集创建的CA指纹:

$ step ca bootstrap --ca-url =" https://tinyca.internal" --fingerprint d6b3b9ef79a42aeeabcd5580b2b516458ddb25d1af4ea7ff0845e624ec1bb609根证书已保存在/home/ubuntu/.step/certs/root_ca.crt中,您的配置已保存在/home/ubuntu/.step/config/defaults.json步骤中。 34; localhost" localhost.crtlocalhost.key✔提供者:[email protected](JWK)[孩子:Kn16nM7lnKBIsUSB-jd5wJDPgRsxzYsvilWTK4Rm2b0]✔请输入密码以解密提供者密钥:✔CA:https://tinyca.internal:443✔证书: localhost.crt✔私钥:localhost.key $步骤证书检查localhost.crt --shortX.509v3 TLS证书(ECDSA P-256)[序列号:2949 ... 3005]主题:localhost发行者:Tiny Intermediate CA Provisioner:carl @ smallstep.com [ID:Kn16 ... m2b0]有效期从:2020-12-08T22:18:34Z到:2020-12-09T22:19:34Z

大!您刚刚使用YubiKey和step-ca签署了您的第一个X.509 TLS叶子证书。

当您要求CA为TLS端点颁发叶证书时,您将获得一个证书文件和一个关联的私钥文件。证书文件将同时包含中间CA证书和您请求的叶证书。这样,信任您的根CA的设备就可以验证从根到中间以及从中间到叶的信任链。

在本部分中,您将为step-ca设置systemd服务,以便在系统启动时启动。

您还将配置systemd以在删除YubiKey时停止CA,并在重新插入YubiKey时重新启动它。

首先,您需要通过添加一些udev规则来告诉udev有关您的YubiKey的知识,这将有助于使YubiKey作为设备在systemd中可见。

$ sudo tee /etc/udev/rules.d/75-yubikey.rules> / dev / null<< EOFACTION ==" add",SUBSYSTEM ==" usb",ENV {PRODUCT} ==" 1050/407 / *",TAG + =" systemd",SYMLINK + =" yubikey" ACTION =="删除",SUBSYSTEM ==" usb",ENV {PRODUCT} ==" 1050 / 407 / *",TAG + =" systemd" EOF $ sudo udevadm控件-重新加载规则

在此,ENV {PRODUCT}值的格式为{vendorId} / {productId} / *。 Yubico的供应商ID为1050,而407是YubiKey 5 NFC的产品ID。如果您使用其他的YubiKey,则可以在此处找到您的型号。

$ sudo tee /etc/systemd/system/step-ca.service> / dev / null<< EOF [单位]说明= step-caBindsTo = dev-yubikey.deviceAfter = dev-yubikey.device [服务]用户= stepGroup = stepExecStart = / bin / sh -c' / usr / local / bin / step-ca /etc/step-ca/config/ca.json'Type=simpleRestart=on-failureRestartSec=10[Install]WantedBy=multi-user.targetEOF$ sudo mkdir /etc/systemd/system/dev-yubikey.device。想要$ sudo ln -s /etc/systemd/system/step-ca.service /etc/systemd/system/dev-yubikey.device.wants/$ sudo systemctl daemon-reload $ sudo systemctl启用step-ca

$ sudo systemctl status step-ca●step-ca.service-step-ca已加载:已加载(/etc/systemd/system/step-ca.service;已启用;供应商预设:已启用)活动:自2020年星期二起处于活动(运行)状态-12-08 14:27:02 PST; 3秒钟前主PID:3269(sh)任务:9(限制:2099)CGroup:/system.slice/step-ca.service├─3269/ bin / sh -c / usr / local / bin / step-ca / etc /step-ca/config/ca.json└─3270/ usr / local / bin / step-ca /etc/step-ca/config/ca.jsonDec 08 14:27:02 tinyca systemd [1]:开始了step- ca.Dec 08 14:27:02 tinyca sh [3270]:2020/12/08 14:27:02在:443上提供HTTPS服务...

完全没有任何SSH访问权限,您的小型CA将是最安全的。对于CA,唯一的开放端口将是443。为了进行维护,您需要插入键盘和显示器。

$ sudo tee /etc/ufw/applications.d/step-ca-server> / dev / null<< EOF [step-ca] title =小步骤CAdescription = step-ca是在线X.509,SSH证书颁发机构端口= 443 / tcp $ sudo ufw允许step-ca $ sudo ufw enableCommand可能会破坏现有的ssh连接。进行运算(y | n)? yFirewall在系统启动时处于活动状态并已启用

在新设备上运行步骤ca bootstrap时(如上),将从CA下载根证书root_ca.crt。如果运行步骤ca bootstrap --install --ca-url = https://your.ca- -fingerprint =您的ca-fingerprint,它将把根证书安装到设备的信任库中。

您还可以使用step命令轻松安装根CA证书(安装步骤证书),进行ACME注册(步骤ca证书example.com example.crt example.key --provisioner acme)以及续订任何尚未获得的证书。 还没有过期(请更新example.crt example.key步骤)。 对于移动设备,通常可以通过将证书通过蓝牙或AirDrop或电子邮件附件发送给自己来安装证书。 确保不仅安装了证书,而且设备确实信任该证书。 这通常涉及设备上的几个确认步骤。 借助ACME设置程序,您可以使用Certbot等软件或 ......