在 Golang 中使用 Gin 获取反向代理与 TLS(到代理服务器)一起工作时遇到问题
Trouble getting reverse proxy working with TLS (to proxied server) in Golang with Gin
我的任务是创建与代理服务建立 TLS 连接所需的反向代理。我拥有的证书在每个请求中都是唯一的,并且在内存中。
我运气不太好,但我尝试了很多方法。这是我现在的位置,希望有人能提供帮助:
func proxy(c *gin.Context) {
/* snip: magic here to get the x509 cert strings and remoteUrl */
proxy := httputil.NewSingleHostReverseProxy(remoteUrl)
cert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: []byte(signedCertString)})
key:= pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: []byte(privateKeyString)})
certificate, err := tls.X509KeyPair(cert, key)
if err != nil {
c.JSON(400, gin.H{"message": "Invalid certificate"})
return
}
proxy.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
Certificates: []tls.Certificate{certificate},
InsecureSkipVerify: true,
}
}
c.Request.Host = remote.Host
c.Request.URL.Scheme = remote.Scheme
c.Request.URL.Host = remote.Host
c.Request.URL.Path = remote.Path
proxy.ServeHTTP(c.Writer, c.Request)
}
我也试过设置 RootCAs
(我想也许我只是对现在 TLS 需要在这种情况下工作感到困惑):
func proxy(c *gin.Context) {
/* snip: magic here to get the x509 cert strings and remoteUrl */
proxy := httputil.NewSingleHostReverseProxy(remoteUrl)
cert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: []byte(signedCertString)})
certPool := x509.NewCertPool()
certPool.AppendCertsFromPEM(cert)
proxy.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certPool,
InsecureSkipVerify: true,
}
}
c.Request.Host = remote.Host
c.Request.URL.Scheme = remote.Scheme
c.Request.URL.Host = remote.Host
c.Request.URL.Path = remote.Path
proxy.ServeHTTP(c.Writer, c.Request)
}
无论如何,我的目标服务器似乎没有发现代理请求是 TLS,我不确定该从哪里着手。
对于 TLS(即 https,即带有 TLS 的 http),您必须连接到正确的服务器端口。它通常是端口 43 或端口 8443。它永远不会与用于 http 的端口相同。所以这意味着要开始,服务器必须为 TLS 提供一个端口,尽管大多数都这样做。
您分享的唯一代码与服务器连接无关。
由于您没有共享任何向服务器发出请求的代码,因此无法显示错误所在。
我现在无法完全重现您的设置,但原则上,您应该在 ReverseProxy.Director
函数中更改请求:
Director must be a function which modifies the request into a new request to be sent using Transport.
简而言之:
proxy.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
Certificates: []tls.Certificate{certificate},
RootCAs: certPool,
InsecureSkipVerify: true,
}
}
proxy.Director = func(req *http.Request) {
req.Host = remote.Host
req.URL.Scheme = remote.Scheme
req.URL.Host = remote.Host
req.URL.Path = remote.Path
}
proxy.ServeHTTP(c.Writer, c.Request)
此外,您可能还需要 TLS 配置中的证书和根 CA。证书是您发送给服务器的证书,rootCA 用于验证服务器提供的证书。
我最终转而直接使用 ReverseProxy
。但最大的问题是我使用的是 RootCAs
而不是 ClientCAs
。这是我最终得到的结果:
clientCAs := x509.NewCertPool()
clientCAs.AppendCertsFromPEM(signedCert)
certificate, err := tls.X509KeyPair(signedCert, privateKey)
proxy := &httputil.ReverseProxy({
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
Certificates: []tls.Certificate{certificate},
ClientCAs: clientCAs
},
Director: func (req *http.Request) {
// Alter request here
}
},
})
proxy.ServeHTTP(w, r)
在此之后,一切都在顺利进行。谢谢大家!
我的任务是创建与代理服务建立 TLS 连接所需的反向代理。我拥有的证书在每个请求中都是唯一的,并且在内存中。
我运气不太好,但我尝试了很多方法。这是我现在的位置,希望有人能提供帮助:
func proxy(c *gin.Context) {
/* snip: magic here to get the x509 cert strings and remoteUrl */
proxy := httputil.NewSingleHostReverseProxy(remoteUrl)
cert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: []byte(signedCertString)})
key:= pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: []byte(privateKeyString)})
certificate, err := tls.X509KeyPair(cert, key)
if err != nil {
c.JSON(400, gin.H{"message": "Invalid certificate"})
return
}
proxy.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
Certificates: []tls.Certificate{certificate},
InsecureSkipVerify: true,
}
}
c.Request.Host = remote.Host
c.Request.URL.Scheme = remote.Scheme
c.Request.URL.Host = remote.Host
c.Request.URL.Path = remote.Path
proxy.ServeHTTP(c.Writer, c.Request)
}
我也试过设置 RootCAs
(我想也许我只是对现在 TLS 需要在这种情况下工作感到困惑):
func proxy(c *gin.Context) {
/* snip: magic here to get the x509 cert strings and remoteUrl */
proxy := httputil.NewSingleHostReverseProxy(remoteUrl)
cert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: []byte(signedCertString)})
certPool := x509.NewCertPool()
certPool.AppendCertsFromPEM(cert)
proxy.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certPool,
InsecureSkipVerify: true,
}
}
c.Request.Host = remote.Host
c.Request.URL.Scheme = remote.Scheme
c.Request.URL.Host = remote.Host
c.Request.URL.Path = remote.Path
proxy.ServeHTTP(c.Writer, c.Request)
}
无论如何,我的目标服务器似乎没有发现代理请求是 TLS,我不确定该从哪里着手。
对于 TLS(即 https,即带有 TLS 的 http),您必须连接到正确的服务器端口。它通常是端口 43 或端口 8443。它永远不会与用于 http 的端口相同。所以这意味着要开始,服务器必须为 TLS 提供一个端口,尽管大多数都这样做。
您分享的唯一代码与服务器连接无关。
由于您没有共享任何向服务器发出请求的代码,因此无法显示错误所在。
我现在无法完全重现您的设置,但原则上,您应该在 ReverseProxy.Director
函数中更改请求:
Director must be a function which modifies the request into a new request to be sent using Transport.
简而言之:
proxy.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
Certificates: []tls.Certificate{certificate},
RootCAs: certPool,
InsecureSkipVerify: true,
}
}
proxy.Director = func(req *http.Request) {
req.Host = remote.Host
req.URL.Scheme = remote.Scheme
req.URL.Host = remote.Host
req.URL.Path = remote.Path
}
proxy.ServeHTTP(c.Writer, c.Request)
此外,您可能还需要 TLS 配置中的证书和根 CA。证书是您发送给服务器的证书,rootCA 用于验证服务器提供的证书。
我最终转而直接使用 ReverseProxy
。但最大的问题是我使用的是 RootCAs
而不是 ClientCAs
。这是我最终得到的结果:
clientCAs := x509.NewCertPool()
clientCAs.AppendCertsFromPEM(signedCert)
certificate, err := tls.X509KeyPair(signedCert, privateKey)
proxy := &httputil.ReverseProxy({
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
Certificates: []tls.Certificate{certificate},
ClientCAs: clientCAs
},
Director: func (req *http.Request) {
// Alter request here
}
},
})
proxy.ServeHTTP(w, r)
在此之后,一切都在顺利进行。谢谢大家!