Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend: Adds support for HTTP/2 #18358

Merged
merged 3 commits into from
Aug 16, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion conf/defaults.ini
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ provisioning = conf/provisioning

#################################### Server ##############################
[server]
# Protocol (http, https, socket)
# Protocol (http, https, h2, socket)
kaydelaney marked this conversation as resolved.
Show resolved Hide resolved
protocol = http

# The ip address to bind to, empty will bind to all interfaces
Expand Down
45 changes: 45 additions & 0 deletions pkg/api/http_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ func (hs *HTTPServer) Run(ctx context.Context) error {
hs.log.Debug("server was shutdown gracefully")
return nil
}
case setting.HTTP2:
err = hs.listenAndServeH2TLS(setting.CertFile, setting.KeyFile)
if err == http.ErrServerClosed {
hs.log.Debug("server was shutdown gracefully")
return nil
}
case setting.HTTPS:
err = hs.listenAndServeTLS(setting.CertFile, setting.KeyFile)
if err == http.ErrServerClosed {
Expand Down Expand Up @@ -181,6 +187,45 @@ func (hs *HTTPServer) listenAndServeTLS(certfile, keyfile string) error {
return hs.httpSrv.ListenAndServeTLS(setting.CertFile, setting.KeyFile)
}

func (hs *HTTPServer) listenAndServeH2TLS(certfile, keyfile string) error {
if certfile == "" {
return fmt.Errorf("cert_file cannot be empty when using HTTP2")
}

if keyfile == "" {
return fmt.Errorf("cert_key cannot be empty when using HTTP2")
}

if _, err := os.Stat(setting.CertFile); os.IsNotExist(err) {
return fmt.Errorf(`Cannot find SSL cert_file at %v`, setting.CertFile)
}

if _, err := os.Stat(setting.KeyFile); os.IsNotExist(err) {
return fmt.Errorf(`Cannot find SSL key_file at %v`, setting.KeyFile)
}

tlsCfg := &tls.Config{
MinVersion: tls.VersionTLS12,
PreferServerCipherSuites: false,
CipherSuites: []uint16{
tls.TLS_CHACHA20_POLY1305_SHA256,
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only tagged myself as a reviewer - as I wanted to understand why the cipher-suite is so narrow. I have not been up to speed with the state of HTTP/2 but thinking whenever this would introduce compatibility issues for existing installations.

I understand we don't want it to be too broad due to security risks, but three seems a bit on the shorter end of the stick.

I don't need a direct answer if we have reasons let's just document them as part of the PR description.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No reason in particular as to why it's so narrow - purely a consequence of this PR being based on #13105. I left it unchanged as I wanted to hear from others if they thought, say, Mozilla's recommendations re: preferred ciphers should be followed before committing it to code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference I think https://wiki.mozilla.org/Security/Server_Side_TLS is the Mozilla recommendation

},
NextProtos: []string{"h2", "http/1.1"},
}

hs.httpSrv.TLSConfig = tlsCfg

return hs.httpSrv.ListenAndServeTLS(setting.CertFile, setting.KeyFile)
}

func (hs *HTTPServer) newMacaron() *macaron.Macaron {
macaron.Env = setting.Env
m := macaron.New()
Expand Down
2 changes: 1 addition & 1 deletion pkg/middleware/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ func AddDefaultResponseHeaders() macaron.Handler {

// AddSecurityHeaders adds various HTTP(S) response headers that enable various security protections behaviors in the client's browser.
func AddSecurityHeaders(w macaron.ResponseWriter) {
if setting.Protocol == setting.HTTPS && setting.StrictTransportSecurity {
if (setting.Protocol == setting.HTTPS || setting.Protocol == setting.HTTP2) && setting.StrictTransportSecurity {
strictHeaderValues := []string{fmt.Sprintf("max-age=%v", setting.StrictTransportSecurityMaxAge)}
if setting.StrictTransportSecurityPreload {
strictHeaderValues = append(strictHeaderValues, "preload")
Expand Down
6 changes: 6 additions & 0 deletions pkg/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type Scheme string
const (
HTTP Scheme = "http"
HTTPS Scheme = "https"
HTTP2 Scheme = "h2"
SOCKET Scheme = "socket"
DEFAULT_HTTP_ADDR string = "0.0.0.0"
)
Expand Down Expand Up @@ -639,6 +640,11 @@ func (cfg *Cfg) Load(args *CommandLineArgs) error {
CertFile = server.Key("cert_file").String()
KeyFile = server.Key("cert_key").String()
}
if protocolStr == "h2" {
Protocol = HTTP2
CertFile = server.Key("cert_file").String()
KeyFile = server.Key("cert_key").String()
}
if protocolStr == "socket" {
Protocol = SOCKET
SocketPath = server.Key("socket").String()
Expand Down