公众号旧文

CT 是域名找线索,TLS 扫描从 IP 反推域名

作者:胖子阅读 —

#互联网资产测绘

很多人第一次接触互联网资产测绘时,会把Certificate Transparency(CT)日志和TLS 扫描混在一起。

因为这两种方法最后似乎都能得到:

域名、证书、IP 之间的关联。

但实际上,它们的出发点完全不同。

可以先记住一句最简单的话:

CT 更像是“从域名找线索”,TLS 扫描更像是“从 IP 反推出域名”。

这两条路径一旦结合起来,就会形成一条非常完整的资产发现链。


一、先看 CT:它更擅长告诉你“有哪些域名存在过”

当一个网站申请公开受信任的 HTTPS 证书时,证书通常会被记录到 Certificate Transparency 日志中。

证书里面最重要的信息之一,就是:

Subject Alternative Name

也就是通常说的:

SAN

例如一个证书里可能包含:

DNS:example.com
DNS:www.example.com
DNS:api.example.com
DNS:admin.example.com

那么只要这个证书进入 CT 日志,这些名字就可能被外部发现。

所以如果别人已经知道你的主域名:

example.com

就可以通过公开 CT 数据继续寻找:

www.example.com
api.example.com
admin.example.com
old.example.com
test.example.com

这就是为什么 CT 经常被用来做:

  • 子域名发现
  • 历史域名发现
  • 证书变更追踪
  • 资产梳理
  • 安全测试前的信息收集

它的典型思路是:

已知域名
↓
查询 CT 日志
↓
读取历史证书
↓
读取 SAN
↓
发现更多域名

所以从方向上看,CT 是:

Domain → Certificate → More Domains

它首先解决的是:

“这个组织还有哪些域名、子域名曾经申请过证书?”


二、但 CT 通常不能直接告诉你真实源站 IP

这是一个非常容易被误解的地方。

假设 CT 日志里出现:

api.example.com

这只能说明:

某张公开证书曾经包含过 api.example.com。

它本身通常不会直接告诉你:

api.example.com
真实源站 = 45.8.173.248

尤其是在网站使用 Cloudflare、Fastly、Akamai 等 CDN 的情况下。

你正常查询:

api.example.com

DNS 很可能只会得到 CDN 的边缘 IP。

比如:

api.example.com
↓
Cloudflare
↓
104.x.x.x
172.x.x.x

真正的网站服务器可能完全藏在后面:

45.8.173.248

所以 CT 更像是:

给你提供“名字”。

但它不一定直接给你:

这个名字背后真正对应哪台服务器。

这时候,另一种方法就开始发挥作用了:

TLS 扫描。


三、TLS 扫描正好反过来:从 IP 出发找域名

假设扫描者现在不知道任何域名,只拿到了一个公网 IP:

45.8.173.248

他可以做一件非常简单的事情:

连接 45.8.173.248:443

如果这个 IP 的 443 端口开放,而且上面运行的是 HTTPS 服务,那么 TCP 连接之后就会发生 TLS 握手。

而 TLS 服务器通常需要返回自己的证书。

例如扫描者执行:

openssl s_client \
  -connect 45.8.173.248:443 \
  </dev/null

如果服务器直接返回了一张证书,扫描者就可以继续读取:

openssl x509 \
  -noout \
  -subject \
  -ext subjectAltName

然后可能看到:

Subject:
CN = api.example.com

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

原本扫描者只知道:

45.8.173.248

现在突然多出了:

api.example.com
www.example.com

于是:

45.8.173.248
↓
443/TLS
↓
Certificate
↓
SAN
↓
api.example.com

这就是:

从 IP 反推出域名。

也可以写成:

IP → TLS → Certificate → Domain

这和 CT 的方向正好相反。


四、为什么证书会泄露域名

HTTPS 的核心问题之一,就是客户端必须确认:

“我现在连接的服务器,到底是不是我要访问的网站?”

所以服务器要给客户端发送一个证书。

证书里会写明:

这张证书可以用于哪些域名。

现在浏览器真正重点检查的是 SAN。

例如:

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

如果扫描者能从某个 IP 上拿到这张证书,那么实际上服务器自己就在告诉对方:

