如何在golang中使用自签名证书设置https服务器

xop*_*oww 5 ssl https go

我正在尝试使用自签名证书设置 https 服务器 ( http.ListenAndServeTLS()),以侦听来自服务的 webhook 更新(我确信该服务使用此类证书没有问题),但它失败并不断打印

<date> <time> http: TLS handshake error from <IP>: remote error: tls: bad certificate
Run Code Online (Sandbox Code Playgroud)

我寻找解决方案并尝试了几种(InsecureSkipVerify在 中设置为 true TLSConfig,将我的证书添加到Certificates配置字段或使用自签名证书签署另一个证书并将后者附加到RootCAs),但没有解决问题(最后一个解决方案毫不奇怪地将错误更改为unknown certificate authority)。

正如我所提到的,我很确定问题与我尝试监听的服务无关,因此在 Go 中设置服务器时我一定缺少一些非常简单的东西。我的代码看起来像这样:

    rootCAs, _ := x509.SystemCertPool()
    if rootCAs == nil {
        rootCAs = x509.NewCertPool()
    }
    certs, _ := ioutil.ReadFile(CA_PATH)
    _ = rootCAs.AppendCertsFromPEM(certs);

    server := http.Server{
        Addr: "",
        Handler: nil,
        TLSConfig: &tls.Config{
            InsecureSkipVerify: true,
            Certificates: []tls.Certificate{ my_cert },
            RootCAs: rootCAs,
        },
    }
    fmt.Println(server.ListenAnsServeTLS(PEM_PATH, KEY_PATH))
Run Code Online (Sandbox Code Playgroud)

Lui*_*lis 10

正如RFC2246中提到的,握手协议建立TLS会话并协商客户端和服务器之间的安全权限。默认情况下,您的机器已经信任来自许多证书颁发机构的一组证书,例如:GoDaddyIdenTrustDigiCert等。当您是证书颁发机构(自签名证书方式)时,您需要向客户端提供证书,并且客户端需要信任该证书。所以你需要做的是:

openssl工具安装后,运行以下命令:

openssl req -new -subj "/C=US/ST=Utah/CN=localhost" -newkey rsa:2048 -nodes -keyout localhost.key -out localhost.csr
Run Code Online (Sandbox Code Playgroud)

该命令生成一个localhost.key文件,该文件是私钥,localhost.csr也是包含公钥的证书签名请求 (CSR)。CN传入的字段-subj是最重要的字段,因为某些浏览器(例如 chrome)需要该信息。CN表示通用名称,它是您希望使用 SSL 保护的域名。然后,您需要生成证书文件:

openssl x509 -req -days 365 -in localhost.csr -signkey localhost.key -out localhost.crt
Run Code Online (Sandbox Code Playgroud)

localhost.crt文件是由上面的命令生成的,它是由您自己的localhost.key私钥签名的自签名证书。该x509标志规定了 SSL/TLS 证书的标准格式,即X.509.

之后,您需要使用证书和密钥来为https自签名服务器提供服务:

log.Fatal(http.ListenAndServeTLS("8081", "localhost.crt","localhost.key", router))
Run Code Online (Sandbox Code Playgroud)

在客户端,非常重要的是它信任服务器证书,而不是使用curl的-k参数,该参数将忽略TLS协议。如果您使用的是 Linux 操作系统,请安装该ca-certificates软件包,然后将其复制localhost.crtca-certificates文件夹:

cp localhost.crt /usr/local/share/ca-certificates/localhost.crt
Run Code Online (Sandbox Code Playgroud)

最后使用以下命令信任该证书:

update-ca-certificates
Run Code Online (Sandbox Code Playgroud)

如果您使用的操作系统与 Linux 不同,您可以执行以下步骤之一:Mac OsWindowsLinux您将在此github 存储库中找到完整的示例。


has*_*chi 6

创建目录golangssl并进入

mkdir golangssl
cd golangssl
Run Code Online (Sandbox Code Playgroud)

生成自签名密钥和证书(如果尚未安装,请安装 openssl)

openssl genrsa -out server.key 2048
openssl ecparam -genkey -name secp384r1 -out server.key
openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
Run Code Online (Sandbox Code Playgroud)

创建文件server.go,内容如下

package main

import (
    "log"
    "net/http"
)

func SecureServer(w http.ResponseWriter, req *http.Request) {
    w.Header().Set("Content-Type", "text/plain")
    w.Write([]byte("Secure Hello World.\n"))
}

func main() {
    http.HandleFunc("/secure", SecureServer)
    err := http.ListenAndServeTLS(":443", "server.crt", "server.key", nil)
    if err != nil {
            log.Fatal("ListenAndServe: ", err)
    }
 }
Run Code Online (Sandbox Code Playgroud)

运行服务器(需要root权限,因为绑定了443端口)

sudo go run server.go
Run Code Online (Sandbox Code Playgroud)

执行请求(-k用于忽略自签名证书)

 curl -k https://localhost/secure
Run Code Online (Sandbox Code Playgroud)

输出应该是

 Secure Hello World.
Run Code Online (Sandbox Code Playgroud)