BLFS Security
p11-kit
备注
make-ca
依赖 p11-kit
,而 p11-kit
依赖 libtasn1
cd /sources
p11_kit_VERSION=0.25.5
tar xf p11-kit-${p11_kit_VERSION}.tar.xz
cd p11-kit-${p11_kit_VERSION}
# 准备发行版特定anchor hook
sed '20,$ d' -i trust/trust-extract-compat &&
cat >> trust/trust-extract-compat << "EOF"
# Copy existing anchor modifications to /etc/ssl/local
/usr/libexec/make-ca/copy-trust-modifications
# Update trust stores
/usr/sbin/make-ca -r
EOF
# 安装
mkdir p11-build &&
cd p11-build &&
meson setup .. \
--prefix=/usr \
--buildtype=release \
-D trust_paths=/etc/pki/anchors &&
ninja
ninja install &&
ln -sfv /usr/libexec/p11-kit/trust-extract-compat \
/usr/bin/update-ca-certificates
make-ca
公钥基础设施 (PKI) 是一种在不受信任的网络上验证未知实体真实性的方法。
PKI 的工作原理是建立信任链,而不是明确信任每个单独的主机或实体。为了使远程实体提供的证书受到信任,该证书必须提供完整的证书链,可以使用本地计算机信任的证书颁发机构 (CA) 的根证书进行验证。
BLFS使用的证书存储取自 Mozilla 基金会,他们制定了此处描述的非常严格的包含政策。
cd /sources
make_ca_VERSION=1.14
tar xf make-ca-${make_ca_VERSION}.tar.gz
cd make-ca-${make_ca_VERSION}
# make-ca脚本会瞎子啊和处理包含在 certdata.txt 文件中的证书作为p11-kit信任模块的信任发布者
make install &&
install -vdm755 /etc/ssl/local
# 注意: 这步一定要确保成功,因为需要下载存放一个 /etc/ssl/certdata.txt
# 这个 certdata.txt 将用于后续 Adding Additional CA Certificates
# 注意: 这个命令执行失败是应为GFW屏蔽了Mozilla的证书下载服务器 https://hg.mozilla.org/ ,需要设置代理
# 注意: 只有这个命令执行成功才能确保本地根证书正确,才能使用 curl 下载 HTTPS 文件
/usr/sbin/make-ca -g
# 需要周期性执行以下命令,所以需要先安装一个fcron以便能够定时执行
# 然后执行以下命令创建定时任务
mkdir /etc/cron.weekly
cat > /etc/cron.weekly/update-pki.sh << "EOF" &&
#!/bin/bash
/usr/sbin/make-ca -g
EOF
chmod 754 /etc/cron.weekly/update-pki.sh
# 添加CA证书 Adding Additional CA Certificates
# 也就是更新之前 ``install -vdm755 /etc/ssl/local`` 在 ``/etc/ssl/local`` 目录下生成的
# CAcert_Class_1_root.pem 和 CAcert_Class_3_root.pem
# 初次安装这个步骤不需要,不过后续更新了 /etc/ssl/certdata.txt 则需要执行
wget http://www.cacert.org/certs/root.crt &&
wget http://www.cacert.org/certs/class3.crt &&
openssl x509 -in root.crt -text -fingerprint -setalias "CAcert Class 1 root" \
-addtrust serverAuth -addtrust emailProtection -addtrust codeSigning \
> /etc/ssl/local/CAcert_Class_1_root.pem &&
openssl x509 -in class3.crt -text -fingerprint -setalias "CAcert Class 3 root" \
-addtrust serverAuth -addtrust emailProtection -addtrust codeSigning \
> /etc/ssl/local/CAcert_Class_3_root.pem &&
/usr/sbin/make-ca -r
# 设置Python3使用系统证书,则添加以下变量
mkdir -pv /etc/profile.d &&
cat > /etc/profile.d/pythoncerts.sh << "EOF"
# Begin /etc/profile.d/pythoncerts.sh
export _PIP_STANDALONE_CERT=/etc/pki/tls/certs/ca-bundle.crt
# End /etc/profile.d/pythoncerts.sh
EOF
make-ca
通常不需要配置,而且,默认的 certdata.txt
由mozilla发布所提供后由 make-ca
创建。不过,这个文件对于一些发行版或Mozilla,使用 nss
版本。(这部分我没有实践)
我在执行
make-ca -g
时遇到报错Unable to get revision from server! Exiting.
,也就是没有能够获得/etc/ssl/certdata.txt
。而这个/etc/ssl/certdata.txt
是用于后续Adding Additional CA Certificates
,所以非常关键。仔细阅读BLFS,这个
certdata.txt
是从 https://hg.mozilla.org 获得的,如果拿不到服务器上这个文件,说明需要从 make-ca release page 下载最新的版本才能解决。但是,比较奇怪,我发现当前 make-ca release page 就是我使用的make-ca-1.14
。所以我暂时不知道怎么解决这个问题
我的 make-ca
安装部署存在问题,导致 curl 下载 HTTPS 文件(包括 git clone https
)都会提示报错:
Cloning into 'libffi'...
fatal: unable to access 'https://gitlab.freedesktop.org/gstreamer/meson-ports/libffi.git/': SSL certificate problem: unable to get local issuer certificate
../meson.build:2218:13: ERROR: Git command failed: ['/usr/bin/git', '-c', 'advice.detachedHead=false', 'clone', '--depth', '1', '--branch', 'meson', 'https://gitlab.freedesktop.org/gstreamer/meson-ports/libffi.git', 'libffi']
对比了 Debian 安装的虚拟机,我发现我的LFS系统 /etc/ssl/certs
是空目录,正常情况下,这个目录下是CA根证书
根据BLFS make-ca
文档,执行 make-ca -g
会下载证书源,但看起来我这个步骤失败
原因是
https://hg.mozilla.org/ 被GFW屏蔽了
执行 -x
运行 /usr/bin/make-ca -g
可以看到需要下载的是 https://hg.mozilla.org/projects/nss/log/tip/lib/ckfw/builtins/certdata.txt ,下载命令实际上是通过 openssl
来完成的:
+ echo GET https://hg.mozilla.org/projects/nss/log/tip/lib/ckfw/builtins/certdata.txt
+ /usr/bin/openssl s_client -ign_eof -connect hg.mozilla.org:443 -verifyCAfile /etc/make-ca/mozilla-ca-root.pem -verifyCApath /etc/ssl/certs -verify_return_error
参考 Using OpenSSL Behind a (Corporate) Proxy , openssl
有一个 -proxy
参数,类似可以传递 -proxy 127.0.0.1:3128
。由于 /usr/bin/make-ca
是一个脚本,检查可以看到该脚本检查环境变量 PROXY
来对应设置 openssl -proxy
,所以通过以下方法成功完成:
openssl
代理export PROXY="117.0.0.1:3128"
/usr/sbin/make-ca -g
成功执行 /usr/sbin/make-ca -g
之后,就能够正常执行 git clone https://...
了
OpenSSH
openssh:
cd /sources
openssh_VERSION=9.8p1
tar xf openssh-${openssh_VERSION}.tar.gz
cd openssh-${openssh_VERSION}
# 准备环境
install -v -g sys -m700 -d /var/lib/sshd &&
groupadd -g 50 sshd &&
useradd -c 'sshd PrivSep' \
-d /var/lib/sshd \
-g sshd \
-s /bin/false \
-u 50 sshd
# 安装
./configure --prefix=/usr \
--sysconfdir=/etc/ssh \
--with-privsep-path=/var/lib/sshd \
--with-default-path=/usr/bin \
--with-superuser-path=/usr/sbin:/usr/bin \
--with-pid-dir=/run &&
make
make install &&
install -v -m755 contrib/ssh-copy-id /usr/bin &&
install -v -m644 contrib/ssh-copy-id.1 \
/usr/share/man/man1 &&
install -v -m755 -d /usr/share/doc/openssh-${openssh_VERSION} &&
install -v -m644 INSTALL LICENCE OVERVIEW README* \
/usr/share/doc/openssh-${openssh_VERSION}
设置
echo "PermitRootLogin no" >> /etc/ssh/sshd_config
echo "PasswordAuthentication no" >> /etc/ssh/sshd_config &&
echo "KbdInteractiveAuthentication no" >> /etc/ssh/sshd_config
# 如果添加了Linux-PAM支持,就可以通过密码认证登陆
sed 's@d/login@d/sshd@g' /etc/pam.d/login > /etc/pam.d/sshd &&
chmod 644 /etc/pam.d/sshd &&
echo "UsePAM yes" >> /etc/ssh/sshd_config
备注
ssh 使用 Linux-PAM 支持来做密码认证,如果不需要密码认证,就不需要Linux-PAM
我采用密钥认证登陆
启动配置
启动配置是通过 BLFS Boot Scripts
cd /sources
blfs_bootscripts_VERSION=20240416
tar xf blfs-bootscripts-${blfs_bootscripts_VERSION}.tar.xz
cd blfs-bootscripts-${blfs_bootscripts_VERSION}
make install-sshd
异常排查
遇到一个非常奇怪的问题,完全一样的 authorized_keys
,分别存放在 root
用户和 admin
用户的 ~/.ssh/
目录下 , root
用户无密码登陆完全正常,但是 admin
用户登陆直接拒绝:
admin@192.168.7.200: Permission denied (publickey).
已经核对:
~/.ssh/
目录700
,~/.ssh/authorized_keys
文件644
或者600
~/.ssh/authorized_keys
文件内容和md5都对比一致
我以前遇到类似密钥无法登陆,基本上就是认证密钥文件属性设置不正确,但这次不是。
我在检查 /etc/shadow
文件时意外发现 admin
账号没有设置过密码。我原本以为我强制通过密钥认证可以不用设置这个普 通用户密码,但是实践发现, 用户账号必须设置密码,即使SSH是通过密钥认证登陆
也就是说,在 /etc/ssh/sshd_config
中设置了(默认)如下:
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
这个不允许用户空密码原来不是指ssh客户端连接以后,用户输入的空密码,而是服务器端用户账号本身就不允许空密码。只要服务器上 的用户密码没有设置,ssh就禁止该账号登陆,哪怕SSH客户端密钥认证是正确的也不行。 空密码校验逻辑在前
sudo
cd /sources
sudo_VERSION=1.9.15p5
tar xf sudo-${sudo_VERSION}.tar.gz
cd sudo-${sudo_VERSION}
./configure --prefix=/usr \
--libexecdir=/usr/lib \
--with-secure-path \
--with-env-editor \
--docdir=/usr/share/doc/sudo-${sudo_VERSION} \
--with-passprompt="[sudo] password for %p: " &&
make
env LC_ALL=C make check |& tee make-check.log
grep failed make-check.log
make install
配置
/etc/sudoers
%wheel ALL=(ALL:ALL) NOPASSWD: ALL
将 admin
用户加入 wheel
组,这样可以无密码切换到 root