Example #1
0
File: tls.go Project: alehano/caddy
// 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).
func SetDefaultTLSParams(c *server.Config) {
	// If no ciphers provided, use all that Caddy supports for the protocol
	if len(c.TLS.Ciphers) == 0 {
		c.TLS.Ciphers = defaultCiphers
	}

	// Not a cipher suite, but still important for mitigating protocol downgrade attacks
	c.TLS.Ciphers = append(c.TLS.Ciphers, tls.TLS_FALLBACK_SCSV)

	// 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.Host != "localhost" {
		c.Port = "443"
	}
}
Example #2
0
// 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"
	}
}
Example #3
0
// Load reads input (named filename) and parses it, returning server
// configurations grouped by listening address.
func Load(filename string, input io.Reader) (Group, error) {
	var configs []server.Config

	// turn off timestamp for parsing
	flags := log.Flags()
	log.SetFlags(0)

	serverBlocks, err := parse.ServerBlocks(filename, input)
	if err != nil {
		return nil, err
	}
	if len(serverBlocks) == 0 {
		return Default()
	}

	// Each server block represents similar hosts/addresses.
	// Iterate each server block and make a config for each one,
	// executing the directives that were parsed.
	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,
				Middleware: make(map[string][]middleware.Middleware),
				ConfigFile: filename,
				AppName:    app.Name,
				AppVersion: app.Version,
			}

			// It is crucial that directives are executed in the proper order.
			for _, 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, which is the
					// server config and the dispenser containing only
					// this directive's tokens.
					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],
					}

					midware, err := dir.setup(controller)
					if err != nil {
						return nil, err
					}
					if midware != nil {
						// TODO: For now, we only support the default path scope /
						config.Middleware["/"] = append(config.Middleware["/"], midware)
					}
					storages[dir.name] = controller.ServerBlockStorage // persist for this server block
				}
			}

			if config.Port == "" {
				config.Port = Port
			}

			configs = append(configs, config)
		}
	}

	// restore logging settings
	log.SetFlags(flags)

	return arrangeBindings(configs)
}
Example #4
0
func Load(filename string, input io.Reader) ([]server.Config, error) {
	var configs []server.Config

	// turn off timestamp for parsing
	flags := log.Flags()
	log.SetFlags(0)

	serverBlocks, err := parse.ServerBlocks(filename, input)
	if err != nil {
		return configs, err
	}

	// Each server block represents a single server/address.
	// Iterate each server block and make a config for each one,
	// executing the directives that were parsed.
	for _, sb := range serverBlocks {
		config := server.Config{
			Host:       sb.Host,
			Port:       sb.Port,
			Root:       Root,
			Middleware: make(map[string][]middleware.Middleware),
			ConfigFile: filename,
			AppName:    app.Name,
			AppVersion: app.Version,
		}

		// It is crucial that directives are executed in the proper order.
		for _, 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, which is the
				// server config and the dispenser containing only
				// this directive's tokens.
				controller := &setup.Controller{
					Config:    &config,
					Dispenser: parse.NewDispenserTokens(filename, tokens),
				}

				midware, err := dir.setup(controller)
				if err != nil {
					return configs, err
				}
				if midware != nil {
					// TODO: For now, we only support the default path scope /
					config.Middleware["/"] = append(config.Middleware["/"], midware)
				}
			}
		}

		if config.Port == "" {
			config.Port = Port
		}

		configs = append(configs, config)
	}

	// restore logging settings
	log.SetFlags(flags)

	return configs, nil
}
Example #5
0
// loadConfigsUpToIncludingTLS loads the configs from input with name filename and returns them,
// the parsed server blocks, the index of the last directive it processed, and an error (if any).
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 Caddyfile.
	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,
				Scheme:     addr.Scheme,
				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
}