From ccc82546b1980f828ddcc32683bdb821481cbbda Mon Sep 17 00:00:00 2001 From: Vladislav Yarmak Date: Sat, 1 Apr 2023 23:55:06 +0300 Subject: [PATCH 1/2] socket activation support --- go.mod | 1 + go.sum | 3 +++ main.go | 44 ++++++++++++++++++++++++++++++++++---------- utils.go | 10 ++++++++-- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index bf76255..4f764fa 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.13 require ( github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/tg123/go-htpasswd v1.2.1 golang.org/x/crypto v0.7.0 diff --git a/go.sum b/go.sum index 4468dfd..cc4c260 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,13 @@ github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962/go.mod h1:kC29dT1vFpj7py2OvG1khBdQpo3kInWP+6QipLbdngo= github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5 h1:IEjq88XO4PuBDcvmjQJcQGg+w+UaafSy8G5Kcb5tBhI= github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5/go.mod h1:exZ0C/1emQJAw5tHOaUDyY1ycttqBAPcxuzf7QbY6ec= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= diff --git a/main.go b/main.go index 502f624..34a741b 100644 --- a/main.go +++ b/main.go @@ -12,6 +12,7 @@ import ( "strings" "time" + "github.com/coreos/go-systemd/v22/activation" "golang.org/x/crypto/acme" "golang.org/x/crypto/acme/autocert" "golang.org/x/crypto/bcrypt" @@ -170,14 +171,40 @@ func run() int { } mainLogger.Info("Starting proxy server...") + var listener net.Listener + if args.bind_address == "" { + // socket activation + listeners, err := activation.Listeners() + if err != nil { + mainLogger.Critical("socket activation failed: %v", err) + return 3 + } + if len(listeners) != 1 { + mainLogger.Critical("socket activation failed: unexpected number of listeners: %d", + len(listeners)) + return 3 + } + if listeners[0] == nil { + mainLogger.Critical("socket activation failed: nil listener returned") + return 3 + } + listener = listeners[0] + } else { + newListener, err := net.Listen("tcp", args.bind_address) + if err != nil { + mainLogger.Critical("listen failed: %v", err) + return 3 + } + listener = newListener + } + if args.cert != "" { - cfg, err1 := makeServerTLSConfig(args.cert, args.key, args.cafile, args.ciphers) + cfg, err1 := makeServerTLSConfig(args.cert, args.key, args.cafile, args.ciphers, !args.disableHTTP2) if err1 != nil { mainLogger.Critical("TLS config construction failed: %v", err1) return 3 } - server.TLSConfig = cfg - err = server.ListenAndServeTLS("", "") + listener = tls.NewListener(listener, cfg) } else if args.autocert { m := &autocert.Manager{ Cache: autocert.DirCache(args.autocertDir), @@ -195,18 +222,15 @@ func run() int { }() } cfg := m.TLSConfig() - cfg, err = updateServerTLSConfig(cfg, args.cafile, args.ciphers) + cfg, err = updateServerTLSConfig(cfg, args.cafile, args.ciphers, !args.disableHTTP2) if err != nil { mainLogger.Critical("TLS config construction failed: %v", err) return 3 } - server.TLSConfig = cfg - err = server.ListenAndServeTLS("", "") - mainLogger.Info("Proxy server started.") - } else { - mainLogger.Info("Proxy server started.") - err = server.ListenAndServe() + listener = tls.NewListener(listener, cfg) } + mainLogger.Info("Proxy server started.") + err = server.Serve(listener) mainLogger.Critical("Server terminated with a reason: %v", err) mainLogger.Info("Shutting down...") return 0 diff --git a/utils.go b/utils.go index 4e65559..35ca854 100644 --- a/utils.go +++ b/utils.go @@ -151,7 +151,7 @@ func copyBody(wr io.Writer, body io.Reader) { } } -func makeServerTLSConfig(certfile, keyfile, cafile, ciphers string) (*tls.Config, error) { +func makeServerTLSConfig(certfile, keyfile, cafile, ciphers string, h2 bool) (*tls.Config, error) { var cfg tls.Config cert, err := tls.LoadX509KeyPair(certfile, keyfile) if err != nil { @@ -171,10 +171,13 @@ func makeServerTLSConfig(certfile, keyfile, cafile, ciphers string) (*tls.Config cfg.ClientAuth = tls.VerifyClientCertIfGiven } cfg.CipherSuites = makeCipherList(ciphers) + if h2 { + cfg.NextProtos = []string{"h2", "http/1.1"} + } return &cfg, nil } -func updateServerTLSConfig(cfg *tls.Config, cafile, ciphers string) (*tls.Config, error) { +func updateServerTLSConfig(cfg *tls.Config, cafile, ciphers string, h2 bool) (*tls.Config, error) { if cafile != "" { roots := x509.NewCertPool() certs, err := ioutil.ReadFile(cafile) @@ -188,6 +191,9 @@ func updateServerTLSConfig(cfg *tls.Config, cafile, ciphers string) (*tls.Config cfg.ClientAuth = tls.VerifyClientCertIfGiven } cfg.CipherSuites = makeCipherList(ciphers) + if h2 { + cfg.NextProtos = []string{"h2", "http/1.1"} + } return cfg, nil } From 02eff463a1b5ae6dd5bd966bb84a55ab45e4e500 Mon Sep 17 00:00:00 2001 From: Vladislav Yarmak Date: Sun, 2 Apr 2023 00:08:35 +0300 Subject: [PATCH 2/2] update help and docs --- README.md | 3 ++- main.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index aa0240d..f9a33f9 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Dumbest HTTP proxy ever. * Supports HTTP/2 * Resilient to DPI (including active probing, see `hidden_domain` option for authentication providers) * Connecting via upstream HTTP(S)/SOCKS5 proxies (proxy chaining) +* systemd socket activation ## Installation @@ -184,7 +185,7 @@ Usage of /home/user/go/bin/dumbproxy: -autocert-whitelist value restrict autocert domains to this comma-separated list -bind-address string - HTTP proxy listen address (default ":8080") + HTTP proxy listen address. Set empty value to use systemd socket activation. (default ":8080") -cafile string CA file to authenticate clients with certificates -cert string diff --git a/main.go b/main.go index 34a741b..7d8b812 100644 --- a/main.go +++ b/main.go @@ -76,7 +76,7 @@ type CLIArgs struct { func parse_args() CLIArgs { var args CLIArgs - flag.StringVar(&args.bind_address, "bind-address", ":8080", "HTTP proxy listen address") + flag.StringVar(&args.bind_address, "bind-address", ":8080", "HTTP proxy listen address. Set empty value to use systemd socket activation.") flag.StringVar(&args.auth, "auth", "none://", "auth parameters") flag.IntVar(&args.verbosity, "verbosity", 20, "logging verbosity "+ "(10 - debug, 20 - info, 30 - warning, 40 - error, 50 - critical)")