openssl安装及生成证书 检查是否已经安装 OpenSSL openssl version
没有安装的话执行以下命令安装: yum -y install openssl openssl-devel
生成证书方式1: 一键脚本生成(支持泛域名) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 #!/bin/bash -e help (){ echo ' ================================================================ ' echo ' --ssl-domain: 生成ssl证书需要的主域名,如不指定则默认为www.rancher.local,如果是ip访问服务,则可忽略;' echo ' --ssl-trusted-ip: 一般ssl证书只信任域名的访问请求,有时候需要使用ip去访问server,那么需要给ssl证书添加扩展IP,多个IP用逗号隔开;' echo ' --ssl-trusted-domain: 如果想多个域名访问,则添加扩展域名(SSL_TRUSTED_DOMAIN),多个扩展域名用逗号隔开;' echo ' --ssl-size: ssl加密位数,默认2048;' echo ' --ssl-cn: 国家代码(2个字母的代号),默认CN;' echo ' 使用示例:' echo ' ./create_self-signed-cert.sh --ssl-domain=www.test.com --ssl-trusted-domain=www.test2.com \ ' echo ' --ssl-trusted-ip=1.1.1.1,2.2.2.2,3.3.3.3 --ssl-size=2048 --ssl-date=3650' echo ' ================================================================' } case "$1 " in -h|--help ) help ; exit ;; esac if [[ $1 == '' ]];then help ; exit ; fi CMDOPTS="$*" for OPTS in $CMDOPTS ;do key=$(echo ${OPTS} | awk -F"=" '{print $1}' ) value=$(echo ${OPTS} | awk -F"=" '{print $2}' ) case "$key " in --ssl-domain) SSL_DOMAIN=$value ;; --ssl-trusted-ip) SSL_TRUSTED_IP=$value ;; --ssl-trusted-domain) SSL_TRUSTED_DOMAIN=$value ;; --ssl-size) SSL_SIZE=$value ;; --ssl-date) SSL_DATE=$value ;; --ca-date) CA_DATE=$value ;; --ssl-cn) CN=$value ;; esac done CA_DATE=${CA_DATE:-3650} CA_KEY=${CA_KEY:-cakey.pem} CA_CERT=${CA_CERT:-cacerts.pem} CA_DOMAIN=cattle-ca SSL_CONFIG=${SSL_CONFIG:-$PWD /openssl.cnf} SSL_DOMAIN=${SSL_DOMAIN:-'www.rancher.local'} SSL_DATE=${SSL_DATE:-3650} SSL_SIZE=${SSL_SIZE:-2048} CN=${CN:-CN} SSL_KEY=$SSL_DOMAIN .key SSL_CSR=$SSL_DOMAIN .csr SSL_CERT=$SSL_DOMAIN .crt echo -e "\033[32m ---------------------------- \033[0m" echo -e "\033[32m | 生成 SSL Cert | \033[0m" echo -e "\033[32m ---------------------------- \033[0m" if [[ -e ./${CA_KEY} ]]; then echo -e "\033[32m ====> 1. 发现已存在CA私钥,备份" ${CA_KEY} "为" ${CA_KEY} "-bak,然后重新创建 \033[0m" mv ${CA_KEY} "${CA_KEY} " -bak openssl genrsa -out ${CA_KEY} ${SSL_SIZE} else echo -e "\033[32m ====> 1. 生成新的CA私钥 ${CA_KEY} \033[0m" openssl genrsa -out ${CA_KEY} ${SSL_SIZE} fi if [[ -e ./${CA_CERT} ]]; then echo -e "\033[32m ====> 2. 发现已存在CA证书,先备份" ${CA_CERT} "为" ${CA_CERT} "-bak,然后重新创建 \033[0m" mv ${CA_CERT} "${CA_CERT} " -bak openssl req -x509 -sha256 -new -nodes -key ${CA_KEY} -days ${CA_DATE} -out ${CA_CERT} -subj "/C=${CN} /CN=${CA_DOMAIN} " else echo -e "\033[32m ====> 2. 生成新的CA证书 ${CA_CERT} \033[0m" openssl req -x509 -sha256 -new -nodes -key ${CA_KEY} -days ${CA_DATE} -out ${CA_CERT} -subj "/C=${CN} /CN=${CA_DOMAIN} " fi echo -e "\033[32m ====> 3. 生成Openssl配置文件 ${SSL_CONFIG} \033[0m" cat > ${SSL_CONFIG} <<EOM [req] req_extensions = v3_req distinguished_name = req_distinguished_name [req_distinguished_name] [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, serverAuth EOM if [[ -n ${SSL_TRUSTED_IP} || -n ${SSL_TRUSTED_DOMAIN} || -n ${SSL_DOMAIN} ]]; then cat >> ${SSL_CONFIG} <<EOM subjectAltName = @alt_names [alt_names] EOM IFS="," dns=(${SSL_TRUSTED_DOMAIN} ) dns+=(${SSL_DOMAIN} ) for i in "${!dns[@]} " ; do echo DNS.$((i+1 )) = ${dns[$i]} >> ${SSL_CONFIG} done if [[ -n ${SSL_TRUSTED_IP} ]]; then ip=(${SSL_TRUSTED_IP} ) for i in "${!ip[@]} " ; do echo IP.$((i+1 )) = ${ip[$i]} >> ${SSL_CONFIG} done fi fi echo -e "\033[32m ====> 4. 生成服务SSL KEY ${SSL_KEY} \033[0m" openssl genrsa -out ${SSL_KEY} ${SSL_SIZE} echo -e "\033[32m ====> 5. 生成服务SSL CSR ${SSL_CSR} \033[0m" openssl req -sha256 -new -key ${SSL_KEY} -out ${SSL_CSR} -subj "/C=${CN} /CN=${SSL_DOMAIN} " -config ${SSL_CONFIG} echo -e "\033[32m ====> 6. 生成服务SSL CERT ${SSL_CERT} \033[0m" openssl x509 -sha256 -req -in ${SSL_CSR} -CA ${CA_CERT} \ -CAkey ${CA_KEY} -CAcreateserial -out ${SSL_CERT} \ -days ${SSL_DATE} -extensions v3_req \ -extfile ${SSL_CONFIG} echo -e "\033[32m ====> 7. 证书制作完成 \033[0m" echo echo -e "\033[32m ====> 8. 以YAML格式输出结果 \033[0m" echo "----------------------------------------------------------" echo "ca_key: |" cat $CA_KEY | sed 's/^/ /' echo echo "ca_cert: |" cat $CA_CERT | sed 's/^/ /' echo echo "ssl_key: |" cat $SSL_KEY | sed 's/^/ /' echo echo "ssl_csr: |" cat $SSL_CSR | sed 's/^/ /' echo echo "ssl_cert: |" cat $SSL_CERT | sed 's/^/ /' echo echo -e "\033[32m ====> 9. 附加CA证书到Cert文件 \033[0m" cat ${CA_CERT} >> ${SSL_CERT} echo "ssl_cert: |" cat $SSL_CERT | sed 's/^/ /' echo echo -e "\033[32m ====> 10. 重命名服务证书 \033[0m" echo "cp ${SSL_DOMAIN} .key tls.key" cp ${SSL_DOMAIN} .key tls.keyecho "cp ${SSL_DOMAIN} .crt tls.crt" cp ${SSL_DOMAIN} .crt tls.crt
复制以上代码另存为create_self-signed-cert.sh或者其他您喜欢的文件名。 脚本参数 --ssl-domain: 生成ssl证书需要的主域名,如不指定则默认为www.rancher.local。如果是ip访问服务,则可忽略;
--ssl-trusted-ip: 一般ssl证书只信任域名的访问请求,有时候需要使用ip去访问server,那么需要给ssl证书添加扩展IP,多个IP用逗号隔开;
--ssl-trusted-domain: 如果想多个域名访问,则添加扩展域名(TRUSTED_DOMAIN),多个TRUSTED_DOMAIN用逗号隔开;
--ssl-size: ssl加密位数,默认2048;
--ssl-cn: 国家代码(2个字母的代号),默认CN;
如果需要配置泛域名,ssl-domain参数配置成*.xx.xx格式充当泛域名,脚本中会将它拼在最后面。
ssl-trusted-domain参数配置成xx.xx充当一级域名。
使用示例 1 2 3 4 5 ./create_self-signed-cert.sh --ssl-domain=www.test.com --ssl-trusted-domain=www.test2.com,www.test3.com \ --ssl-trusted-ip=1.1.1.1,2.2.2.2,3.3.3.3 --ssl-size=2048 --ssl-date=3650 ./create_self-signed-cert.sh --ssl-domain=*.test.com --ssl-trusted-domain=test.com \ --ssl-trusted-ip=1.1.1.1,2.2.2.2,3.3.3.3 --ssl-size=2048 --ssl-date=3650
执行完成之后,目录可以看到有新文件生成 1 2 3 4 5 6 7 8 9 10 cacerts-root .crt cacerts-root .srl cakey-root .key create-ca.sh openssl .cnf test .com .crt test .com .csr test .com .key tls .crt tls .key
生成证书方式2: 手动签发泛域名证书 修改openssl.cnf配置文件 具体修改如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [root@docker02 ~] [ req ] ……………… req_extensions = v3_req ……………… [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @SubjectAlternativeName [SubjectAlternativeName] DNS.1 = zhangbook.com DNS.2 = *.zhangbook.com
说明:本次我们以 *.zhangbook.com 泛域名为例。
创建根证书 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [root@docker02 ssl] /root/software/ssl [root@docker02 ssl] [root@docker02 ssl] [root@docker02 ssl] ……………… Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:BJ Locality Name (eg, city) [Default City]:BeiJing Organization Name (eg, company) [Default Company Ltd]:BTC Organizational Unit Name (eg, section) []:MOST Common Name (eg, your name or your server's hostname) []:xiaowu # 这里就是证书上的:颁发者 Email Address []:ca@test.com
当然上述的公钥制作方式需要交互式输入信息,如果不想频繁输入,那么可以使用如下命令:
1 2 openssl req -sha256 -new -x509 -days 36500 -key CA.key -out CA.crt -config /etc/pki/tls/openssl.cnf -subj "/C=CN/ST=BJ/L=BeiJing/O=BTC/OU=MOST/CN=xiaowu/emailAddress=ca@test.com"
subj内容详解:
1 2 3 4 5 6 7 C = Country Name (2 letter code) ST = State or Province Name (full name) L = Locality Name (eg, city) [Default City] O = Organization Name (eg, company) [Default Company Ltd] OU = Organizational Unit Name (eg, section) CN = Common Name (eg, your name or your server's hostname) emailAddress = Email Address
此时的的文件有:
1 2 3 4 [root@docker02 ssl] total 32 -rw-r--r-- 1 root root 1387 Oct 2 10:25 CA.crt -rw-r--r-- 1 root root 1679 Oct 2 10:04 CA.key
自签发泛域名证书 操作步骤为:
生成域名私钥 生成证书签发请求文件 使用自签署的CA,生成域名公钥 具体如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 openssl genrsa -out zhangbook.com.key 2048 openssl req -new -sha256 -key zhangbook.com.key -out zhangbook.com.csr -config /etc/pki/tls/openssl.cnf ……………… Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:BJ Locality Name (eg, city) [Default City]:BeiJing Organization Name (eg, company) [Default Company Ltd]:BTC Organizational Unit Name (eg, section) []:MOST Common Name (eg, your name or your server's hostname) []:*.zhangbook.com # 这里就是证书上的:颁发给 Email Address []:ca@test.com Please enter the following ' extra' attributes to be sent with your certificate request A challenge password []:123456 An optional company name []:BTC ……………… # 生成 zhangbook.com.csr 证书签发请求 非交互式 openssl req -new -sha256 -key zhangbook.com.key -out zhangbook.com.csr -config /etc/pki/tls/openssl.cnf -subj "/C=CN/ST=BJ/L=BeiJing/O=BTC/OU=MOST/CN=*.zhangbook.com/emailAddress=ca@test.com"
PS1:上面的Common Name 就是在这步填写 *.zhangbook.com ,表示的就是该证书支持泛域名,common name一定要在SubjectAlternativeName中包含
PS2:进行CA签名获取证书时,需要注意国家、省、单位需要与CA证书相同,否则会报异常
查看签名请求文件信息 1 openssl req -in zhangbook.com.csr -text
1 openssl ca -in zhangbook.com.csr -md sha256 -days 36500 -out zhangbook.com.crt -cert CA.crt -keyfile CA.key -extensions v3_req -config /etc/pki/tls/openssl.cnf
这里证书有效时间为100年。
PS1:即便是你前面是sha256的根证书和sha256的请求文件,如果这里不加 -md sha256,那么默认是按照sha1进行签名的
PS2:在执行时,可能出现如下错误
异常问题处理,如没有问题则忽略 异常问题1 1 2 3 4 5 Using configuration from /etc/pki/tls/openssl.cnf /etc/pki/CA/index.txt: No such file or directory unable to open '/etc/pki/CA/index.txt' 140652962035600:error:02001002:system library:fopen:No such file or directory:bss_file.c:402:fopen('/etc/pki/CA/index.txt' ,'r' ) 140652962035600:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:404:
处理:这时我们创建该文件即可
1 touch /etc/pki/CA/index.txt
异常问题2 然后我们继续使用 【自签署的CA,签署zhangbook.com.crt】;结果又出现新问题
1 2 3 4 5 Using configuration from /etc/pki/tls/openssl.cnf /etc/pki/CA/serial: No such file or directory error while loading serial number 140087163742096:error:02001002:system library:fopen:No such file or directory:bss_file.c:402:fopen('/etc/pki/CA/serial' ,'r' ) 140087163742096:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:404:
处理:使用如下命令即可。表示:用来跟踪最后一次颁发证书的序列号。
1 echo "01" > /etc/pki/CA/serial
之后我们再次执行 【自签署的CA,签署zhangbook.com.crt 】 就正常了。详情如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [root@docker02 ssl] Using configuration from /etc/pki/tls/openssl.cnf Check that the request matches the signature Signature ok Certificate Details: Serial Number: 1 (0x1) Validity Not Before: Oct 2 03:42:39 2020 GMT Not After : Sep 8 03:42:39 2120 GMT Subject: countryName = CN stateOrProvinceName = BJ organizationName = BTC organizationalUnitName = MOST commonName = *.zhangbook.com emailAddress = ca@test.com X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Key Usage: Digital Signature, Non Repudiation, Key Encipherment X509v3 Subject Alternative Name: DNS:zhangbook.com, DNS:*.zhangbook.com Certificate is to be certified until Sep 8 03:42:39 2120 GMT (36500 days) Sign the certificate? [y/n]:y <== 需要输入的 1 out of 1 certificate requests certified, commit? [y/n]y <== 需要输入的 Write out database with 1 new entries Data Base Updated
说明:此时我们再看,/etc/pki/CA/index.txt 和 /etc/pki/CA/serial 文件信息。如下:
1 2 3 4 5 [root@docker02 ~] V 21200908034239Z 01 unknown /C=CN/ST=BJ/O=BTC/OU=MOST/CN=*.zhangbook.com/emailAddress=ca@test.com [root@docker02 ~] [root@docker02 ~] 02
由上可知:域名签署信息已经保存到index.txt文件;并且证书序列serial文件已经更新【从01变为了02】。
PS:
同一个域名不能签署多次;由于签署了*.zhangbook.com,且已经被记录,因此不能再次被签署。除非删除该记录。 注意index.txt文件和serial文件的关系。serial文件内容为index.txt文件内容行数加1。 查看证书信息 1 openssl x509 -in zhangbook.com.crt -text
验证签发证书是否有效 1 2 [root@docker02 ssl] zhangbook.com.crt: OK
此时的文件有:
1 2 3 4 5 6 7 [root@docker02 ssl] total 32 -rw-r--r-- 1 root root 1387 Oct 2 10:25 CA.crt -rw-r--r-- 1 root root 1679 Oct 2 10:04 CA.key -rw-r--r-- 1 root root 4364 Oct 2 11:42 zhangbook.com.crt -rw-r--r-- 1 root root 1151 Oct 2 10:48 zhangbook.com.csr -rw-r--r-- 1 root root 1679 Oct 2 10:44 zhangbook.com.key
此时我们已经完成自签发证书。
将crt转pem格式 命令如下:
1 openssl x509 -in zhangbook.com.crt -out zhangbook.com.pem -outform PEM
生成 p12 格式的证书 利用生成的CA根证书和服务证书的crt 和 key 文件生成 p12 文件
1 2 3 4 5 openssl pkcs12 -export -in zhangbook.com.crt -inkey zhangbook.com.key -passin pass:CS2i1QkR -name *.zhangbook.com -chain -CAfile CA.crt -password pass:CS2i1QkR -caname *.zhangbook.com -out zhangbook.com.p12 openssl pkcs12 -export -in zhangbook.com.crt -inkey zhangbook.com.key -out zhangbook.com.p12 -name "*.zhangbook.com"
查看p12证书信息 【keytool命令依赖于Java,因此需要先安装Java】
1 2 3 4 5 6 7 [root@docker02 ssl] Enter keystore password: <== 输入:CS2i1QkR Keystore type : PKCS12 Keystore provider: SunJSSE Your keystore contains 1 entry ………………
转换 p12 证书为 jks 证书文件 使用jdk keytool工具进而生成tomcat/jboss端使用的证书文件【需要安装 Java】。
具体如下:
1 2 3 4 5 6 7 8 9 10 [root@docker02 ssl] Importing keystore zhangbook.com.p12 to zhangbook.com.jks... Enter destination keystore password: <== 输入 jks 证书的密码,如:CS2i1QkR Re-enter new password: <== 重复输入 jks 证书的密码,如:CS2i1QkR Enter source keystore password: <== 输入 p12 证书的密码,这里是:CS2i1QkR Entry for alias *.zhangbook.com successfully imported. Import command completed: 1 entries successfully imported, 0 entries failed or cancelled Warning: The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore zhangbook.com.jks -destkeystore zhangbook.com.jks -deststoretype pkcs12" .
PS:p12证书和jks证书的密码相同,防止出现各种异常情况。
利用 jks 证书生成 cer 证书 具体如下
1 keytool -export -alias *.zhangbook.com -keystore zhangbook.com.jks -storepass CS2i1QkR -file zhangbook.com.cer
-storepass CS2i1QkR 为jks证书密码
利用 cer 证书文件生成 jdk 所使用的文件 具体如下
1 keytool -import -alias *.zhangbook.com -keystore cacerts -file zhangbook.com.cer
查询证书过期时间 openssl x509 -in signed.crt -noout -dates
.crt和.key分别代表证书和私钥文件,扩展名是按照文件用途来分的。而.pem是一种文件格式, pem文件是文本格式的,其他证书格式还有DER。
正常情况下,openssl已签发过的域名不可重复签发,需要在撤销之后才能重新签发,否则会报错TXT_DB error number 2 failed to update database
在默认配置中,openssl将所有签名证书的副本保存在/etc/pki/CA/newcerts中,以其索引号命名。因此,可以查找 /etc/pki/CA/index.txt获取要撤销密钥的序列号,例如1013,然后执行以下命令:
1 openssl ca -revoke /etc/pki/CA/newcerts/1013.pem -keyfile CA.key -cert CA.crt
-keyfile和-cert只在与openssl.cnf设置不同的情况下才需要。
或者你也可以修改/etc/pki/CA/index.txt.attr中的unique_subject = no来允许多个证书具有相同的公共名称。如果您已经发布了原始证书,那么撤销旧证书是更可取的解决方案,即使不运行OSCP服务器或提供crl。
nginx配置以及浏览器授信 1 2 3 4 5 6 7 8 9 10 11 ssl_certificate ca/signed.crt; ssl_certificate_key ca/signed.key; ssl_verify_client on ; ssl_client_certificate ca/ca.crt; ssl_session_cache shared:SSL:1m ; ssl_session_timeout 5m ; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_prefer_server_ciphers on ; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 ;
默认情况下浏览器会报证书无效,并且第一次访问时会提示不安全,需要手动点击继续前往不安全的站点,才可以访问。
如果有配置客户端认证, 需导入.p12后缀的个人证书(如果有旧证书, 需要先删除,再导入新证书 ) 证书安装完成之后,重启浏览器,最好清理一下浏览器缓存,否则地址栏可能仍会提示“不安全”红叉。