3、OpenSSL实战:使用OpenSSL生成自签名CA证书、服务器证书、客户端证书。

好,咱们进入实战环节。前两章我们把PKI和证书链的理论捋了一遍,说实话,光看理论容易晕。我自己当年学的时候,也是看了好几遍概念,一上手还是懵。所以这一章,咱们直接动手,用OpenSSL把CA证书、服务器证书、客户端证书全部生成一遍。

你想想看,OPC UA通信里,客户端和服务器要建立安全信道,靠的就是这一套证书体系。说白了,你手里得有把“信任的尺子”,而CA就是那个发尺子的人。

本章核心目标: 搭建一个完整的自签名PKI体系,包含根CA、服务器证书、客户端证书。所有操作均使用OpenSSL命令行完成。

3.1 环境准备与目录结构

我个人习惯,做证书相关的工作前,先把目录结构搭好。这样后面操作不会乱。我在项目中见过不少同事,证书文件散落一地,最后自己都分不清哪个是哪个。

建议你按下面的结构来创建:

mkdir -p ~/opcua-pki/{ca,server,client}
cd ~/opcua-pki

目录说明:

目录 用途
ca/ 存放根CA的私钥、证书、以及CA相关的数据库文件
server/ 存放服务器证书的私钥、证书请求、以及最终签发的证书
client/ 存放客户端证书的私钥、证书请求、以及最终签发的证书

嗯,这里要注意,生产环境中CA的私钥一定要妥善保管,最好放在离线机器或者硬件加密模块里。我们这里是实验环境,就先放在ca目录下。

3.2 生成根CA证书

根CA是整个信任链的锚点。所有其他证书的信任,最终都追溯到它。所以第一步,咱们先创建根CA的私钥和自签名证书。

3.2.1 生成CA私钥

私钥是核心中的核心。我建议使用aes256加密,这样每次使用私钥时都需要输入密码,多一层保护。

openssl genrsa -aes256 -out ca/ca-key.pem 4096

执行后会提示你输入一个密码,记得记好。我曾经有个同事,设了个超复杂的密码,结果自己忘了,最后只能重新生成整个CA……

3.2.2 生成CA自签名证书

有了私钥,接下来用私钥给自己签发证书。这就是“自签名”的含义——自己证明自己。

openssl req -new -x509 -days 3650 -key ca/ca-key.pem -sha256 -out ca/ca-cert.pem

命令执行后,会交互式地让你填写证书信息。这里我列一下常用字段:

字段 示例值 说明
Country Name CN 国家代码,两位字母
Organization Name My OPC UA Lab 组织名称
Common Name My Root CA CA的唯一标识名,很重要

Common Name(CN)字段在OPC UA中会被用作证书的主题名称,建议取一个有意义的名称。

小技巧: 如果你不想交互式输入,可以用 -subj 参数一次性指定所有字段。例如:-subj "/C=CN/O=My OPC UA Lab/CN=My Root CA"。我平时写脚本批量生成证书时,都用这种方式。

3.3 生成服务器证书

服务器证书用于OPC UA服务器向客户端证明自己的身份。客户端会验证这个证书是否由受信任的CA签发。

3.3.1 生成服务器私钥

这里我不用加密了,因为服务器启动时需要自动加载私钥,输入密码会打断自动化流程。当然,如果你对安全要求极高,也可以加密,配合systemd的密码输入服务。

openssl genrsa -out server/server-key.pem 2048

注意,服务器证书的密钥长度我用的是2048位。4096位更安全,但性能开销也更大。OPC UA规范中,2048位是推荐的最低标准。

3.3.2 生成证书签名请求(CSR)

CSR就是“请CA帮我签个名”的请求文件。里面包含了服务器的公钥和身份信息。

openssl req -new -key server/server-key.pem -out server/server.csr -sha256 \
  -subj "/C=CN/O=My OPC UA Lab/CN=opcua-server.example.com"

