用户在 Apache 上配置基于域名的国密 SSL证书虚拟主机,关键是从 `NameVirtualHost` 指令入手,结合 SNI 技术实现多站点共享端口,并通过 `GmSSL` 编译版 Apache 和特定模块来支持国密算法。下面是具体的配置方案:
1. 环境前提
配置前,Apache 版本必须在 2.2.12 以上,并且编译时需支持 SNI(这是多域名 SSL 虚拟主机的基础)。由于 原生 Apache 系列并不支持国密算法,你需要先完成以下两步:
安装 GmSSL:下载并安装 `GmSSL`(一个支持国密算法(SM2/SM3/SM4)的 OpenSSL 分支)。
重新编译 Apache:将 Apache 与 `GmSSL` 库链接,进行重新编译。编译时,`./configure` 参数中要包含 `--with-ssl=/path/to/gmssl`,以指向你的 `GmSSL` 安装路径。
2. 双证书配置示例
当前,很多浏览器还不原生支持国密算法,为保证网站对所有访客都可访问,最佳实践是采用 SM2 国密证书与 RSA 证书并存的**双证书部署方案。这能确保国密浏览器使用 SM2 证书,而普通浏览器则回退到 RSA 证书。
下面是一个完整的 Apache 虚拟主机 `ssl.conf` 配置示例,它通过 **NameVirtualHost** 和 SNI 技术,将两个不同域名的 HTTPS 站点部署在同一个 IP 地址上。
apache
# 1. 启用虚拟主机并监听443端口
Listen 443
# 核心指令:声明监听443端口的基于域名的虚拟主机
NameVirtualHost *:443
# 2. 为第一个域名 (example1.com) 启用双证书
<VirtualHost *:443>
ServerName example1.com
DocumentRoot "/var/www/html/example1"
# 启用SSL引擎
SSLEngine on
# --- RSA证书配置 ---
SSLCertificateFile "/etc/ssl/rsa/example1.com.crt"
SSLCertificateKeyFile "/etc/ssl/rsa/example1.com.key"
SSLCertificateChainFile "/etc/ssl/rsa/ca_bundle.crt"
# --- 国密 SM2 证书配置 (通过 GmSSL 模块启用) ---
# 注意:此处参数因 GmSSL 模块实现而异,请查阅相关文档
GMSSLCertificateFile "/etc/ssl/sm2/example1.com.sm2.crt"
GMSSLCertificateKeyFile "/etc/ssl/sm2/example1.com.sm2.key"
# 配置国密专用的加密套件
SSLCipherSuite "ECDHE-SM2-WITH-SM4-GCM-SM3:HIGH:!aNULL"
# 可选配置:优先使用服务器端推荐的加密套件顺序
SSLHonorCipherOrder on
<Directory "/var/www/html/example1">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
# 3. 为第二个域名 (example2.com) 启用双证书
<VirtualHost *:443>
ServerName example2.com
DocumentRoot "/var/www/html/example2"
SSLEngine on
# --- RSA证书配置 ---
SSLCertificateFile "/etc/ssl/rsa/example2.com.crt"
SSLCertificateKeyFile "/etc/ssl/rsa/example2.com.key"
SSLCertificateChainFile "/etc/ssl/rsa/ca_bundle.crt"
# --- 国密 SM2 证书配置 ---
GMSSLCertificateFile "/etc/ssl/sm2/example2.com.sm2.crt"
GMSSLCertificateKeyFile "/etc/ssl/sm2/example2.com.sm2.key"
# 配置国密专用的加密套件,与上例保持一致
SSLCipherSuite "ECDHE-SM2-WITH-SM4-GCM-SM3:HIGH:!aNULL"
SSLHonorCipherOrder on
<Directory "/var/www/html/example2">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
配置指令说明
`Listen 443` 与 `NameVirtualHost *:443`:这是实现单 IP 多 HTTPS 站点的核心。`Listen` 指令通知 Apache 在 443 端口监听,而 `NameVirtualHost` 指令则声明了所有来自 443 端口的请求将使用基于域名的虚拟主机进行分发。
`<VirtualHost *:443>`:配置块中的 `*` 代表任意 IP 地址,这使其能够与 `NameVirtualHost` 声明相匹配。
`GMSSLCertificateFile` 等:这是启用国密算法的关键,需要通过 `GmSSL` 模块加载并配置 SM2 证书和对应的 SM4 加密算法套件。
`SSLHonorCipherOrder on`:该指令指示 Apache 优先使用服务器端配置的加密套件顺序,而非客户端的偏好,建议开启以提高安全性。
3. 配置验证
1. 重启 Apache:完成配置后,重启 Apache 服务使改动生效。
2. 验证国密通道(使用国密浏览器)**:在支持国密算法的浏览器(如密信浏览器、红莲花浏览器)中访问 `https://example1.com`,检查地址栏是否出现安全锁标识。
3. 验证 RSA 通道(使用普通浏览器):在 Chrome、Firefox 等常用浏览器中访问相同域名,也应能正常打开 HTTPS 页面,这表明 RSA 回退配置成功。
4. 常见问题排查
Apache 启动报错 "Cannot define multiple Listeners on the same IP:port"
最常见的原因是 SSL 配置文件(如 `ssl.conf`)被重复加载了多次。请检查 Apache 的主配置文件(如 `httpd.conf`),确保 `ssl.conf` 没有被重复引用多次。
Apache 启动时报错 "name-based virtual host in conjunction with SSL!!"
这个警告信息意味着你的 Apache 没有正确启用或识别 SNI 支持。请先确认你的 Apache 版本在 2.2.12 以上,并检查编译时是否对 OpenSSL 启用了 TLS 扩展支持。可以通过 `httpd -V` 查看 Apache 版本和编译参数。
配置验证报错 "The GMSSLCertificateFile directive is not recognized"
这个错误是因为缺少国密模块支持,说明当前的 Apache 是官方版本,没有被重新编译或没有链接到 `GmSSL` 库。你需要重新根据 `GmSSL` 文档编译部署。
浏览器(或代理)不支持,应如何处理?
部分老旧或特定配置的客户端可能不支持 SNI。在这种情况下,如果必须保证服务可用,可以为需要单独证书的域名配置独立的 IP 地址或端口,或使用一张包含所有域名的多域名(SAN)证书。