我至少和这些域名存在某种关系。

因此证书本身天然就是一种很有价值的资产元数据。


五、现实情况还要加一个 SNI

不过现代 HTTPS 还有一个非常重要的机制:

SNI,Server Name Indication。

现在一台服务器上通常不会只放一个网站。

例如:

45.8.173.248
├── a.example.com
├── b.example.com
├── api.example.com
└── admin.example.com

这些网站可能全部使用:

443

那服务器怎么知道客户端到底想访问哪个网站?

答案就是:

客户端在 TLS ClientHello 里发送 SNI。

例如:

server_name = api.example.com

Nginx、Caddy、Apache 等服务器看到这个名字后,就知道:

应该返回 api.example.com 对应的证书。

所以如果直接扫描:

openssl s_client -connect 45.8.173.248:443

未必能拿到 api.example.com 的证书。

服务器可能只会返回一个:

default certificate

甚至直接拒绝连接。


六、这也是为什么“已知域名 + 已知 IP”特别强

假设通过 CT,扫描者已经发现:

api.example.com

然后又通过其他渠道怀疑:

45.8.173.248

可能是这个网站的真实源站。

现在他就可以进行验证:

openssl s_client \
  -connect 45.8.173.248:443 \
  -servername api.example.com \
  </dev/null

这里:

-connect

决定真正连接哪个 IP:

45.8.173.248

而:

-servername

决定 TLS SNI:

api.example.com

如果服务器返回:

SAN:
DNS:api.example.com

那这条关联就非常强了。

整条逻辑变成:

CT
↓
发现 api.example.com
↓
找到疑似 IP
↓
45.8.173.248
↓
带 api.example.com 的 SNI 发起 TLS 握手
↓
服务器返回 api.example.com 证书
↓
验证 IP ↔ 域名关系

这已经不只是“猜测”。

而是服务器自己通过 TLS 响应提供了证据。


七、curl –resolve 本质上也是同一个原理

很多人测试 CDN 源站时会用:

curl --resolve \
  api.example.com:443:45.8.173.248 \
  https://api.example.com/

这条命令看起来比较神奇,但拆开后其实很简单。

它告诉 curl:

不要把 api.example.com 解析到正常 DNS IP

而是强制:

api.example.com
→ 45.8.173.248

但是访问 URL 仍然是:

https://api.example.com/

所以最终网络行为是:

TCP:
45.8.173.248:443

TLS SNI:
api.example.com

HTTP Host:
api.example.com

如果 45.8.173.248 真的是这个网站的源站,就可能正常返回网站。

所以:

openssl s_client -servername

主要验证 TLS 层。

而:

curl --resolve

可以继续验证 HTTP 层。


八、互联网资产搜索引擎就是大规模做这件事

自己扫描一个 IP 很简单。

真正厉害的是把这个过程扩大到整个互联网。

例如:

  • Shodan
  • Censys
  • ZoomEye
  • FOFA

这类平台会持续扫描公网地址。

它们可能扫描:

443
8443
9443
10443

等大量可能运行 TLS 的端口。

扫描后会保存:

IP
端口
TLS 版本
Cipher
Certificate Subject
Certificate SAN
Issuer
证书指纹
证书有效期
HTTP Header
HTTP Title
Server Banner

例如数据库里可能形成这样的记录:

IP:
45.8.173.248

Port:
443

TLS certificate SAN:
api.example.com
www.example.com

Issuer:
Let's Encrypt

HTTP Server:
nginx

于是以后别人搜索:

api.example.com

平台就可能反过来告诉他:

某个 IP 曾经返回过包含这个域名的证书

这也是为什么:

即使你后来已经修改 DNS,也不代表历史关联一定消失。

因为扫描平台可能已经保存过旧数据。


九、CT 和 TLS 扫描结合后,信息发现能力会强很多

单独看 CT:

example.com
↓
CT
↓
api.example.com

单独看 IP 扫描:

45.8.173.248
↓
TLS
↓
api.example.com

但是如果把两边结合:

已知 example.com
        ↓
        CT
        ↓
发现 api.example.com
        ↓
