mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-22 08:18:29 +02:00
feat(ReverseProxy): add SSL/TLS configuration options and build TLS config method
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
package route
|
package route
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -44,10 +43,12 @@ func NewReverseProxyRoute(base *Route) (*ReveseProxyRoute, gperr.Error) {
|
|||||||
trans = a.Transport()
|
trans = a.Transport()
|
||||||
proxyURL = nettypes.NewURL(agent.HTTPProxyURL)
|
proxyURL = nettypes.NewURL(agent.HTTPProxyURL)
|
||||||
} else {
|
} else {
|
||||||
trans = gphttp.NewTransport()
|
tlsConfig, err := httpConfig.BuildTLSConfig(base.ProxyURL)
|
||||||
if httpConfig.NoTLSVerify {
|
if err != nil {
|
||||||
trans.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //nolint:gosec
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trans = gphttp.NewTransportWithTLSConfig(tlsConfig)
|
||||||
if httpConfig.ResponseHeaderTimeout > 0 {
|
if httpConfig.ResponseHeaderTimeout > 0 {
|
||||||
trans.ResponseHeaderTimeout = httpConfig.ResponseHeaderTimeout
|
trans.ResponseHeaderTimeout = httpConfig.ResponseHeaderTimeout
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,118 @@
|
|||||||
package route
|
package route
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/yusing/go-proxy/internal/gperr"
|
||||||
|
nettypes "github.com/yusing/go-proxy/internal/net/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HTTPConfig struct {
|
type HTTPConfig struct {
|
||||||
NoTLSVerify bool `json:"no_tls_verify,omitempty"`
|
NoTLSVerify bool `json:"no_tls_verify,omitempty"`
|
||||||
ResponseHeaderTimeout time.Duration `json:"response_header_timeout,omitempty" swaggertype:"primitive,integer"`
|
ResponseHeaderTimeout time.Duration `json:"response_header_timeout,omitempty" swaggertype:"primitive,integer"`
|
||||||
DisableCompression bool `json:"disable_compression,omitempty"`
|
DisableCompression bool `json:"disable_compression,omitempty"`
|
||||||
|
|
||||||
|
// SSL/TLS proxy options (nginx-like)
|
||||||
|
SSLServerName *string `json:"ssl_server_name,omitempty"` // SNI server name
|
||||||
|
SSLTrustedCertificate string `json:"ssl_trusted_certificate,omitempty"` // Path to trusted CA certificates
|
||||||
|
SSLCertificate string `json:"ssl_certificate,omitempty"` // Path to client certificate
|
||||||
|
SSLCertificateKey string `json:"ssl_certificate_key,omitempty"` // Path to client certificate key
|
||||||
|
SSLProtocols []string `json:"ssl_protocols,omitempty"` // Allowed TLS protocols
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildTLSConfig creates a TLS configuration based on the HTTP config options.
|
||||||
|
func (cfg *HTTPConfig) BuildTLSConfig(targetURL *nettypes.URL) (*tls.Config, gperr.Error) {
|
||||||
|
tlsConfig := &tls.Config{}
|
||||||
|
|
||||||
|
// Handle InsecureSkipVerify (legacy NoTLSVerify option)
|
||||||
|
if cfg.NoTLSVerify {
|
||||||
|
tlsConfig.InsecureSkipVerify = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle ssl_server_name (SNI)
|
||||||
|
if cfg.SSLServerName != nil {
|
||||||
|
switch *cfg.SSLServerName {
|
||||||
|
case "off":
|
||||||
|
// Disable SNI by setting empty string
|
||||||
|
tlsConfig.ServerName = ""
|
||||||
|
case "on", "":
|
||||||
|
// Use hostname from target URL for SNI
|
||||||
|
tlsConfig.ServerName = targetURL.Hostname()
|
||||||
|
default:
|
||||||
|
tlsConfig.ServerName = *cfg.SSLServerName
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Default behavior - use hostname for SNI
|
||||||
|
tlsConfig.ServerName = targetURL.Hostname()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle ssl_trusted_certificate
|
||||||
|
if cfg.SSLTrustedCertificate != "" {
|
||||||
|
caCertData, err := os.ReadFile(cfg.SSLTrustedCertificate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, gperr.New("failed to read trusted certificate file").
|
||||||
|
Subject(cfg.SSLTrustedCertificate).
|
||||||
|
With(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
caCertPool := x509.NewCertPool()
|
||||||
|
if !caCertPool.AppendCertsFromPEM(caCertData) {
|
||||||
|
return nil, gperr.New("failed to parse trusted certificates").
|
||||||
|
Subject(cfg.SSLTrustedCertificate)
|
||||||
|
}
|
||||||
|
tlsConfig.RootCAs = caCertPool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle ssl_certificate and ssl_certificate_key (client certificates)
|
||||||
|
if cfg.SSLCertificate != "" {
|
||||||
|
if cfg.SSLCertificateKey == "" {
|
||||||
|
return nil, gperr.New("ssl_certificate_key is required when ssl_certificate is specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
clientCert, err := tls.LoadX509KeyPair(cfg.SSLCertificate, cfg.SSLCertificateKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, gperr.New("failed to load client certificate").
|
||||||
|
Subject(cfg.SSLCertificate).
|
||||||
|
With(err)
|
||||||
|
}
|
||||||
|
tlsConfig.Certificates = []tls.Certificate{clientCert}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle ssl_protocols (TLS versions)
|
||||||
|
if len(cfg.SSLProtocols) > 0 {
|
||||||
|
var minVersion, maxVersion uint16
|
||||||
|
|
||||||
|
for _, protocol := range cfg.SSLProtocols {
|
||||||
|
var version uint16
|
||||||
|
switch strings.ToLower(protocol) {
|
||||||
|
case "tlsv1.0":
|
||||||
|
version = tls.VersionTLS10
|
||||||
|
case "tlsv1.1":
|
||||||
|
version = tls.VersionTLS11
|
||||||
|
case "tlsv1.2":
|
||||||
|
version = tls.VersionTLS12
|
||||||
|
case "tlsv1.3":
|
||||||
|
version = tls.VersionTLS13
|
||||||
|
default:
|
||||||
|
return nil, gperr.New("unsupported TLS protocol").
|
||||||
|
Subject(protocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
if minVersion == 0 || version < minVersion {
|
||||||
|
minVersion = version
|
||||||
|
}
|
||||||
|
if maxVersion == 0 || version > maxVersion {
|
||||||
|
maxVersion = version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfig.MinVersion = minVersion
|
||||||
|
tlsConfig.MaxVersion = maxVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlsConfig, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user