惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
Google DeepMind News
Google DeepMind News
Engineering at Meta
Engineering at Meta
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
宝玉的分享
宝玉的分享
Latest news
Latest news
aimingoo的专栏
aimingoo的专栏
云风的 BLOG
云风的 BLOG
美团技术团队
V
Visual Studio Blog
F
Full Disclosure
腾讯CDC
H
Help Net Security
D
DataBreaches.Net
M
MIT News - Artificial intelligence
罗磊的独立博客
博客园 - 司徒正美
N
Netflix TechBlog - Medium
U
Unit 42
Vercel News
Vercel News
I
InfoQ
S
SegmentFault 最新的问题
B
Blog RSS Feed
博客园 - 三生石上(FineUI控件)
Microsoft Security Blog
Microsoft Security Blog
有赞技术团队
有赞技术团队
博客园_首页
The GitHub Blog
The GitHub Blog
T
Tailwind CSS Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
NISL@THU
NISL@THU
P
Privacy & Cybersecurity Law Blog
Recorded Future
Recorded Future
Y
Y Combinator Blog
S
Schneier on Security
P
Proofpoint News Feed
T
Tenable Blog
Cloudbric
Cloudbric
博客园 - 【当耐特】
The Register - Security
The Register - Security
人人都是产品经理
人人都是产品经理
Google DeepMind News
Google DeepMind News
C
Cyber Attacks, Cyber Crime and Cyber Security
量子位
A
Arctic Wolf
N
News and Events Feed by Topic
H
Hacker News: Front Page
MongoDB | Blog
MongoDB | Blog
The Hacker News
The Hacker News
Webroot Blog
Webroot Blog

Liups233の小站

YubiKey OpenPGP 智能卡使用指南 - Liups233の小站 通过 WKD / OPENPGPKEY DNS 记录部署 GPG 公钥 - Liups233の小站 OpenLiteSpeed 安装与建站配置 详细教程 - Liups233 使用 DNSCrypt-Proxy 为 Linux 配置加密 DNS - Liups233 WordPress 7.0 编辑器改回无衬线字体 - Liups233の小站 Redis 数据库权限与 Unix Socket 配置 - Liups233の小站 Docker 自建 RustDesk 远程和 API 服务 - Liups233の小站 ChatGPT Go 印度区免费试用白嫖 1 年 - Liups233の小站 使用 S/MIME 证书签名并加密电子邮件 - Liups233の小站 为 WordPress 外发邮件添加 S/MIME 签名 - Liups233の小站 网站域名变更迁移教程/记录 - Liups233の小站 将动漫视频刻录为视频光盘-蓝光/AVCHD DVD - Liups233の小站 百乐 CUSTOM 912 钢笔使用体验 - Liups233の小站 使用 Cloudflare mTLS 用户端凭证保护博客登入页面 - Liups233の小站 Kobo 手动安装 NickelMenu 和 KOReader - Liups233の小站 Kobo 阅读器字典缺字解决 - Liups233の小站 iCloud+ 域名邮箱的注册和使用 - Liups233の小站 9 美元一年的通配符 SSL 证书 - Liups233の小站 宝塔面板 Nginx 启用 Brotli 和 Pagespeed - Liups233の小站 拷贝 DVD/Blu-ray 光盘并使用 MeGUI 压制 - Liups233の小站 Spotify 相较 Apple Music 的优点 - Liups233の小站 欧卡/美卡自定义手排挡位布局 - Liups233の小站 内地居民到港开户汇丰和中银香港全过程 - Liups233の小站 给光驱刷入 LibreDrive 固件解锁区域和加密限制 - Liups233の小站 个人博客适用的 Cloudflare 防火墙和缓存规则 - Liups233の小站 为Kobo阅读器添加Google Drive和Dropbox功能 - Liups233の小站 百乐 PILOT Capless Fermo 钢笔评测 - Liups233の小站 业余无线电 B 类考试笔记 - Liups233の小站 黑白阅读器的绝唱?Kobo Clara BW 简单评测 - Liups233の小站 八重洲 WIRES-X 网络注册与使用教程 - Liups233の小站 异世的同路人 — 恋语 Juliamo 游戏简评 - Liups233の小站 欢迎加入我的 FreeDMR 服务器 - Liups233の小站 低至 6 港币一年的 Club SIM eSIM 保号卡 - Liups233の小站 H310/H710(P)/H810 阵列卡刷写为直通模式 - Liups233の小站
Cloudflare 设置 mTLS 验证来源拉取 - Liups233の小站
Liups233 · 2026-05-10 · via Liups233の小站

前言

在之前 这篇文章 中有提到,使用 Cloudflare 相互 TLS(mTLS)可以保护网站后台等敏感页面不被公网任意访问,只有在客户端提交证书并经过验证后才可以访问。同样的,这种技术也可以用于 Cloudflare 边缘服务器请求原始服务器的过程,即只有在边缘服务器向原始服务器提交经过验证的证书后,原始服务器才返回内容给边缘服务器。本文将讲述如何生成 mTLS CA 和证书,并在网页服务器和 Cloudflare 中配置验证来源拉取。

注:本次教程中使用的 mTLS 是基于主机名称的验证(Per-hostname Authentication),必须要使用非根域名(例如 www.liups.net 而不是 liups.net,或者也可能是我没找到方法)。如果你使用的域名是根域名,则建议使用区域层级的验证(Zone-level Authentication),稍后会提到。

目录

原理

我们使用 openssl 生成一个 CA 根证书,并用这个根证书创建一个客户端证书。然后,我们会将客户端证书及其私钥上传到 Cloudflare 后台,并且设置了 Cloudflare 边缘节点(作为客户端)在请求原始服务器上的特定域名时,如果要求提交客户端证书,就提交我们上传的证书。

而我们在原始服务器的网页服务器上设置了强制验证和 CA 根证书路径,达成以下效果:

  • 客户端访问服务器时,服务器主动要求客户端提供客户端证书,不提供则直接拒绝连接;
  • 客户端向服务器发送客户端证书(含公钥),同时用本地的客户端私钥对握手前置信息做数字签名,把签名结果一并发给服务器;
  • 服务器首先校验客户端证书:是否由配置的 CA 根证书签发、是否过期、证书信息合法,再用客户端证书里的公钥校验数字签名是否有效,证书非法或签名无效会直接拒绝连接。

以上解释只考虑了 mTLS 但没考虑 TLS,mTLS 属于 TLS 握手过程的一部分,只有当客户端在 TLS 的第一步确认了服务器证书合法后才会进行第二步的 mTLS 步骤。也就是说,网页服务器上必须配置 HTTPS 才能设置 mTLS。

通过这种方式,可以避免服务器 IP 泄露后,攻击者绕过 Cloudflare 直接访问源站,确保流量来源一定是经过核准的边缘节点。

证书创建

注:以下操作最好在网页服务所在的服务器上执行,当然如果你电脑就是 Linux 那当我没说

CA 根证书

我们在 /etc/certs 文件夹下操作,先创建一个用于 CA 证书的密钥:

sudo mkdir /etc/certs
cd /etc/certs
sudo openssl ecparam -name prime256v1 -genkey -noout -out rootca.key

然后基于这个密钥创建 CA 证书(days 后面的 3650 表示 CA 证书过多少天失效):

sudo openssl req -x509 -new -nodes -key rootca.key -sha256 -days 3650 -out rootca.crt