历史 DNS / DNS / 页面 / 邮件 / 扫描
        ↓
怀疑 45.8.173.248
        ↓
带 api.example.com SNI 扫描 45.8.173.248:443
        ↓
拿到对应证书
        ↓
确认关系

这时候资产发现就形成了闭环。

所以安全研究里经常不是只依赖一个数据源。

而是:

CT
+
DNS
+
历史 DNS
+
TLS
+
HTTP
+
证书指纹
+
搜索引擎

相互验证。


十、Cloudflare 并不自动解决这个问题

很多人有一个误区:

“我的网站已经开了 Cloudflare 橙云,所以别人肯定不知道源站。”

实际上 Cloudflare 主要解决的是:

普通 DNS 查询

不会直接返回你的源站 IP。

例如:

api.example.com
↓
104.x.x.x

别人看到的是 Cloudflare。

但如果真实源站:

45.8.173.248

仍然允许所有互联网用户直接访问:

45.8.173.248:443

那么问题依然存在。

尤其如果源站根据 SNI:

api.example.com

返回正确证书和网站内容,那么一旦源站 IP 被其他方法猜到,Cloudflare 就可能被绕过。

所以真正稳妥的结构应该是:

Internet
   ↓
Cloudflare
   ↓
Origin

而不是:

Internet ───────────→ Origin
   ↓
Cloudflare ─────────→ Origin

也就是说,源站最好只接受:

Cloudflare → 443

而普通公网地址:

Internet → Origin:443

应该无法建立有效连接。


十一、最重要的不是“隐藏证书”,而是控制源站可达性

有时候有人发现证书 SAN 暴露域名以后,第一反应是:

那我换一张证书不就行了吗?

这只能解决部分问题。

因为别人还可以从:

  • 历史证书
  • HTTP 内容
  • favicon hash
  • 页面标题
  • Server Header
  • SSH Banner
  • 其他端口
  • 历史 DNS
  • 邮件记录
  • 应用指纹

继续做关联。

因此真正有效的防护原则其实很简单:

不需要公网直接访问的服务,就不要允许公网直接访问。

例如网站源站使用 Cloudflare 时:

443
只允许 Cloudflare IP

管理后台:

只允许 Tailscale / WireGuard

数据库:

只监听 localhost 或私网

内部 API:

不绑定 0.0.0.0

当互联网扫描者根本无法和服务建立连接时:

扫描 IP
↓
TIMEOUT / DROP

自然也就拿不到:

TLS Certificate
HTTP Header
Title
Banner

这比单纯试图“隐藏证书信息”可靠得多。


十二、一张图理解两者的区别

CT 的方向:

已知域名
   ↓
Certificate Transparency
   ↓
证书
   ↓
SAN
   ↓
更多域名

TLS 扫描的方向:

已知 IP
   ↓
连接 443
   ↓
TLS 握手
   ↓
服务器证书
   ↓
SAN
   ↓
发现域名

结合起来:

CT
域名 ───────→ 更多域名
 ↑                 ↓
 │                 │
 │                 ↓
 │              DNS / 历史数据
 │                 ↓
 │                 IP
 │                 ↓
 └──── TLS 证书 ← 443 扫描

最终形成:

Domain
↕
Certificate
↕
IP

这就是互联网资产测绘中非常典型的一条信息关联链。


总结

如果只记住两句话就够了:

CT 的优势,是从已知域名继续发现更多域名。

TLS 扫描的优势,是从一个公网 IP 上读取证书,再反推出它可能关联的域名。

而真正强大的地方,并不是任何一种技术单独使用。

而是把:

CT
DNS
历史 DNS
TLS
HTTP

串起来。

这也是为什么一个网站即使使用了 CDN,只要源站仍然直接暴露在公网,而且还能返回真实域名对应的 TLS 证书,就仍然可能被互联网资产测绘平台建立:

真实 IP ↔ 域名

的关联。

所以从防御角度看,最重要的原则从来不是:

“怎样让别人看不到我的证书?”

而是:

哪些服务真的需要直接暴露给整个互联网?

如果答案是不需要,那么最好的处理方式,就是从网络层让它根本不可达。