最后更新时间: | 查看所有文档
有时人们希望获得“localhost”主机名的证书,无论是用于本地开发,还是与需要与 Web 应用程序通信的本地应用程序一起分发。Let's Encrypt 无法提供“localhost”的证书,因为没有人拥有它,它也没有像“.com”或“.net”一样根植于顶级域名。您可以设置自己的域名,该域名恰好解析到127.0.0.1
,并使用 DNS 挑战获取其证书。但是,这通常不是一个好主意,而且还有更好的选择。
用于本地开发
如果您正在开发 Web 应用程序,则运行像 Apache 或 Nginx 这样的本地 Web 服务器并在 Web 浏览器中通过http://localhost:8000/
访问它很有用。但是,Web 浏览器在 HTTP 页面和 HTTPS 页面上的行为存在细微差别。主要区别在于:在 HTTPS 页面上,任何从 HTTP URL 加载 JavaScript 的请求都会被阻止。因此,如果您在本地使用 HTTP 进行开发,您可能会添加一个在开发机器上可以正常工作的脚本标签,但在部署到 HTTPS 生产网站时会中断。为了捕获此类问题,在本地 Web 服务器上设置 HTTPS 很有用。但是,您不希望一直看到证书警告。如何在本地获得绿色锁?
最佳选择:生成您自己的证书,无论是自签名证书还是本地根签名证书,并在操作系统的信任存储中信任它。然后在本地 Web 服务器中使用该证书。有关详细信息,请参见下文。
用于与 Web 应用程序通信的本地应用程序
有时,开发人员希望提供可与网站一起使用的可下载本地应用程序,以提供额外的功能。例如,Dropbox 和 Spotify 桌面应用程序会扫描来自您机器上的所有文件的,而 Web 应用程序无法执行此操作。一种常见的方法是这些本地应用程序在 localhost 上提供 Web 服务,并让 Web 应用程序通过 XMLHTTPRequest (XHR) 或 WebSockets 向其发出请求。Web 应用程序几乎总是使用 HTTPS,这意味着浏览器将禁止它向非安全 URL 发出 XHR 或 WebSockets 请求。这称为混合内容阻止。为了与 Web 应用程序通信,本地应用程序需要提供安全的 Web 服务。
幸运的是,现代浏览器认为http://127.0.0.1:8000/
是一个“潜在可信的” URL,因为它引用了回环地址。发送到127.0.0.1
的流量保证不会离开您的机器,因此被认为可以自动防止网络拦截。这意味着,如果您的 Web 应用程序是 HTTPS,并且您在127.0.0.1
上提供本地应用程序 Web 服务,则两者可以通过 XHR 愉快地通信。不幸的是,localhost 还没有得到同样的待遇。此外,WebSockets 对于这两个名称都没有得到这种待遇。
您可能很想通过在全局 DNS 中设置一个恰好解析为127.0.0.1
的域名(例如,localhost.example.com
),获取该域名的证书,将该证书和相应的私钥与本地应用程序一起发布,并告诉您的 Web 应用程序与https://localhost.example.com:8000/
通信而不是http://127.0.0.1:8000/
来解决这些限制。不要这样做。这会让您的用户面临风险,并且您的证书可能会被吊销。
通过引入域名而不是 IP 地址,您使攻击者能够在中间(MitM)进行 DNS 查找并注入指向不同 IP 地址的响应。然后,攻击者可以假装是本地应用程序并将虚假响应发送回 Web 应用程序,这可能会危害您在 Web 应用程序端的帐户,具体取决于它的设计方式。
在这种情况下,成功的 MitM 是可能的,因为为了使其正常工作,您必须将证书的私钥与本地应用程序一起发布。这意味着任何下载本地应用程序的人都可以获得私钥的副本,包括攻击者。这被认为是您私钥的泄露,如果您的证书颁发机构 (CA) 意识到这一点,则必须吊销您的证书。许多本地应用程序因其证书被发布私钥而被吊销。
不幸的是,这使得本地应用程序没有很多安全可靠的选择来与它们相应的网站通信。如果浏览器进一步加强从 Web 访问 localhost 的权限,情况可能会变得更加棘手。
另请注意,导出提供特权本地 API 的 Web 服务本身就存在风险,因为您未经授权的网站可能会访问它们。如果您选择这条路线,请务必了解跨域资源共享,使用 Access-Control-Allow-Origin,并确保使用内存安全的 HTTP 解析器,因为即使您不允许访问的来源也可以发送预检请求,这可能会利用解析器中的漏洞。
制作和信任您自己的证书
任何人都可以在没有 CA 的帮助下制作自己的证书。唯一的区别是,您自己制作的证书不会被任何人信任。对于本地开发来说,这很好。
使用此 openssl 命令为 localhost 生成私钥和自签名证书的最简单方法是
openssl req -x509 -out localhost.crt -keyout localhost.key \
-newkey rsa:2048 -nodes -sha256 \
-subj '/CN=localhost' -extensions EXT -config <( \
printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
然后,您可以使用 localhost.crt 和 localhost.key 配置本地 Web 服务器,并将 localhost.crt 安装到本地信任根列表中。
如果您希望在开发证书中获得更多现实性,则可以使用minica生成您自己的本地根证书,并签发由它签名的最终实体(又称叶子)证书。然后,您将导入根证书而不是自签名的最终实体证书。
您还可以选择使用带有点的域名,例如www.localhost
,方法是在 /etc/hosts 中将其添加为127.0.0.1
的别名。这会 subtly 更改浏览器处理 cookie 存储的方式。