解决思路,生成一个根证书,然后再用根证书签发具体的域名证书,把根证书导入容器中的授信证书中,把域名证书导入nginx
最终目标
- 生成一个自签的根证书(Root CA)
- 用根证书签发一个域名证书(如
x.abc.edu.cn) - 把根证书导入 Docker 容器 / 系统 / JDK truststore
- 让 Java 应用访问该 HTTPS 域名时,不报证书错误
🧱 一、生成 Root CA(根证书)
# 1. 生成 Root 私钥
openssl genrsa -out rootCA.key 2048
# 2. 生成 Root CA 证书(有效期10年)
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 \
-out rootCA.crt \
-subj "/C=CN/ST=Test/L=Test/O=TestOrg/OU=TestUnit/CN=MyCustomRootCA"
📜 二、为目标域名签发证书
你要签发的是 x.abc.edu.cn 的证书:
1. 创建域名私钥
openssl genrsa -out x.abc.edu.cn.key 2048
2. 创建 CSR(证书签名请求)
openssl req -new -key x.abc.edu.cn.key -out x.abc.edu.cn.csr \
-subj "/C=CN/ST=Test/L=Test/O=MyOrg/CN=x.abc.edu.cn"
3. 创建 SAN 配置(x.abc.edu.cn 的 Subject Alternative Name)
创建文件 san.ext:
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = x.abc.edu.cn
4. 用 Root CA 签发域名证书
openssl x509 -req -in x.abc.edu.cn.csr \
-CA rootCA.crt -CAkey rootCA.key -CAcreateserial \
-out x.abc.edu.cn.crt -days 365 -sha256 -extfile san.ext
内联式
openssl x509 -req -in x.abc.edu.cn.csr \
-CA rootCA.crt -CAkey rootCA.key -CAcreateserial \
-out x.abc.edu.cn.crt -days 365 -sha256 \
-extfile <(cat <<EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment
subjectAltName=DNS:x.abc.edu.cn
EOF
)
你现在有了:
- 根证书(
rootCA.crt) - 域名私钥(
x.abc.edu.cn.key) - 域名证书(
x.abc.edu.cn.crt)
🧪 三、验证证书(可选)
openssl verify -CAfile rootCA.crt x.abc.edu.cn.crt
# 输出应为:x.abc.edu.cn.crt: OK
查看证书
openssl x509 -in x.abc.edu.cn.crt -text -noout
📦 四、导入 Root CA 到容器或系统信任链
🐳 A. 容器(Debian / Ubuntu 系列)
- 复制
rootCA.crt到容器/usr/local/share/ca-certificates/
docker cp rootCA.crt container_id:/usr/local/share/ca-certificates/myroot.crt
- 更新 CA 信任列表:
docker exec container_id update-ca-certificates
或者在 Dockerfile 中写:
COPY rootCA.crt /usr/local/share/ca-certificates/myroot.crt
RUN update-ca-certificates
☕ B. 如果容器内有其它应用,也可采用JDK 的 truststore 导入(容器或宿主)
# 默认 truststore 路径
$JAVA_HOME/jre/lib/security/cacerts
# 导入根证书到 JDK cacerts(密码默认是 changeit)
keytool -import -trustcacerts -keystore $JAVA_HOME/jre/lib/security/cacerts \
-storepass changeit \
-alias myrootca \
-file rootCA.crt
可通过以下命令验证是否成功导入:
keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit | grep myrootca
🌐 五、部署 nginx 使用你签发的域名证书
server {
listen 443 ssl;
server_name x.abc.edu.cn;
ssl_certificate /path/to/x.abc.edu.cn.crt;
ssl_certificate_key /path/to/x.abc.edu.cn.key;
location / {
proxy_pass https://REAL_SERVER;
proxy_ssl_verify off;
}
}
然后加一条本地 /etc/hosts(容器内也可):
127.0.0.1 x.abc.edu.cn
✅ 最终效果
- 你构造了一套自定义的 PKI 系统(Root + Leaf Cert)
- 用根CA签发了相关域名的证书,构成了证书信任链,最终base容器只需导入根CA并授信,后续用根CA签发的域名,容器都能采用https访问
- 不修改 Java 源码,访问
https://x.abc.edu.cn成功通过 TLS 校验 - 容器或系统内的所有 Java 应用将信任你伪造的证书