apache 不支持直接基于 ssl 证书序列号做黑名单访问控制,因 mod_ssl 的 sslrequire 指令不提供 serial 匹配语法且无法执行“不在列表中”逻辑;可行方案是结合 mod_rewrite 调用外部脚本或使用 mod_lua 编写校验逻辑,并确保 ca 可信验证。

Apache 本身不支持直接基于 SSL 证书序列号(Serial Number)做访问控制或黑名单。mod_ssl 提供的是 TLS 握手层的加密与身份验证能力,它能读取客户端证书(如果启用双向认证),但 不内置按序列号匹配、拒绝特定证书的访问控制指令。
为什么不能直接用序列号做黑名单
mod_ssl 的 SSLRequire 系列指令(如 SSLRequireSSL、SSLRequire)仅支持有限的证书属性匹配,例如:
- SSL_CLIENT_S_DN_CN(通用名)
- SSL_CLIENT_S_DN_O(组织名)
- SSL_CLIENT_I_DN(签发者 DN)
- SSL_CLIENT_M_SERIAL(注意:这是十六进制字符串,且 Apache 不提供直接用于 deny 的比较函数)
关键限制在于:Apache 2.4 不支持将 SSL_CLIENT_M_SERIAL 与正则或字符串列表做“不在允许列表中”这类逻辑判断,也没有类似 SSLRequire !serial=xxx 的语法。即使你拿到序列号,也无法在 .htaccess 或
可行的替代方案
要实现“基于证书序列号的业务访问黑名单”,需结合外部逻辑。以下是两种主流且生产可用的方式:
- 使用 mod_ssl + mod_rewrite + 自定义脚本校验:启用客户端证书验证(SSLVerifyClient require),在请求头中提取 SSL_CLIENT_M_SERIAL,通过 RewriteCond 调用外部 CGI 或 Lua 脚本查询黑名单数据库(如 Redis 或文本文件),返回 403 拒绝访问。
-
改用 mod_ssl + mod_authnz_external 或 mod_lua:在
或 中配置 AuthType SSL,配合 ExternalAuth 或 LuaAuthzProvider,编写 Lua 函数读取 SSL_CLIENT_M_SERIAL 并比对预置黑名单数组,返回 AUTH_DENIED。
操作要点提醒
若选择 Lua 方式(推荐轻量级部署):
- 确保已加载 mod_lua:
LoadModule lua_module modules/mod_lua.so - 在虚拟主机中启用客户端证书:
SSLVerifyClient require和SSLCACertificateFile /path/to/ca.crt - 用 Lua 获取序列号:
local serial = ngx.var.ssl_client_m_serial or ""(OpenResty)或 Apache Lua API 中的r:headers_in("SSL_CLIENT_M_SERIAL") - 黑名单建议存为哈希表(如 Lua table)或外部键值存储,避免每次读文件;序列号格式通常为十六进制大写无分隔符(如
012ABC34567890DEF),需统一大小写处理
不复杂但容易忽略:序列号本身不具备防篡改性,黑名单机制必须配合可信 CA 验证(即只信任你指定的 CA 签发的证书),否则攻击者可伪造任意序列号的自签名证书绕过检查。











