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 之前,请确保您具备以下条件:
- 一台运行 Nginx 的服务器: 通常是 Linux 系统(如 Ubuntu, CentOS, Debian)。确保您拥有服务器的 root 或 sudo 权限。
- 已安装并运行的 Nginx: 如果尚未安装,请根据您的操作系统类型进行安装。
- 一个域名: 您的网站需要一个已注册并指向您的服务器 IP 地址的域名。例如:
your_domain.com
。 - 域名解析 (DNS): 您的域名记录(A 记录或 AAAA 记录)已正确指向您的服务器公网 IP 地址。
- 对 Nginx 配置文件的基本了解: 知道 Nginx 的主配置文件位置(通常是
/etc/nginx/nginx.conf
)以及虚拟主机配置文件位置(如/etc/nginx/sites-available/
和/etc/nginx/sites-enabled/
)。 - 防火墙设置: 确保服务器的防火墙已允许通过 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-nginxCentOS/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.com
和www.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-data
或nginx
)能够读取证书文件(.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). The600
permission for the private key is standard and safe.
第三步:配置 Nginx
现在,您可以修改 Nginx 配置文件来启用 HTTPS。
-
找到配置文件: 您的网站配置可能在
/etc/nginx/nginx.conf
的http
块内,或者更常见的是在/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 ok
和test is successful
,则表示配置没有语法错误。 -
重新加载或重启 Nginx: 使新的配置生效。对于大多数改动,重新加载即可,无需中断服务。
“`bash
sudo systemctl reload nginx # 或 service nginx reload如果 reload 不起作用或出现问题,可以尝试重启
sudo systemctl restart nginx # 或 service nginx restart
“`
第四步:测试 HTTPS 配置
配置完成后,进行全面的测试是必不可少的。
-
浏览器访问: 打开浏览器,输入您的域名,确保地址栏显示 HTTPS 前缀和一个锁图标。点击锁图标可以查看证书详情,确认证书是您刚刚安装的,并且由正确的 CA 签发。同时,尝试访问网站的不同页面,确保没有混合内容警告(Mixed Content Warning,即 HTTPS 页面加载了通过 HTTP 引用的资源,如图片、CSS、JS 文件等)。如果出现混合内容警告,需要在网页源代码中将所有 HTTP 资源链接改为 HTTPS。
-
在线 SSL 检测工具: 使用专业的在线工具检查您的 SSL 配置的安全等级。推荐使用 SSL Labs 的 SSL Server Test (ssllabs.com/ssltest/)。输入您的域名,工具会扫描您的服务器配置,并给出详细的报告,包括支持的协议、加密套件、是否存在漏洞等,并给出一个评分(A+是最好的)。争取达到 A 或 A+。
-
检查重定向: 在浏览器中输入
http://your_domain.com
,确认它会自动重定向到https://your_domain.com
。 -
命令行测试:
- 使用
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 版本,并根据建议调整配置(如禁用已知的弱协议或加密套件)。
第六步:故障排除
在配置过程中可能会遇到各种问题,以下是一些常见的故障排除步骤:
-
检查 Nginx 错误日志: Nginx 的错误日志文件(通常在
/var/log/nginx/error.log
)会记录配置加载错误、证书读取问题、握手失败等详细信息。这是排除问题的第一步。 -
检查 Nginx 配置语法: 再次运行
sudo nginx -t
确保没有语法错误。 -
检查证书文件路径和权限: 确认
ssl_certificate
和ssl_certificate_key
指令中的文件路径是否正确,以及 Nginx 进程用户是否有读取这些文件的权限(特别是私钥文件的 600 权限和证书文件的 644 权限)。 -
检查防火墙: 确保服务器防火墙允许入站连接到 443 端口。可以使用
sudo ufw status
(UFW) 或sudo firewall-cmd --list-all
(firewalld) 检查规则。可以使用telnet your_domain.com 443
或nc -zv your_domain.com 443
从外部测试端口连通性。 -
检查域名解析: 确保您的域名正确解析到服务器的公网 IP 地址。可以使用
ping your_domain.com
或dig your_domain.com
检查 DNS 解析。 -
检查证书链: 如果浏览器或 SSL Labs 报告证书链不完整,请确认您在
ssl_certificate
指令中指定的证书文件包含了完整的证书链(您的证书 + 所有中间证书)。如果您使用单独的私钥和证书文件,并且 CA 提供了单独的中间证书文件,您可能需要合并它们或使用ssl_trusted_certificate
指令(用于 OCSP stapling)。 -
混合内容警告: 检查浏览器开发工具 (F12) 控制台中的警告信息,查找通过 HTTP 加载的资源。修改网页源代码,将这些资源的 URL 从
http://
改为https://
,或者使用相对路径或协议相对路径//your_domain.com/...
。 -
证书过期: 如果证书过期,浏览器会显示警告或阻止访问。检查证书的有效期,及时续订。
总结:安全连接的未来
通过以上详细步骤,您应该能够在 Nginx 服务器上成功配置 HTTPS,为您的网站启用安全加密连接。从获取证书到优化安全设置,每一步都至关重要。HTTPS 不仅是技术上的配置,更是对用户数据安全和隐私负责任的表现。
记住,HTTPS 的世界是动态变化的。新的安全威胁和技术改进会不断涌现。定期检查您的 SSL/TLS 配置(例如,使用 SSL Labs)并保持 Nginx 和 OpenSSL 软件的更新是维护网站安全和性能的关键。拥抱 HTTPS,不仅仅是为了排名或消除浏览器警告,更是构建一个更安全、更可信赖互联网环境的重要一环。