From d45415080a58f9d55a3681983125c13536af92ea Mon Sep 17 00:00:00 2001 From: Umputun Date: Sat, 3 Apr 2021 01:20:24 -0500 Subject: [PATCH] allow custom https and http ports --- app/main.go | 13 ++++++++----- app/proxy/proxy.go | 18 ++++++++++++------ app/proxy/proxy_test.go | 28 ++++++++++++++++++++++++---- app/proxy/ssl.go | 13 +++++++------ 4 files changed, 51 insertions(+), 21 deletions(-) diff --git a/app/main.go b/app/main.go index 1a0042e..4f227d8 100644 --- a/app/main.go +++ b/app/main.go @@ -27,11 +27,12 @@ var opts struct { ProxyHeaders []string `short:"x" long:"header" env:"HEADER" description:"proxy headers"` SSL struct { - Type string `long:"type" env:"TYPE" description:"ssl (auto) support" choice:"none" choice:"static" choice:"auto" default:"none"` //nolint - Cert string `long:"cert" env:"CERT" description:"path to cert.pem file"` - Key string `long:"key" env:"KEY" description:"path to key.pem file"` - ACMELocation string `long:"acme-location" env:"ACME_LOCATION" description:"dir where certificates will be stored by autocert manager" default:"./var/acme"` - ACMEEmail string `long:"acme-email" env:"ACME_EMAIL" description:"admin email for certificate notifications"` + Type string `long:"type" env:"TYPE" description:"ssl (auto) support" choice:"none" choice:"static" choice:"auto" default:"none"` //nolint + Cert string `long:"cert" env:"CERT" description:"path to cert.pem file"` + Key string `long:"key" env:"KEY" description:"path to key.pem file"` + ACMELocation string `long:"acme-location" env:"ACME_LOCATION" description:"dir where certificates will be stored by autocert manager" default:"./var/acme"` + ACMEEmail string `long:"acme-email" env:"ACME_EMAIL" description:"admin email for certificate notifications"` + RedirHttpPort int `long:"http-port" env:"HTTP_PORT" description:"http port for redirect to https and acme challenge test"` } `group:"ssl" namespace:"ssl" env-namespace:"SSL"` Assets struct { @@ -161,10 +162,12 @@ func makeSSLConfig() (config proxy.SSLConfig, err error) { config.SSLMode = proxy.SSLStatic config.Cert = opts.SSL.Cert config.Key = opts.SSL.Key + config.RedirHttpPort = opts.SSL.RedirHttpPort case "auto": config.SSLMode = proxy.SSLAuto config.ACMELocation = opts.SSL.ACMELocation config.ACMEEmail = opts.SSL.ACMEEmail + config.RedirHttpPort = opts.SSL.RedirHttpPort } return config, err } diff --git a/app/proxy/proxy.go b/app/proxy/proxy.go index cfc4e66..5fd9c16 100644 --- a/app/proxy/proxy.go +++ b/app/proxy/proxy.go @@ -5,6 +5,8 @@ import ( "net/http" "net/http/httputil" "net/url" + "regexp" + "strconv" "strings" "time" @@ -16,6 +18,7 @@ import ( "github.com/pkg/errors" ) +// Http is a proxy server for both http and https type Http struct { Matcher Address string @@ -29,6 +32,8 @@ type Http struct { Version string } +// Matcher source info (server and route) to the destination url +// If no match found return ok=false type Matcher interface { Match(srv, src string) (string, bool) } @@ -78,11 +83,11 @@ func (h *Http) Run(ctx context.Context) error { httpsServer = h.makeHTTPSServer(h.Address, handler) httpsServer.ErrorLog = log.ToStdLogger(log.Default(), "WARN") - httpServer = h.makeHTTPServer(h.toHttp(h.Address), h.httpToHTTPSRouter()) + httpServer = h.makeHTTPServer(h.toHttp(h.Address, h.SSLConfig.RedirHttpPort), h.httpToHTTPSRouter()) httpServer.ErrorLog = log.ToStdLogger(log.Default(), "WARN") go func() { - log.Printf("[INFO] activate http redirect server on %s", h.toHttp(h.Address)) + log.Printf("[INFO] activate http redirect server on %s", h.toHttp(h.Address, h.SSLConfig.RedirHttpPort)) err := httpServer.ListenAndServe() log.Printf("[WARN] http redirect server terminated, %s", err) }() @@ -94,11 +99,11 @@ func (h *Http) Run(ctx context.Context) error { httpsServer = h.makeHTTPSAutocertServer(h.Address, handler, m) httpsServer.ErrorLog = log.ToStdLogger(log.Default(), "WARN") - httpServer = h.makeHTTPServer(h.toHttp(h.Address), h.httpChallengeRouter(m)) + httpServer = h.makeHTTPServer(h.toHttp(h.Address, h.SSLConfig.RedirHttpPort), h.httpChallengeRouter(m)) httpServer.ErrorLog = log.ToStdLogger(log.Default(), "WARN") go func() { - log.Printf("[INFO] activate http challenge server on port %s", h.toHttp(h.Address)) + log.Printf("[INFO] activate http challenge server on port %s", h.toHttp(h.Address, h.SSLConfig.RedirHttpPort)) err := httpServer.ListenAndServe() log.Printf("[WARN] http challenge server terminated, %s", err) }() @@ -108,8 +113,9 @@ func (h *Http) Run(ctx context.Context) error { return errors.Errorf("unknown SSL type %v", h.SSLConfig.SSLMode) } -func (h *Http) toHttp(address string) string { - return strings.Replace(address, ":443", ":80", 1) +func (h *Http) toHttp(address string, httpPort int) string { + rx := regexp.MustCompile(`(.*):(\d*)`) + return rx.ReplaceAllString(address, "$1:") + strconv.Itoa(httpPort) } func (h *Http) gzipHandler() func(next http.Handler) http.Handler { diff --git a/app/proxy/proxy_test.go b/app/proxy/proxy_test.go index b7c2fa6..7447154 100644 --- a/app/proxy/proxy_test.go +++ b/app/proxy/proxy_test.go @@ -37,14 +37,12 @@ func TestHttp_Do(t *testing.T) { }}) go func() { - err := svc.Run(context.Background()) - assert.Equal(t, context.DeadlineExceeded, err) + _ = svc.Run(context.Background()) }() h.Matcher = svc go func() { - err := h.Run(ctx) - assert.Equal(t, context.DeadlineExceeded, err) + _ = h.Run(ctx) }() time.Sleep(10 * time.Millisecond) @@ -86,3 +84,25 @@ func TestHttp_Do(t *testing.T) { } } + +func TestHttp_toHttp(t *testing.T) { + + tbl := []struct { + addr string + port int + res string + }{ + {"localhost:1234", 80, "localhost:80"}, + {"m.example.com:443", 8080, "m.example.com:8080"}, + {"192.168.1.1:1443", 8080, "192.168.1.1:8080"}, + } + + h := Http{} + for i, tt := range tbl { + tt := tt + t.Run(strconv.Itoa(i), func(t *testing.T) { + assert.Equal(t, tt.res, h.toHttp(tt.addr, tt.port)) + }) + } + +} diff --git a/app/proxy/ssl.go b/app/proxy/ssl.go index 8315c07..a3ff691 100644 --- a/app/proxy/ssl.go +++ b/app/proxy/ssl.go @@ -28,12 +28,13 @@ const ( // SSLConfig holds all ssl params for rest server type SSLConfig struct { - SSLMode sslMode - Cert string - Key string - ACMELocation string - ACMEEmail string - FQDNs []string + SSLMode sslMode + Cert string + Key string + ACMELocation string + ACMEEmail string + FQDNs []string + RedirHttpPort int } // httpToHTTPSRouter creates new router which does redirect from http to https server