httplib: Add --xxx-min-tls-version option to select minimum tls values for HTTP servers
This allows administrators to disable TLS 1.0 and 1.1, for example. Example: rclone rcd --rc-min-tls-version=tls1.2 --rc-cert <cert> --rc-key <key>
This commit is contained in:
parent
188b9f8cf1
commit
d2fef05fe4
6 changed files with 61 additions and 2 deletions
|
@ -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.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.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.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")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,10 @@ supply ` + "`--client-ca`" + ` also.
|
||||||
of that with the CA certificate. ` + "`--key`" + ` should be the PEM encoded
|
of that with the CA certificate. ` + "`--key`" + ` should be the PEM encoded
|
||||||
private key and ` + "`--client-ca`" + ` should be the PEM encoded client
|
private key and ` + "`--client-ca`" + ` should be the PEM encoded client
|
||||||
certificate authority certificate.
|
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
|
// Options contains options for the http Server
|
||||||
|
@ -126,6 +130,7 @@ type Options struct {
|
||||||
BasicPass string // password for BasicUser
|
BasicPass string // password for BasicUser
|
||||||
Auth AuthFn `json:"-"` // custom Auth (not set by command line flags)
|
Auth AuthFn `json:"-"` // custom Auth (not set by command line flags)
|
||||||
Template string // User specified template
|
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
|
// AuthFn if used will be used to authenticate user, pass. If an error
|
||||||
|
@ -141,6 +146,7 @@ var DefaultOpt = Options{
|
||||||
ServerReadTimeout: 1 * time.Hour,
|
ServerReadTimeout: 1 * time.Hour,
|
||||||
ServerWriteTimeout: 1 * time.Hour,
|
ServerWriteTimeout: 1 * time.Hour,
|
||||||
MaxHeaderBytes: 4096,
|
MaxHeaderBytes: 4096,
|
||||||
|
MinTLSVersion: "tls1.0",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server contains info about the running http server
|
// 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
|
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?
|
// FIXME make a transport?
|
||||||
s.httpServer = &http.Server{
|
s.httpServer = &http.Server{
|
||||||
Addr: s.Opt.ListenAddr,
|
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
|
ReadHeaderTimeout: 10 * time.Second, // time to send the headers
|
||||||
IdleTimeout: 60 * time.Second, // time to keep idle connections open
|
IdleTimeout: 60 * time.Second, // time to keep idle connections open
|
||||||
TLSConfig: &tls.Config{
|
TLSConfig: &tls.Config{
|
||||||
MinVersion: tls.VersionTLS10, // disable SSL v3.0 and earlier
|
MinVersion: minTLSVersion,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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-job-expire-interval duration Interval to check for expired async jobs (default 10s)
|
||||||
--rc-key string SSL PEM Private key
|
--rc-key string SSL PEM Private key
|
||||||
--rc-max-header-bytes int Maximum size of request header (default 4096)
|
--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-no-auth Don't require auth for certain methods
|
||||||
--rc-pass string Password for authentication
|
--rc-pass string Password for authentication
|
||||||
--rc-realm string Realm for authentication (default "rclone")
|
--rc-realm string Realm for authentication (default "rclone")
|
||||||
|
|
|
@ -41,6 +41,11 @@ SSL PEM Private key
|
||||||
|
|
||||||
Maximum size of request header (default 4096)
|
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
|
### --rc-user=VALUE
|
||||||
|
|
||||||
User name for authentication.
|
User name for authentication.
|
||||||
|
|
|
@ -59,6 +59,10 @@ supply ` + "`--client-ca`" + ` also.
|
||||||
of that with the CA certificate. ` + "`--key`" + ` should be the PEM encoded
|
of that with the CA certificate. ` + "`--key`" + ` should be the PEM encoded
|
||||||
private key and ` + "`--client-ca`" + ` should be the PEM encoded client
|
private key and ` + "`--client-ca`" + ` should be the PEM encoded client
|
||||||
certificate authority certificate.
|
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()
|
// 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
|
SslCertBody []byte // SSL PEM key (concatenation of certificate and CA certificate) body, ignores SslCert
|
||||||
SslKeyBody []byte // SSL PEM Private key body, ignores SslKey
|
SslKeyBody []byte // SSL PEM Private key body, ignores SslKey
|
||||||
ClientCA string // Client certificate authority to verify clients with
|
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
|
// DefaultOpt is the default values used for Options
|
||||||
|
@ -84,6 +89,7 @@ var DefaultOpt = Options{
|
||||||
ServerReadTimeout: 1 * time.Hour,
|
ServerReadTimeout: 1 * time.Hour,
|
||||||
ServerWriteTimeout: 1 * time.Hour,
|
ServerWriteTimeout: 1 * time.Hour,
|
||||||
MaxHeaderBytes: 4096,
|
MaxHeaderBytes: 4096,
|
||||||
|
MinTLSVersion: "tls1.0",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server interface of http server
|
// Server interface of http server
|
||||||
|
@ -151,8 +157,23 @@ func NewServer(listeners, tlsListeners []net.Listener, opt Options) (Server, err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
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{
|
tlsConfig = &tls.Config{
|
||||||
MinVersion: tls.VersionTLS10, // disable SSL v3.0 and earlier
|
MinVersion: minTLSVersion,
|
||||||
Certificates: []tls.Certificate{cert},
|
Certificates: []tls.Certificate{cert},
|
||||||
}
|
}
|
||||||
} else if len(listeners) == 0 && len(tlsListeners) != 0 {
|
} 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.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.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.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")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -494,6 +494,16 @@ func Test_useSSL(t *testing.T) {
|
||||||
}},
|
}},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "basic",
|
||||||
|
args: args{opt: Options{
|
||||||
|
SslCert: "",
|
||||||
|
SslKey: "test",
|
||||||
|
ClientCA: "",
|
||||||
|
MinTLSVersion: "tls1.2",
|
||||||
|
}},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue