关于ssl:如何使用openssl创建自签名证书

How to create a self-signed certificate with OpenSSL

我正在向嵌入式Linux设备添加HTTPS支持。我尝试通过以下步骤生成自签名证书:

1
2
3
4
openssl req -new > cert.csr
openssl rsa -in privkey.pem -out key.pem
openssl x509 -in cert.csr -out cert.pem -req -signkey key.pem -days 1001
cat key.pem>>cert.pem

这是可行的,但我在google chrome中遇到了一些错误:

This is probably not the site you are looking for!
The site's security certificate is not trusted!

我错过什么了吗?这是生成自签名证书的正确方法吗?


您可以在一个命令中执行此操作:

1
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

如果您不想用密码短语保护您的私钥,也可以添加-nodes(no DES的缩写)。否则,它将提示您输入"至少4个字符"的密码。

可以用任何数字替换days参数(365),以影响到期日期。然后它会提示您输入"国家名称"之类的内容,但您只需点击enter并接受默认值。

添加-subj '/CN=localhost'以抑制对证书内容的疑问(用所需域替换localhost)。

自签名证书不会与任何第三方进行验证,除非您以前将其导入浏览器。如果您需要更多的安全性,您应该使用由证书颁发机构(CA)签名的证书。


Am I missing something? Is this the correct way to build a self-signed certificate?

Ok.

创建自签名证书很容易。您只需使用openssl req命令。创建一个可以被大量客户机(如浏览器和命令行工具)使用的客户端可能很困难。好的。

这很困难,因为浏览器有自己的需求集,而且它们比IETF更具限制性。浏览器使用的需求记录在CA/BROWSER论坛上(见下文参考资料)。限制出现在两个关键领域:(1)信任锚,(2)DNS名称。好的。

现代浏览器(比如我们在2014/2015年使用的Warez)想要一个链接到信任锚的证书,并且他们希望在证书中以特定的方式显示DNS名称。浏览器也在积极对抗自签名服务器证书。好的。

有些浏览器并不能很容易地导入自签名服务器证书。事实上,你不能使用一些浏览器,比如Android的浏览器。所以完整的解决方案是成为你自己的权威。好的。

在没有成为您自己的权威的情况下,您必须获得正确的DNS名称,才能给证书最大的成功机会。但我鼓励你成为自己的权威。很容易成为你自己的权威,它会回避所有的信任问题(谁比你更值得信任?).好的。

This is probably not the site you are looking for!
The site's security certificate is not trusted!

Ok.

这是因为浏览器使用预先定义的信任锚列表来验证服务器证书。自签名证书不会链接回受信任的锚。好的。

