在Golang中使用Gin实现TLS反向代理到代理服务器时出现问题

3

我被委托创建一个反向代理,该代理需要与被代理的服务建立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加密传输,我不确定该如何继续处理。
3个回答

1

我现在无法完全复制您的设置,但原则上,您应该在{{link1:ReverseProxy.Director}}函数内修改请求:

Director必须是一个函数,它将请求修改为使用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配置中同时使用证书和根证书。 证书是您发送到服务器的证书,而根证书用于验证服务器提供的证书。


1
对于TLS(即使用TLS的https),您必须连接到正确的服务器端口。通常是端口43或端口8443。它永远不会与http使用的端口相同。这意味着首先,服务器必须提供TLS端口,尽管大多数服务器都会提供。您分享的唯一代码与连接到服务器无关。由于您没有分享任何向服务器发出请求的代码,因此无法展示其错误之处。这里是一个示例

上面的代码设置了一个代理,内部发出请求。它可以工作并代理,但我不确定TLS连接是否正确,因为服务器似乎没有确认它。我会再次检查端口。 - Ben Lesh

0

最终我决定直接使用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)

之后,一切都运行得非常顺利。谢谢大家!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接