执行命令后,会提示输入证书的基本信息,只需要在 Common Name 中填写 根域名,其他栏位填「.」(半角点号),例如:

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:.
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:.
Organization Name (eg, company) [Internet Widgits Pty Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (e.g. server FQDN or YOUR name) []:liups.net
Email Address []:.

然后 CA 根证书(rootca.crt)和密钥(rootca.key)就创建好了。

用户端证书创建

接下来开始创建要上传到 Cloudflare 的 mTLS 用户端证书,这里先生成密钥和 CSR:

sudo openssl req -new -nodes -out cert.csr -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout cert.key

接下来一样要填写信息,Common Name 此时要填写 完整域名,最后的 A challenge password 和 An optional company name 什么都不填,直接回车,其依旧填「.」,例如:

-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:.
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:.
Organization Name (eg, company) [Internet Widgits Pty Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (e.g. server FQDN or YOUR name) []:www.liups.net
Email Address []:.

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

然后生成一个签发用的属性文件:

echo "basicConstraints=CA:FALSE" | sudo tee cert.v3.ext

接着使用 CA 证书对 CSR 进行签发(子证书的到期日必须比 CA 根证书短,我这里就减了一天):

sudo openssl x509 -req -in cert.csr -CA rootca.crt -CAkey rootca.key -CAcreateserial -out cert.crt -days 3649 -sha256 -extfile ./cert.v3.ext

然后就会生成签发后的子证书(cert.crt),这个待会要和密钥(cert.key)一起上传到 Cloudflare 后台,可以先用 sftp 下载到电脑上。

打开 Cloudflare 仪表板,点击你的域名,转到 SSL/TLS>概观,确认 SSL/TLS 加密的状态是「完整」或「完整(严格)」。如果不是,需要点击右边的「设定」进行修改:选择「自定义 SSL/TLS」,再选择「完整」或「完整(严格)」。注意:请确保你的源站已经配置好了 SSL 证书和 HTTPS 访问才能修改,否则网站将无法访问。

Cloudflare SSL/TLS 加密设置
Cloudflare SSL/TLS 加密设置

然后转到 SSL/TLS>原始服务器>验证来源拉取,如图:

验证来源拉取 mTLS 设置
验证来源拉取 mTLS 设置

在下方「每个主机名称」的右边,点击「上传凭证」,然后依次上传证书(cert.crt)和密钥(cert.key),再点击「继续」。之后会显示上传的证书的信息,确认 CN 显示的是根域名(而不是子域名),再点击「继续」。在下一个界面,添加适用于这个证书的子域名,再点击「储存」即可。

然后回到验证来源拉取设置的主界面,将全域和区域层级的开关关掉,避免冲突。

然后,转到 Caching>设定,打开开发模式,这样可以即时看到更改,等一切结束后就可以关闭了,如图:

打开 Cloudflare 缓存开发模式
打开 Cloudflare 缓存开发模式

网页服务器设置

注意:接下来的操作可能会让网站无法访问,请自行斟酌。

对于 Nginx,在站点配置里加入以下两行:

ssl_verify_client on;
ssl_client_certificate /etc/certs/rootca.crt;

对于 Apcache,在站点配置里加入以下两行:

SSLVerifyClient require
SSLCACertificateFile /etc/certs/rootca.crt

添加好配置后,重启网页服务器,然后在浏览器打开一个隐私窗口访问你的网站,如果能正常打开就行。

但如果你和我一样用的是うまい的 OpenLiteSpeed😋,可以看接下来的配置教程。

OpenLiteSpeed 配置

操作前,可以先将关键的 rootca.crt 文件移动到 LiteSpeed Web Server 的默认证书目录下,避免权限问题:

sudo mv /etc/cert/rootca.crt /usr/local/lsws/conf/cert/
sudo chown lsadm:lsadm /usr/local/lsws/conf/cert/rootca.crt

然后打开 OpenLiteSpeed 面板,点击左侧的「虚拟主机」,然后进入网站对应虚拟主机的设定,如图:

OpenLiteSpeed 进入虚拟主机设置
OpenLiteSpeed 进入虚拟主机设置

进入虚拟主机设定后,点击菜单栏的「SSL」,点击「SSL 私钥和证书」右边的编辑按钮,然后在 CA 证书文件里填写 conf/cert/rootca.crt(注意是在 CA 证书文件里填写,而不是 CA 证书路径),然后保存。

然后翻到 SSL 选项卡最下面的「客户端验证」部分,点击编辑。将客户端验证设置为 require,验证深度设置为 1,然后保存,最后进行平滑重启即可。然后在浏览器打开一个隐私窗口访问你的网站,如果能正常打开就行。

检验 mTLS 是否强制生效

注意:操作 hosts 文件有风险

如果你想看下是否确实强制 mTLS 是否生效,可以在服务器上,设置 hosts 将网站的完整域名解析到 127.0.0.1:

echo "127.0.0.1 <域名>" | sudo tee -a /etc/hosts  # 将解析添加到 hosts 最后一行

然后分别执行两个 curl 命令:

curl -k https://<域名>
curl -k --cert /etc/certs/cert.crt --key /etc/certs/cert.key https://<域名>

如果第一个命令有报错 tlsv13 alert certificate required, errno 0,而第二个命令正常执行并返回内容,就没问题了。测试完成后,记得复原 hosts 文件:

sudo sed -i '$d' /etc/hosts  # 删去 hosts 文件最后一行

为了安全性,生成的 cert.crtcert.keyrootca.key 也可以删掉了。

其它

如果有另一个子域名的网站需要设置,其实不需要在原本的 CA 上再签发子证书,直接重新再创建 CA 根证书就可以,因为不同的虚拟主机可以设置验证不同的 CA 根证书。如果证书过期了,同样重新创建 CA 根证书,再签发新的子证书就行。

这样签发一个子证书就更换根证书虽然麻烦,但可以避免泄露的子证书能够通过验证(因为我们更换根证书了,之前泄露的子证书不能通过验证)。正规 PKI 肯定是有吊销列表的,我们也可以配置,但好像更麻烦了。

验证来源拉取更像是一种安全性的增强,但并不是基础。如果你的服务器只连接了 Cloudflare,推荐用防火墙设置只允许边缘服务器的 IP 访问网站的 443 端口(TCP 和 UDP)。

mTLS 是一个非常有用的技术,也可以用来保护网站后台,教程见〈使用 Cloudflare mTLS 用户端凭证保护博客登入页面〉,也欢迎回到 主页 阅读更多文章。