避免这种情况的最佳方法是:好的。

  • 创建自己的权限(即成为CA)
  • 为服务器创建证书签名请求(CSR)
  • 用CA密钥签署服务器的CSR
  • 在服务器上安装服务器证书
  • 在客户端上安装CA证书
  • 第1步-创建您自己的权限只意味着用CA: true创建一个自签名证书,并正确使用密钥。这意味着主题和发行者是同一个实体,CA在基本约束中设置为true(也应标记为critical),密钥用法为keyCertSigncrlSign(如果使用crls),主题密钥标识符(ski)与颁发机构密钥标识符(aki)相同。好的。

    要成为自己的证书颁发机构,请参见*如何与证书颁发机构签署证书签名请求?堆栈溢出时。然后,将您的CA导入浏览器使用的信任存储区。好的。

    步骤2-4大致是您现在为面向公共的服务器所做的,当您登记CA(如Startcom或Cacert)的服务时。步骤1和步骤5允许您避免第三方权限,并充当您自己的权限(谁比您更值得信任?).好的。

    避免浏览器警告的第二个最佳方法是信任服务器的证书。但有些浏览器,比如Android的默认浏览器,不允许你这样做。所以它永远不会在平台上工作。好的。

    浏览器(以及其他类似的用户代理)不信任自签名证书的问题将成为物联网(IOT)中的一个大问题。例如,当你连接到恒温器或冰箱进行编程时会发生什么?答案是,就用户体验而言,没有什么好的。好的。

    W3C的webappsec工作组正在着手研究这个问题。例如,请参见建议:将HTTP标记为非安全。好的。

    How to create a self-signed certificate with OpenSSL

    Ok.

    下面的命令和配置文件创建自签名证书(它还向您展示了如何创建签名请求)。它们与其他答案在一个方面有所不同:用于自签名证书的DNS名称位于使用者备用名称(SAN)中,而不是通用名称(CN)。好的。

    DNS名称通过配置文件和行subjectAltName = @alternate_names放置在SAN中(无法通过命令行执行)。然后在配置文件中有一个alternate_names部分(您应该对此进行调优以适应您的口味):好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    [ alternate_names ]

    DNS.1       = example.com
    DNS.2       = www.example.com
    DNS.3       = mail.example.com
    DNS.4       = ftp.example.com

    # Add these if you need them. But usually you don't want them or
    #   need them in production. You may need them for development.
    # DNS.5       = localhost
    # DNS.6       = localhost.localdomain
    # DNS.7       = 127.0.0.1

    # IPv6 localhost
    # DNS.8     = ::1

    将DNS名称放在SAN而不是CN中很重要,因为IETF和CA/BROWSER论坛都指定了这种做法。它们还指定不推荐使用CN中的DNS名称(但不禁止使用)。如果您将DNS名称放在CN中,那么它必须包含在CA/B策略下的SAN中。因此,您不能避免使用主题备用名称。好的。

    如果您不在SAN中输入DNS名称,那么在遵循CA/BROWSER论坛指南的浏览器和其他用户代理下,证书将无法验证。好的。

    相关:浏览器遵循CA/BROWSER论坛策略,而不是IETF策略。这就是使用openssl(通常遵循ietf)创建的证书有时不能在浏览器下验证(浏览器遵循ca/b)的原因之一。它们是不同的标准,有不同的发布策略和不同的验证要求。好的。

    创建自签名证书(注意添加-x509选项):好的。

    1
    2
    openssl req -config example-com.conf -new -x509 -sha256 -newkey rsa:2048 -nodes \
        -keyout example-com.key.pem -days 365 -out example-com.cert.pem

    创建签名请求(注意缺少-x509选项):好的。

    1
    2
    openssl req -config example-com.conf -new -sha256 -newkey rsa:2048 -nodes \
        -keyout example-com.key.pem -days 365 -out example-com.req.pem

    打印自签名证书:好的。

    1
    openssl x509 -in example-com.cert.pem -text -noout

    打印签名请求:好的。

    1
    openssl req -in example-com.req.pem -text -noout

    配置文件(通过-config选项传递)好的。

    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
    [ req ]
    default_bits        = 2048
    default_keyfile     = server-key.pem
    distinguished_name  = subject
    req_extensions      = req_ext
    x509_extensions     = x509_ext
    string_mask         = utf8only

    # The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
    #   Its sort of a mashup. For example, RFC 4514 does not provide emailAddress.
    [ subject ]
    countryName         = Country Name (2 letter code)
    countryName_default     = US

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

    localityName            = Locality Name (eg, city)
    localityName_default        = New York

    organizationName         = Organization Name (eg, company)
    organizationName_default    = Example, LLC

    # Use a friendly name here because it's presented to the user. The server's DNS
    #   names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
    #   by both IETF and CA/Browser Forums. If you place a DNS name here, then you
    #   must include the DNS name in the SAN too (otherwise, Chrome and others that
    #   strictly follow the CA/Browser Baseline Requirements will fail).
    commonName          = Common Name (e.g. server FQDN or YOUR name)
    commonName_default      = Example Company

    emailAddress            = Email Address
    emailAddress_default        = [email protected]

    # Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
    [ x509_ext ]

    subjectKeyIdentifier        = hash
    authorityKeyIdentifier    = keyid,issuer

    # You only need digitalSignature below. *If* you don't allow
    #   RSA Key transport (i.e., you use ephemeral cipher suites), then
    #   omit keyEncipherment because that's key transport.
    basicConstraints        = CA:FALSE
    keyUsage            = digitalSignature, keyEncipherment
    subjectAltName          = @alternate_names
    nsComment           ="OpenSSL Generated Certificate"

    # RFC 5280, Section 4.2.1.12 makes EKU optional
    #   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
    #   In either case, you probably only need serverAuth.
    # extendedKeyUsage    = serverAuth, clientAuth

    # Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
    [ req_ext ]

    subjectKeyIdentifier        = hash

    basicConstraints        = CA:FALSE
    keyUsage            = digitalSignature, keyEncipherment
    subjectAltName          = @alternate_names
    nsComment           ="OpenSSL Generated Certificate"

    # RFC 5280, Section 4.2.1.12 makes EKU optional
    #   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
    #   In either case, you probably only need serverAuth.
    # extendedKeyUsage    = serverAuth, clientAuth

    [ alternate_names ]

    DNS.1       = example.com
    DNS.2       = www.example.com
    DNS.3       = mail.example.com
    DNS.4       = ftp.example.com

    # Add these if you need them. But usually you don't want them or
    #   need them in production. You may need them for development.
    # DNS.5       = localhost
    # DNS.6       = localhost.localdomain
    # DNS.7       = 127.0.0.1

    # IPv6 localhost
    # DNS.8     = ::1

    您可能需要对chrome执行以下操作。否则chrome可能会抱怨公用名无效(ERR_CERT_COMMON_NAME_INVALID)。我不知道在这个实例中,SAN中的IP地址和CN之间的关系是什么。好的。

    1
    2
    3
    4
    5
    # IPv4 localhost
    # IP.1       = 127.0.0.1

    # IPv6 localhost
    # IP.2     = ::1

    在X.509/pkix证书中还有其他有关处理DNS名称的规则。有关规则,请参阅这些文件:好的。

    • RFC 5280,Internet X.509公钥基础结构证书和证书吊销列表(CRL)配置文件
    • RFC 6125,在传输层安全(TLS)上下文中使用X.509(pkix)证书在Internet公钥基础设施中表示和验证基于域的应用程序服务标识
    • RFC 6797,附录A,HTTP严格传输安全(HSTS)
    • RFC 7469,HTTP的公钥固定扩展
    • CA/浏览器论坛基线要求
    • CA/浏览器论坛扩展验证指南

    列出了RFC 6797和RFC 7469,因为它们比其他RFC和CA/B文档更具限制性。RFC6797和7469也不允许IP地址。好的。好啊。


    以下是@diegows's answer中描述的选项,在文档中更详细地描述了这些选项:

    1
    openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days XXX
    1
    req

    PKCS#10 certificate request and certificate generating utility.

    1
    -x509

    this option outputs a self signed certificate instead of a certificate request.
    This is typically used to generate a test certificate or a self signed root CA.

    1
    -newkey arg

    this option creates a new certificate request and a new private key. The argument
    takes one of several forms. rsa:nbits, where nbits is the number of bits,
    generates an RSA key nbits in size.

    1
    -keyout filename

    this gives the filename to write the newly created private key to.

    1
    -out filename

    This specifies the output filename to write to or standard output by default.

    1
    -days n

    when the -x509 option is being used this specifies the number of days to certify
    the certificate for. The default is 30 days.

    1
    -nodes

    if this option is specified then if a private key is created it will not be encrypted.

    文档实际上比上面更详细;我只是在这里总结一下。


    截至2019年,以下命令可满足您的所有需求,包括SAN:

    1
    openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout example.key -out example.crt -extensions san -config <(echo"[req]"; echo distinguished_name=req; echo"[san]"; echo subjectAltName=DNS:example.com,DNS:example.net,IP:10.0.0.1) -subj /CN=example.com

    在openssl≥1.1.1中,可以缩短为:

    1
    openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout example.key -out example.crt -subj /CN=example.com -addext subjectAltName=DNS:example.com,DNS:example.net,IP:10.0.0.1

    它创建的证书

    • example.comexample.net域有效,
    • 也适用于IP地址10.0.0.1(SAN),
    • 相对强劲(截至2019年),以及
    • 有效期为3650天(~10年)。

    它创建以下文件:

    • 私钥:example.key
    • 证书:example.crt

    所有信息都在命令行中提供。没有烦人的交互输入。配置文件没有乱七八糟的地方。所有必要的步骤都由这个OpenSSL调用执行:从私钥生成到自签名证书。

    备注1:加密参数

    由于证书是自签名的,需要由用户手动接受,因此使用短到期或弱加密是没有意义的。

    将来,您可能希望对rsa密钥使用多于4096位的值,以及比sha256更强的哈希算法,但到2019年,这些值是正常的。它们足够强大,同时受到所有现代浏览器的支持。

    备注2:参数"-nodes"

    理论上,您可以省略-nodes参数(意思是"no des encryption"),在这种情况下,example.key将使用密码加密。但是,对于服务器安装来说,这几乎从来没有用过,因为您要么必须在服务器上存储密码,要么必须在每次重新启动时手动输入密码。

    备注3:Mingw

    在mingw bash的windows上,应该在命令前面加上MSYS_NO_PATHCONV=1

    1
    MSYS_NO_PATHCONV=1 openssl ...

    或者,在普通的cmd.exewindows命令提示符中运行该命令。

    备注4:另见

    • 直接在命令行上向openssl提供subjectAltname
    • 如何通过命令行向SSL证书添加多个电子邮件地址?
    • 有关msys_no_pathconv的详细信息


    我无法评论,所以我将把这作为一个单独的答案。我发现接受的一行回答有一些问题:

    • 一行程序在密钥中包含一个密码短语。
    • 一行程序使用sha-1,在许多浏览器中,它在控制台中抛出警告。

    下面是一个简化的版本,它删除了密码短语,提高了安全性以禁止警告,并在注释中包含了一个建议以传入-subj以删除完整的问题列表:

    1
    2
    3
    4
    openssl genrsa -out server.key 2048
    openssl rsa -in server.key -out server.key
    openssl req -sha256 -new -key server.key -out server.csr -subj '/CN=localhost'
    openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt

    将"localhost"替换为所需的任何域。您将需要逐个运行前两个命令,因为OpenSSL将提示输入密码短语。

    要将两者合并为.pem文件,请执行以下操作:

    1
    cat server.crt server.key > cert.pem


    现代浏览器现在对格式良好的自签名证书抛出一个安全错误,如果它们缺少SAN(使用者备用名称)。OpenSSL不提供命令行方式来指定这一点,因此许多开发人员的教程和书签突然过时了。

    重新运行的最快方法是使用一个简短的、独立的conf文件:

  • 创建openssl配置文件(示例:req.cnf)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    [req]
    distinguished_name = req_distinguished_name
    x509_extensions = v3_req
    prompt = no
    [req_distinguished_name]
    C = US
    ST = VA
    L = SomeCity
    O = MyCompany
    OU = MyDivision
    CN = www.company.com
    [v3_req]
    keyUsage = critical, digitalSignature, keyAgreement
    extendedKeyUsage = serverAuth
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = www.company.com
    DNS.2 = company.com
    DNS.3 = company.net
  • 创建引用此配置文件的证书

    1
    2
    openssl req -x509 -nodes -days 730 -newkey rsa:2048 \
     -keyout cert.key -out cert.pem -config req.cnf -sha256
  • https://support.citrix.com/article/ctx135602中的配置示例


    我建议添加-sha256参数以使用sha-2哈希算法,因为主要浏览器正在考虑将"sha-1证书"显示为不安全。

    接受答案的同一命令行-@diegows添加了-sha256

    openssl req -x509 -sha256 -newkey rsa:2048 -keyout key.pem -out cert.pem -days XXX

    谷歌安全博客中的更多信息。

    更新日期:2018年5月。正如评论中提到的那样,使用SHA-2不会给自签名证书添加任何安全性。但我仍然建议将它作为一个好习惯,不要使用过时的/不安全的加密散列函数。完整的解释是,为什么最终实体证书以上的证书可以基于SHA-1?.


    这是我在本地框中使用的脚本,用于在自签名证书中设置SAN(SubjectAltname)。

    此脚本采用域名(example.com),并在同一证书中为*.example.com和example.com生成SAN。下面的部分是注释。命名脚本(例如generate-ssl.sh)并授予它可执行权限。这些文件将写入与脚本相同的目录。

    Chrome58以后需要在自签名证书中设置SAN。

    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
    #!/usr/bin/env bash

    # Set the TLD domain we want to use
    BASE_DOMAIN="example.com"

    # Days for the cert to live
    DAYS=1095

    # A blank passphrase
    PASSPHRASE=""

    # Generated configuration file
    CONFIG_FILE="config.txt"

    cat > $CONFIG_FILE <<-EOF
    [req]
    default_bits = 2048
    prompt = no
    default_md = sha256
    x509_extensions = v3_req
    distinguished_name = dn

    [dn]
    C = CA
    ST = BC
    L = Vancouver
    O = Example Corp
    OU = Testing Domain
    emailAddress = webmaster@$BASE_DOMAIN
    CN = $BASE_DOMAIN

    [v3_req]
    subjectAltName = @alt_names

    [alt_names]
    DNS.1 = *.$BASE_DOMAIN
    DNS.2 = $BASE_DOMAIN
    EOF

    # The file name can be anything
    FILE_NAME="$BASE_DOMAIN"

    # Remove previous keys
    echo"Removing existing certs like $FILE_NAME.*"
    chmod 770 $FILE_NAME.*
    rm $FILE_NAME.*

    echo"Generating certs for $BASE_DOMAIN"

    # Generate our Private Key, CSR and Certificate
    # Use SHA-2 as SHA-1 is unsupported from Jan 1, 2017

    openssl req -new -x509 -newkey rsa:2048 -sha256 -nodes -keyout"$FILE_NAME.key" -days $DAYS -out"$FILE_NAME.crt" -passin pass:$PASSPHRASE -config"$CONFIG_FILE"

    # OPTIONAL - write an info to see the details of the generated crt
    openssl x509 -noout -fingerprint -text <"$FILE_NAME.crt">"$FILE_NAME.info"

    # Protect the key
    chmod 400"$FILE_NAME.key"

    此脚本还写入信息文件,因此您可以检查新证书并验证SAN设置是否正确。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
                    ...
                    28:dd:b8:1e:34:b5:b1:44:1a:60:6d:e3:3c:5a:c4:
                    da:3d
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:*.example.com, DNS:example.com
    Signature Algorithm: sha256WithRSAEncryption
         3b:35:5a:d6:9e:92:4f:fc:f4:f4:87:78:cd:c7:8d:cd:8c:cc:
         ...

    如果您使用的是Apache,那么可以在配置文件中引用上述证书,如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <VirtualHost _default_:443>
        ServerName example.com
        ServerAlias www.example.com
        DocumentRoot /var/www/htdocs

        SSLEngine on
        SSLCertificateFile path/to/your/example.com.crt
        SSLCertificateKeyFile path/to/your/example.com.key
    </VirtualHost>

    记住重新启动Apache(或nginx或iis)服务器,新证书才能生效。


    2017一班轮:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    openssl req \
    -newkey rsa:2048 \
    -x509 \
    -nodes \
    -keyout server.pem \
    -new \
    -out server.pem \
    -subj /CN=localhost \
    -reqexts SAN \
    -extensions SAN \
    -config <(cat /System/Library/OpenSSL/openssl.cnf \
        <(printf '[SAN]
    subjectAltName=DNS:localhost')) \
    -sha256 \
    -days 3650

    这也适用于Chrome57,因为它提供了SAN,而不需要另一个配置文件。这是从这里的一个答案中提取的。

    这将创建一个同时包含私钥和证书的.pem文件。如果需要,可以将它们移动到单独的.pem文件中。


    一班轮FTW。我喜欢保持简单。为什么不使用一个包含所有所需参数的命令呢?这就是我喜欢它的方式-这将创建一个X509证书及其PEM密钥:

    1
    2
    3
    4
    5
    openssl req -x509 \
     -nodes -days 365 -newkey rsa:4096 \
     -keyout self.key.pem \
     -out self-x509.crt \
     -subj"/C=US/ST=WA/L=Seattle/CN=example.com/[email protected]"

    这个命令包含了您通常为证书详细信息提供的所有答案。通过这种方式,您可以设置参数并运行命令,获取输出—然后喝咖啡。

    >此处更多


    你的一般程序是正确的。命令的语法如下。

    1
    openssl req -new -key {private key file} -out {output file}

    但是,将显示警告,因为浏览器无法通过使用已知证书颁发机构(CA)验证证书来验证标识。

    由于这是一个自签名证书,因此没有CA,您可以安全地忽略该警告并继续。如果你想得到一个真实的证书,可以被任何人在公共互联网上识别,那么程序如下。

  • 生成私钥
  • 使用该私钥创建CSR文件
  • 向CA提交CSR(Verisign或其他等)
  • 在Web服务器上安装从CA收到的证书
  • 根据类型cert将其他证书添加到身份验证链
  • 我在一篇关于保护连接的文章中对此有了更多的详细信息:使用openssl创建安全证书


    一个内衬版本2017:

    CentOS:

    1
    2
    3
    4
    5
    6
    7
    8
    openssl req -x509 -nodes -sha256 -newkey rsa:2048 \
    -keyout localhost.key -out localhost.crt \
    -days 3650 \
    -subj"CN=localhost" \
    -reqexts SAN -extensions SAN \
    -config <(cat /etc/pki/tls/openssl.cnf <(printf"
    [SAN]
    subjectAltName=IP:127.0.0.1,DNS:localhost"))

    Ubuntu:

    1
    2
    3
    4
    5
    6
    7
    8
    openssl req -x509 -nodes -sha256 -newkey rsa:2048 \
    -keyout localhost.key -out localhost.crt \
    -days 3650 \
    -subj"CN=localhost" \
    -reqexts SAN -extensions SAN \
    -config <(cat /etc/ssl/openssl.cnf <(printf"
    [SAN]
    subjectAltName=IP:127.0.0.1,DNS:localhost"))

    Generate keys

    I am using /etc/mysql for cert storage because /etc/apparmor.d/usr.sbin.mysqld contains /etc/mysql/*.pem r.

    1
    2
    3
    4
    5
    6
    7
    8
    sudo su -
    cd /etc/mysql
    openssl genrsa -out ca-key.pem 2048;
    openssl req -new -x509 -nodes -days 1000 -key ca-key.pem -out ca-cert.pem;
    openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server-key.pem -out server-req.pem;
    openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem;
    openssl req -newkey rsa:2048 -days 1000 -nodes -keyout client-key.pem -out client-req.pem;
    openssl x509 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem;

    Add configuration

    /etc/mysql/my.cnf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [client]
    ssl-ca=/etc/mysql/ca-cert.pem
    ssl-cert=/etc/mysql/client-cert.pem
    ssl-key=/etc/mysql/client-key.pem

    [mysqld]
    ssl-ca=/etc/mysql/ca-cert.pem
    ssl-cert=/etc/mysql/server-cert.pem
    ssl-key=/etc/mysql/server-key.pem

    在我的设置中,Ubuntu服务器登录到:/var/log/mysql/error.log

    后续注意事项:

    • SSL error: Unable to get certificate from '...'

      如果您的证书文件不在Apparmors配置中,则可能会拒绝MySQL对它的读取访问。如前步骤^所述,将我们的所有证书保存为默认由Apparmor批准的/etc/mysql/目录中的.pem文件(或修改您的apparmor/selinux以允许访问存储它们的任何位置)。

    • SSL error: Unable to get private key

      您的MySQL服务器版本可能不支持默认的rsa:2048格式。

      将生成的rsa:2048转换为普通rsa,使用:

      1
      2
      openssl rsa -in server-key.pem -out server-key.pem
      openssl rsa -in client-key.pem -out client-key.pem
    • 检查本地服务器是否支持SSL:


      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      mysql -u root -p
      mysql> show variables like"%ssl%";
      +---------------+----------------------------+
      | Variable_name | Value                      |
      +---------------+----------------------------+
      | have_openssl  | YES                        |
      | have_ssl      | YES                        |
      | ssl_ca        | /etc/mysql/ca-cert.pem     |
      | ssl_capath    |                            |
      | ssl_cert      | /etc/mysql/server-cert.pem |
      | ssl_cipher    |                            |
      | ssl_key       | /etc/mysql/server-key.pem  |
      +---------------+----------------------------+
    • 验证与数据库的连接是否经过SSL加密:


      Verifying connection

      When logged in to the MySQL instance, you can issue the query:

      1
      show status like 'Ssl_cipher';

      If your connection is not encrypted, the result will be blank:

      1
      2
      3
      4
      5
      6
      7
      mysql> show status like 'Ssl_cipher';
      +---------------+-------+
      | Variable_name | Value |
      +---------------+-------+
      | Ssl_cipher    |       |
      +---------------+-------+
      1 row in set (0.00 sec)

      Otherwise, it would show a non-zero length string for the cypher in use:

      1
      2
      3
      4
      5
      6
      7
      mysql> show status like 'Ssl_cipher';
      +---------------+--------------------+
      | Variable_name | Value              |
      +---------------+--------------------+
      | Ssl_cipher    | DHE-RSA-AES256-SHA |
      +---------------+--------------------+
      1 row in set (0.00 sec)
    • 特定用户连接需要SSL("需要SSL"):


      • SSL

      Tells the server to permit only SSL-encrypted connections for the account.

      1
      2
      GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
        REQUIRE SSL;

      To connect, the client must specify the --ssl-ca option to authenticate the server certificate, and may additionally specify the --ssl-key and --ssl-cert options. If neither --ssl-ca option nor --ssl-capath option is specified, the client does not authenticate the server certificate.

    备用链接:关于使用ssl连接mysql的安全php的冗长教程。


    正如已经详细讨论过的,自签名证书不受Internet信任。您可以将自签名证书添加到许多浏览器,但不能添加到所有浏览器。或者,您可以成为自己的证书颁发机构。

    不想从证书颁发机构获得签名证书的主要原因是成本——赛门铁克对证书每年收取995-1999美元之间的费用——仅对于用于内部网络的证书,赛门铁克每年收取399美元。如果你是在处理信用卡付款或是在一家高利润公司的利润中心工作,那么这种成本是很容易证明的。对于一个在互联网上创建的个人项目,或者一个以最低预算运行的非营利性项目,或者如果一个在一个组织的成本中心工作,成本中心总是试图用更少的钱做更多的事情,这是很多人负担不起的。

    另一种选择是使用certbot(请参阅关于certbot)。certbot是一个易于使用的自动客户端,用于获取和部署Web服务器的SSL/TLS证书。

    如果设置了certbot,则可以使其为您创建和维护由let's encrypt证书颁发机构颁发的证书。

    这个周末我为我的组织做了这个。我在服务器(Ubuntu 16.04)上安装了certbot所需的包,然后运行了安装和启用certbot所需的命令。有人可能需要一个用于certbot的DNS插件-我们目前正在使用DigitalOcean,但可能很快就会迁移到另一个服务。

    请注意,有些指示不太正确,需要用谷歌的一些小戳和时间来弄清楚。这是我第一次花了不少时间,但现在我想我可以在几分钟内完成。

    对于DigitalOcean,我遇到的一个难题是,我被提示输入DigitalOcean凭证ini文件的路径。脚本所指的是应用程序和API页以及该页上的标记/键选项卡。您需要为DigitalOcean的API拥有或生成一个个人访问令牌(读写)——这是一个65个字符的十六进制字符串。然后需要将此字符串放入运行certbot的Web服务器上的文件中。该文件的第一行可以是注释(注释以开头)。第二条线是:

    1
    dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff

    一旦我了解了如何为DigitalOcean的API设置读写令牌,使用certbot设置通配符证书就非常容易了。请注意,不必设置通配符证书,您可以指定希望证书应用到的每个域和子域。通配符证书需要包含DigitalOcean个人访问令牌的凭证ini文件。

    请注意,公钥证书(也称为身份证书或SSL证书)将过期并需要续订。因此,您需要定期(重复)更新您的证书。certbot文档包括更新证书。

    我的计划是编写一个脚本,使用openssl命令获取证书的到期日期,并在证书到期30天或30天以下时触发续订。然后我将把这个脚本添加到cron并每天运行一次。

    下面是读取证书到期日期的命令:

    1
    2
    root@prod-host:~# /usr/bin/openssl x509 -enddate -noout -in path-to-certificate-pem-file
    notAfter=May 25 19:24:12 2019 GMT

    这里提供了使用openssl的rsa和ecdsa的自签名证书和证书链创建脚本。