MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

HTTPS证书的申请、配置与验证流程

2022-05-133.1k 阅读

HTTPS 证书的申请

证书颁发机构(CA)的选择

在申请 HTTPS 证书之前,首先要选择一个合适的证书颁发机构(Certificate Authority,CA)。CA 是一个受信任的实体,负责验证网站所有者的身份,并颁发数字证书。常见的 CA 有 Let's Encrypt、Comodo、Symantec(现名为 DigiCert)、GlobalSign 等。

  • Let's Encrypt:这是一个非营利性的 CA,提供免费的 HTTPS 证书,适合个人网站和小型企业使用。其优点是成本低,且通过自动化的流程可以方便快捷地获取证书。但免费证书的有效期较短,通常为 90 天,需要定期续签。
  • 商业 CA:如 Comodo、Symantec 等,提供不同等级的证书,包括域名验证(Domain Validation,DV)证书、组织验证(Organization Validation,OV)证书和扩展验证(Extended Validation,EV)证书。商业 CA 的证书价格相对较高,但具有更高的信任度,有效期一般为 1 - 3 年。例如,EV 证书在浏览器地址栏会显示企业名称并以绿色高亮显示,增强用户对网站安全性的信心。

Let's Encrypt 证书申请流程

以 Let's Encrypt 为例,介绍证书的申请步骤。Let's Encrypt 支持多种方式获取证书,这里以 Certbot 工具为例,Certbot 是 Let's Encrypt 官方推荐的客户端,支持多种操作系统和 Web 服务器。

  1. 安装 Certbot
    • 在 Ubuntu 系统上
      sudo apt update
      sudo apt install certbot python3-certbot-nginx
      
    • 在 CentOS 系统上
      sudo yum install epel - release
      sudo yum install certbot python3-certbot - nginx
      
  2. 申请证书: 假设你的网站域名为 example.com,并且使用 Nginx 作为 Web 服务器。
    sudo certbot --nginx -d example.com -d www.example.com
    

上述命令中,--nginx 选项表示 Certbot 会自动检测并配置 Nginx 服务器,-d 选项用于指定要申请证书的域名,可以指定多个域名。运行该命令后,Certbot 会引导你完成一些配置步骤,例如输入邮箱地址(用于接收证书过期提醒等信息),同意服务条款等。

  1. 证书获取: 如果一切顺利,Certbot 会成功获取证书,并自动配置 Nginx 服务器使用该证书。证书文件通常会保存在 /etc/letsencrypt/live/example.com/ 目录下,包含 cert.pem(证书文件)、privkey.pem(私钥文件)和 chain.pem(证书链文件)等。

商业 CA 证书申请流程

商业 CA 的证书申请流程相对复杂一些,一般需要以下步骤:

  1. 准备资料

    • 对于 DV 证书,通常只需要提供域名信息和有效的邮箱地址。
    • 对于 OV 和 EV 证书,除了域名信息外,还需要提供企业的相关证明文件,如营业执照副本、法人身份证明等,以验证企业的真实性和合法性。
  2. 提交申请: 访问所选商业 CA 的官方网站,按照其指引填写申请表格,上传相关资料。在填写申请表格时,需要准确填写域名、组织名称、联系人信息等内容。

  3. 验证身份: CA 会对提交的资料进行审核和身份验证。对于 DV 证书,一般通过发送验证邮件到域名的 WHOIS 信息中的邮箱地址,或者在网站根目录放置特定文件等方式进行验证。对于 OV 和 EV 证书,CA 可能会通过电话、邮件等方式与企业相关人员进行沟通,核实企业信息。

  4. 支付费用: 审核通过后,根据所选证书类型和有效期,在 CA 网站上完成费用支付。支付方式通常包括信用卡、PayPal 等。

  5. 获取证书: 支付完成后,CA 会颁发证书。你可以在 CA 网站的用户账户中下载证书文件,通常会包含证书文件(.crt.cer 格式)、私钥文件(.key 格式)和证书链文件(.p7b.pem 格式等)。

HTTPS 证书的配置

