Apache在一个IP上绑定多张HTTPS证书的核心是SNI机制:客户端在TLS握手初期明文发送域名,服务器据此加载对应证书;需满足Apache≥2.2.12、OpenSSL≥0.9.8f、mod_ssl启用,且每个<VirtualHost *:443>块内独立配置SSLEngine on、专属证书路径及ServerName。

Apache 在一个 IP 上绑定多张 HTTPS 证书,核心就是靠 TLS 层的 SNI(Server Name Indication)机制。它让客户端在 TLS 握手最开始就明文发送目标域名,服务器据此加载对应证书,从而避免“所有域名都返回第一个配置的证书”这种常见错配。
确保底层支持 SNI
不是装了 Apache 就能用 SNI,必须同时满足:
- Apache 版本 ≥ 2.2.12(生产环境建议 ≥ 2.4.8);运行 httpd -V | grep -i ssl 查看 OpenSSL 版本,需显示类似 OpenSSL 1.1.1w;若输出为空或含 BoringSSL,说明未正确链接 OpenSSL
- mod_ssl 模块已启用:Debian/Ubuntu 执行 a2enmod ssl 并重启;RHEL/CentOS 检查 httpd.conf 中 LoadModule ssl_module modules/mod_ssl.so 是否取消注释
- 操作系统 OpenSSL 库版本 ≥ 0.9.8f(现代系统基本达标,但 CentOS 6 等旧系统需确认)
每个域名配专属证书路径
SNI 生效的前提是 SSL 配置完全隔离——不能混用、不能写在全局配置里:
Apache 2.4.62 官方 tar.gz 源码包是 Linux 及类 Unix 系统构建 Web 服务器的核心基础。通过源码编译安装,开发者能够灵活定制模块、优化性能并精准控制安装路径,满足多样化的业务需求。
- 为 site-a.com 单独准备证书文件,例如:
/etc/ssl/certs/site-a.com.crt(或 fullchain.pem)、/etc/ssl/private/site-a.com.key - 为 site-b.net 单独准备另一套,路径必须不同,例如:
/etc/ssl/certs/site-b.net.crt、/etc/ssl/private/site-b.net.key - 禁止在 ssl.conf 或主配置中设置 SSLCertificateFile;所有证书路径必须放在各自的 <VirtualHost *:443> 块内部
- 使用 Let’s Encrypt 时,应分别运行:
certbot --apache -d site-a.com -d www.site-a.com
和
certbot --apache -d site-b.net -d www.site-b.net
避免跨域名复用同一组证书文件
正确编写虚拟主机配置
Apache 2.4 不再需要 NameVirtualHost *:443,直接定义多个 <VirtualHost *:443> 即可。每个块必须完整、独立:
- 每个块内必须显式包含:SSLEngine on、SSLCertificateFile、SSLCertificateKeyFile,推荐也加上 SSLCertificateChainFile(或用 fullchain.pem 合并)
- 必须指定 ServerName,并用 ServerAlias 覆盖所有访问入口(如 www、api 子域)
- 确保主配置中存在 Listen 443(通常在 ports.conf 或 httpd.conf 中)
- 用 apachectl -t -D DUMP_VHOSTS 查看实际生效的虚拟主机列表及匹配顺序,确认无冲突或默认兜底块干扰
验证证书与域名是否严格匹配
即使配置全对,证书本身不匹配也会触发浏览器警告:
- 证书的 Subject Alternative Name (SAN) 字段必须包含当前访问的完整域名(如 example.com 和 www.example.com 需同时列出)
- 若用自签名或私有 CA 证书,客户端需信任其根证书;Let’s Encrypt 等公信证书一般无此问题
- 可用 openssl s_client -connect site-a.com:443 -servername site-a.com -showcerts 直接检查握手时返回的证书是否为你配置的那张

















