// setDefaultTLSParams sets the default TLS cipher suites, protocol versions, // and server preferences of a server.Config if they were not previously set // (it does not overwrite; only fills in missing values). It will also set the // port to 443 if not already set, TLS is enabled, TLS is manual, and the host // does not equal localhost. func setDefaultTLSParams(c *server.Config) { // If no ciphers provided, use default list if len(c.TLS.Ciphers) == 0 { c.TLS.Ciphers = defaultCiphers } // Not a cipher suite, but still important for mitigating protocol downgrade attacks // (prepend since having it at end breaks http2 due to non-h2-approved suites before it) c.TLS.Ciphers = append([]uint16{tls.TLS_FALLBACK_SCSV}, c.TLS.Ciphers...) // Set default protocol min and max versions - must balance compatibility and security if c.TLS.ProtocolMinVersion == 0 { c.TLS.ProtocolMinVersion = tls.VersionTLS10 } if c.TLS.ProtocolMaxVersion == 0 { c.TLS.ProtocolMaxVersion = tls.VersionTLS12 } // Prefer server cipher suites c.TLS.PreferServerCipherSuites = true // Default TLS port is 443; only use if port is not manually specified, // TLS is enabled, and the host is not localhost if c.Port == "" && c.TLS.Enabled && (!c.TLS.Manual || c.TLS.OnDemand) && c.Host != "localhost" { c.Port = "443" } }
func loadConfigsUpToIncludingTLS(filename string, input io.Reader) ([]server.Config, []parse.ServerBlock, int, error) { var configs []server.Config // Each server block represents similar hosts/addresses, since they // were grouped together in the Corefile. serverBlocks, err := parse.ServerBlocks(filename, input, true) if err != nil { return nil, nil, 0, err } if len(serverBlocks) == 0 { newInput := DefaultInput() serverBlocks, err = parse.ServerBlocks(newInput.Path(), bytes.NewReader(newInput.Body()), true) if err != nil { return nil, nil, 0, err } } var lastDirectiveIndex int // we set up directives in two parts; this stores where we left off // Iterate each server block and make a config for each one, // executing the directives that were parsed in order up to the tls // directive; this is because we must activate Let's Encrypt. for i, sb := range serverBlocks { onces := makeOnces() storages := makeStorages() for j, addr := range sb.Addresses { config := server.Config{ Host: addr.Host, Port: addr.Port, Root: Root, ConfigFile: filename, AppName: AppName, AppVersion: AppVersion, } // It is crucial that directives are executed in the proper order. for k, dir := range directiveOrder { // Execute directive if it is in the server block if tokens, ok := sb.Tokens[dir.name]; ok { // Each setup function gets a controller, from which setup functions // get access to the config, tokens, and other state information useful // to set up its own host only. controller := &setup.Controller{ Config: &config, Dispenser: parse.NewDispenserTokens(filename, tokens), OncePerServerBlock: func(f func() error) error { var err error onces[dir.name].Do(func() { err = f() }) return err }, ServerBlockIndex: i, ServerBlockHostIndex: j, ServerBlockHosts: sb.HostList(), ServerBlockStorage: storages[dir.name], } // execute setup function and append middleware handler, if any midware, err := dir.setup(controller) if err != nil { return nil, nil, lastDirectiveIndex, err } if midware != nil { config.Middleware = append(config.Middleware, midware) } storages[dir.name] = controller.ServerBlockStorage // persist for this server block } // Stop after TLS setup, since we need to activate Let's Encrypt before continuing; // it makes some changes to the configs that middlewares might want to know about. if dir.name == "tls" { lastDirectiveIndex = k break } } configs = append(configs, config) } } return configs, serverBlocks, lastDirectiveIndex, nil }