如何使用错误的证书进行https请求?

top*_*kip 110 ssl https go

说我想以https://golang.org编程方式获得.目前golang.org(ssl)有一个错误的证书,*.appspot.com当我运行时,它发布给了:

package main

import (
    "log"
    "net/http"
)

func main() {
    _, err := http.Get("https://golang.org/")
    if err != nil {
        log.Fatal(err)
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到了(正如我所料)

Get https://golang.org/: certificate is valid for *.appspot.com, *.*.appspot.com, appspot.com, not golang.org
Run Code Online (Sandbox Code Playgroud)

现在,我想自己信任这个证书(想象一下我可以验证指纹等的自发证书):我如何提出请求并验证/信任证书?

我可能需要使用openssl下载证书,将其加载到我的文件中并填充tls.Configstruct!

cyb*_*lia 241

安全说明:禁用安全检查很危险,应该避免

您可以针对默认客户端的所有请求全局禁用安全检查:

package main

import (
    "fmt"
    "net/http"
    "crypto/tls"
)

func main() {
    http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
    _, err := http.Get("https://golang.org/")
    if err != nil {
        fmt.Println(err)
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以禁用客户端的安全检查:

package main

import (
    "fmt"
    "net/http"
    "crypto/tls"
)

func main() {
    tr := &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }
    client := &http.Client{Transport: tr}
    _, err := client.Get("https://golang.org/")
    if err != nil {
        fmt.Println(err)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我想知道在哪里放置一个可信证书,以便在没有`InsecureSkipVerify:true`的情况下使用连接.那可能吗? (17认同)
  • `NameToCertificate`可能会有所帮助,请参阅`tls.Config`文档:http://golang.org/pkg/crypto/tls/#Config (7认同)
  • 很多人最终试图禁用主机名检查(不完全禁用证书检查).这是错误的答案.Go要求您在tls配置中设置ServerName以匹配您连接的主机的CN(如果它不是您连接的DNS名称).InsecureSkipVerify并不比端口的普通远程telnet更安全.此设置无身份验证.用户ServerName而不是! (7认同)
  • 注意:像这样创建的传输对于其大多数字段使用零值,因此**将丢失所有默认值**.正如[以下答案](/sf/answers/3220794881/)建议的那样,您可能希望将它们复制过来.我们有很多乐趣搞清楚[为什么我们的文件描述符用完了](http://muratknecht.de/tech/pitfalls-disabling-ssl-verification-with-insecureskipverify-golang/),因为我们输了`Dialer.Timeout`. (6认同)

Rob*_*Rob 16

所有这些答案都是错误的!不要InsecureSkipVerify用于处理与主机名不匹配的CN.转到开发商不明智地是坚定的关于不禁用主机名检查(其中有合法的用途-隧道,NATS,共享群集证书等),同时也有一些看起来类似,但实际上完全忽略证书检查.您需要知道证书有效并由您信任的证书签名.但在常见情况下,您知道CN与您连接的主机名不匹配.对于那些,请ServerName继续tls.Config.如果tls.Config.ServerName== remoteServerCN,则证书检查将成功.这就是你想要的. InsecureSkipVerify表示没有认证; 这对于一个中间人而言已经成熟; 打败使用TLS的目的.

有一个合法用途InsecureSkipVerify:使用它连接到主机并获取其证书,然后立即断开连接.如果您设置要使用的代码InsecureSkipVerify,通常是因为您没有ServerName正确设置(它需要来自env var或其他东西 - 不要对这个要求感到厌烦......做得正确).

特别是,如果您使用客户端证书并依赖它们进行身份验证,那么您基本上会有一个实际上不再登录的虚假登录.拒绝这样做的代码InsecureSkipVerify,或者你将通过艰难的方式了解它有什么问题!

  • 在企业中,您实际上不信任任何商业CA(例如:如果他们在美国境外),并替换为您的企业的一个CA,您只需要验证这是您的一个证书.主机名检查适用于用户期望主机名匹配但DNS不安全的情况.在企业中,通常连接到机器名称/ IP无法匹配的_cluster_机器,因为它是在新IP下生成的机器的精确克隆.dns名称查找cert,cert是id,而不是dns名称. (4认同)
  • 这个答案非常具有误导性.如果您接受任何有效签名的证书而不管主机名,您仍然无法获得真正的安全性.我可以轻松获得我控制的任何域的有效证书; 如果您只是要为TLS检查指定我的主机名,那么您将失去验证我真的是我说的我.那时,证书"合法"的事实并不重要; 这是_still_错误,而你在中间仍然容易受到伤害. (2认同)
  • 想法是客户端代码仅信任企业CA。实际上,它比当前使用的CA系统安全得多。在这种情况下,任何东西(Thawte,Versign等)都不受信任。只是我们运行的CA。Web浏览器具有巨大的信任列表。彼此通信的服务在其信任文件中仅具有一个CA。 (2认同)

Jon*_*Lin 14

这是一种方法,可以在不丢失默认设置的情况下完成DefaultTransport,并且不需要根据用户评论提出虚假请求.

defaultTransport := http.DefaultTransport.(*http.Transport)

// Create new Transport that ignores self-signed SSL
httpClientWithSelfSignedTLS := &http.Transport{
  Proxy:                 defaultTransport.Proxy,
  DialContext:           defaultTransport.DialContext,
  MaxIdleConns:          defaultTransport.MaxIdleConns,
  IdleConnTimeout:       defaultTransport.IdleConnTimeout,
  ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout,
  TLSHandshakeTimeout:   defaultTransport.TLSHandshakeTimeout,
  TLSClientConfig:       &tls.Config{InsecureSkipVerify: true},
}
Run Code Online (Sandbox Code Playgroud)

  • 见上面的评论。所有这些都是错误的! (2认同)

小智 12

如果您想保持默认传输设置,正确的方法是现在(从 Go 1.13 开始):

customTransport := http.DefaultTransport.(*http.Transport).Clone()
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
client = &http.Client{Transport: customTransport}
Run Code Online (Sandbox Code Playgroud)

Transport.Clone制作传输的深层副本。这样您就不必担心丢失任何Transport随着时间的推移添加到结构中的新字段。


Cor*_*ian 7

如果要使用http包中的默认设置,因此不需要创建新的传输和客户端对象,可以更改为忽略证书验证,如下所示:

tr := http.DefaultTransport.(*http.Transport)
tr.TLSClientConfig.InsecureSkipVerify = true
Run Code Online (Sandbox Code Playgroud)

  • 这样做会导致"恐慌:运行时错误:无效的内存地址或无指针取消引用" (7认同)
  • 如果在此之前未使用默认的http请求者,则必须强制执行伪造请求,以便初始化它的默认传输 (6认同)