本教程不依赖面板,基本完全在终端中运行,以便节约面板所占用的空间和避免潜在的隐私泄露问题。
一、介绍一下 HTTPS
HTTPS (Hypertext Transfer Protocol Secure) 是一种安全的超文本传输协议,它是 HTTP 的安全版本。它通过在 HTTP 和 TCP 之间添加一个安全层(SSL/TLS)来保护数据传输的安全性。简单来说,HTTPS 就是 HTTP + SSL/TLS。
1.1 为什么需要 HTTPS?
在互联网上,数据通过 HTTP 协议进行传输时,是以明文形式进行的。这意味着任何能够拦截网络流量的人都可以看到正在传输的数据,例如用户名、密码、信用卡信息等敏感信息。这会导致严重的安全风险,包括:
- 数据窃取: 黑客可以窃取用户的敏感信息,例如账户密码、信用卡信息等,用于非法目的。
- 中间人攻击: 黑客可以伪装成网站或用户,拦截并篡改传输的数据,例如插入恶意广告、钓鱼链接等。
- 数据篡改: 黑客可以篡改正在传输的数据,例如修改网页内容、订单信息等。
HTTPS 通过使用 SSL/TLS 协议,解决了以上安全问题,主要体现在以下几个方面:
- 数据加密: HTTPS 对传输的数据进行加密,即使被拦截也无法读取,保证了数据的机密性。
- 身份验证: HTTPS 可以验证网站的身份,防止用户访问到伪造的钓鱼网站。
- 数据完整性: HTTPS 可以确保数据在传输过程中没有被篡改,保证了数据的完整性。
1.2 HTTPS 的工作原理
HTTPS 的工作原理主要基于 SSL/TLS 协议,其握手过程可以概括为以下几个步骤:
-
客户端发起连接请求: 客户端 (例如浏览器) 向服务器发送连接请求,并指定使用的 SSL/TLS 版本。
-
服务器返回证书: 服务器向客户端发送数字证书,其中包含服务器的公钥和证书颁发机构 (CA) 的信息。
-
客户端验证证书:
客户端验证证书的有效性,包括:
- 证书是否由可信的 CA 颁发。
- 证书是否过期。
- 证书是否被吊销。
- 证书中的域名是否与正在访问的网站域名匹配。
-
客户端生成预主密钥 (Pre-Master Secret): 客户端生成一个随机的预主密钥,并使用服务器的公钥对其进行加密。
-
客户端发送加密的预主密钥: 客户端将加密后的预主密钥发送给服务器。
-
服务器解密预主密钥: 服务器使用自己的私钥解密预主密钥。
-
双方生成主密钥 (Master Secret): 客户端和服务器都使用相同的算法,根据预主密钥、客户端随机数和服务器随机数生成主密钥。
-
双方生成会话密钥: 客户端和服务器使用主密钥生成用于加密和解密数据的会话密钥。
-
安全连接建立: 双方使用会话密钥对数据进行加密和解密,开始安全的 HTTPS 通信。
1.3 HTTPS 的优势
- 安全性: 保护用户数据安全,防止数据泄露、篡改和中间人攻击。
- 信任: 浏览器地址栏显示安全锁(或保险箱)标识,提升用户对网站的信任度。
- SEO 排名: Google 等搜索引擎将 HTTPS 作为排名因素之一,HTTPS 网站的排名通常更高。
- 未来趋势: HTTPS 已成为互联网安全标准,越来越多的网站正在转向 HTTPS。
1.4 总结:HTTPS 和 HTTP 的区别
特性 | HTTP | HTTPS |
---|---|---|
安全性 | 不安全,数据明文传输 | 安全,数据加密传输 |
URL 前缀 | http:// |
https:// |
证书 | 不需要 | 需要 SSL/TLS 证书 |
性能 | 略快(因为无需加密解密) | 略慢(因为需要加密解密) |
SEO 排名 | 较低 | 较高 |
二、获取 SSL/TLS 证书
要配置 HTTPS,首先需要获取由受信任的证书颁发机构 (CA) 签发的 SSL/TLS 证书。证书中包含网站的公钥和身份信息,用于客户端验证服务器身份和建立加密连接。
免费获取 HTTPS 证书的方式有很多,可以参考这篇知乎文章。这里介绍两种方式:
- Acme.sh 申请证书
- Cloudflare 申请源证书
但首先,你应当在你的域名提供商那里添加 DNS 的 A 记录到你的源服务器 IP,如果你想使用Cloudflare 申请源证书
则请打开 Cloudflare 的小黄云。
2.1 Acme.sh 申请证书(更推荐)
Acme.sh 是一个实现了 ACME 协议的 Shell 脚本客户端,可以用于从 Let’s Encrypt 等免费 CA 自动申请和续期 SSL/TLS 证书。它支持多种验证方式,例如 DNS 验证和文件验证,非常适合自动化部署。
Acme.sh项目的 Github 仓库:
2.1.1 安装 Acme.sh
可以使用以下命令安装 Acme.sh:
curl https://get.acme.sh | sh -s
或者
wget -O - https://get.acme.sh | sh
打开自动更新:
acme.sh --upgrade --auto-upgrade
请注意,以上操作不一定要在 VPS 中进行,你甚至可以在自己的电脑上运行,但是这样你就无法享受 90 天自动续期证书的功能了(如果你的电脑不长期开机),所以推荐在 VPS 中执行。
2.1.2 更改默认证书
acme.sh --set-default-ca --server letsencrypt
Acme 被 ZeroSSL 收购,其默认的证书方式为 ZeroSSL ,但此证书生成时会携带邮箱。没有人希望自己的邮箱泄露,因此更换证书提供方为 Let’s Encrypt。
当然,也可以在生成证书时加一个--server
参数来决定生成什么证书
--server letsencrypt
2.1.3 申请证书
Acme.sh 支持多种 DNS 服务商的 API,可以自动添加 DNS 记录进行验证。这里以使用 Cloudflare API 为例,演示如何申请证书。如果你的域名没有托管在 Cloudflare,而是其它服务商例如 DNSPod,请查看 Acme.sh 的官方 wiki:Acme Wiki - How to use DNS API。
请注意:以下所有步骤均请将example.com
换做你自己的域名!
-
获取 Cloudflare API 密钥:
- 登录 Cloudflare 账户,进入 “My Profile” → “API Tokens”。
- 创建一个 API Token,选择 “Edit zone DNS(编辑区域 DNS)” 模板,并设置“区域资源”为需要申请证书的域名。
- 复制生成的 API Token。
-
设置环境变量:
将 API Token 设置为环境变量:
export CF_Token="YOUR_CLOUDFLARE_API_TOKEN" export CF_Account_ID="YOUR_CLOUDFLARE_ACCOUNT_ID"
CF_Account_ID
为账户的 ID, 可在域名的 “概述” 页面的右下角找到(中文为账户 ID
)。 -
执行申请命令:
使用以下命令申请证书,请将
example.com
替换成你的域名:acme.sh --issue --dns dns_cf -d example.com -d www.example.com
如果是申请泛域名证书(强烈推荐),可以使用如下命令:
acme.sh --issue --dns dns_cf -d example.com -d '*.example.com'
由于 DNS 传播有延迟,这个命令的执行时间从 25 秒到 2 分钟不等,请坐和放宽。
2.1.4 安装证书
申请成功后,Acme.sh 会将证书和密钥文件保存在 ~/.acme.sh/example.com/
目录下。
可以使用以下命令将证书和密钥安装到指定目录,例如 /etc/nginx/ssl/
:
acme.sh --install-cert -d example.com \
--key-file /etc/nginx/ssl/example.com.key \
--fullchain-file /etc/nginx/ssl/fullchain.cer \
--reloadcmd "service nginx force-reload"
将上述命令中 /etc/nginx/ssl/
替换成您所使用 Web 服务器的证书文件路径。--reloadcmd
可以用来设置证书更新后自动重启 Web 服务器的命令。
2.1.5 自动续期
Acme.sh 会自动设置一个 cron 任务,每天检查证书是否需要续期,并在需要时自动续期证书。
可以使用以下命令查看 cron 任务:
crontab -l
2.2 Cloudflare 申请源证书
这个方法要求你把域名托管到 Cloudflare。
- 进入 Cloudflare 控制台,选择你想要配置的域名。
- 在 Cloudflare 的侧栏点击 SSL/TLS
- 点击 配置,选择 完全(严格)并保存
- 在侧栏点击 边缘证书
- 开启下列选项
- 始终使用 HTTPS
- 随机加密
- TLS 1.3
- 自动 HTTPS 重写
- 证书透明度监视
- 选择 源服务器
- 开启 经过身份验证的源服务器拉取
- 点击 创建证书
- 证书有效期选择 15 年
- 点击 创建
- 分别复制源证书、私钥,妥善保存,后面要用。
三、配置 Nginx 使用 HTTPS
在获取 SSL/TLS 证书后,我们需要配置 Web 服务器来使用 HTTPS。以下是在 Nginx 上配置 HTTPS 的步骤。
3.1 安装 Nginx
如果你的服务器上还没有安装 Nginx,可以使用以下命令进行安装:
-
Debian / Ubuntu:
sudo apt update sudo apt install nginx
-
CentOS / RHEL:
sudo yum update sudo yum install nginx
3.2 配置 Nginx
-
将证书和密钥文件复制到 Nginx 配置目录下:
通常情况下,Nginx 的证书和密钥文件建议存放在
/etc/nginx/ssl/
目录下。如果该目录不存在,可以创建它:sudo mkdir -p /etc/nginx/ssl
然后使用 acme.sh 的命令安装证书:
acme.sh --install-cert -d example.com \ --key-file /etc/nginx/ssl/example.com.key \ --fullchain-file /etc/nginx/ssl/example.com.crt \ --reloadcmd "service nginx force-reload"
如果刚才使用了 Cloudflare 源证书,请直接创建
/etc/nginx/ssl/example.com.key
和/etc/nginx/ssl/example.com.crt
并写入刚才在 Cloudflare 获得的证书 & 密钥。 -
编辑 Nginx 配置文件:
打开你的网站的 Nginx 配置文件,通常位于
/etc/nginx/sites-available/
目录下,例如/etc/nginx/sites-available/example.com
。如果没有你的网站的配置文件,可以创建一个新的:
sudo nano /etc/nginx/sites-available/example.com
或者如果你是要添加二级域名,则:
sudo nano /etc/nginx/sites-available/test.example.com
-
添加 HTTPS 配置:
在配置文件中,添加以下内容:
server { listen 443 ssl; server_name example.com; ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; location / { proxy_pass http://localhost:3000; # Forward to Docker app # Add WebSocket support proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # Standard headers 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; # Timeouts for WebSocket connections proxy_read_timeout 60s; proxy_send_timeout 60s; } }
将上述配置中
example.com
替换为你的域名,/etc/nginx/ssl/example.com.crt
和/etc/nginx/ssl/example.com.key
替换为你实际的证书和密钥文件路径。这段配置的含义是:
listen 443 ssl;
: 监听 443 端口,并启用 SSL。server_name
: 指定域名。ssl_certificate
: 指定证书文件路径。location /
: 默认的 location 块,可以根据你的网站需求进行配置。例如配置反向代理等。
-
添加 HTTP 重定向到 HTTPS (可选):
如果你希望将所有 HTTP 请求都重定向到 HTTPS,可以添加以下配置:
server { listen 80; server_name example.com; return 301 https://$host$request_uri; # Allow Certbot ACME challenges for SSL renewal location ~ /.well-known/acme-challenge { allow all; } }
上述配置表示监听 80 端口的所有请求,使用 301 永久重定向到对应的 HTTPS 地址。
-
启用网站配置:
如果你的网站配置文件位于
/etc/nginx/sites-available/
目录下,你需要创建一个软链接到/etc/nginx/sites-enabled/
目录来启用它:sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
-
检查 Nginx 配置并重启:
使用以下命令检查 Nginx 配置语法是否正确:
sudo nginx -t
如果配置正确,输出应该类似:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
然后重启 Nginx 服务使配置生效:
sudo service nginx restart
或者
sudo systemctl restart nginx
3.3 测试 HTTPS
配置完成后,使用浏览器访问你的网站 https://example.com
,检查是否能够正常访问,并且浏览器地址栏是否显示安全锁标识。
四、 HTTPS 配置的最佳实践
配置好 HTTPS 后,为了进一步提高网站的安全性和性能,建议遵循以下最佳实践:
4.1 使用强加密协议和算法
-
禁用过时的 SSL/TLS 协议: 仅启用 TLS 1.2 和 TLS 1.3 协议,禁用 SSLv2、SSLv3、TLS 1.0 和 TLS 1.1 等不安全的协议。在 Nginx 配置中,可以使用以下指令:
ssl_protocols TLSv1.2 TLSv1.3;
-
配置安全的加密算法套件: 优先使用支持前向保密 (Forward Secrecy) 的 ECDHE 密钥交换算法和 AES-GCM 等高强度加密算法。避免使用弱加密算法,如 RC4、DES 等。在 Nginx 配置中,可以使用以下指令:
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384'; ssl_prefer_server_ciphers on;
4.2 启用 HSTS (HTTP Strict Transport Security)
HSTS 强制浏览器始终使用 HTTPS 访问网站,即使在地址栏输入 HTTP 地址也会自动跳转到 HTTPS。这可以有效防止中间人攻击和协议降级攻击。在 Nginx 配置中,可以添加以下指令启用 HSTS:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
max-age
: 指定 HSTS 策略的有效期,单位为秒 (一年为 31536000 秒)。includeSubDomains
: 可选参数,表示 HSTS 策略适用于所有子域名。preload
: 可选参数,表示将域名添加到浏览器的 HSTS 预加载列表中。需要注意的是,添加到预加载列表需要额外申请,且可能需要较长时间才能生效。
注意: 启用 HSTS 后,如果网站的 HTTPS 证书出现问题,用户在 max-age
指定的时间内将无法访问网站。因此,在启用 HSTS 之前,请确保网站的 HTTPS 配置稳定可靠。
4.3 启用 OCSP Stapling
OCSP (Online Certificate Status Protocol) 用于查询证书的吊销状态。OCSP Stapling 是一种优化方案,由服务器主动获取 OCSP 响应并将其发送给客户端,从而减少客户端的查询时间,提高访问速度。在 Nginx 配置中,可以添加以下指令启用 OCSP Stapling:
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/example.com.crt; # 使用 fullchain.cer
ssl_stapling on;
: 启用 OCSP Stapling。ssl_stapling_verify on;
: 启用 OCSP Stapling 验证。ssl_trusted_certificate
: 指定受信任的证书链文件,用于验证 OCSP 响应的有效性,通常是你的证书的完整证书链 (fullchain.cer)。
4.4 配置 HTTP/2
HTTP/2 是 HTTP 协议的下一代版本,支持多路复用、头部压缩等特性,可以显著提高网站的加载速度。在 Nginx 1.9.5 及以上版本中,可以通过在 listen
指令中添加 http2
参数来启用 HTTP/2:
已弃用,请转到 #12
注意: 启用 HTTP/2 需要客户端和服务器都支持该协议。
4.5 定期更新证书
SSL/TLS 证书都有有效期,需要定期更新。Let’s Encrypt 证书的有效期为 90 天,Acme.sh 会自动续期证书。你需要确保续期任务正常运行,并在证书过期之前更新证书。
五、 常见问题及解决方法
5.1 浏览器提示“不安全”或“连接不完全安全”
- 证书过期: 检查证书是否过期,如果过期,需要更新证书。
- 证书链不完整: 某些浏览器可能需要完整的证书链才能验证证书的有效性。请确保服务器配置中使用的证书文件是包含完整证书链的文件 (例如 Let’s Encrypt 的
fullchain.cer
)。 - 混合内容: 如果 HTTPS 页面中加载了 HTTP 资源 (例如图片、脚本、样式表等),浏览器会提示“连接不完全安全”。需要将所有资源都改为 HTTPS。
- 使用了弱加密协议或算法: 参考 4.1 节,配置强加密协议和算法。
5.2 网站访问速度慢
- 未启用 OCSP Stapling: 参考 4.3 节,启用 OCSP Stapling。
- 未启用 HTTP/2: 参考 4.4 节,启用 HTTP/2。
- 服务器性能不足: 升级服务器硬件或优化服务器配置。
5.3 Acme.sh 自动续期失败
- 网络问题: 检查服务器的网络连接是否正常。
- DNS 验证配置错误: 检查 DNS API 密钥是否正确,以及 DNS 记录是否正确配置。
- HTTP 验证配置错误: 检查 Web 服务器是否允许访问
.well-known/acme-challenge/
目录,以及 80 端口是否开放。 - Acme.sh 脚本权限问题: 确保 Acme.sh 脚本具有执行权限。
- 服务器时间错误: 请确保服务器时间设置正确, 否则将无法通过验证.
5.4 Nginx 无法启动或重启
- 配置文件语法错误: 使用
nginx -t
命令检查配置文件语法是否正确。 - 证书或密钥文件路径错误: 检查配置文件中指定的证书和密钥文件路径是否正确。
- 端口被占用: 检查 443 端口是否被其他进程占用。
5.5 忘记续期证书导致证书过期
- 尽快手动续期证书: 使用Acme.sh 的
--renew
参数手动续期证书。例如:acme.sh --renew -d example.com
- 检查自动续期任务: 确保Acme.sh 的自动续期任务已正确配置且正常运行。例如:
crontab -l
题外话
- Cloudflare 申请源证书部分参考 [超详细教学] 教你从零开始,入坑域名、云服务器并部署 New API + Open WebUI!
- 第一次写长文,码字不易,给个赞吧