一、问题根源:为什么浏览器不信任内网证书?
首先,我们需要理解浏览器显示"不安全"的根本原因。这通常并非你的Web服务本身有问题,而是因为:
证书颁发机构(CA)的策略限制:
所有公共信任的CA(如 Let's Encrypt, DigiCert, GeoTrust 等)遵循 CA/Browser Forum 基线要求,明确禁止为公网无法解析的内部IP地址(如 192.168.x.x, 10.x.x.x, 172.16.x.x)和保留域名(如 .local)签发公开信任的SSL证书。
这是为了防止证书被滥用和仿冒,保障整个互联网PKI体系的安全。
证书主题不匹配:
你使用的自签名证书或为域名签发的证书,其Subject Alternative Name (SAN)字段中不包含你正在访问的内网IP地址。
所以,我们的解决方案都围绕着如何"绕过"或"适应"这一规则展开。
二、方案一:使用域名替代IP(推荐首选)
这是最优雅、最接近生产环境的解决方案。核心思想是:为一个公网可解析的域名,配置指向内网IP的DNS记录。
实施步骤:
拥有一个域名:
你需要拥有一个在互联网上注册的合法域名(例如 example.com)。这可以是你在阿里云万网购买的任意域名。
创建DNS A记录:
在你的域名DNS管理面板中,添加一条A记录,将一个子域名解析到你的内网IP。
示例:
记录类型:A
主机记录:dev 或 internal 或 nas (根据用途自定义)
记录值:192.168.1.100 (你的内网服务器IP)
这样,你就得到了一个指向内网的完整域名:dev.example.com。
申请并部署证书:
现在,你可以使用这个域名 dev.example.com,通过任何公共CA(如阿里云SSL证书服务提供的免费DV证书,或 Let's Encrypt)申请一个完全可信的SSL证书。
关键点:CA只验证你对域名 dev.example.com 的所有权(通过DNS解析验证),它并不关心这个域名最终解析到哪里。即使它解析到内网IP,证书依然有效。
内网DNS解析(可选但重要):
为了让内网用户也能通过 dev.example.com 访问,你需要在内网的DNS服务器(如路由器或专门的DNS服务)上,同样配置一条A记录,将 dev.example.com 指向 192.168.1.100。这样,无论用户在内网还是外网(通过VPN),都能正确解析。
优势:
✅ 获得浏览器100%的信任(小绿锁)。
✅ 证书自动续签,无需手动干预(使用ACME客户端)。
✅ 符合安全最佳实践,便于管理。
适用场景:所有拥有公网域名的场景,是最推荐的方案。
三、方案二:搭建私有PKI/根证书(适用于企业)
如果你没有公网域名,或者需要为大量内网服务签发证书,搭建一个私有的公钥基础设施是最专业的选择。
实施步骤:
创建私有根证书:
使用 OpenSSL 或 cfssl 等工具,在自己的服务器上创建一个自签名的根证书。
将根证书设为系统信任:
将这个自签名的根证书导入到所有需要访问该内网服务的客户端设备(电脑、手机等)的"受信任的根证书颁发机构"存储区。
Windows:通过组策略或手动安装到"受信任的根证书颁发机构"。
macOS:使用"钥匙串访问"添加,并设置为"始终信任"。
Linux:复制到 /usr/local/share/ca-certificates/ 并运行 update-ca-certificates。
手机:下载证书文件并在设置中安装为CA证书。
用私有根证书签发服务器证书:
使用你的私有CA,为你的内网IP地址签发服务器证书。在生成证书签名请求时,务必在 subjectAltName 字段中明确指定你的内网IP。
示例 OpenSSL 配置文件 san.conf:
ini
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = CN
ST = Zhejiang
L = Hangzhou
O = MyCompany
OU = IT
CN = 192.168.1.100 # 你的内网IP
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
IP.1 = 192.168.1.100 # 再次指定内网IP
在Web服务器上配置证书:
将签发出的服务器证书和私钥部署到你的Nginx、Apache等Web服务器上。
优势:
✅ 高度可控,可以为任意内网IP或域名签发证书。
✅ 适合大规模、标准化的企业内网环境。
劣势:
❌ 需要在所有客户端手动部署根证书,移动端和IoT设备管理成本高。
三、方案三:使用mkcert快速生成本地开发证书(适用于开发)
对于个人开发者或小团队,mkcert 是一个完美的工具。它简化了方案二的流程,实现了"一键信任"。
实施步骤:
安装mkcert:
macOS: brew install mkcert
Linux: 参考GitHub releases页面下载二进制文件。
Windows: choco install mkcert 或手动下载exe。
安装本地CA:
在命令行执行 mkcert -install。这个命令会在你的系统上创建一个本地CA,并自动将其设置为信任。
为内网IP生成证书:
mkcert 192.168.1.100 localhost 127.0.0.1 ::1 myapp.local
你可以一次性为多个IP和域名生成一个证书。命令会生成两个文件:192.168.1.100+3-key.pem (私钥) 和 192.168.1.100+3.pem (证书)。
配置Web服务器:
在Nginx配置中指向这两个文件。
nginx
server {
listen 443 ssl;
server_name 192.168.1.100;
ssl_certificate /path/to/192.168.1.100+3.pem;
ssl_certificate_key /path/to/192.168.1.100+3-key.pem;
...
}
优势:
✅ 极其简单快捷,几乎是零配置。
✅ 生成的证书在安装过mkcert CA的本机上被完全信任。
劣势:
❌ 信任仅限于安装了该CA的本地计算机,不适合生产或跨团队共享。
四、总结与方案选择
方案 适用场景 优点 缺点
方案一:域名解析 拥有公网域名,需要长期稳定服务 浏览器完全信任,易于管理续签 需要拥有并管理一个公网域名
方案二:私有PKI 企业内网,大量服务,高安全性要求 高度可控,标准化 客户端部署复杂,维护成本高
方案三:mkcert 个人开发、测试环境 极其简单、快速 仅限本地信任,不适合生产
最终建议:
个人开发:毫不犹豫地选择 mkcert。
中小型企业/团队:强烈推荐方案一,成本低、效果好、一劳永逸。
大型企业/金融机构:采用方案二,建立完整的私有PKI体系,满足安全和合规要求。
希望这篇详细的指南能帮助你彻底解决内网SSL证书的信任问题!如果你有更多疑问,欢迎在评论区交流。
互动话题:
你在为内网服务配置HTTPS时还遇到过哪些"坑"?你使用的是哪种方案?有没有更好的工具或技巧分享?欢迎在评论区留下你的经验!