局域网内搭建浏览器可信任的SSL证书

首先是为什么要干这个事情,你可能会说随便搞个自签名证书难道不能用吗?答案是还真的不能用,的确对于开发来说搞个自签名的证书就行了。但是一旦放到生产环境浏览器对证书有效性进行验证的时候便是不可信状态,这时就必须要用户点击一下继续访问,但是对于我们即将实施项目的自动化要求来说没法这样干。你可能又会说了现在这个环境在阿里云、华为云这些平台上随便申请一个免费的证书难道不行吗?答案是真的不行,因为项目的特殊要求最终我们部署的环境是完全没有外网访问的,就只能在局域网环境下运行及意味着不光是SSL证书的问题我们连DNS服务器都要自己建。这时候你可能又要说了那么直接用http访问就可以了,干嘛要用ssl证书呀?答案是这个项目需要使用WebRTC进行音视频多人会议,而WebRTC只能在https下运行。

其实上面的说法有一个点需要更正一下,自签名证书其实也可以但是一旦对超过100个客户端进行分发简直是要命的事情,所以我们通过Windows域控的方式统一对下属计算机进行证书分发保证可用性。

1.原理

SSL证书的信任机制其实是非常简单的,第一需要一个机构证书,第二是需要服务端证书,一般来说机构证书被称为CA证书,而服务端证书就称为服务器证书吧。那么为啥https非常安全呢?答案其实不复杂,下面就是一段逻辑性描述来说明为啥https是安全的。

通常情况下我们在给Nginx、Tomcat、IIS上配置的证书便是服务器证书,那么它是怎么保证客户端访问的地址绝对没有被拦截修改的呢?其实也不复杂,当我们的浏览器发起一个请求的时候到服务端上时,对应web服务器会通过证书的秘钥将http响应值进行一次加密,然后将密文与明文同时返回出来,客户端浏览器接收到响应之后会将密文对称解码然后和明文进行对比,这样一来便可以保证响应值没有被串改。

这个时候逻辑上稍微厉害一点都会发现一个问题,客户端是怎么解码的?这里的答案就是服务端在响应的时候同时会将证书的公钥也返回,这个公钥只能解码对应私钥加密的信息,同时这个公钥无法加密只能解密,这样一来如果如果某人想要拦截http请求便必须知道对应的私钥才行,否则浏览器一旦发现解密信息对不上便知道了响应数据已经被拦截修改过了。

如果你反应过来了你会发现一个新的问题,那么假设拦截这自己搞了一对有效的私钥和公钥然后伪装为服务器不就行了,恭喜你盲生发现了华点。这里就需要CA证书来处理了。其实服务器证书的公钥是由CA证书的秘钥配对加密来的,这样一来当请求返回的服务器公钥和通过CA证书进行验证时便会发现这个公钥是不是由机构签发的公钥,一旦对应不上则说明服务器不是原来CA证书签发服务器证书,这就证明你的请求被第三方拦截了。同时CA证书对于浏览器而言只有公钥,也就是说安装证书时本质上就是将CA证书的公钥导入到你的电脑上了,至此除开CA机构的证书发放者没有知道CA证书的秘钥是什么这样一来便可以保证下面几个非常关键的安全性:

  • 你请求的服务绝对是官方的服务器,绝对不是黑客自建的服务器。
  • 服务器响应给你的数据绝对是正确的,期间黑客绝对无法对其进行修改。

证书的结构如下:

这里还有一个问题便是这些CA证书是哪来的,自己的电脑上又重来没有导入过什么证书。这里便是一个非常无耻躺着赚钱的商业模式了,微软、谷歌、苹果等公司提供了操作系统和浏览器,他们便是第一方的CA机构,他们的系统自己肯定信任自己对吧?所以系统安装的时候他们的CA公钥已经安装到你们的系统里面了,然后这几家巨头合伙说那么这些CA公钥在每种系统都有,然后就是一写第三方公司和这些巨头打成了合作,这些公司的机构证书也被巨头们信任所以理所当然的入库了,这些三方机构便是大名鼎鼎的SymantecGeoTrust几个巨头,这些机构一个单域名的签名证书都敢直接拿出来卖,一年好几千,对他们而言无法就是给下发的证书进行一次签名而已,真正的躺着赚钱。

2.开始制作证书

这里我使用的证书工具是openssl,经典工具,坦白的说非常难用。

2.1创建CA证书

首先第一步肯定是制作一个机构证书也就是CA证书出来,这里有两种方案,第一是直接用openssl创建CA证书,另一种是windows域控生成域组织的CA证书,我们分开说。

2.1.1通过openssl创建CA证书

第一步是创建一个秘钥,这个便是CA证书的根本,之后所有的东西都来自这个秘钥:

# 通过rsa算法生成2048位长度的秘钥
openssl genrsa -out myCA.key 2048

第二步是通过秘钥加密机构信息形成公钥:

# 公钥包含了机构信息,在输入下面的指令之后会有一系列的信息输入,这些信息便是机构信息,公司名称地址什么的
# 这里还有一个过期信息,CA证书也会过期,openssl默认是一个月,我们直接搞到100年
openssl req -utf8 -new -x509 -key myCA.key -out myCA.cer -days 36500

这一步需要输入的机构信息有点,分别说一下:

参数名称参数值
Country Name国家代码,比如中国就是CN
State or Province Name省名称
Locality Name城市名称
Organization Name机构名称
Organizational Unit Name机构单位名称
Common Name重点参数:授权给什么,因为机构是根节点所以是授权给自己
Email Address邮件地址

2.1.2通过windows域控创建CA证书

这种便是我采用的方案,执行上比直接用openssl创建证书复杂多了,但是好处也非常多,一方面域控下级的所有计算机天然对域控服务就是信任状态,第二是域控制器能够通过组策略域内同步CA证书,本质上来讲相对于多了一个CA证书同步与分发的机制。我这边使用的Windows Server 2016,其他版本区别也不大。

第一步是在域控上启用证书服务

第二步是安装完毕之后配置证书

这里非常简单,我都不想说了,直接根据提示输入相关信息就行了,在过期时间那一步最好将时间拉长,我还是使用的100年。

第三步是通过组策略进行分发

策略路径是:计算机策略/Windows设置/安全设置/公钥策略/受信任的根证书颁发机构计算机策略/Windows设置/安全设置/公钥策略/受信任的发布者证书。将上面创建的证书导出之后,在这里导入即可。

2.2创建服务器证书

在得到CA证书之后,需要通过openssl工具对证书进行转换得到公钥(.crt文件)和密钥(.key文件),无论CA证书是怎么来的到这里之后就没有任何区别了,服务器证书的制作流程相较CA证书要复杂一点点。

第一步通过openssl工具创建服务器的秘钥:

# 通过RSA算法生成长度2048位的秘钥
openssl genrsa -out server.key 2048

第二步这里是创建一个签名请求

需要将服务器信息写入到请求文件之中,然后通过CA机构证书对请求签名形成服务器证书公钥,这一步要复杂一些,很多网上的教程在这里都GG了主要原因没有把原理搞清楚。

首先https证书的公钥不同于自定义情况下的加密证书,这里需要安装浏览器标准进行配置,首先openssl默认的证书版本是V1,V1在支持https时部分浏览器依旧会认为不安全,所以需要使用V3版本;同时openssl即便是使用V3版本依旧没有附带V3的subjectAltName字段数据(这里是证书对应的IP地址或者域名,可以用通配符)。但是这些东西命令行没法指定所以需要配置文件,我这里准备了一个:

tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7

[ ca ]
default_ca = CA_default  # The default ca section

[ CA_default ]
dir  = ./demoCA  # Where everything is kept
certs  = $dir/certs  # Where the issued certs are kept
crl_dir  = $dir/crl  # Where the issued crl are kept
database = $dir/index.txt # database index file.
new_certs_dir = $dir/newcerts  # default place for new certs.
certificate = $dir/cacert.pem  # The CA certificate
serial  = $dir/serial   # The current serial number
crlnumber = $dir/crlnumber # the current crl number
crl  = $dir/crl.pem   # The current CRL
private_key = $dir/private/cakey.pem# The private key
RANDFILE = $dir/private/.rand # private random number file
x509_extensions = usr_cert  # The extentions to add to the cert
name_opt  = ca_default  # Subject Name options
cert_opt  = ca_default  # Certificate field options
default_days = 365   # how long to certify for
default_crl_days= 30   # how long before next CRL
default_md = default  # use public key default MD
preserve = no   # keep passed DN ordering
policy  = policy_match

[ policy_match ]
countryName  = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName  = supplied
emailAddress  = optional

[ policy_anything ]
countryName  = optional
stateOrProvinceName = optional
localityName  = optional
organizationName = optional
organizationalUnitName = optional
commonName  = supplied
emailAddress  = optional

[ req ]
default_bits  = 1024
default_keyfile  = privkey.pem
distinguished_name = req_distinguished_name
attributes  = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
string_mask = utf8only
req_extensions = v3_req # The extensions to add to a certificate request

[ req_distinguished_name ]
countryName   = Country Name (2 letter code)
countryName_default  = CN
countryName_min   = 2
countryName_max   = 2

stateOrProvinceName  = State or Province Name (full name)
stateOrProvinceName_default = BeiJing

localityName   = Locality Name (eg, city)

0.organizationName  = Organization Name (eg, company)
0.organizationName_default = myca
organizationalUnitName  = Organizational Unit Name (eg, section)
commonName   = Common Name (e.g. server FQDN or YOUR name)
commonName_max   = 64
emailAddress   = Email Address
emailAddress_max  = 64

[ req_attributes ]
challengePassword  = A challenge password
challengePassword_min  = 4
challengePassword_max  = 20
unstructuredName  = An optional company name

[ usr_cert ]
basicConstraints=CA:FALSE
nsCertType = client, email, objsign
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
nsComment   = "OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

[ svr_cert ]
basicConstraints=CA:FALSE
nsCertType   = server
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyAgreement
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
extendedKeyUsage = serverAuth,clientAuth

[ v3_req ]
subjectAltName = @alt_names

# 这里是重点,需要将里面配置为最终服务端需要的域名或者IP
# 这里可以写多个,能够自行添加DNS.X = XXXXXX
[ alt_names ]
DNS.1 = xunshi.com
DNS.2 = *.xunshi.com
IP.1 = 192.168.0.2
IP.2 = 192.168.0.3

[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = CA:true

[ crl_ext ]
authorityKeyIdentifier=keyid:always

[ proxy_cert_ext ]
basicConstraints=CA:FALSE
nsComment   = "OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo

[ tsa ]
default_tsa = tsa_config1 # the default TSA section

[ tsa_config1 ]
dir  = ./demoCA  # TSA root directory
serial  = $dir/tsaserial # The current serial number (mandatory)
crypto_device = builtin  # OpenSSL engine to use for signing
signer_cert = $dir/tsacert.pem  # The TSA signing certificate
     # (optional)
certs  = $dir/cacert.pem # Certificate chain to include in reply
     # (optional)
signer_key = $dir/private/tsakey.pem # The TSA private key (optional)

default_policy = tsa_policy1  # Policy if request did not specify it
     # (optional)
other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional)
digests  = md5, sha1  # Acceptable message digests (mandatory)
accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
clock_precision_digits  = 0 # number of digits after dot. (optional)
ordering  = yes # Is ordering defined for timestamps?
    # (optional, default: no)
tsa_name  = yes # Must the TSA name be included in the reply?
    # (optional, default: no)
ess_cert_id_chain = no # Must the ESS cert id chain be included?
    # (optional, default: no)

将上面的配置内容保存为openssl.cnf放到生成的服务器证书文件的目录下(注意:修改alt_names里面的域名或者IP为最终部署需要的地址,支持通配符),然后执行创建签名申请文件即可,执行运行:

# 和创建CA时一样这里需要输入一堆服务器信息,输入项也是相同的。
# 不过在输入Common Name(CN)最好直接输入服务器的IP地址或者域名。
openssl req -utf8 -config openssl.cnf -new -out server.req -key server.key 

PS:上述配置文件使用sha1算法生产的证书,部分浏览器已经已经不信任该算法了,如果你使用的时候遇到sha1相关的问题,可以参考评论区的kevin同学提供的方案

如果你遇到sha1问题,用稍微新一点的openssl.cnf文件 https://github.com/openssl/openssl/blob/master/apps/openssl.cnf
同时还要在这个文件里稍微改一下,把下述的配置加入进去
“`
[ v3_req ]
subjectAltName = @alt_names
# 这里是重点,需要将里面配置为最终服务端需要的域名或者IP
# 这里可以写多个,能够自行添加DNS.X = XXXXXX
[ alt_names ]
DNS.1 = xunshi.com
DNS.2 = *.xunshi.com
“`
加上。
最后用请求生成密钥的时候 用下面这个指令 使用sha384代替默认的sha1
openssl x509 -req -extfile openssl.cnf -extensions v3_req -in server.req -out server.cer -CAkey myCA.key -CA myCA.cer -sha384 -days 36500 -CAcreateserial -CAserial serial

第三步通过CA机构证书对服务器证书进行签名认证

# 这里没有什么需要说的,本质上就是将签名请求文件进行签名最终得到服务器的公钥
openssl x509 -req  -extfile openssl.cnf -extensions v3_req -in server.req -out server.cer -CAkey myCA.key -CA myCA.cer -days 36500 -CAcreateserial -CAserial serial

第四步部署证书

这里应该没有什么需要说的了,我们通过Nginx部署,最终得到server.key就是秘钥,server.cer文件就是公钥只需要配置给Nginx就行了。

3.信任CA机构证书

如果通过Windows域控创建的CA证书,其证书本身通过组策略便可以给每一个域下计算机添加机构信任。如果你没有域控只是通过openssl创建的CA证书也没有关系,只需要将CA证书的公钥(myCA.cer文件)导入到系统信任的根证书颁发机构里面就行了:

这个界面在windows的internet选型->内容->证书可以打开,导入即可,也可以直接双击cer文件进行证书安装,最终不光是windows系统,任何操作系统都可以安装证书来进行对CA机构的进行信任操作。

在对证书进行信任之后通过https打开浏览器进入内网DNS或者host配置的域名便可以得到没有任何警告的内容的安全连接:

如果是Mac系统访问逻辑也是一样的通过安装CA证书并且在钥匙串内添加信任之后依然可以正常访问:

在Android手机上也是一样,安装并且信任证书之后可以正常访问:

4.总结

本来对我对https的认证逻辑其实理解没有多深入,以前也只是用过SSL证书进行TCP传输加密而已,经过对openssl的学习现在至少在理解上达到了及格水平,不过这次学习论证与探索的过程我个人极其不愉快,本来这东西在有了理解之后大家都看得出来不是什么很难的东西,事实上我也只用了一天半就搞定了。但是网上充斥大量垃圾内容,不光没有什么正向内容甚至不少内容还TM起了误导的作用,整个中文互联网检索体系下就没有找到一篇文章稍微详细描述整个搭建逻辑与流程,简直了,最终我只能从https原理和openssl的官方文档开始看起,过于离谱了。基本上可以得到一个结论现在天天写一些所谓干货的博主简直就是滥竽充数,其内容千篇一律大多数也是抄袭来的基本上什么都没有说清楚简直浪费时间。

最后说一下https的原理,在解释清楚之后其实不是绝对上的安全,结合本文各位可以想一下怎样去伪造一个页面出来?假设我是黑客来搞入侵其实只需要一个小小的脚本就可以了,我们自行制作CA和服务证书之后,通过修改HOST文件对域名解析进行劫持将其引导到我们自己的服务器,然后将我们自己制作CA证书注入目标电脑的受信任证书组,这样一来对于被入侵者已经看到是安全连接但是其请求已经被我们拦截了。所以各位不要看到https就以为安全了,一旦你的电脑本身就被入侵了那么https也是形同虚设的,所以在执行高风险操作的时候最好还是点开站点的证书看看对应的CA机构是不是被修改过。