这里CN字段填的是服务器的域名或IP地址。OPC UA客户端在连接时,会检查证书中的CN是否与实际的服务器地址匹配。如果不匹配,连接会失败。我在项目中遇到过好几次这种问题,都是因为CN填错了。

3.3.3 使用CA签发服务器证书

这一步,CA用自己的私钥,给服务器的CSR签名,生成最终的服务器证书。

openssl x509 -req -in server/server.csr -CA ca/ca-cert.pem -CAkey ca/ca-key.pem \
  -CAcreateserial -out server/server-cert.pem -days 365 -sha256

参数说明:

  • -CAcreateserial:自动创建序列号文件,用于跟踪CA签发了多少张证书。
  • -days 365:证书有效期1年。生产环境建议根据安全策略调整。

注意: 每次用CA签发证书时,都会更新序列号文件。如果你在多台机器上操作,记得把序列号文件同步,否则可能出现序列号冲突。我曾经因为这个问题,导致两张证书的序列号相同,排查了好久。

3.4 生成客户端证书

客户端证书的生成流程和服务器证书几乎一样,只是用途不同。客户端证书用于向服务器证明客户端的身份。

3.4.1 生成客户端私钥

openssl genrsa -out client/client-key.pem 2048

3.4.2 生成客户端CSR

openssl req -new -key client/client-key.pem -out client/client.csr -sha256 \
  -subj "/C=CN/O=My OPC UA Lab/CN=opcua-client-001"

客户端的CN可以是一个设备ID或者用户名,不需要是域名。

3.4.3 使用CA签发客户端证书

openssl x509 -req -in client/client.csr -CA ca/ca-cert.pem -CAkey ca/ca-key.pem \
  -CAcreateserial -out client/client-cert.pem -days 365 -sha256

3.5 验证证书链

证书都生成好了,怎么确认没问题?OpenSSL提供了验证命令。

3.5.1 验证服务器证书

openssl verify -CAfile ca/ca-cert.pem server/server-cert.pem

如果输出 server/server-cert.pem: OK,说明证书链完整,信任关系正确。

3.5.2 验证客户端证书

openssl verify -CAfile ca/ca-cert.pem client/client-cert.pem

3.5.3 查看证书详情

有时候需要检查证书里的具体字段,比如有效期、主题、签发者等。

openssl x509 -in server/server-cert.pem -text -noout

这个命令会输出证书的所有详细信息。我经常用它来排查证书不匹配的问题。

3.6 本章核心流程总结

为了让你对整个流程有个直观的认识,我画了一张流程图。这张图展示了从CA创建到最终证书验证的完整链路。

自签名PKI证书生成流程 1. 生成CA私钥 2. 生成CA自签名证书 3. 生成服务器私钥 4. 生成服务器CSR 5. CA签发服务器证书 6. 生成客户端私钥 7. 生成客户端CSR 8. CA签发客户端证书 9. 使用CA证书验证服务器/客户端证书

3.7 常见问题与避坑指南

  • 证书过期: 我见过不少OPC UA连接突然中断的情况,查到最后发现是证书过期了。建议在证书到期前30天设置提醒,或者使用较长的有效期(比如3年)。
  • CN不匹配: 客户端连接服务器时,会检查服务器证书的CN是否与连接地址一致。如果你用IP地址连接,CN里也要填IP地址,而不是域名。
  • 私钥权限: 私钥文件一定要设置严格的权限,建议 chmod 600。我曾经在客户现场发现服务器私钥是644权限,任何用户都能读,这太危险了。
  • CA证书分发: 所有客户端和服务器都必须信任同一个CA证书。把 ca-cert.pem 安全地分发到每台机器上,并导入到系统的信任存储中。

我的经验: 在实际项目中,我通常会写一个shell脚本,把整个证书生成流程自动化。这样每次部署新设备时,只需要运行一个脚本,传入设备名称和IP地址,就能自动生成并签发证书。既减少了人工出错的可能,也提高了效率。