diff --git a/cmd/serve/httplib/httpflags/httpflags.go b/cmd/serve/httplib/httpflags/httpflags.go index 109604f0e..d06ab8076 100644 --- a/cmd/serve/httplib/httpflags/httpflags.go +++ b/cmd/serve/httplib/httpflags/httpflags.go @@ -29,6 +29,7 @@ func AddFlagsPrefix(flagSet *pflag.FlagSet, prefix string, Opt *httplib.Options) flags.StringVarP(flagSet, &Opt.BasicPass, prefix+"pass", "", Opt.BasicPass, "Password for authentication") flags.StringVarP(flagSet, &Opt.BaseURL, prefix+"baseurl", "", Opt.BaseURL, "Prefix for URLs - leave blank for root") flags.StringVarP(flagSet, &Opt.Template, prefix+"template", "", Opt.Template, "User-specified template") + flags.StringVarP(flagSet, &Opt.MinTLSVersion, prefix+"min-tls-version", "", Opt.MinTLSVersion, "Minimum TLS version that is acceptable") } diff --git a/cmd/serve/httplib/httplib.go b/cmd/serve/httplib/httplib.go index 82a29817f..10d8eb1ec 100644 --- a/cmd/serve/httplib/httplib.go +++ b/cmd/serve/httplib/httplib.go @@ -108,6 +108,10 @@ supply ` + "`--client-ca`" + ` also. of that with the CA certificate. ` + "`--key`" + ` should be the PEM encoded private key and ` + "`--client-ca`" + ` should be the PEM encoded client certificate authority certificate. + +--min-tls-version is minimum TLS version that is acceptable. Valid + values are "tls1.0", "tls1.1", "tls1.2" and "tls1.3" (default + "tls1.0"). ` // Options contains options for the http Server @@ -126,6 +130,7 @@ type Options struct { BasicPass string // password for BasicUser Auth AuthFn `json:"-"` // custom Auth (not set by command line flags) Template string // User specified template + MinTLSVersion string // MinTLSVersion contains the minimum TLS version that is acceptable } // AuthFn if used will be used to authenticate user, pass. If an error @@ -141,6 +146,7 @@ var DefaultOpt = Options{ ServerReadTimeout: 1 * time.Hour, ServerWriteTimeout: 1 * time.Hour, MaxHeaderBytes: 4096, + MinTLSVersion: "tls1.0", } // Server contains info about the running http server @@ -276,6 +282,20 @@ func NewServer(handler http.Handler, opt *Options) *Server { s.Opt.BaseURL = "/" + s.Opt.BaseURL } + var minTLSVersion uint16 + switch opt.MinTLSVersion { + case "tls1.0": + minTLSVersion = tls.VersionTLS10 + case "tls1.1": + minTLSVersion = tls.VersionTLS11 + case "tls1.2": + minTLSVersion = tls.VersionTLS12 + case "tls1.3": + minTLSVersion = tls.VersionTLS13 + default: + log.Fatalf("Invalid value for --min-tls-version") + } + // FIXME make a transport? s.httpServer = &http.Server{ Addr: s.Opt.ListenAddr, @@ -286,7 +306,7 @@ func NewServer(handler http.Handler, opt *Options) *Server { ReadHeaderTimeout: 10 * time.Second, // time to send the headers IdleTimeout: 60 * time.Second, // time to keep idle connections open TLSConfig: &tls.Config{ - MinVersion: tls.VersionTLS10, // disable SSL v3.0 and earlier + MinVersion: minTLSVersion, }, } diff --git a/docs/content/flags.md b/docs/content/flags.md index 90fbb2a5f..acf93f6c7 100644 --- a/docs/content/flags.md +++ b/docs/content/flags.md @@ -119,6 +119,7 @@ These flags are available for every command. --rc-job-expire-interval duration Interval to check for expired async jobs (default 10s) --rc-key string SSL PEM Private key --rc-max-header-bytes int Maximum size of request header (default 4096) + --rc-min-tls-version string Minimum TLS version that is acceptable --rc-no-auth Don't require auth for certain methods --rc-pass string Password for authentication --rc-realm string Realm for authentication (default "rclone") diff --git a/docs/content/rc.md b/docs/content/rc.md index 9d87e2e65..51d291720 100644 --- a/docs/content/rc.md +++ b/docs/content/rc.md @@ -41,6 +41,11 @@ SSL PEM Private key Maximum size of request header (default 4096) +### --rc-min-tls-version=VALUE + +The minimum TLS version that is acceptable. Valid values are "tls1.0", +"tls1.1", "tls1.2" and "tls1.3" (default "tls1.0"). + ### --rc-user=VALUE User name for authentication. diff --git a/lib/http/http.go b/lib/http/http.go index 1ff7c1148..527555504 100644 --- a/lib/http/http.go +++ b/lib/http/http.go @@ -59,6 +59,10 @@ supply ` + "`--client-ca`" + ` also. of that with the CA certificate. ` + "`--key`" + ` should be the PEM encoded private key and ` + "`--client-ca`" + ` should be the PEM encoded client certificate authority certificate. + +--min-tls-version is minimum TLS version that is acceptable. Valid + values are "tls1.0", "tls1.1", "tls1.2" and "tls1.3" (default + "tls1.0"). ` // Middleware function signature required by chi.Router.Use() @@ -76,6 +80,7 @@ type Options struct { SslCertBody []byte // SSL PEM key (concatenation of certificate and CA certificate) body, ignores SslCert SslKeyBody []byte // SSL PEM Private key body, ignores SslKey ClientCA string // Client certificate authority to verify clients with + MinTLSVersion string // MinTLSVersion contains the minimum TLS version that is acceptable. } // DefaultOpt is the default values used for Options @@ -84,6 +89,7 @@ var DefaultOpt = Options{ ServerReadTimeout: 1 * time.Hour, ServerWriteTimeout: 1 * time.Hour, MaxHeaderBytes: 4096, + MinTLSVersion: "tls1.0", } // Server interface of http server @@ -151,8 +157,23 @@ func NewServer(listeners, tlsListeners []net.Listener, opt Options) (Server, err if err != nil { log.Fatal(err) } + var minTLSVersion uint16 + switch opt.MinTLSVersion { + case "tls1.0": + minTLSVersion = tls.VersionTLS10 + case "tls1.1": + minTLSVersion = tls.VersionTLS11 + case "tls1.2": + minTLSVersion = tls.VersionTLS12 + case "tls1.3": + minTLSVersion = tls.VersionTLS13 + default: + err = errors.New("Invalid value for --min-tls-version") + log.Fatalf(err.Error()) + return nil, err + } tlsConfig = &tls.Config{ - MinVersion: tls.VersionTLS10, // disable SSL v3.0 and earlier + MinVersion: minTLSVersion, Certificates: []tls.Certificate{cert}, } } else if len(listeners) == 0 && len(tlsListeners) != 0 { @@ -410,6 +431,7 @@ func AddFlagsPrefix(flagSet *pflag.FlagSet, prefix string, Opt *Options) { flags.StringVarP(flagSet, &Opt.SslKey, prefix+"key", "", Opt.SslKey, "SSL PEM Private key") flags.StringVarP(flagSet, &Opt.ClientCA, prefix+"client-ca", "", Opt.ClientCA, "Client certificate authority to verify clients with") flags.StringVarP(flagSet, &Opt.BaseURL, prefix+"baseurl", "", Opt.BaseURL, "Prefix for URLs - leave blank for root") + flags.StringVarP(flagSet, &Opt.MinTLSVersion, prefix+"min-tls-version", "", Opt.MinTLSVersion, "Minimum TLS version that is acceptable") } diff --git a/lib/http/http_test.go b/lib/http/http_test.go index 1c2618be2..fd9850059 100644 --- a/lib/http/http_test.go +++ b/lib/http/http_test.go @@ -494,6 +494,16 @@ func Test_useSSL(t *testing.T) { }}, want: true, }, + { + name: "basic", + args: args{opt: Options{ + SslCert: "", + SslKey: "test", + ClientCA: "", + MinTLSVersion: "tls1.2", + }}, + want: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {