关于ssl:如何在Linux Chrome和Firefox上信任自签名的localhost证书

How to trust self-signed localhost certificates on Linux Chrome and Firefox

我尝试为指向127.0.0.1的自定义本地域生成自签名证书:

1
2
# /etc/hosts
127.0.0.1 subdomain.domain.local

我使用openssl生成了一个自签名证书,并记住过去一切正常。但似乎自Chrome 58以来,使用自签名证书的限制要多得多。

我的尝试以"您的连接不是私密"结束,其中包含以下错误之一:

  • 如果我像过去那样继续,"安全证书是不可信任的"。
  • 尝试将其导入Chrome时"不是证书颁发机构"。
  • 导入其CA后使用证书时"主题备用名称丢失"。

我很确定我在这个过程中遗漏了一些东西。请问,任何人都可以提供有效的配置来处理替代名称以及创建相应CA和证书的确切步骤,以便Chrome和Firefox可以处理我的本地自定义域吗?


TLDR

  • 创建文件generate.sh

    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
    #!/usr/bin/env bash
    find . \( -name"$1.*" -o -name"*.srl" \) -type f -delete
    cp /usr/lib/ssl/openssl.cnf $1.cnf
    python <(
    cat <<"END"
    import sys
    from ConfigParser import ConfigParser
    from StringIO import StringIO

    domain = sys.argv[1]

    config = ConfigParser()
    config.optionxform = lambda option: option

    name ="{}.cnf".format(domain)

    with open(name,"rb") as stream:
      config.readfp(StringIO("[top]
    " + stream.read()))

    config.set(" v3_ca","subjectKeyIdentifier","hash")
    config.set(" v3_ca","authorityKeyIdentifier","keyid:always,issuer")
    config.set(" v3_ca","basicConstraints","critical, CA:TRUE, pathlen:3")
    config.set(" v3_ca","keyUsage","critical, cRLSign, keyCertSign")
    config.set(" v3_ca","nsCertType","sslCA, emailCA")

    config.set(" v3_req","basicConstraints","CA:FALSE")
    config.set(" v3_req","keyUsage","nonRepudiation, digitalSignature, keyEncipherment")
    config.set(" v3_req","subjectAltName","@alt_names")
    config.remove_option(" v3_req","extendedKeyUsage")

    config.add_section(" alt_names")
    config.set(" alt_names","DNS.1", domain)
    config.set(" alt_names","DNS.2","*.{}".format(domain))

    config.set(" req","req_extensions","v3_req")

    with open(name,"wb") as stream:
        config.write(stream)
    END
    ) $1
    tail -n +2 $1.cnf > $1.cnf.tmp && mv $1.cnf.tmp $1.cnf
    echo"$1
    " | openssl genrsa -aes256 -out $1.ca.key 2048
    chmod 400 $1.ca.key
    openssl req -new -x509 -subj"/CN=$1" -extensions v3_ca -days 3650 -key $1.ca.key -sha256 -out $1.ca.crt -config $1.cnf
    openssl genrsa -out $1.key 2048
    openssl req -subj"/CN=$1" -extensions v3_req -sha256 -new -key $1.key -out $1.csr
    openssl x509 -req -extensions v3_req -days 3650 -sha256 -in $1.csr -CA $1.ca.crt -CAkey $1.ca.key -CAcreateserial -out $1.crt -extfile $1.cnf
    openssl x509 -in $1.crt -text -noout
  • 拨打./generate.sh example.com

    Requires Python 2

  • All credits go to this excellent article by Fabian Lee.

    使用OpenSSL创建受信任的CA和SAN证书

  • 自定义openssl.cnf
  • 创建CA证书
  • 使用CA签名的SAN创建服务器证书
  • 条件

    作为先决条件,请确保已安装SSL软件包:

    1
    $ sudo apt install libssl1.0.0 -y

    定制openssl.cnf

    第一步是获取系统上可用的openssl.cnf模板。在Ubuntu上,这可以在/usr/lib/ssl/openssl.cnf找到。您可以在MacOS上的/System/Library/OpenSSL/中找到它,在Redhat上找到/etc/pki/tls

    1
    2
    3
    export prefix="mydomain"

    cp /usr/lib/ssl/openssl.cnf $prefix.cnf

    $prefix.cnf需要使用有关我们将要生成的证书的特定信息进行修改。

    [ v3_ca ]部分下,添加以下值。对于CA,这表示我们正在创建将用于密钥签名的CA.

    1
    2
    3
    4
    5
    6
    [ v3_ca ]
    subjectKeyIdentifier=hash
    authorityKeyIdentifier=keyid:always,issuer
    basicConstraints = critical, CA:TRUE, pathlen:3
    keyUsage = critical, cRLSign, keyCertSign
    nsCertType = sslCA, emailCA

    然后在[ v3_req ]部分下,为此证书设置以下所有有效的备用名称。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [ v3_req ]
    basicConstraints = CA:FALSE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    #extendedKeyUsage=serverAuth
    subjectAltName = @alt_names

    [ alt_names ]
    DNS.1 = mydomain.com
    DNS.2 = *.dydomain.com

    同时取消注释[ req ]部分下的以下行,以便使用v3扩展创建证书请求。

    1
    req_extensions = v3_req

    当我们生成每种类型的密钥时,我们指定要使用的扩展部分,这就是为什么我们可以共享$prefix.cnf来创建CA和SAN证书。

    创建CA证书

    现在我们将开始使用OpenSSL来创建必要的密钥和证书。首先生成私有/公共RSA密钥对:

    1
    2
    3
    openssl genrsa -aes256 -out ca.key.pem 2048

    chmod 400 ca.key.pem

    这使用基于AES256的密码对密钥文件进行编码。
    然后我们需要创建自签名的根CA证书。

    1
    openssl req -new -x509 -subj"/CN=myca" -extensions v3_ca -days 3650 -key ca.key.pem -sha256 -out ca.pem -config $prefix.cnf

    您可以使用以下方法验证此根CA证书:

    1
    openssl x509 -in ca.pem -text -noout

    这将显示根CA证书,IssuerSubject将是相同的,因为这是自签名的。这被标记为CA:TRUE意味着它将被识别为根CA证书;意味着浏览器和操作系统将允许将其导入其受信任的根证书存储区。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Issuer: CN=myca
    ...
    Subject: CN=myca
    ...
    X509v3 Basic Constraints:
      critical CA:TRUE, pathlen:3
    X509v3 Key Usage:
      critical Certificate Sign, CRL Sign
    Netscape Cert Type:
      SSL CA, S/MIME CA

    创建由CA签名的服务器证书

    现在创建了根CA,我们切换到服务器证书。首先生成私有/公共RSA密钥对:

    1
    openssl genrsa -out $prefix.key.pem 2048

    我们没有在此密钥上加密码,因为CA是更有价值的目标,我们可以随时重新生成服务器证书,但请随意采取这一额外的预防措施。

    然后创建服务器证书签名请求:

    1
    openssl req -subj"/CN=$prefix" -extensions v3_req -sha256 -new -key $prefix.key.pem -out $prefix.csr

    然后使用以下命令生成服务器证书:服务器签名请求,CA签名密钥和CA证书。

    1
    openssl x509 -req -extensions v3_req -days 3650 -sha256 -in $prefix.csr -CA ca.pem -CAkey ca.key.pem -CAcreateserial -out $prefix.crt -extfile $prefix.cnf

    $prefix.key.pem是服务器私钥,$prefix.crt是服务器证书。验证证书:

    1
    openssl x509 -in $prefix.crt -text -noout

    这将显示证书,Issuer将是CA名称,而Subject是前缀。这未设置为CA,Subject Alternative Name字段包含浏览器认为有效的URL。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Issuer:
     CN=myca
    ...
    Subject:
      CN=mydomain
    ...
    X509v3 Basic Constraints:
      CA:FALSE
    X509v3 Key Usage:
      Digital Signature, Non Repudiation, Key Encipherment
    X509v3 Subject Alternative Name:
      DNS:mydomain.com, DNS:*.mydomain.com

    浏览器评估

    当您首次使用带有CA签名的SAN证书在站点上指向Chrome或Firefox时,它将抛出与自签名SAN证书相同类型的例外。这是因为根CA证书不是已签名证书的可信来源。

    Linux的

    在Linux上,Chrome管理自己的证书存储区,您应再次将ca.pem导入Authorities。现在应该使安全图标变为绿色。
    enter image description here

    视窗

    在Chrome设置(chrome://settings)中,搜索certificates并单击Manage Certificates。在Windows上,这将打开Windows证书管理器,您应该在Trusted Root Certification Authorities选项卡中导入ca.pem文件。这相当于在local user受信任的根存储(不是计算机级别)中通过mmc.exe添加它。

    火狐

    在Firefox选项about:preferences中,搜索certificates并单击View Certificates。转到Authorities选项卡并导入ca.pem。选中此框以使其信任网站,现在,当您访问该页面时,锁定图标应变为绿色。
    enter image description here