对特定主机使用 TLS/SSL 客户端身份验证

Using TLS/SSL Client Authentication for specific hosts

如何在使用像 httprouter by julienschmidt 这样的反向代理时对特定主机使用 TLS/SSL 客户端身份验证?

我可以使用 http.DefaultTransport 在全局事务中设置客户端证书。

transport := &http.Transport{
    TLSClientConfig: &tls.Config{
        Certificates: []tls.Certificate{cert},
    },
}

http.DefaultTransport = transport

但只想对特定主机使用客户端证书,例如:

  1. host1 的 cert1
  2. host2 的 cert2
  3. 其他客户端证书

更新

我预计回调 GetConfigForClientHandlerGetCertificateHandler 将被调用。此时我可以对 info.ServerName 做出反应。但是只有 GetClientCertificate 被调用,没有关于目标 info.ServerName.

的信息
func main() {
    transport := &http.Transport{
        TLSClientConfig: &tls.Config{
            GetConfigForClient:   GetConfigForClientHandler,
            GetClientCertificate: GetClientCertificateHandler,
            GetCertificate:       GetCertificateHandler,
        },
    }

    http.DefaultTransport = transport

    // Host which enforce client certificate authentication
    resp, err := http.Get("https://example.com")
    if err != nil {
        fmt.Println("Error", err)
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}

func GetClientCertificateHandler(info *tls.CertificateRequestInfo) (*tls.Certificate, error) {
    fmt.Println("GetClientCertificateHandler")
    panic("GetClientCertificateHandler")
}

func GetConfigForClientHandler(info *tls.ClientHelloInfo) (*tls.Config, error) {
    fmt.Println("GetConfigForClientHandler for:", info.ServerName)
    panic("GetConfigForClientHandler")
}

func GetCertificateHandler(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
    fmt.Println("GetCertificateHandler for:", info.ServerName)
    panic("GetCertificateHandler")
}
  1. 创建一个为所有主机共享的 TLS 配置。可能你不需要在那里设置太多。但是您想设置一个 Config.GetConfigForClient 处理程序。
  2. 在该处理程序中,您检查 ClientHelloInfo.ServerName. That is the requested host. You then modify the TLS config to require client auth there (Config.ClientAuth).
  3. tls.NewListener
  4. 包裹你的net.Listener
  5. http.Serve 中使用您的 TLS net.Listener(您可以在此处使用 httprouter)