在 Nginx 中配置 HTTPS 证书

  1. 找到 Nginx 配置文件: 在大多数 Linux 系统中,Nginx 的主配置文件位于 /etc/nginx/nginx.conf,而虚拟主机的配置文件通常在 /etc/nginx/sites - available/ 目录下。假设你的虚拟主机配置文件为 /etc/nginx/sites - available/example.com

  2. 编辑虚拟主机配置文件: 添加或修改以下内容,配置 HTTPS 服务器块:

    server {
        listen 443 ssl;
        server_name example.com www.example.com;
    
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;
    
        location / {
            # 网站根目录和其他配置
            root /var/www/html/example.com;
            index index.html index.php;
            try_files $uri $uri/ =404;
        }
    }
    
    • listen 443 ssl:表示监听 443 端口,并启用 SSL/TLS 协议。
    • server_name:指定服务器的域名。
    • ssl_certificate:指定证书文件路径,对于 Let's Encrypt 证书,fullchain.pem 包含了证书和证书链。
    • ssl_certificate_key:指定私钥文件路径。
    • ssl_protocols:指定允许使用的 SSL/TLS 协议版本,TLSv1.2 和 TLSv1.3 是目前较为安全的版本。
    • ssl_ciphers:指定允许使用的加密套件,这里配置为只使用高强度加密套件,排除不安全的加密方式。
  3. 启用虚拟主机配置: 如果虚拟主机配置文件在 /etc/nginx/sites - available/ 目录下,需要在 /etc/nginx/sites - enabled/ 目录下创建一个符号链接:

    sudo ln -s /etc/nginx/sites - available/example.com /etc/nginx/sites - enabled/
    
  4. 检查配置并重启 Nginx

    sudo nginx -t
    sudo systemctl restart nginx
    

    nginx -t 命令用于检查 Nginx 配置文件是否有语法错误。如果没有错误,重启 Nginx 服务使配置生效。

在 Apache 中配置 HTTPS 证书

  1. 找到 Apache 配置文件: 在大多数 Linux 系统中,Apache 的主配置文件为 /etc/httpd/conf/httpd.conf,虚拟主机的配置文件通常在 /etc/httpd/conf.d/ 目录下。假设你的虚拟主机配置文件为 /etc/httpd/conf.d/example.com.conf

  2. 编辑虚拟主机配置文件: 添加或修改以下内容,配置 HTTPS 虚拟主机:

    <VirtualHost *:443>
        ServerName example.com
        ServerAlias www.example.com
    
        DocumentRoot /var/www/html/example.com
        ErrorLog /var/log/httpd/example.com - error.log
        CustomLog /var/log/httpd/example.com - access.log combined
    
        SSLEngine on
        SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
        SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
    
        <FilesMatch "\.(cgi|shtml|phtml|php)$">
            SSLOptions +StdEnvVars
        </FilesMatch>
        <Directory /var/www/cgi - bin>
            SSLOptions +StdEnvVars
        </Directory>
    </VirtualHost>
    
    • ServerNameServerAlias:指定服务器的域名。
    • DocumentRoot:指定网站根目录。
    • SSLEngine on:启用 SSL 引擎。
    • SSLCertificateFile:指定证书文件路径。
    • SSLCertificateKeyFile:指定私钥文件路径。
    • SSLCertificateChainFile:指定证书链文件路径。
  3. 检查配置并重启 Apache

    sudo httpd -t
    sudo systemctl restart httpd
    

    httpd -t 命令用于检查 Apache 配置文件是否有语法错误。如果没有错误,重启 Apache 服务使配置生效。

在 Tomcat 中配置 HTTPS 证书

  1. 生成密钥库: 如果你的证书是由商业 CA 颁发的,通常会收到一个 .pfx.p12 格式的文件。可以使用以下命令将其转换为 Java 密钥库(.jks)格式:
    keytool -importkeystore -srckeystore example.pfx -srcstoretype PKCS12 -destkeystore example.jks -deststoretype JKS
    

如果是 Let's Encrypt 证书,需要先将 cert.pemprivkey.pemchain.pem 合并为一个文件,例如 combined.pem,然后使用以下命令生成密钥库:

openssl pkcs12 -export -in combined.pem -out example.p12 -name tomcat -CAfile chain.pem -caname root
keytool -importkeystore -srckeystore example.p12 -srcstoretype PKCS12 -destkeystore example.jks -deststoretype JKS
  1. 配置 Tomcat: 编辑 Tomcat 的 server.xml 文件,通常位于 $CATALINA_HOME/conf/ 目录下,添加或修改以下内容:

    <Connector
        protocol="org.apache.coyote.http11.Http11NioProtocol"
        port="8443" maxThreads="200"
        scheme="https" secure="true" SSLEnabled="true">
        <SSLHostConfig>
            <Certificate
                certificateFile="conf/localhost.crt"
                certificateKeyFile="conf/localhost.key"
                type="RSA" />
        </SSLHostConfig>
    </Connector>
    
    • port:指定 HTTPS 监听端口,默认为 8443。
    • schemesecure:设置为 httpstrue,表示启用 HTTPS。
    • SSLEnabled:启用 SSL。
    • certificateFilecertificateKeyFile:指定证书文件和私钥文件路径。如果使用的是密钥库,则需要修改为:
    <Connector
        protocol="org.apache.coyote.http11.Http11NioProtocol"
        port="8443" maxThreads="200"
        scheme="https" secure="true" SSLEnabled="true"
        keystoreFile="conf/your - keystore.jks"
        keystorePass="your - keystore - password"
        type="RSA" />
    
    • keystoreFile:指定密钥库文件路径。
    • keystorePass:指定密钥库密码。
  2. 重启 Tomcat: 在 $CATALINA_HOME/bin/ 目录下执行以下命令:

    sudo./shutdown.sh
    sudo./startup.sh
    

