本文档对原流程进行了语法修正与结构整理,目标是让你可以按步骤直接执行。
请先理解并替换以下占位符:
SERVER_DOMAIN_PLACEHOLDER:服务器域名ALT_SERVER_DOMAIN_PLACEHOLDER:备用域名(可选)SERVER_IP_PLACEHOLDER:服务器 IPv4 地址HOST_IP_PLACEHOLDER:主机地址占位ROOT_CA_CN:根 CA 的 Common NameORG_PLACEHOLDER/ORG_UNIT_PLACEHOLDER/STATE_PLACEHOLDER/CITY_PLACEHOLDER
建议以下工作目录作为示例:~/myCA
cd ~
mkdir -p myCA/signedcerts myCA/private
cd myCA
echo '01' > serial
touch index.txt目录用途:
~/myCA:CA 主目录(证书、数据库、请求等)~/myCA/signedcerts:已签发证书副本~/myCA/private:CA 私钥
在 ~/myCA/caconfig.cnf 写入:
[ ca ]
default_ca = local_ca
[ local_ca ]
dir = /home/<username>/myCA
certificate = $dir/cacert.pem
database = $dir/index.txt
new_certs_dir = $dir/signedcerts
private_key = $dir/private/cakey.pem
serial = $dir/serial
default_crl_days = 365
default_days = 1825
default_md = SHA256
policy = local_ca_policy
x509_extensions = local_ca_extensions
copy_extensions = copy
[ local_ca_policy ]
commonName = supplied
stateOrProvinceName = supplied
countryName = supplied
emailAddress = supplied
organizationName = supplied
organizationalUnitName = supplied
[ local_ca_extensions ]
basicConstraints = CA:false
subjectAltName = DNS:SERVER_DOMAIN_PLACEHOLDER
nsCertType = server
[ req ]
default_bits = 2048
default_keyfile = /home/<username>/myCA/private/cakey.pem
default_md = SHA256
prompt = no
distinguished_name = root_ca_distinguished_name
x509_extensions = root_ca_extensions
[ root_ca_distinguished_name ]
commonName = ROOT_CA_CN
stateOrProvinceName = STATE_PLACEHOLDER
countryName = XX
emailAddress = admin@example.invalid
organizationName = ORG_PLACEHOLDER
organizationalUnitName = ORG_UNIT_PLACEHOLDER
[ root_ca_extensions ]
basicConstraints = CA:true注意:将 /home/<username>/myCA 中的 <username> 改为真实用户名。
export OPENSSL_CONF=~/myCA/caconfig.cnf
openssl req -x509 -newkey rsa:2048 -out cacert.pem -outform PEM -days 1825可选:导出 .crt 格式
openssl x509 -in cacert.pem -out cacert.crt生成结果:
~/myCA/cacert.pem:根 CA 证书~/myCA/private/cakey.pem:根 CA 私钥
在 ~/myCA/exampleserver.cnf 写入:
[ req ]
prompt = no
distinguished_name = server_distinguished_name
[ server_distinguished_name ]
commonName = SERVER_DOMAIN_PLACEHOLDER
stateOrProvinceName = STATE_PLACEHOLDER
countryName = XX
emailAddress = admin@example.invalid
organizationName = ORG_PLACEHOLDER
organizationalUnitName = ORG_UNIT_PLACEHOLDER
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# [ alt_names ]
# DNS.1 = SERVER_DOMAIN_PLACEHOLDER
# DNS.2 = ALT_SERVER_DOMAIN_PLACEHOLDERcommonName 必须与目标域名一致,否则会出现主机名不匹配。
export OPENSSL_CONF=~/myCA/exampleserver.cnf
openssl req -newkey rsa:1024 -keyout tempkey.pem -keyform PEM -out tempreq.pem -outform PEM方式 A(去掉私钥密码,常见于自动化启动):
openssl rsa < tempkey.pem > server_key.pem方式 B(保留私钥密码):
mv tempkey.pem server_key.pemexport OPENSSL_CONF=~/myCA/caconfig.cnf
openssl ca -in tempreq.pem -out server_crt.pemrm -f tempkey.pem tempreq.pem最终文件:
server_crt.pem:服务器证书server_key.pem:服务器私钥
以下示例以 Debian/Ubuntu 的 Apache 路径为参考。
sudo mkdir -p /var/www/lab
sudo touch /var/www/lab/index.html创建 /etc/apache2/sites-available/lab-ssl.conf:
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
ServerAdmin admin@example.invalid
DocumentRoot /var/www/lab
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /home/<username>/myCA/server_crt.pem
SSLCertificateKeyFile /home/<username>/myCA/server_key.pem
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
</VirtualHost>
</IfModule>sudo a2enmod ssl
sudo a2ensite lab-ssl.conf
sudo systemctl restart apache2浏览器访问:
https://SERVER_DOMAIN_PLACEHOLDER
如果浏览器提示不受信任,需要导入根 CA 证书(cacert.pem 或 cacert.crt)。
在 /etc/hosts 中加入映射:
SERVER_IP_PLACEHOLDER SERVER_DOMAIN_PLACEHOLDER
SERVER_IP_PLACEHOLDER ALT_SERVER_DOMAIN_PLACEHOLDER
HOST_IP_PLACEHOLDER HOST_PLACEHOLDER
# IPv6 placeholders
IPV6_LOOPBACK_PLACEHOLDER ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
caconfig.cnf中的 SAN(若你启用了域名限制)
subjectAltName = DNS:SERVER_DOMAIN_PLACEHOLDERexampleserver.cnf中的commonName
commonName = SERVER_DOMAIN_PLACEHOLDER- Apache 配置中的访问域名与证书路径。
修改后,按第 5 节重新生成并签发服务器证书。
commonName与访问域名不一致:浏览器会报证书名称错误。- 根 CA 未导入系统/浏览器信任库:浏览器会提示证书不受信任。
- 使用加密私钥启动服务:每次重启服务可能需要输入私钥密码。
- 证书路径错误:Apache 启动失败,先检查
SSLCertificateFile与SSLCertificateKeyFile。