-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathserver.go
143 lines (118 loc) · 3.67 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// +build go1.8
// enforce go 1.8+ just so we can support X25519 curve :)
package backend
import (
"crypto/tls"
"fmt"
"net/http"
"os"
"time"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/spf13/viper"
)
var (
// set timeouts to avoid Slowloris attacks.
httpWriteTimeout = time.Second * 15
httpReadTimeout = time.Second * 15
// the maximum amount of time to wait for the
// next request when keep-alives are enabled
httpIdleTimeout = time.Second * 60
// PCI compliance as of Jun 30, 2018: anything under TLS 1.1 must be disabled
// we bump this up to TLS 1.2 so we can support best possible ciphers
tlsMinVersion = uint16(tls.VersionTLS12)
// allowed ciphers when in hardened mode
// disable CBC suites (Lucky13 attack) this means TLS 1.1 can't work (no GCM)
// only use perfect forward secrecy ciphers
tlsCiphers = []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
// these ciphers require go 1.8+
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
}
// EC curve preference when in hardened mode
// curve reference: http://safecurves.cr.yp.to/
tlsCurvePreferences = []tls.CurveID{
// this curve is a non-NIST curve with no NSA influence. Prefer this over all others!
// this curve required go 1.8+
tls.X25519,
// These curves are provided by NIST; prefer in descending order
tls.CurveP521,
tls.CurveP384,
tls.CurveP256,
}
)
func startHTTPServer() (err error) {
// create routes
mux := newRouter()
// get server config
srv := configureHTTPServer(mux)
// get TLS config
tlsConifig, err := configureTLS()
if err != nil {
log.Fatalf("error configuring TLS: %s", err)
return
}
srv.TLSConfig = &tlsConifig
// start the server
if viper.GetBool("server.tls.enabled") {
// cert and key should already be configured
log.Info("starting HTTP server with TLS")
err = srv.ListenAndServeTLS("", "")
} else {
err = srv.ListenAndServe()
}
if err != nil {
log.Info("starting HTTP server")
log.Fatalf("failed to start server: %s", err)
}
return
}
func configureHTTPServer(mux *mux.Router) (httpServer *http.Server) {
// apply standard http server settings
address := fmt.Sprintf(
"%s:%s",
viper.GetString("server.bind_address"),
viper.GetString("server.bind_port"),
)
httpServer = &http.Server{
Addr: address,
WriteTimeout: httpWriteTimeout,
ReadTimeout: httpReadTimeout,
IdleTimeout: httpIdleTimeout,
}
// explicitly enable keep-alives
httpServer.SetKeepAlivesEnabled(true)
// stdout access log enable/disable
if viper.GetBool("server.access_log") {
httpServer.Handler = handlers.CombinedLoggingHandler(os.Stdout, mux)
} else {
httpServer.Handler = mux
}
return
}
// configure TLS as defined in configuration
func configureTLS() (tlsConfig tls.Config, err error) {
if !viper.GetBool("server.tls.enabled") {
log.Debug("TLS not enabled, skipping TLS config")
return
}
// attempt to load configured cert/key
log.Info("TLS enabled, loading cert and key")
log.Debugf("loading TLS cert and key: %s %s", viper.GetString("server.tls.cert_chain"), viper.GetString("server.tls.private_key"))
cert, err := tls.LoadX509KeyPair(viper.GetString("server.tls.cert_chain"), viper.GetString("server.tls.private_key"))
if err != nil {
return
}
// configure hardened TLS settings
tlsConfig.Certificates = []tls.Certificate{cert}
tlsConfig.MinVersion = tlsMinVersion
tlsConfig.InsecureSkipVerify = false
tlsConfig.PreferServerCipherSuites = true
tlsConfig.CurvePreferences = tlsCurvePreferences
tlsConfig.CipherSuites = tlsCiphers
return
}