如何确定SSL/TLS证书所接受的全部有效SNI?
如何确定SSL/TLS证书所接受的全部有效SNI?
哥们儿,我太懂这种被SNI搞懵的感觉了——明明证书上只有一个SAN和CN,却有好几个SNI能正常通,想找出所有有效SNI确实有点挠头。结合你描述的场景,其实核心原因是服务器端配置了基于SNI的虚拟主机,不是证书本身包含这些SNI值。下面给你几个实用的方法来排查:
1. 批量探测候选域名(最直接的方法)
既然你已经发现:发送有效SNI时,服务器会返回包含对应域名的SAN;无效SNI则返回默认的jack.whatever.com。那我们可以写个简单脚本批量测试候选域名,自动筛选出有效SNI。
比如用Bash脚本:
# 先准备一个候选域名列表文件domains.txt,每行一个域名 cat domains.txt | while read domain; do echo "正在测试: $domain" # 静默执行s_client,提取返回证书的SAN字段 san_result=$(echo -n | openssl s_client -connect {你的IP地址}:443 -servername "$domain" 2>/dev/null | openssl x509 -noout -text | grep -A2 'Subject Alternative Name') # 对比是否是默认证书的SAN if ! echo "$san_result" | grep -q "jack.whatever.com"; then echo "✅ 有效SNI: $domain" >> valid_snis.txt else echo "❌ 无效SNI: $domain" fi done
- 关于候选域名来源:可以从公司内部域名清单、常见子域名(比如www、api、test等)、或者用子域名枚举工具(比如Amass、Subfinder,注意要合规,只能扫描你有权限测试的服务器)生成。
2. 查看服务器配置(如果有访问权限)
如果你能接触到服务器的配置文件(比如Nginx、Apache),那直接看虚拟主机配置就能得到所有有效SNI:
- Nginx:找
server块里的server_name指令,每个指令后的域名就是支持的SNI(包括别名) - Apache:找
<VirtualHost>块里的ServerName和ServerAlias,这些就是对应SNI的有效域名
不过你说不管理证书,大概率也没服务器权限,这条就当补充参考。
3. 用TLS扫描工具辅助探测(进阶玩法)
一些专业的TLS扫描工具能帮你快速发现虚拟主机的痕迹:
- nmap:用
nmap --script ssl-cert -p 443 {你的IP地址}命令,结合不同SNI测试,对比返回的证书差异;也可以用ssl-enum-ciphers脚本,有时候能间接发现不同虚拟主机的加密套件差异,从而推断SNI。 - tls-scan:专门的TLS扫描工具,能批量测试SNI并返回证书信息,比手动写脚本更高效。
为啥会出现这种“证书SAN和有效SNI不匹配”的情况?
其实不是证书支持多个SNI,而是服务器端做了基于SNI的虚拟主机分流:当你发送SNI请求时,服务器会根据这个域名匹配对应的虚拟主机配置,返回该主机绑定的证书(可能包含多个SAN);如果SNI不匹配任何虚拟主机,就返回默认配置的证书(也就是你看到的jack.whatever.com)。证书本身不会存储所有允许的SNI,所有规则都在服务器配置里。
备注:内容来源于stack exchange,提问作者jackbmg




