// SecureCiphers updates a *tls.Config with a secure ciphersuite configuration. // If c is nil, a new config will be provided. func SecureCiphers(c *tls.Config) *tls.Config { if c == nil { c = &tls.Config{} } c.MinVersion = tls.VersionTLS10 // disable SSLv3 c.MaxVersion = tls.VersionTLS12 // enable TLS_FALLBACK_SCSV: https://go-review.googlesource.com/#/c/1776/ // Use all available ciphersuites minus RC4 and 3DES in a sane order. // This configuration has forward secrecy for supported browsers, and gets // an ‘A’ grade on SSL Labs. c.CipherSuites = []uint16{ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, } c.PreferServerCipherSuites = true return c }
// ListenAndServeTLSWithSNI serves TLS with Server Name Indication (SNI) support, which allows // multiple sites (different hostnames) to be served from the same address. This method is // adapted directly from the std lib's net/http ListenAndServeTLS function, which was // written by the Go Authors. It has been modified to support multiple certificate/key pairs. func ListenAndServeTLSWithSNI(srv *http.Server, tlsConfigs []TLSConfig) error { addr := srv.Addr if addr == "" { addr = ":https" } config := new(tls.Config) if srv.TLSConfig != nil { *config = *srv.TLSConfig } if config.NextProtos == nil { config.NextProtos = []string{"http/1.1"} } // Here we diverge from the stdlib a bit by loading multiple certs/key pairs // then we map the server names to their certs var err error config.Certificates = make([]tls.Certificate, len(tlsConfigs)) for i, tlsConfig := range tlsConfigs { config.Certificates[i], err = tls.LoadX509KeyPair(tlsConfig.Certificate, tlsConfig.Key) if err != nil { return err } } config.BuildNameToCertificate() // Customize our TLS configuration config.MinVersion = tlsConfigs[0].ProtocolMinVersion config.MaxVersion = tlsConfigs[0].ProtocolMaxVersion config.CipherSuites = tlsConfigs[0].Ciphers config.PreferServerCipherSuites = tlsConfigs[0].PreferServerCipherSuites // TLS client authentication, if user enabled it err = setupClientAuth(tlsConfigs, config) if err != nil { return err } // Create listener and we're on our way conn, err := net.Listen("tcp", addr) if err != nil { return err } tlsListener := tls.NewListener(conn, config) return srv.Serve(tlsListener) }
func ListenAndServeTLSWithSNI(srv *http.Server, tlsConfigs []TLSConfig) error { addr := srv.Addr if addr == "" { addr = ":https" } config := new(tls.Config) if srv.TLSConfig != nil { *config = *srv.TLSConfig } if config.NextProtos == nil { config.NextProtos = []string{"http/1.1"} } var err error config.Certificates = make([]tls.Certificate, len(tlsConfigs)) for i, tlsConfig := range tlsConfigs { config.Certificates[i], err = tls.LoadX509KeyPair(tlsConfig.Certificate, tlsConfig.Key) if err != nil { return err } } config.BuildNameToCertificate() config.MinVersion = tlsConfigs[0].ProtocolMinVersion config.MaxVersion = tlsConfigs[0].ProtocolMaxVersion config.CipherSuites = tlsConfigs[0].Ciphers config.PreferServerCipherSuites = tlsConfigs[0].PreferServerCipherSuites err = setupClientAuth(tlsConfigs, config) if err != nil { return err } conn, err := net.Listen("tcp", addr) if err != nil { return err } tlsListener := tls.NewListener(conn, config) return srv.Serve(tlsListener) }
// MakeTLSConfig reduces configs into a single tls.Config. // If TLS is to be disabled, a nil tls.Config will be returned. func MakeTLSConfig(configs []*Config) (*tls.Config, error) { if configs == nil || len(configs) == 0 { return nil, nil } config := new(tls.Config) ciphersAdded := make(map[uint16]struct{}) configMap := make(configGroup) for i, cfg := range configs { if cfg == nil { // avoid nil pointer dereference below configs[i] = new(Config) continue } // Key this config by its hostname; this // overwrites configs with the same hostname configMap[cfg.Hostname] = cfg // Can't serve TLS and not-TLS on same port if i > 0 && cfg.Enabled != configs[i-1].Enabled { thisConfProto, lastConfProto := "not TLS", "not TLS" if cfg.Enabled { thisConfProto = "TLS" } if configs[i-1].Enabled { lastConfProto = "TLS" } return nil, fmt.Errorf("cannot multiplex %s (%s) and %s (%s) on same listener", configs[i-1].Hostname, lastConfProto, cfg.Hostname, thisConfProto) } // Union cipher suites for _, ciph := range cfg.Ciphers { if _, ok := ciphersAdded[ciph]; !ok { ciphersAdded[ciph] = struct{}{} config.CipherSuites = append(config.CipherSuites, ciph) } } // Can't resolve conflicting PreferServerCipherSuites settings if i > 0 && cfg.PreferServerCipherSuites != configs[i-1].PreferServerCipherSuites { return nil, fmt.Errorf("cannot both use PreferServerCipherSuites and not use it") } config.PreferServerCipherSuites = cfg.PreferServerCipherSuites // Go with the widest range of protocol versions if config.MinVersion == 0 || cfg.ProtocolMinVersion < config.MinVersion { config.MinVersion = cfg.ProtocolMinVersion } if cfg.ProtocolMaxVersion > config.MaxVersion { config.MaxVersion = cfg.ProtocolMaxVersion } // Go with the strictest ClientAuth type if cfg.ClientAuth > config.ClientAuth { config.ClientAuth = cfg.ClientAuth } } // Is TLS disabled? If so, we're done here. // By now, we know that all configs agree // whether it is or not, so we can just look // at the first one. if len(configs) == 0 || !configs[0].Enabled { return nil, nil } // Default cipher suites if len(config.CipherSuites) == 0 { config.CipherSuites = defaultCiphers } // For security, ensure TLS_FALLBACK_SCSV is always included if config.CipherSuites[0] != tls.TLS_FALLBACK_SCSV { config.CipherSuites = append([]uint16{tls.TLS_FALLBACK_SCSV}, config.CipherSuites...) } // Set up client authentication if enabled if config.ClientAuth != tls.NoClientCert { pool := x509.NewCertPool() clientCertsAdded := make(map[string]struct{}) for _, cfg := range configs { for _, caFile := range cfg.ClientCerts { // don't add cert to pool more than once if _, ok := clientCertsAdded[caFile]; ok { continue } clientCertsAdded[caFile] = struct{}{} // Any client with a certificate from this CA will be allowed to connect caCrt, err := ioutil.ReadFile(caFile) if err != nil { return nil, err } if !pool.AppendCertsFromPEM(caCrt) { return nil, fmt.Errorf("error loading client certificate '%s': no certificates were successfully parsed", caFile) } } } config.ClientCAs = pool } // Associate the GetCertificate callback, or almost nothing we just did will work config.GetCertificate = configMap.GetCertificate return config, nil }
func main() { http.HandleFunc("/", newLoggingHandleFunc(rootHandler)) http.HandleFunc("/new", newLoggingHandleFunc(newHandler)) http.HandleFunc("/view/", newLoggingHandleFunc(newGzipHandleFunc(titleHandler(viewHandler)))) http.HandleFunc("/edit/", newLoggingHandleFunc(newGzipHandleFunc(titleHandler(editHandler)))) http.HandleFunc("/save/", newLoggingHandleFunc(titleHandler(saveHandler))) http.HandleFunc("/del/", newLoggingHandleFunc(titleHandler(delHandler))) http.HandleFunc("/front", newLoggingHandleFunc(newGzipHandleFunc(frontHandler))) http.HandleFunc("/hsts_hpkp", hsts_hpkp) log.SetPrefix("goWiki: ") log.Println("listening... on port", HTTPS_PORT) go func() { for { err := func() error { var OCSPC OCSPCert var err error cert, err := tls.LoadX509KeyPair(CERT, KEY) if err != nil { return err } OCSPC.cert = &cert if OCSPC.cert.Leaf, err = x509.ParseCertificate(OCSPC.cert.Certificate[0]); err != nil { return err } issuerRAW, err := ioutil.ReadFile(ISSUER) if err != nil { return err } for { var issuerPEM *pem.Block issuerPEM, issuerRAW = pem.Decode(issuerRAW) if issuerPEM == nil { break } if issuerPEM.Type == "CERTIFICATE" { OCSPC.issuer, err = x509.ParseCertificate(issuerPEM.Bytes) if err != nil { return err } } } if OCSPC.issuer == nil { return errors.New("no issuer") } OCSPC.req, err = ocsp.CreateRequest(OCSPC.cert.Leaf, OCSPC.issuer, nil) if err != nil { return err } err = OCSPC.updateStaple() if err != nil { return err } go OCSPC.stapleLoop() TLSConfig := new(tls.Config) TLSConfig.Certificates = []tls.Certificate{cert} TLSConfig.CipherSuites = []uint16{ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA} TLSConfig.PreferServerCipherSuites = true TLSConfig.MinVersion = tls.VersionTLS11 //MaxVersion needed because of bug with TLS_FALLBACK_SCSV gonna be fixed in go 1.5 TLSConfig.MaxVersion = tls.VersionTLS12 TLSConfig.NextProtos = []string{"http/1.1"} TLSConfig.GetCertificate = func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { OCSPC.RLock() defer OCSPC.RUnlock() return OCSPC.cert, nil } ln, err := net.Listen("tcp", HTTPS_PORT) if err != nil { return err } tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, TLSConfig) return new(http.Server).Serve(tlsListener) }() if err != nil { log.Println(err) } time.Sleep(time.Second * TIMEOUT) } }() for { log.Println("redirecting from port", HTTP_PORT, "to", HTTPS_PORT) err := http.ListenAndServe(HTTP_PORT, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-Frame-Options", "SAMEORIGIN") w.Header().Set("Server", "Jesus") log.Println("redirecting http", r.RemoteAddr, "to https", DOMAIN+HTTPS_PORT+r.URL.Path) http.Redirect(w, r, "https://"+DOMAIN+HTTPS_PORT+r.URL.Path, http.StatusMovedPermanently) })) if err != nil { log.Println(err) } time.Sleep(time.Second * TIMEOUT) } }
func smtpRelay(payload []byte, sendTo []string) (err error) { conf := new(tls.Config) //conf.CipherSuites = []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA} conf.InsecureSkipVerify = true conf.MinVersion = tls.VersionSSL30 conf.MaxVersion = tls.VersionTLS10 relay := cfg.Mail.SMTPRelay port := cfg.Mail.SMTPPort /* The following section tries to get the MX record for the recipient email address, when there is only a single recipient. If it succeeds, the email will be sent directly to the recipient MX. */ if cfg.Mail.MXRelay && len(sendTo) == 1 { mx, err := mxLookup(sendTo[0]) if err == nil { Trace.Printf( "Doing direct relay for %s to %s:25.", sendTo[0], mx, ) relay = mx port = 25 } } serverAddr := fmt.Sprintf("%s:%d", relay, port) conn, err := net.Dial("tcp", serverAddr) if err != nil { Warn.Printf("Dial Error: Server=%s, Error=%s", serverAddr, err) return } client, err := smtp.NewClient(conn, relay) if err != nil { Warn.Printf( "SMTP Connection Error: Server=%s, Error=%s", serverAddr, err, ) return } // Test is the remote MTA supports STARTTLS ok, _ := client.Extension("STARTTLS") if ok && cfg.Mail.UseTLS { if err = client.StartTLS(conf); err != nil { Warn.Printf( "Error performing STARTTLS: Server=%s, Error=%s", serverAddr, err, ) return } } // If AUTH is supported and a UserID and Password are configured, try to // authenticate to the remote MTA. ok, _ = client.Extension("AUTH") if ok && cfg.Mail.Username != "" && cfg.Mail.Password != "" { auth := smtp.PlainAuth( "", cfg.Mail.Username, cfg.Mail.Password, cfg.Mail.SMTPRelay, ) if err = client.Auth(auth); err != nil { Warn.Printf("Auth Error: Server=%s, Error=%s", serverAddr, err) return } } // Remailer.Address is a legacy setting as clients may also need to // set the sender address if their ISPs MTA demands it's valid. // TODO remove cfg.Remailer.Address in a later version (27/04/2015) var sender string if cfg.Mail.Sender != "" { sender = cfg.Mail.Sender } else { sender = cfg.Remailer.Address } if err = client.Mail(sender); err != nil { Warn.Printf("SMTP Error: Server=%s, Error=%s", serverAddr, err) return } for _, addr := range sendTo { if err = client.Rcpt(addr); err != nil { Warn.Printf("Error: %s\n", err) return } } w, err := client.Data() if err != nil { Warn.Printf("Error: %s\n", err) return } _, err = w.Write(payload) if err != nil { Warn.Printf("Error: %s\n", err) return } err = w.Close() if err != nil { Warn.Printf("Error: %s\n", err) return } client.Quit() return }