HTTPS 证书的验证

浏览器验证

最简单的验证方法是在浏览器中访问配置了 HTTPS 的网站。在现代浏览器中,如果证书配置正确且有效,地址栏会显示一个安全锁图标,点击该图标可以查看证书的详细信息,包括颁发机构、有效期、证书所有者等。

如果证书存在问题,浏览器会显示警告信息,例如:

  • 证书过期:提示证书已过期,用户访问网站时会看到明显的警告,因为过期的证书无法保证通信的安全性。
  • 证书不受信任:可能是由于使用了不受信任的 CA 颁发的证书,或者证书链不完整。这种情况下,浏览器可能会阻止用户访问,或者提示用户是否继续访问,存在一定的安全风险。

使用 OpenSSL 命令行工具验证

  1. 验证证书有效期: 可以使用以下命令查看证书的有效期:
    openssl x509 -noout -dates -in /path/to/cert.pem
    

例如,对于 Let's Encrypt 证书:

openssl x509 -noout -dates -in /etc/letsencrypt/live/example.com/cert.pem

输出结果类似:

notBefore=Sep 15 10:20:40 2023 GMT
notAfter=Dec 14 10:20:40 2023 GMT

这表明证书的生效时间为 2023 年 9 月 15 日 10:20:40,过期时间为 2023 年 12 月 14 日 10:20:40。

  1. 验证证书链: 使用以下命令验证证书链的完整性:
    openssl verify -CAfile /path/to/ca - bundle.pem /path/to/cert.pem
    

对于 Let's Encrypt 证书,可以使用其提供的证书链文件:

openssl verify -CAfile /etc/letsencrypt/archive/example.com/chain1.pem /etc/letsencrypt/live/example.com/cert.pem

如果证书链验证通过,会输出 cert.pem: OK;如果验证失败,会显示相应的错误信息,如 error 20 at 0 depth lookup:unable to get local issuer certificate,表示无法找到本地颁发者证书,可能是证书链不完整。

  1. 验证证书与域名的匹配: 可以通过解析证书中的 Subject Alternative Name(SAN)字段来验证证书是否与域名匹配。使用以下命令:
    openssl x509 -noout -text -in /path/to/cert.pem | grep -A 1 'Subject Alternative Name'
    

例如:

openssl x509 -noout -text -in /etc/letsencrypt/live/example.com/cert.pem | grep -A 1 'Subject Alternative Name'

输出结果可能如下:

X509v3 Subject Alternative Name:
    DNS:example.com, DNS:www.example.com

这表明证书的 SAN 字段包含了 example.comwww.example.com,与配置的域名相匹配。如果域名不在 SAN 字段中,证书与域名不匹配,可能导致浏览器警告。

编写代码验证证书

以 Python 为例,可以使用 ssl 模块来验证证书。以下是一个简单的示例:

import socket
import ssl


def verify_certificate(host, port):
    context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
    context.verify_mode = ssl.CERT_REQUIRED
    context.load_verify_locations('/path/to/ca - bundle.pem')

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.connect((host, port))
        with context.wrap_socket(sock, server_hostname = host) as ssl_sock:
            try:
                cert = ssl_sock.getpeercert()
                print('Certificate details:')
                for key, value in cert.items():
                    print(f'{key}: {value}')
                print('Certificate verification successful.')
            except ssl.SSLError as e:
                print(f'Certificate verification failed: {e}')


if __name__ == '__main__':
    verify_certificate('example.com', 443)

在上述代码中:

  • context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2):创建一个 SSL 上下文,指定使用 TLSv1.2 协议。
  • context.verify_mode = ssl.CERT_REQUIRED:设置验证模式为必须验证证书。
  • context.load_verify_locations('/path/to/ca - bundle.pem'):加载 CA 证书链文件用于验证。
  • with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:创建一个 TCP 套接字。
  • with context.wrap_socket(sock, server_hostname = host):将套接字包装为 SSL 套接字,并指定服务器主机名。
  • cert = ssl_sock.getpeercert():获取服务器的证书。
  • 如果证书验证成功,打印证书详细信息并提示验证成功;如果验证失败,捕获 SSLError 并打印错误信息。

通过以上全面的申请、配置与验证流程,可以确保网站在 HTTPS 协议下安全可靠地运行,为用户提供加密的通信环境,保护用户数据和隐私。