局域网内搭建浏览器可信任的SSL证书》有76条留言

  1. 博主总结说的太对了。
    网上文章抄来抄去,错误的地方都是一样。 抄抄又回到那个CSDN,可能还要收费。
    还好现在有了ChatGPT,已经很少用搜索。 有问题就问AI。

  2. 我将证书部署至nginx后,加入域下的计算机的浏览器上访问,出现 NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM,是什么原因呢?

      1. 非常感谢博主在这个场景下提供了完整的思路,我测试成功了,有点小建议,文件中提到的升级sha1到sha384时,文中写道“最后用请求生成密钥的时候 用下面这个指令 使用sha384代替默认的sha1”,没有把对应的命令给出来,我测试用的这条命令“openssl x509 -req -extfile openssl.cnf -extensions v3_req -in server.req -out server.cer -CAkey myCA.key -CA myCA.cer -sha384 -days 36500 -CAcreateserial -CAserial serial”,中间加上了-sha384

        1. 客气客气,我之前写这篇博文的时候sha1还不是不安全的加密,后面是评论区指出的,我补充就不是很详细,但是原理是一样的

  3. 这就有个问题,比如我构建一个站点上线的时候用的证书就是用这个方法给签名的,那就不需要付钱了?那可信CA那边咋收钱呢?

  4. 博主你好!我也是内网,没有域控,请问有什么方法可以把自签名证书自动安装到用户电脑上嘛?跪求大佬回复

  5. 请问nginx搭建的加密服务使用的自签名证书,虽然会证书报警但不会TLS握手失败,但是我自己写的加密服务直接报证书不合法,tls握手失败,把自签名证书添加到浏览器里面就合法了,这是有什么原理吗,如何才能让自签名报个警告但是握手还能成功呢

    1. 建议你重新读一下这篇文章,你提到的问题已经在文章里面解释的很清楚了,校验逻辑不是你的自签名证书,而是这个证书的来源

      1. 你最后给 服务器证书进行签名认证 时使用的 CA证书是 使用 openssl 生成的呢 还是 通过 域控生成 导出来的 呢,

  6. 哇,绝了绝了,说的很有道理,网上一搜一堆没用的,要不就是几句话能说明白的,要搞一大堆

  7. 感谢大佬写blog,但是有个小问题
    如果服务器没有域名,使用ip来访问,但是https的端口又不是443,填写common name和alt_names的时候需要加端口号吗?

  8. 我前几年看了一篇富途的文章手把手学会了制作ca,没想到时间都过去了五六年了,这些知识还是这么多人不会,可见国内的技术根本没发展。

    1. 也不能这么说吧,毕竟行业这几年也有不少新人加入,而且对于大部分程序员来说SSL也不是什么面试的必要指标,大家不了解也很正常;我真正生气的点在于这么基础的东西,就没有几个文章能够讲清楚,过于离谱

  9. 我找到原因了,
    1. 要先打开 keychain 并选择到 system 上 再导入, 不能在iCloud上导入。
    2.服务证书的有效期100年会被认为无效,1年是可以的,CA证书有效期100年是可以的。

  10. 我在mac上导入CA证书时报错, “localhost” 是我CA证书的 Common Name , 不知道是不是因为这个问题,CA证书的Common Name不应该是一个域名吧!

    An error occurred. Unable to import “localhost”.

    Error: -25294

  11. 我自定义了一个证书链,然后把根证书 导入了受信任的根证书,二级证书导入了中间证书机构,但是访问网站是,还是提示不安全,请问可能原因是什么?
    CONNECTED(00000003)
    depth=2 C = CN, ST = HB, L = WH, O = edu, OU = marvin, CN = Marvin Root Certificate Authority
    verify error:num=19:self signed certificate in certificate chain

    Certificate chain
    0 s:/C=CN/ST=HB/L=WH/O=edu/OU=bingo/CN=*.od.com
    i:/C=CN/ST=HB/O=edu/OU=marvin/CN=Marvin Intermediate Certificate Authority
    1 s:/C=CN/ST=HB/O=edu/OU=marvin/CN=Marvin Intermediate Certificate Authority
    i:/C=CN/ST=HB/L=WH/O=edu/OU=marvin/CN=Marvin Root Certificate Authority
    2 s:/C=CN/ST=HB/L=WH/O=edu/OU=marvin/CN=Marvin Root Certificate Authority
    i:/C=CN/ST=HB/L=WH/O=edu/OU=marvin/CN=Marvin Root Certificate Authority

    Server certificate
    —–BEGIN CERTIFICATE—–
    MIIERjCCAi6gAwIBAgIJALD8x4SX70A8MA0GCSqGSIb3DQEBCwUAMG0xCzAJBgNV
    BAYTAkNOMQswCQYDVQQIDAJIQjEMMAoGA1UECgwDZWR1MQ8wDQYDVQQLDAZtYXJ2
    aW4xMjAwBgNVBAMMKU1hcnZpbiBJbnRlcm1lZGlhdGUgQ2VydGlmaWNhdGUgQXV0
    aG9yaXR5MB4XDTIzMDIyNjA5MzMyNVoXDTI0MDMwNzA5MzMyNVowWDELMAkGA1UE
    BhMCQ04xCzAJBgNVBAgMAkhCMQswCQYDVQQHDAJXSDEMMAoGA1UECgwDZWR1MQ4w
    DAYDVQQLDAViaW5nbzERMA8GA1UEAwwIKi5vZC5jb20wggEiMA0GCSqGSIb3DQEB
    AQUAA4IBDwAwggEKAoIBAQDaZ4dQFfMFIc44gZoAqbppQ54u1udRIcKvHvIOZ4Ir
    17DD7bPJBWIzB9q+yBlZ7SqfefpnsL3l8GhLknQy6f7B7BOe47HVu9xrheCG/tQj
    IhoIbQd9ox9Ga3XfmaBue3p4SRSXWv4bvT8xD78ifEpYQDawCygY48CB4aRuEZN6
    ZLPWmhLMrzlrliGJgbbAvAlbdSt3wZJNAl0EzMC7xSDDB6yLNiu9WMttl8arHO+U
    orZkRHOAPLDtIa0TTzFADvJTuw3HeICnJVawSwtQJOZqAFPhTsHtR8shHO//5dtX
    bzhJEAxQaKbOqWAgK0/wglj9CHRI5KA9PVl/ezA0Na95AgMBAAEwDQYJKoZIhvcN
    AQELBQADggIBAHQnHbwJFDxa5+mRUPaipkC+af8kHkgk9aAJdKnp0gs8fbAjLV5D
    OXYeFfSPsEEiUyVAjvW3ZVZYeJLWOHSR+XcAiABn/U02TjpREH7vO91fGbrYJamt
    qFR3cq3qGn+c3QH0Yb0L/RQAD8S/ipDOsUnpCoSGUUMgnjc/yAdeeEygiIbPbEmx
    plcp2OI1bMkVQuMl82jelWdp1hFLmFtg4LrxNM/3vO1Q57z9VbCOfp8Ke6bDArkO
    WUVzwjaIEUfPHKR7ww1q1b2+3zw3kRSZtkeNcyEV0/aqbMqHH/WOa++nyjkj/0/K
    LpYfUvsRV10D/yPSv2b55YkauRf/zbXF8bICP8d1rWpofjYOktEKxqsKsSor7XJl
    5GDXAZulJBgEEUGIl+HNSHYy5V5MH76Q081TgQtiwcv3aFZppIcvx8IOMGmau+3w
    n+NQl1nXjYKtpGx7hHNHqirZNXjLTNTLkVFUIQlEcf7XUQ9OQKuW7K8mYBPLXM9G
    /WxoHth3GIBN3VMVjxTj6L5NtyKIHbLH8yK3rGlTt+p5nNz7O8Fh1++d1froSTb8
    LkUuP75WwrSKyBzvRraS5YZbRYFvSd3V9PWaGmcoFFnNzAbE/dwsk6Z4v6Nr9TIL
    SuoHZbmgJGxC4B8DcSAud5FJXxWiELKLa4rSbDVn7C8627nX/n34t0jI
    —–END CERTIFICATE—–
    subject=/C=CN/ST=HB/L=WH/O=edu/OU=bingo/CN=*.od.com
    issuer=/C=CN/ST=HB/O=edu/OU=marvin/CN=Marvin Intermediate Certificate Authority

    No client certificate CA names sent
    Peer signing digest: SHA512
    Server Temp Key: ECDH, P-256, 256 bits

    SSL handshake has read 4742 bytes and written 415 bytes

    New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
    Server public key is 2048 bit
    Secure Renegotiation IS supported
    Compression: NONE
    Expansion: NONE
    No ALPN negotiated
    SSL-Session:
    Protocol : TLSv1.2
    Cipher : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: A23FF2C9688BD347D7AB77616A9D9E1108C6C6D0A44B17391D4825075025DCCE
    Session-ID-ctx:
    Master-Key: F1CBFA67E17EB265B6C911E9EDD0D24A991894CB19E0BD6570C9059BF4DA17BF7EA38CD89C43225C58C5A239414F6C0F
    Key-Arg : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 – b4 62 a6 3a 43 66 84 16-9c 7f b5 d0 e0 63 5e e4 .b.:Cf…….c^.
    0010 – 54 85 63 fc 44 d4 10 ac-79 ce 52 b7 bd 3a 0f fe T.c.D…y.R..:..
    0020 – 3f 4b 69 20 64 41 9a f5-f5 29 a3 34 d8 4c 0a 46 ?Ki dA…).4.L.F
    0030 – 22 e9 75 dc cb 97 26 b2-9f 19 29 f3 01 9c ba 71 “.u…&…)….q
    0040 – 2c 5e 17 91 ab 5d 75 01-f5 5f f8 41 0c 79 36 03 ,^…]u.._.A.y6.
    0050 – ef 60 70 9f b2 d6 2e 0a-8b af 20 bc 9c 18 59 c9 .`p……. …Y.
    0060 – f4 aa e1 38 ff 89 14 35-8d a1 5b 63 44 d6 fd 8f …8…5..[cD…
    0070 – 4b fb a5 4f d9 26 29 01-7d 7a 93 3c f1 7f 36 b8 K..O.&).}z.<..6.
    0080 – cc 4b 99 0b e6 98 d2 c0-57 06 33 77 dc 29 d9 83 .K……W.3w.)..
    0090 – c8 45 35 35 63 92 b7 4e-63 fd 72 16 90 4c 7e 33 .E55c..Nc.r..L~3
    00a0 – 24 92 00 20 ed 71 c5 fa-37 c6 6d 44 4f 04 37 ca $.. .q..7.mDO.7.

    Start Time: 1677479813
    Timeout : 300 (sec)
    Verify return code: 19 (self signed certificate in certificate chain)

  12. 如果你遇到sha1问题,用稍微新一点的openssl.cnf文件 https://github.com/openssl/openssl/blob/master/apps/openssl.cnf
    同时还要在这个文件里稍微改一下,把下述的配置加入进去
    “`
    [ v3_req ]
    subjectAltName = @alt_names
    # 这里是重点,需要将里面配置为最终服务端需要的域名或者IP
    # 这里可以写多个,能够自行添加DNS.X = XXXXXX
    [ alt_names ]
    DNS.1 = xunshi.com
    DNS.2 = *.xunshi.com
    “`
    加上。

    最后用请求生成密钥的时候 用下面这个指令 使用sha384代替默认的sha1。

  13. 文章中所提供的openssl.cnf,在目前版本的火狐和chrome中已经不能用了,显示The certificate is not trusted because it was signed using a signature algorithm that was disabled because that algorithm is not secure.
    问题在于低版本的sha1加密算法已经不被支持,请后来的同学使用更高版本的

  14. 内网环境中http站点里嵌套https页面也遇到同样问题,上级部门没有DNS,需要访问我们系统,没建域控,通过博主的文章找到了思路,打算写个脚本打开首页时安装证书。

  15. PS C:\Program Files\OpenSSL-Win64\bin> .\openssl.exe x509 -req -extfile e:\ssl\openssl.conf -extensions v3_req -in e:\ssl\server.req -out e:\ssl\server.cer -CAkey e:\ssl\myCA.key -CA e:\ssl\myCA.cer -days 7200 -CAcreateserial -CAserial serial
    Certificate request self-signature ok
    subject=C = cn, ST = gd, L = sz, O = sundy, OU = sundy, CN = sundy
    7C360000:error:80000005:system library:BIO_new_file:Input/output error:crypto\bio\bss_file.c:67:calling fopen(serial, w)
    7C360000:error:10080002:BIO routines:BIO_new_file:system lib:crypto\bio\bss_file.c:77:

    卡死在最后一步了。。。。。。

    1. 终于有人看懂了,不知道为什么现在搞技术的都这么浮夸,我这个文章算是几乎没有废话了都没几个有耐心看完

  16. openssl.cnf 是一个配置文件还是一个类似脚本的东西?
    下面是报错的内容,我应该怎么做?
    [root@localhost ssl]# openssl req -config openssl.cnf -new -out server.req -key server.key
    Error Loading request extension section v3_req
    140206333278016:error:2207507C:X509 V3 routines:v2i_GENERAL_NAME_ex:missing value:crypto/x509v3/v3_alt.c:512:
    140206333278016:error:22098080:X509 V3 routines:X509V3_EXT_nconf:error in extension:crypto/x509v3/v3_conf.c:47:name=subjectAltName, value=nextcloud.net

  17. 你好 麻烦问下 我是通过域环境下搭建的CA centos上的Apache服务现在需要ssl证书 centos通过OpenSS生成.csr请求文件 通过CA签名后 导入到Apache配置文件中 为什么还是不安全的啊 ?

  18. 我有一个问题,尽管将CA证书添加了认证之后,查询证书的相信信息的时候,可以看到“这个证书的目的是:所有应用程序策略”,但是Chrome浏览器还是会提示“证书无效”,这是什么原因啊?难道是Chrome浏览器自己还有一层校验么?

  19. 大佬,我按照你的流程走了一遍,我的网站是 IP地址+端口的,不管是发布在IIS,还是nginx, edge浏览器还是提示不安全,是IP地址不行吗?必须用域名吗?

      1. 大佬!我今天试了下内网ip+端口,客户端机是win10,IP好像没有用,域名才有用,不知道是不是不同系统下对浏览器对证书域名的校验不一样?

  20. # 这里是重点,需要将里面配置为最终服务端需要的域名或者IP
    # 这里可以写多个,能够自行添加DNS.X = XXXXXX
    [ alt_names ]
    DNS.1 = 内网服务器ip

    我的网站地址是内网ip,是不是在这里配置了ip,浏览器就不会出现不安全的提示?

      1. 并不是啊,Chrome只认域名啊,如果只用ip的话,尽管证书是没有问题的,但是Chrome还是会提示不安全。

  21. 同时openssl即便是使用V3版本依旧没有附带V3的subjectAltName字段数据(这里是证书对应的IP地址或者域名,可以用通配符)。但是这些东西命令行没法指定所以需要配置文件。
    可以不用配置文件的:
    证书请求:
    openssl req -new -sha256 -key server.key \
    -subj “/C=CN/ST=HeNan/L=ZhengZhou/O=JACKADAM/OU=jack/CN=server.jackadam.ml/[email protected]” \
    -extensions v3_req \
    -config <(cat /etc/pki/tls/openssl.cnf \
    <(printf "[req]\nreq_extensions = req_ext\n[req_ext]\nsubjectAltName=DNS:server.jackadam.ml")) \
    -out SANserver.csr
    但是证书签名,不会带入请求中的SAN扩展,还得手动指定:
    openssl ca -in SANserver.csr \
    -policy policy_anything \
    -cert rootCA.crt \
    -keyfile rootCA.key \
    -batch \
    -extensions SAN \
    -config <(cat /etc/pki/tls/openssl.cnf \
    <(printf "[SAN]\nsubjectAltName=DNS:server.jackadam.ml")) \
    -out ./SANserver.crt

    而且你用的是X509自签名,不是CA签名。证书吊销以后,客户端是不会同步跟踪到这个证书被注销。
    证书吊销列表(CRL)与证书状态在线查询协议(OCSP)无法使用。
    我也在尝试,生成证书后,包含CRL OCSP,也不知道是放CA证书还是用户证书。

  22. 博主您好,我在WindowsServer上运行了一个AzureDevOps,通过客户端浏览器访问时提示https不安全,显示证书无效;在服务器上的应用使用SMTP邮件提醒功能时也提示无法建立安全的SSL,远程证书无效。
    搭建的过程就是按照教程里做的,OpenSSL生成CA证书,服务器证书,证书签名,在客户端信任CA证书。部署证书是在IIS上导入,绑定到网站服务。
    操作的具体步骤和注意事项应该都注意到了,但还是不能建立安全的SSL连接,实在是找不到问题出在哪了。
    服务器是一台虚拟机,使用的是内网ip地址,可以连接上外网。

    1. 根据你说明的信息我完全无法分析哪一步出了问题,建议系统学习一下证书机制,通过客户端错误进行调试

  23. 求助博主
    您好,请问这一步:第三步通过CA机构证书对服务器证书进行签名认证 ,中,需要向CA机构进行申请吗,因为我看到文章标题是局域网环境的https搭建;服务器如果没分配公网ip,不花钱向第三方机构申请也是可以参考这篇文章进行搭建的吗。提问不太专业,如果有幸被看到,感谢回复!

    1. CA机构可以是你自己呀,通过openssl就可以创建机构证书,公网或者内网都可以使用,无非就是这个证书是否被信任,我们自己签名的证书肯定是默认不被信任的需要自行给证书添加信任。线上的一些权威机构证书需要花钱,这一部分就是大家默认都信任的证书。

  24. 感谢您的这篇博客,我刚过了一遍,准备在测试服务器上配置https,太有用了!

留下回复