杏泉网络:PKI篇

前情提要:
如何搭建自己的『暗网』
杏泉网络:DNS篇
杏泉网络:OSPF篇

本来,这种VPN网络内部的流量,裸奔也没啥关系,毕竟有VPN兜底,但是架不住某些应用/浏览器API要求在HTTPS环境下才能使用,于是一不做二不休,把自己的PKI也开起来呗

前言

关于PKI(公钥基础设施)的介绍,网上一搜一大把,在这里就不做赘述了。由于我们用的是内网域名和内网IP,成品CA(例如ZeroSSL)无法直接签发这种类型的证书,所以我们需要做一个内部信任的CA机构。

此外提一嘴关于证书的问题,因为手头的设备都比较新,所以笔者选择ECC证书而不是RSA证书(毕竟,快,具体来说是Ed25519)。但是如果你需要兼容老设备,就需要注意一下这个问题。另外一个例外是安卓的IKEv2客户端,似乎只能使用RSA证书(至少Android 14是如此),笔者未具体测试,这里也先略过

CA的建立

CA是PKI的重要组成部分,其他证书都是从CA的基础上发展起来的。如果没有CA,你就得针对各个域名都来一次安装证书的操作,显得不便

# 生成CA私钥
# 如果你想用ECC,又担心兼容性,可以把 Ed25519 换成 prime256v1
openssl genpkey -algorithm Ed25519 -out ca.key

# 指定启用v3证书模式,而且是CA证书
# 证书的CN等字段需要自己修改下
cat > ca.cnf << EOF
[ req ]
distinguished_name = dn
x509_extensions = v3_ca
prompt = no

[ dn ]
C = CN
ST = XQ
L = XQ
O = XQ
OU = xingQuan
CN = XQNetwork Root CA

[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:TRUE
keyUsage = critical, keyCertSign, cRLSign
EOF

# 自签名CA证书,
openssl req -new -x509 -key ca.key -out ca.crt -days 3650 -config ca.cnf

执行完毕后,目录下就有了私钥ca.key和证书ca.crtCA私钥一定要保存好,最好把别的用户的写权限关掉,防止被恶意修改

信任证书

我们自己签发的证书,当然在默认情况下不会受到设备的信任,因此需要手动把上面生成的CA证书传到所需要用的设备上并导入到设备中。

具体的方法其实很简单,无非就是双击安装,或者如果你是移动端的话,在设置里面选择导入。具体操作方法网上都有描述,不再赘述,比如下面的这些教程:

  • Linux 和 Windows 下自签发证书的导入(此处Linux指的是Debian,笔者不是很喜欢这种泛指Linux的做法)
  • 安卓的话,设置里面,基本上就是找加密与凭据,然后里面就有CA证书导入选项,记得把证书后缀名改成.crt

这里特别提一嘴安卓端,可能会出现『需要私钥』的情况。但实际上你要真的导入CA证书的话根本用不着私钥(想想看,CA会把私钥给你吗?)。具体原因,要么是签发证书操作不规范(具体怎么个不规范,笔者没有深究),要么是确实不支持SHA256算法的证书,要么就是你的设备比较老,不支持ed25519系列证书(这就需要换算法)。前两个问题的话解决办法详见笔者的这篇博文。所以这里其实建议你在生成完CA证书后先导入试试,免得签发其他证书后才发现用不了,又要修改,麻烦。

签发服务器证书

有了CA证书,接下来的事情就好办很多了。笔者有一个日用的脚本,在Windows下运行,可以很方便地生成多域名证书和IP证书,这里贴在下面,基于WTFPL协议开源。

@echo off

setlocal enabledelayedexpansion

set /p cn=请输入域名1(默认:test.com):
if not defined cn set cn=test.com


set /p cn2=请输入域名2(不需要请直接回车):
if not defined cn2 set cn2=NO_NEED

set /p fileName=请输入证书文件名(默认与域名一致):
if not defined fileName set fileName=%cn%

echo 生成私钥
openssl ecparam -out "%fileName%.key" -name prime256v1 -genkey
echo 生成REQ
openssl req -key "%fileName%.key" -new -out "%fileName%.req" -subj "/C=CN/ST=Liyue/L=ChihuRock/O=CHR/OU=CHR/CN=%cn%"
echo 签发

echo authorityKeyIdentifier=keyid,issuer >> ssl.conf
echo basicConstraints=CA:FALSE >> ssl.conf
echo keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment >> ssl.conf
echo subjectAltName = @alt_names >> ssl.conf

echo [alt_names] >> ssl.conf
echo DNS.1 = %cn% >> ssl.conf
if not "%cn2%"=="NO_NEED" (
  echo DNS.2 = %cn2% >> ssl.conf
)
rem 如果你想签IP证书,那么就把上面的语句替换为:
rem echo [alt_names] >> ssl.conf
rem echo IP.1 = %cn% >> ssl.conf
rem (开头的rem别输进去,这是批处理的注释)

openssl x509 -req -extfile ssl.conf -in "%fileName%.req" -CA ca.crt -CAkey ca.key -out "%fileName%.crt" -CAcreateserial -days 3650
openssl x509 -noout -fingerprint -sha256 -in "%fileName%.crt" >"%fileName%.fp.txt"

del ssl.conf
del "%fileName%.req"

md "%fileName%"

copy "%fileName%.crt" "%fileName%"
copy "%fileName%.key" "%fileName%"
copy "%fileName%.fp.txt" "%fileName%"

del "%fileName%.crt"
del "%fileName%.key"
del "%fileName%.fp.txt"

echo 结束
pause

执行完毕后就能在脚本目录看到对应的文件夹,里面就有证书和私钥(以及,指纹,如果你想玩证书固定的话)

写在最后

简单水文章。

其实上面的方法,很自然的,放到公网上使用也没有关系,而且你设备信任了证书,自然就不会再有不安全弹窗,方便且安全。

上面的操作如果有错误的地方请各位大神在评论区不吝赐教,谢谢。

(完)


木头箱子脆脆,但是这样正好

如无特殊声明,本站内容均遵循 CC BY-NC-SA 4.0 协议

转载请注明出处并保留作者信息,谢谢!

none
最后修改于:2025年05月23日 11:25

添加新评论

提醒:站长手头紧,没有配备『评论回复邮件提醒』功能
评论后,劳烦您隔一段时间回到本页面查看站长回复(一般都会回)