mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-11-04 03:27:23 -05:00 
			
		
		
		
	Added tls option block including: ciphers, protocols and cache options
Signed-off-by: Guilherme Rezende <guilhermebr@gmail.com>
This commit is contained in:
		
							parent
							
								
									cf2808ae45
								
							
						
					
					
						commit
						823a7eac03
					
				@ -1,10 +1,38 @@
 | 
				
			|||||||
package setup
 | 
					package setup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/mholt/caddy/middleware"
 | 
						"crypto/tls"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/mholt/caddy/middleware"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Map of supported protocols
 | 
				
			||||||
 | 
					// SSLv3 will be not supported in next release
 | 
				
			||||||
 | 
					var supportedProtocols = map[string]uint16{
 | 
				
			||||||
 | 
						"ssl3":   tls.VersionSSL30,
 | 
				
			||||||
 | 
						"tls1.0": tls.VersionTLS10,
 | 
				
			||||||
 | 
						"tls1.1": tls.VersionTLS11,
 | 
				
			||||||
 | 
						"tls1.2": tls.VersionTLS12,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Map of supported ciphers
 | 
				
			||||||
 | 
					// For security reasons caddy will not support RC4 ciphers
 | 
				
			||||||
 | 
					var supportedCiphers = map[string]uint16{
 | 
				
			||||||
 | 
						"ECDHE-RSA-AES128-GCM-SHA256":   tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
 | 
				
			||||||
 | 
						"ECDHE-ECDSA-AES128-GCM-SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
 | 
				
			||||||
 | 
						"ECDHE-RSA-AES128-CBC-SHA":      tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
 | 
				
			||||||
 | 
						"ECDHE-RSA-AES256-CBC-SHA":      tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
 | 
				
			||||||
 | 
						"ECDHE-ECDSA-AES256-CBC-SHA":    tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
 | 
				
			||||||
 | 
						"ECDHE-ECDSA-AES128-CBC-SHA":    tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
 | 
				
			||||||
 | 
						"RSA-AES128-CBC-SHA":            tls.TLS_RSA_WITH_AES_128_CBC_SHA,
 | 
				
			||||||
 | 
						"RSA-AES256-CBC-SHA":            tls.TLS_RSA_WITH_AES_256_CBC_SHA,
 | 
				
			||||||
 | 
						"ECDHE-RSA-3DES-EDE-CBC-SHA":    tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
 | 
				
			||||||
 | 
						"RSA-3DES-EDE-CBC-SHA":          tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TLS(c *Controller) (middleware.Middleware, error) {
 | 
					func TLS(c *Controller) (middleware.Middleware, error) {
 | 
				
			||||||
	c.TLS.Enabled = true
 | 
						c.TLS.Enabled = true
 | 
				
			||||||
	if c.Port == "http" {
 | 
						if c.Port == "http" {
 | 
				
			||||||
@ -12,7 +40,7 @@ func TLS(c *Controller) (middleware.Middleware, error) {
 | 
				
			|||||||
		log.Printf("Warning: TLS was disabled on host http://%s."+
 | 
							log.Printf("Warning: TLS was disabled on host http://%s."+
 | 
				
			||||||
			" Make sure you are specifying https://%s in your config (if you haven't already)."+
 | 
								" Make sure you are specifying https://%s in your config (if you haven't already)."+
 | 
				
			||||||
			" If you meant to serve tls on port 80,"+
 | 
								" If you meant to serve tls on port 80,"+
 | 
				
			||||||
			" specify port 80 in your config (http://%s:80).", c.Host, c.Host, c.Host)
 | 
								" specify port 80 in your config (https://%s:80).", c.Host, c.Host, c.Host)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for c.Next() {
 | 
						for c.Next() {
 | 
				
			||||||
@ -25,6 +53,64 @@ func TLS(c *Controller) (middleware.Middleware, error) {
 | 
				
			|||||||
			return nil, c.ArgErr()
 | 
								return nil, c.ArgErr()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		c.TLS.Key = c.Val()
 | 
							c.TLS.Key = c.Val()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Optional block
 | 
				
			||||||
 | 
							for c.NextBlock() {
 | 
				
			||||||
 | 
								switch c.Val() {
 | 
				
			||||||
 | 
								case "protocols":
 | 
				
			||||||
 | 
									args := c.RemainingArgs()
 | 
				
			||||||
 | 
									if len(args) != 2 {
 | 
				
			||||||
 | 
										return nil, c.ArgErr()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									value, ok := supportedProtocols[strings.ToLower(args[0])]
 | 
				
			||||||
 | 
									if !ok {
 | 
				
			||||||
 | 
										return nil, c.ArgErr()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									c.TLS.ProtocolMinVersion = value
 | 
				
			||||||
 | 
									value, ok = supportedProtocols[strings.ToLower(args[1])]
 | 
				
			||||||
 | 
									if !ok {
 | 
				
			||||||
 | 
										return nil, c.ArgErr()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									c.TLS.ProtocolMaxVersion = value
 | 
				
			||||||
 | 
								case "ciphers":
 | 
				
			||||||
 | 
									for c.NextArg() {
 | 
				
			||||||
 | 
										value, ok := supportedCiphers[strings.ToUpper(c.Val())]
 | 
				
			||||||
 | 
										if !ok {
 | 
				
			||||||
 | 
											return nil, c.ArgErr()
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										c.TLS.Ciphers = append(c.TLS.Ciphers, value)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								case "cache":
 | 
				
			||||||
 | 
									if !c.NextArg() {
 | 
				
			||||||
 | 
										return nil, c.ArgErr()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									c.TLS.CacheSize, _ = strconv.Atoi(c.Val())
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									return nil, c.ArgErr()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If no Ciphers provided, use all caddy supportedCiphers
 | 
				
			||||||
 | 
						if len(c.TLS.Ciphers) == 0 {
 | 
				
			||||||
 | 
							for _, v := range supportedCiphers {
 | 
				
			||||||
 | 
								c.TLS.Ciphers = append(c.TLS.Ciphers, v)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If no ProtocolMin provided, set default MinVersion to TLSv1.1 for security reasons
 | 
				
			||||||
 | 
						if c.TLS.ProtocolMinVersion == 0 {
 | 
				
			||||||
 | 
							c.TLS.ProtocolMinVersion = tls.VersionTLS11
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//If no ProtocolMax provided, use crypto/tls default MaxVersion(tls1.2)
 | 
				
			||||||
 | 
						if c.TLS.ProtocolMaxVersion == 0 {
 | 
				
			||||||
 | 
							c.TLS.ProtocolMaxVersion = tls.VersionTLS12
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//If no cachesize provided, set default to 64
 | 
				
			||||||
 | 
						if c.TLS.CacheSize == 0 {
 | 
				
			||||||
 | 
							c.TLS.CacheSize = 64
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil, nil
 | 
						return nil, nil
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										78
									
								
								config/setup/tls_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								config/setup/tls_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					package setup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/tls"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestTLSParseNoOptional(t *testing.T) {
 | 
				
			||||||
 | 
						c := newTestController(`tls cert.crt cert.key`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := TLS(c)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("Expected no errors, got: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(c.TLS.Ciphers) != len(supportedCiphers) {
 | 
				
			||||||
 | 
							t.Errorf("Expected %v Ciphers, got %v", len(supportedCiphers), len(c.TLS.Ciphers))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.TLS.ProtocolMinVersion != tls.VersionTLS11 {
 | 
				
			||||||
 | 
							t.Errorf("Expected 'tls1.1' ProtocolMinVersion , got %v", c.TLS.ProtocolMinVersion)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.TLS.ProtocolMaxVersion != tls.VersionTLS12 {
 | 
				
			||||||
 | 
							t.Errorf("Expected ProtocolMaxVersion 0, got %v", c.TLS.ProtocolMaxVersion)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.TLS.CacheSize != 64 {
 | 
				
			||||||
 | 
							t.Errorf("Expected CacheSize 64, got %v", c.TLS.CacheSize)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestTLSParseIncompleteParams(t *testing.T) {
 | 
				
			||||||
 | 
						c := newTestController(`tls`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := TLS(c)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							t.Errorf("Expected errors, but no error returned")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c = newTestController(`tls cert.key`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = TLS(c)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							t.Errorf("Expected errors, but no error returned")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestTLSParseWithOptionalParams(t *testing.T) {
 | 
				
			||||||
 | 
						params := `tls cert.crt cert.key {
 | 
				
			||||||
 | 
					            protocols ssl3 tls1.2
 | 
				
			||||||
 | 
					            ciphers RSA-3DES-EDE-CBC-SHA RSA-AES256-CBC-SHA ECDHE-RSA-AES128-GCM-SHA256
 | 
				
			||||||
 | 
					            cache 128
 | 
				
			||||||
 | 
					        }`
 | 
				
			||||||
 | 
						c := newTestController(params)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := TLS(c)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("Expected no errors, got: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.TLS.ProtocolMinVersion != tls.VersionSSL30 {
 | 
				
			||||||
 | 
							t.Errorf("Expected 'ssl3' ProtocolMinVersion, got %#v", c.TLS.ProtocolMinVersion)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.TLS.ProtocolMaxVersion != tls.VersionTLS12 {
 | 
				
			||||||
 | 
							t.Errorf("Expected 'tls1.2' ProtocolMaxVersion, got %v", c.TLS.ProtocolMaxVersion)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(c.TLS.Ciphers) != 3 {
 | 
				
			||||||
 | 
							t.Errorf("Expected 3 Ciphers, got %v", len(c.TLS.Ciphers))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.TLS.CacheSize != 128 {
 | 
				
			||||||
 | 
							t.Errorf("Expected CacheSize 128, got %v", c.TLS.CacheSize)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -55,8 +55,13 @@ func (c Config) Address() string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// TLSConfig describes how TLS should be configured and used,
 | 
					// TLSConfig describes how TLS should be configured and used,
 | 
				
			||||||
// if at all. A certificate and key are both required.
 | 
					// if at all. A certificate and key are both required.
 | 
				
			||||||
 | 
					// Ciphers, Protocols and CacheSize are optional
 | 
				
			||||||
type TLSConfig struct {
 | 
					type TLSConfig struct {
 | 
				
			||||||
	Enabled     bool
 | 
						Enabled            bool
 | 
				
			||||||
	Certificate string
 | 
						Certificate        string
 | 
				
			||||||
	Key         string
 | 
						Key                string
 | 
				
			||||||
 | 
						Ciphers            []uint16
 | 
				
			||||||
 | 
						ProtocolMinVersion uint16
 | 
				
			||||||
 | 
						ProtocolMaxVersion uint16
 | 
				
			||||||
 | 
						CacheSize          int
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -132,8 +132,18 @@ func ListenAndServeTLSWithSNI(srv *http.Server, tlsConfigs []TLSConfig) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	config.BuildNameToCertificate()
 | 
						config.BuildNameToCertificate()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add a session cache LRU algorithm with default capacity (64)
 | 
						// Here we change some crypto/tls defaults based on caddyfile
 | 
				
			||||||
	config.ClientSessionCache = tls.NewLRUClientSessionCache(0)
 | 
						// If no config provided, we set defaults focused in security
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add a session cache LRU algorithm
 | 
				
			||||||
 | 
						config.ClientSessionCache = tls.NewLRUClientSessionCache(tlsConfigs[0].CacheSize)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config.MinVersion = tlsConfigs[0].ProtocolMinVersion
 | 
				
			||||||
 | 
						config.MaxVersion = tlsConfigs[0].ProtocolMaxVersion
 | 
				
			||||||
 | 
						config.CipherSuites = tlsConfigs[0].Ciphers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Server ciphers have priority over client ciphers
 | 
				
			||||||
 | 
						config.PreferServerCipherSuites = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	conn, err := net.Listen("tcp", addr)
 | 
						conn, err := net.Listen("tcp", addr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user