我正在尝试使用自签名证书设置 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会话并协商客户端和服务器之间的安全权限。默认情况下,您的机器已经信任来自许多证书颁发机构的一组证书,例如:GoDaddy、IdenTrust、DigiCert等。当您是证书颁发机构(自签名证书方式)时,您需要向客户端提供证书,并且客户端需要信任该证书。所以你需要做的是:
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.crt到ca-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 Os、Windows、Linux。您将在此github 存储库中找到完整的示例。
创建目录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)
| 归档时间: |
|
| 查看次数: |
15623 次 |
| 最近记录: |