Nginx 配置 HTTPS (SSL) 完整指南 – wiki基地


Nginx 配置 HTTPS (SSL) 完整指南

引言:迈入安全与信任的 HTTPS 世界

在当今互联网环境中,网站使用 HTTPS (Hypertext Transfer Protocol Secure) 而非传统的 HTTP 已经成为一种标准和必要。HTTPS 通过使用 SSL/TLS 协议对数据进行加密,确保用户与服务器之间的通信不被窃听、篡改,并验证网站的身份。这不仅提升了用户的数据安全和隐私,也增强了用户对网站的信任。此外,现代浏览器、搜索引擎(如 Google)也越来越倾向于支持和推广 HTTPS,将其作为网站排名的重要因素,甚至对未使用 HTTPS 的网站标记为“不安全”。

Nginx 作为一款高性能的 HTTP 和反向代理服务器,因其稳定、高效和灵活的特性而被广泛应用于各种规模的 Web 服务。本指南将详细、完整地介绍如何在 Nginx 服务器上配置 HTTPS (SSL),从获取 SSL 证书到优化安全设置,帮助您为网站启用加密连接。

准备工作:开始之前的必要条件

在着手配置 Nginx HTTPS 之前,请确保您具备以下条件:

  1. 一台运行 Nginx 的服务器: 通常是 Linux 系统(如 Ubuntu, CentOS, Debian)。确保您拥有服务器的 root 或 sudo 权限。
  2. 已安装并运行的 Nginx: 如果尚未安装,请根据您的操作系统类型进行安装。
  3. 一个域名: 您的网站需要一个已注册并指向您的服务器 IP 地址的域名。例如:your_domain.com
  4. 域名解析 (DNS): 您的域名记录(A 记录或 AAAA 记录)已正确指向您的服务器公网 IP 地址。
  5. 对 Nginx 配置文件的基本了解: 知道 Nginx 的主配置文件位置(通常是 /etc/nginx/nginx.conf)以及虚拟主机配置文件位置(如 /etc/nginx/sites-available//etc/nginx/sites-enabled/)。
  6. 防火墙设置: 确保服务器的防火墙已允许通过 443 端口(HTTPS 默认端口)。如果使用防火墙(如 UFW, firewalld),需要相应地开放端口。

第一步:获取 SSL 证书

SSL 证书是启用 HTTPS 的核心。它由证书颁发机构 (Certificate Authority, CA) 签发,用于证明网站的身份。获取 SSL 证书有多种途径:

1. 使用 Let’s Encrypt (推荐,免费自动化)

Let’s Encrypt 是一个免费、开放的自动化证书颁发机构,广受欢迎。通过 Certbot 工具,可以轻松地自动化获取和续订证书的过程。

  • 安装 Certbot: Certbot 官方网站 (certbot.eff.org) 提供了针对不同操作系统和 Web 服务器的详细安装指南。以 Ubuntu 为例:

    bash
    sudo apt update
    sudo apt install certbot python3-certbot-nginx

    CentOS/RHEL:

    bash
    sudo dnf install epel-release # 或 yum install epel-release
    sudo dnf install certbot python3-certbot-nginx # 或 yum install certbot python3-certbot-nginx

  • 获取证书: 使用 Certbot 的 Nginx 插件可以自动化完成证书申请、Nginx 配置修改(添加 HTTPS server block)以及证书续订。

    bash
    sudo certbot --nginx -d your_domain.com -d www.your_domain.com

    your_domain.comwww.your_domain.com 替换为您的实际域名。Certbot 会引导您完成邮箱注册、同意服务条款等步骤。如果一切顺利,Certbot 会自动修改您的 Nginx 配置文件,添加 HTTPS 配置,并提示您是否将所有 HTTP 请求重定向到 HTTPS。选择重定向是一个好习惯。

  • 证书续订: Let’s Encrypt 证书的有效期是 90 天。Certbot 安装时通常会自动设置一个定时任务(cron job 或 systemd timer)来定期检查并续订证书。您可以手动测试续订:

    bash
    sudo certbot renew --dry-run

    如果测试成功,自动续订通常就能正常工作。

2. 从商业 CA 购买证书

商业 CA (如 DigiCert, Sectigo, GoDaddy 等) 提供不同类型的证书(域名验证 DV, 组织验证 OV, 扩展验证 EV),价格和服务也各不相同。购买过程通常包括以下步骤:

  • 生成私钥 (Private Key): 在您的服务器上生成一个私钥文件。

    “`bash
    openssl genrsa -out your_domain.key 2048 # 生成 2048 位 RSA 私钥

    或者使用 4096 位: openssl genrsa -out your_domain.key 4096

    对于 ECDSA 私钥 (更现代): openssl ecparam -genkey -name prime256v1 -out your_domain.key

    “`

    请妥善保管这个私钥文件,这是证书安全的核心。不要与任何人分享。

  • 生成证书签名请求 (CSR): 使用私钥生成一个 CSR 文件。您需要输入一些信息,如国家、省份、城市、组织名称(可选)、组织单位名称(可选)以及最重要的通用名称 (Common Name)。通用名称必须是您要申请证书的域名(例如 your_domain.com*.your_domain.com 对于泛域名证书)。

    bash
    openssl req -new -key your_domain.key -out your_domain.csr

    系统会提示您输入详细信息。请确保 Common Name 填写正确。

  • 提交 CSR 给 CA: 将生成的 your_domain.csr 文件的内容复制,粘贴到您购买证书的 CA 网站的相应位置。

  • 完成域名验证 (DV): CA 需要验证您是否拥有或控制该域名。验证方法包括:
    • 文件验证:在您网站的特定目录下放置一个指定的文件。
    • DNS 验证:添加一个特定的 TXT 记录到您的域名 DNS 中。
    • 邮件验证:CA 发送验证邮件到域名的特定邮箱(如 admin@your_domain.com, webmaster@your_domain.com 等)。
  • 下载证书文件: 验证通过后,CA 会颁发证书。您通常会收到几个文件:

    • 您的域名证书 (your_domain.crt 或类似的名称)
    • 中间证书 (Intermediate Certificate) 或证书链文件 (Certificate Chain/Bundle)
    • 根证书 (Root Certificate) – 通常不需要单独配置,它包含在证书链中。
  • 合并证书链(如果需要): 有些 CA 会将您的域名证书和中间证书分开提供。为了让浏览器能够验证证书的完整链条直到受信任的根证书,您需要将它们合并到一个文件中。通常是将中间证书(可能不止一个)和您的域名证书按顺序合并,中间证书在您的域名证书之后。

    “`bash
    cat your_domain.crt intermediate_certificate.crt > your_domain_bundle.crt

    如果有多个中间证书,按 CA 提供的顺序合并:

    cat your_domain.crt intermediate1.crt intermediate2.crt > your_domain_bundle.crt

    “`

    最终用于 Nginx 配置的将是您的私钥文件 (your_domain.key) 和合并后的证书链文件 (your_domain_bundle.crt 或 CA 直接提供的 .pem 文件)。

3. 使用自签名证书 (仅限测试)

自签名证书是由您自己生成和签发的证书,而非由受信任的 CA 签发。由于没有 CA 的信任背书,浏览器访问使用自签名证书的网站时会发出安全警告。因此,自签名证书绝对不应该用于生产环境,仅适用于开发或内部测试。

  • 生成自签名证书和私钥:

    bash
    openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout selfsigned.key -out selfsigned.crt

    解释:
    * -x509: 输出 x509 格式的证书。
    * -nodes: 不使用密码保护私钥(方便测试,生产环境私钥通常会加密)。
    * -days 365: 证书有效期(天)。
    * -newkey rsa:2048: 生成一个新的 2048 位 RSA 私钥。
    * -keyout selfsigned.key: 私钥输出文件。
    * -out selfsigned.crt: 证书输出文件。
    * 您同样需要输入一些信息,Common Name 可以是域名或服务器 IP。

第二步:上传证书文件到服务器

无论通过哪种方式获取证书,您都需要将私钥文件 (.key) 和证书文件(.crt.pem 或合并后的 .bundle.crt)上传到您的服务器。

  • 选择存储位置: 建议将证书文件存放在一个安全、标准的位置,例如:

    • 证书文件 (.crt/.pem/.bundle.crt): /etc/ssl/certs/
    • 私钥文件 (.key): /etc/ssl/private/
  • 上传文件: 使用 scp 或其他安全文件传输工具将文件上传到服务器的上述目录。

  • 设置文件权限: 这是非常重要的一步,尤其是对于私钥文件。私钥文件只能被 root 用户或拥有 Nginx 进程权限的用户读取。

    bash
    sudo chown root:root /etc/ssl/private/your_domain.key
    sudo chmod 600 /etc/ssl/private/your_domain.key # 只有所有者有读写权限
    sudo chown root:root /etc/ssl/certs/your_domain_bundle.crt
    sudo chmod 644 /etc/ssl/certs/your_domain_bundle.crt # 所有者读写,组和其他用户只读

    确保 Nginx 进程用户(通常是 www-datanginx)能够读取证书文件(.crt/.pem),但不能读取私钥文件(.key)。chmod 600 for the key is a strong measure to ensure only root can read it, relying on Nginx running as root initially to read the key during startup, or configuring Nginx to run as a specific user that can read the key (less common for the key itself). The 600 permission for the private key is standard and safe.

第三步:配置 Nginx

现在,您可以修改 Nginx 配置文件来启用 HTTPS。

  • 找到配置文件: 您的网站配置可能在 /etc/nginx/nginx.confhttp 块内,或者更常见的是在 /etc/nginx/sites-available/ 目录下创建独立的配置文件,然后在 /etc/nginx/sites-enabled/ 创建符号链接启用它。例如,为您的域名创建一个文件 /etc/nginx/sites-available/your_domain.conf

  • 编辑配置文件: 打开您的网站配置文件进行编辑。

    bash
    sudo nano /etc/nginx/sites-available/your_domain.conf

  • 配置 HTTPS Server Block: 您需要创建一个监听 443 端口并启用 SSL 的 server 块。

    “`nginx
    server {
    listen 443 ssl http2; # 监听 443 端口,启用 SSL/TLS,并启用 HTTP/2 (推荐)
    listen [::]:443 ssl http2; # 监听 IPv6 地址的 443 端口

    server_name your_domain.com www.your_domain.com; # 替换为您的域名
    
    ssl_certificate /etc/ssl/certs/your_domain_bundle.crt; # 您的证书文件路径 (包含证书链)
    ssl_certificate_key /etc/ssl/private/your_domain.key; # 您的私钥文件路径
    
    # ===================== 安全和性能优化配置 =====================
    
    # 1. SSL/TLS 协议版本:禁用不安全的旧版本
    ssl_protocols TLSv1.2 TLSv1.3; # 推荐只启用 TLSv1.2 和 TLSv1.3
    
    # 2. SSL/TLS 加密套件 (Ciphers): 选择安全且高性能的加密套件
    # 使用 Mozilla SSL Configuration Generator (https://mozilla.github.io/server-side-tls/ssl-config-generator/)
    # 生成适合您的 Nginx 版本和 OpenSSL 版本的配置。以下是一个示例 (Intermediate compatibility):
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
    # 优先使用服务器端的加密套件顺序
    ssl_prefer_server_ciphers on;
    
    # 3. SSL 会话缓存: 提高性能,避免每次连接都进行完整握手
    ssl_session_cache shared:SSL:10m; # 10MB 缓存可以存储约 100,000 个会话
    ssl_session_timeout 10m; # 会话超时时间
    
    # 4. SSL 会话 ticket (可选): 关闭以增强前向保密性 (Forward Secrecy)
    # 需要 Nginx 1.5.9 或更高版本,且编译时禁用 session tickets
    # ssl_session_tickets off;
    
    # 5. OCSP Stapling: 提高性能和隐私,检查证书吊销状态
    # 需要在 nginx.conf 的 http 块或 server 块中配置 resolver
    # resolver 8.8.8.8 8.8.4.4 valid=300s; # 例如使用 Google DNS,设置缓存有效期
    # resolver_timeout 5s;
    ssl_stapling on;
    ssl_stapling_verify on;
    # 如果你的CA提供了 OCSP responder,可能需要指定信任的证书链
    # ssl_trusted_certificate /etc/ssl/certs/your_ca_chain.crt; # 包含中间证书和根证书
    
    # 6. HSTS (HTTP Strict Transport Security): 强制浏览器使用 HTTPS
    # 在所有响应中添加 Strict-Transport-Security 头部
    # max-age: 强制使用 HTTPS 的秒数 (一年约 31536000 秒)
    # includeSubDomains: 对所有子域名也强制使用 HTTPS
    # preload: (可选) 提交到浏览器预加载列表,但请谨慎使用,一旦加入很难移除
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    
    # 7. 其他安全头部 (可选,推荐):
    # add_header X-Frame-Options "DENY"; # 防止点击劫持
    # add_header X-Content-Type-Options "nosniff"; # 防止浏览器误判资源类型
    # add_header X-XSS-Protection "1; mode=block"; # 开启浏览器的 XSS 过滤
    # add_header Referrer-Policy "no-referrer-when-downgrade"; # 控制 referrer 信息
    
    # 8. 差分隐私 (Diffie-Hellman parameters): 增强 DHE/EDH 加密套件的安全性 (如果使用)
    # 建议生成一个强的 dhparam 文件,并指定路径
    # 生成方法: openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 # 或 4096
    # ssl_dhparam /etc/ssl/certs/dhparam.pem;
    
    # ===================== 网站根目录和索引文件 =====================
    root /var/www/your_website_root; # 您的网站文件存放路径
    index index.html index.htm index.nginx-debian.html;
    
    # ===================== 路径匹配和代理设置 =====================
    location / {
        try_files $uri $uri/ =404;
    }
    
    # 如果是反向代理到应用服务器 (如 Node.js, Python, PHP-FPM 等)
    # location / {
    #     proxy_pass http://localhost:8000; # 或上游服务器地址
    #     proxy_set_header Host $host;
    #     proxy_set_header X-Real-IP $remote_addr;
    #     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    #     proxy_set_header X-Forwarded-Proto $scheme; # 传递协议信息
    #     # 其他代理相关配置...
    # }
    
    # Error pages
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html; # Nginx 默认错误页面路径
    }
    

    }
    “`

  • 配置 HTTP 到 HTTPS 的重定向: 为了强制所有用户使用 HTTPS,您需要将访问 HTTP (端口 80) 的请求重定向到 HTTPS (端口 443)。在同一个配置文件中添加另一个 server 块:

    “`nginx
    server {
    listen 80;
    listen [::]:80; # 监听 IPv6 地址的 80 端口

    server_name your_domain.com www.your_domain.com; # 替换为您的域名
    
    # 方式一:使用 return 指令 (推荐,简单高效)
    return 301 https://$host$request_uri;
    
    # 方式二:使用 rewrite 指令 (更灵活但性能略低)
    # rewrite ^/(.*)$ https://$host/\ permanent;
    

    }
    ``
    这个
    server` 块监听 80 端口,匹配您的域名,然后使用 301 永久重定向将所有请求导向到对应的 HTTPS 地址。

  • 启用站点配置: 如果您在 sites-available 目录创建了文件,需要创建符号链接到 sites-enabled 目录来启用它。

    bash
    sudo ln -s /etc/nginx/sites-available/your_domain.conf /etc/nginx/sites-enabled/

  • 检查 Nginx 配置语法: 在重新加载或重启 Nginx 之前,务必检查配置文件的语法是否有误。

    bash
    sudo nginx -t

    如果输出显示 syntax is oktest is successful,则表示配置没有语法错误。

  • 重新加载或重启 Nginx: 使新的配置生效。对于大多数改动,重新加载即可,无需中断服务。

    “`bash
    sudo systemctl reload nginx # 或 service nginx reload

    如果 reload 不起作用或出现问题,可以尝试重启

    sudo systemctl restart nginx # 或 service nginx restart

    “`

第四步:测试 HTTPS 配置

配置完成后,进行全面的测试是必不可少的。

  1. 浏览器访问: 打开浏览器,输入您的域名,确保地址栏显示 HTTPS 前缀和一个锁图标。点击锁图标可以查看证书详情,确认证书是您刚刚安装的,并且由正确的 CA 签发。同时,尝试访问网站的不同页面,确保没有混合内容警告(Mixed Content Warning,即 HTTPS 页面加载了通过 HTTP 引用的资源,如图片、CSS、JS 文件等)。如果出现混合内容警告,需要在网页源代码中将所有 HTTP 资源链接改为 HTTPS。

  2. 在线 SSL 检测工具: 使用专业的在线工具检查您的 SSL 配置的安全等级。推荐使用 SSL Labs 的 SSL Server Test (ssllabs.com/ssltest/)。输入您的域名,工具会扫描您的服务器配置,并给出详细的报告,包括支持的协议、加密套件、是否存在漏洞等,并给出一个评分(A+是最好的)。争取达到 A 或 A+。

  3. 检查重定向: 在浏览器中输入 http://your_domain.com,确认它会自动重定向到 https://your_domain.com

  4. 命令行测试:

    • 使用 curl 测试 HTTPS 连接和重定向:
      bash
      curl -I http://your_domain.com # 检查 HTTP 重定向
      curl -I https://your_domain.com # 检查 HTTPS 连接和头部信息
    • 使用 openssl 检查证书链、协议和加密套件:
      bash
      openssl s_client -connect your_domain.com:443 -servername your_domain.com < /dev/null | openssl x509 -noout -text # 查看证书详细信息
      openssl s_client -connect your_domain.com:443 -servername your_domain.com -showcerts < /dev/null # 查看证书链
      openssl s_client -connect your_domain.com:443 -servername your_domain.com -tls1_2 # 测试是否支持 TLSv1.2
      openssl s_client -connect your_domain.com:443 -servername your_domain.com -tls1_3 # 测试是否支持 TLSv1.3
      # 可以通过不断改变 -tls 版本来测试支持情况

第五步:进一步优化安全和性能

一旦 HTTPS 正常工作,您可以考虑进一步优化配置以提升安全性和性能。

  • HTTP/2: 在 Nginx 配置中 listen 指令后面添加 http2 即可启用 HTTP/2 协议(需要 Nginx 1.9.5 及更高版本,且 OpenSSL 1.0.2 或更高版本)。HTTP/2 提供了多路复用、头部压缩等特性,能显著提升网站加载速度。
    nginx
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

  • 启用 Gzip 压缩 (如果还没启用): Gzip 可以压缩文本类资源(HTML, CSS, JS 等),减少传输大小,提升加载速度。通常在 http 块或 server 块中配置。
    nginx
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;

  • 配置 Resolver for OCSP Stapling: 如果您的服务器需要通过域名解析来获取 OCSP 响应者的地址,需要在 Nginx 配置中指定 DNS 服务器。通常在 http 块或 server 块中配置。
    nginx
    resolver 8.8.8.8 8.8.4.4 valid=300s; # 使用 Google DNS
    resolver_timeout 5s;

    然后确保 ssl_stapling on;ssl_stapling_verify on; 已启用。

  • 生成强大的 Diffie-Hellman 参数 (如果使用 DHE ciphers): 虽然 ECDHE (Ephemeral Elliptic Curve Diffie-Hellman) 加密套件提供了更好的前向保密性且速度更快,但如果您的加密套件列表中包含了 DHE 或 EDH(Ephemeral Diffie-Hellman)套件,生成并使用一个强大的 DH 参数文件可以增强其安全性,防止 Logjam 攻击。
    bash
    openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096 # 生成 4096 位的 DH 参数,可能需要一些时间

    然后添加到 Nginx 配置中:
    nginx
    ssl_dhparam /etc/ssl/certs/dhparam.pem;

  • 定期更新证书: Let’s Encrypt 证书有效期 90 天,商业证书有效期通常一年或更长。设置自动续订(对于 Let’s Encrypt)或在到期前及时手动续订商业证书,避免证书过期导致网站不可访问。

  • 关注安全漏洞: 关注 SSL/TLS 协议和 Nginx 本身的最新安全动态,及时更新 Nginx 和 OpenSSL 版本,并根据建议调整配置(如禁用已知的弱协议或加密套件)。

第六步:故障排除

在配置过程中可能会遇到各种问题,以下是一些常见的故障排除步骤:

  1. 检查 Nginx 错误日志: Nginx 的错误日志文件(通常在 /var/log/nginx/error.log)会记录配置加载错误、证书读取问题、握手失败等详细信息。这是排除问题的第一步。

  2. 检查 Nginx 配置语法: 再次运行 sudo nginx -t 确保没有语法错误。

  3. 检查证书文件路径和权限: 确认 ssl_certificatessl_certificate_key 指令中的文件路径是否正确,以及 Nginx 进程用户是否有读取这些文件的权限(特别是私钥文件的 600 权限和证书文件的 644 权限)。

  4. 检查防火墙: 确保服务器防火墙允许入站连接到 443 端口。可以使用 sudo ufw status (UFW) 或 sudo firewall-cmd --list-all (firewalld) 检查规则。可以使用 telnet your_domain.com 443nc -zv your_domain.com 443 从外部测试端口连通性。

  5. 检查域名解析: 确保您的域名正确解析到服务器的公网 IP 地址。可以使用 ping your_domain.comdig your_domain.com 检查 DNS 解析。

  6. 检查证书链: 如果浏览器或 SSL Labs 报告证书链不完整,请确认您在 ssl_certificate 指令中指定的证书文件包含了完整的证书链(您的证书 + 所有中间证书)。如果您使用单独的私钥和证书文件,并且 CA 提供了单独的中间证书文件,您可能需要合并它们或使用 ssl_trusted_certificate 指令(用于 OCSP stapling)。

  7. 混合内容警告: 检查浏览器开发工具 (F12) 控制台中的警告信息,查找通过 HTTP 加载的资源。修改网页源代码,将这些资源的 URL 从 http:// 改为 https://,或者使用相对路径或协议相对路径 //your_domain.com/...

  8. 证书过期: 如果证书过期,浏览器会显示警告或阻止访问。检查证书的有效期,及时续订。

总结:安全连接的未来

通过以上详细步骤,您应该能够在 Nginx 服务器上成功配置 HTTPS,为您的网站启用安全加密连接。从获取证书到优化安全设置,每一步都至关重要。HTTPS 不仅是技术上的配置,更是对用户数据安全和隐私负责任的表现。

记住,HTTPS 的世界是动态变化的。新的安全威胁和技术改进会不断涌现。定期检查您的 SSL/TLS 配置(例如,使用 SSL Labs)并保持 Nginx 和 OpenSSL 软件的更新是维护网站安全和性能的关键。拥抱 HTTPS,不仅仅是为了排名或消除浏览器警告,更是构建一个更安全、更可信赖互联网环境的重要一环。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部