测试已启用 HTTPS 但尚未配置域名的站点
在搭建好Web站点并配置了SSL证书后,由于某些原因,还不能将正式的域名指向该该站。比如正在进行服务器迁移,必须确保新服务器一切正常,并在特定的时间才能进行切换。此时,该如何测试站点除了域名之外,已经配置正确?最显而易见的方式,其实就是修改域名解析。既然无法修改公共的DNS记录,那么可以修改本地的 hosts 文件;除此之外,还可以使用 cURL 或者编程实现。
修改本地 hosts 文件设置 IP 🔗
不同系统的 hosts 文件位置不同。在 macOS 和 Linux,它位于 /etc/hosts
;而在 Windows系统,它位于 c:\Windows\System32\Drivers\etc\hosts
。无论在哪种系统,都需要管理员权限才可以修改。比如记录为:
10.20.30.1 myapp.local
修改之后,重启浏览器即可测试站点。如果在使用 Chrome 浏览器,那么可以在 Developer Tools 的 Network 选项卡显示 Remote Address;这样在访问站点时,可进一步确认域名指向正确。
通过 SNI 访问服务器 🔗
对于 HTTP 请求,通常我们可以使用 IP 地址访问,并且设置 Host
请求头,服务器即可判断客户端请求的域名。但是,对于 HTTPS 的站点,在处理请求之前,客户端会与服务器建立 TLS 连接。在建立连接的过程中,客户端就会检查服务器的证书。此时服务器证书与请求的IP或者其他域名不配置,证书校验就会失败。因此,设置 Host
请求头是没有用的。
为此,客户端需要使用 SNI,告诉服务器请求的域名。
SNI 是 “Server Name Indication” 的缩写,即服务器名称指示 ,是一种 TLS(Transport Layer Security,传输层安全协议,其前身是 SSL,Secure Sockets Layer)扩展,用于在建立 TLS 连接时,客户端向服务器发送它想要访问的主机名。
以下示例中,假定站点的正式域名为 myapp.local
,而站点暂时的域名为 myapp.cdn.local
。我们最终期望使用前者访问站点,但目前前者并未指向站点;而 myapp.cdn.local
已经指向站点。
使用 cURL 设置 SNI 🔗
使用 --connect-to
参数即可:
curl --connect-to myapp.local:443:myapp.cdn.local:443 https://myapp.local
另一种方式使用 --resolve
参数。
使用程序设置 SNI 🔗
想在程序中使用 SNI,那么需要一些特殊的设置。我尝试使用 Python 实现类似 curl
的效果,没搞定;但是使用 Go 语言,使用标准库即可正常访问站点。代码如下:
package main
import (
"crypto/tls"
"log"
"net/http"
"net/http/httputil"
)
func main() {
requestURL := "https://mapp.cdn.local"
serverName := "myapp.local"
transport := &http.Transport{
TLSClientConfig: &tls.Config{
ServerName: serverName,
},
}
client := &http.Client{
Transport: transport,
}
resp, err := client.Get(requestURL)
if err != nil {
log.Fatalf("Failed to make request: %v", err)
}
defer resp.Body.Close()
dump, err := httputil.DumpResponse(resp, true)
if err != nil {
log.Fatalf("Failed to dump response: %v", err)
}
log.Printf("%s", dump)
}