是否可以使用 net/http 在 golang 中托管多个域 TLS?

Posted

技术标签:

【中文标题】是否可以使用 net/http 在 golang 中托管多个域 TLS?【英文标题】:Is it possible to host multiple domain TLS in golang with net/http? 【发布时间】:2016-06-09 02:07:17 【问题描述】:

我有多个具有不同证书的域(比如说 abc.com 和 xyz.org)。是否可以使用基于主机名的密钥和证书而无需深入底层和 net.Listen 等。只需使用简单的 http.ListenAndServeTLS(...) 或类似的? 基本上和nginx一样。

【问题讨论】:

【参考方案1】:

BuildNameToCertificate() 将从证书中嗅探主机名。如果没有匹配 SNI 信息,则它为 [0] 提供服务。 https://golang.org/src/crypto/tls/common.go?s=18204:18245#L947

Go 1.14 更新 - 请参阅 https://github.com/golang/go/commit/eb93c684d40de4924fc0664d7d9e98a84d5a100b

package main

import (
    "crypto/tls"
    "net/http"
    "time"

    "log"
)

func myHandler(w http.ResponseWriter, r *http.Request) 
    w.Write([]byte("tls"))


func main() 
    t := log.Logger
    var err error
    tlsConfig := &tls.Config
    tlsConfig.Certificates = make([]tls.Certificate, 3)
    // go http server treats the 0'th key as a default fallback key
    tlsConfig.Certificates[0], err = tls.LoadX509KeyPair("test0.pem", "key.pem")
    if err != nil 
        t.Fatal(err)
    
    tlsConfig.Certificates[1], err = tls.LoadX509KeyPair("test1.pem", "key.pem")
    if err != nil 
        t.Fatal(err)
    
    tlsConfig.Certificates[2], err = tls.LoadX509KeyPair("test2.pem", "key.pem")
    if err != nil 
        t.Fatal(err)
    

    // as of go 1.14 this line is no longer needed
    // load the certs as above and skip BuildNameToCertificate()
    tlsConfig.BuildNameToCertificate()

    http.HandleFunc("/", myHandler)
    server := &http.Server
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
        TLSConfig:      tlsConfig,
    

    listener, err := tls.Listen("tcp", ":8443", tlsConfig)
    if err != nil 
        t.Fatal(err)
    
    log.Fatal(server.Serve(listener))

【讨论】:

服务器没有任何 StartTLS 方法! 用一个工作示例更正。这个更完整的示例正确地创建了侦听器并启动了服务器。 我应该如何在这里添加我的路由器? @foo 我正在使用 gorilla mux 进行路由。我之前只使用了一个证书。所以,我使用了 http.ListenAndServe(port,cert,key,router)。如何在这里使用相同的路由器? 提醒 tls.NameToCertificate 已弃用。 NameToCertificate 仅允许将单个证书与给定名称相关联。将该字段留空,让库从证书中选择第一个兼容链。

以上是关于是否可以使用 net/http 在 golang 中托管多个域 TLS?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Golang 的 net/http 包读取流响应正文?

Golang“net/http”错误:未定义:DetectContentType

golang 性能测试pprof

如何在 golang net/http 中使用 Transport 添加头信息

Golang net/http 爬虫[1]

Golang使用net/http包写http服务端