apache通过sni在单ip上为多域名提供独立https服务,核心是在tls握手初期根据clienthello中的明文域名匹配virtualhost并加载对应证书;需满足apache≥2.2.12、openssl≥0.9.8f、mod_ssl启用且客户端支持sni,每个virtualhost必须独立配置sslcertificatefile和sslcertificatekeyfile。
apache 通过 sni(server name indication)实现在单个 ip 地址上为多个域名提供各自独立的 https 服务,核心是让服务器在 tls 握手初期就根据客户端发来的域名选择对应证书。只要满足基础环境要求,配置本身并不复杂,但细节容易出错。
确认运行环境支持 SNI
这是前提,缺一不可:
- Apache 版本 ≥ 2.2.12(推荐 2.4.8+),且编译时启用了 OpenSSL 支持(可通过
httpd -V | grep -i ssl查看) - OpenSSL 版本 ≥ 0.9.8f(实际建议 ≥ 1.0.2 或 1.1.1,以兼容 TLS 1.2/1.3 和稳定 SNI 回调)
- mod_ssl 模块已启用(Debian/Ubuntu 运行
a2enmod ssl;RHEL/CentOS 检查LoadModule ssl_module modules/mod_ssl.so是否在配置中) - 客户端需支持 SNI(IE6/WinXP、Android 2.x 等旧环境不支持;现代浏览器、curl 7.18.1+、Java 7u25+ 均支持)
每个虚拟主机必须独立配置证书路径
SNI 生效的关键在于 Apache 能按域名精确加载证书。不能把证书路径写在全局 SSL 配置里,也不能多个 <virtualhost></virtualhost> 共用同一组 SSLCertificateFile 和 SSLCertificateKeyFile。
- 每个
<virtualhost></virtualhost>块内必须显式声明自己的证书与私钥,例如:SSLCertificateFile /etc/letsencrypt/live/site-a.com/fullchain.pemSSLCertificateKeyFile /etc/letsencrypt/live/site-a.com/privkey.pem - 若使用中间证书(如 Let’s Encrypt 的 chain),加上:
SSLCertificateChainFile /etc/letsencrypt/live/site-a.com/chain.pem(Apache 2.4.8+ 可省略,因 fullchain.pem 已包含) - 避免混用证书:比如
site-a.com和site-b.com的证书不能共用一个fullchain.pem文件,否则 SNI 匹配失效,所有请求都返回第一个站点的证书
正确组织虚拟主机配置结构
Apache 2.4 不再需要 NameVirtualHost *:443,但必须确保每个 HTTPS 虚拟主机绑定到相同 IP:Port(通常是 *:443),并用 ServerName 明确标识域名。
- 示例两个站点配置片段(放在
sites-available/下单独文件或httpd-vhosts.conf中): <virtualhost><br> ServerName example.com<br> DocumentRoot /var/www/example<br> SSLEngine on<br> SSLCertificateFile /etc/ssl/certs/example.crt<br> SSLCertificateKeyFile /etc/ssl/private/example.key<br></virtualhost>
<virtualhost><br> ServerName api.example.com<br> DocumentRoot /var/www/api<br> SSLEngine on<br> SSLCertificateFile /etc/ssl/certs/api.crt<br> SSLCertificateKeyFile /etc/ssl/private/api.key<br></virtualhost>
- 配置完成后务必执行
apache2ctl configtest(Debian)或httpd -t(RHEL)验证语法,无误后再重启服务
处理不支持 SNI 的旧客户端(可选)
如果需要兼容 IE6/WinXP 等极旧环境,可设 SSLStrictSNIVHostCheck off(放在全局 SSL 配置段,如 ssl.conf 中,不能放在某个 <virtualhost></virtualhost> 内)。这样当客户端不带 SNI 时,Apache 会 fallback 到第一个定义的 HTTPS 虚拟主机证书——虽然可能不匹配域名,但至少能建立连接。生产环境多数设为 off,默认即如此。











