From 92820f73dc1eaf7869a8656ccafb13c38cdc77d5 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Sun, 2 Jul 2017 01:58:11 +0200 Subject: tls settings con now be fully configured --- src/daq/s5proxy/sample.json | 17 +- src/daq/s5proxy/src/s5proxy/config.go | 284 ++++++++++++++++++++++++++++++++-- 2 files changed, 284 insertions(+), 17 deletions(-) diff --git a/src/daq/s5proxy/sample.json b/src/daq/s5proxy/sample.json index 8ec6dc1..cd72df2 100644 --- a/src/daq/s5proxy/sample.json +++ b/src/daq/s5proxy/sample.json @@ -3,8 +3,21 @@ "protocol": "http+https", "redirect2https": 301, "tls": { - "certificate": "fullchain.pem", - "certificate-key": "private.key" + "certificate": "fullchain.pem", + "certificate-key": "private.key", + "min-protocol-version": "TLSv1", + "ciphers": [ + "ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "ECDHE_RSA_WITH_AES_256_CBC_SHA", + "RSA_WITH_AES_256_GCM_SHA384", + "RSA_WITH_AES_256_CBC_SHA" + ], + "prefer-server-ciphers": true, + "ecdh-curves": [ + "secp521r1", + "secp384r1", + "secp256r1" + ] }, "connect": "http://emc01.spreadspace.org:8000", "request_header": [ diff --git a/src/daq/s5proxy/src/s5proxy/config.go b/src/daq/s5proxy/src/s5proxy/config.go index d8c61e0..d145393 100644 --- a/src/daq/s5proxy/src/s5proxy/config.go +++ b/src/daq/s5proxy/src/s5proxy/config.go @@ -34,6 +34,7 @@ package main import ( "crypto/tls" + "encoding/hex" "encoding/json" "errors" "fmt" @@ -44,6 +45,11 @@ import ( "time" ) +//********************************************* +//********** HTTP/HTTPS Proxy Configuration + +//********** ProtocolType + type ProtocolType string const ( @@ -79,6 +85,8 @@ func (p *ProtocolType) UnmarshalText(data []byte) (err error) { return p.fromString(string(data)) } +//********** RedirectCode + type RedirectCode int func (r RedirectCode) String() string { @@ -116,6 +124,8 @@ func (r *RedirectCode) UnmarshalJSON(data []byte) (err error) { return r.fromString(string(data)) } +//********** Operation + type Operation string const ( @@ -154,6 +164,8 @@ func (o *Operation) UnmarshalText(data []byte) (err error) { return o.fromString(string(data)) } +//********** HeaderOperation + type HeaderOperation struct { Operation Operation `json:"op"` Header string `json:"header"` @@ -171,23 +183,256 @@ func (h *HeaderOperation) Parse() (err error) { return nil } +//********************************************* +//********** TLS Configuration + +//********** ProtocolType + type TLSProtocolVersion uint16 -type TLSCipher uint16 +func (pv TLSProtocolVersion) String() string { + switch pv { + case tls.VersionSSL30: + return "SSLv3" + case tls.VersionTLS10: + return "TLSv1" + case tls.VersionTLS11: + return "TLSv1.1" + case tls.VersionTLS12: + return "TLSv1.2" + } + return "unknown tls protocol" +} + +func (pv *TLSProtocolVersion) fromString(str string) (err error) { + switch strings.ToUpper(str) { + case "SSLV3": + *pv = tls.VersionSSL30 + case "TLSV1": + *pv = tls.VersionTLS10 + case "TLSV1.1": + *pv = tls.VersionTLS11 + case "TLSV1.2": + *pv = tls.VersionTLS12 + default: + return fmt.Errorf("invalid tls protocol version: '" + str + "'") + } + return +} + +func (pv TLSProtocolVersion) MarshalText() (data []byte, err error) { + data = []byte(pv.String()) + return +} + +func (pv *TLSProtocolVersion) UnmarshalText(data []byte) (err error) { + return pv.fromString(string(data)) +} + +//********** CipherSuite + +type TLSCipherSuite uint16 + +func (cs TLSCipherSuite) String() string { + switch uint16(cs) { + case tls.TLS_RSA_WITH_RC4_128_SHA: + return "RSA_WITH_RC4_128_SHA" + case tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA: + return "RSA_WITH_3DES_EDE_CBC_SHA" + case tls.TLS_RSA_WITH_AES_128_CBC_SHA: + return "RSA_WITH_AES_128_CBC_SHA" + case tls.TLS_RSA_WITH_AES_256_CBC_SHA: + return "RSA_WITH_AES_256_CBC_SHA" + case tls.TLS_RSA_WITH_AES_128_CBC_SHA256: + return "RSA_WITH_AES_128_CBC_SHA256" + case tls.TLS_RSA_WITH_AES_128_GCM_SHA256: + return "RSA_WITH_AES_128_GCM_SHA256" + case tls.TLS_RSA_WITH_AES_256_GCM_SHA384: + return "RSA_WITH_AES_256_GCM_SHA384" + case tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + return "ECDHE_ECDSA_WITH_RC4_128_SHA" + case tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + return "ECDHE_ECDSA_WITH_AES_128_CBC_SHA" + case tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + return "ECDHE_ECDSA_WITH_AES_256_CBC_SHA" + case tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA: + return "ECDHE_RSA_WITH_RC4_128_SHA" + case tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "ECDHE_RSA_WITH_3DES_EDE_CBC_SHA" + case tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + return "ECDHE_RSA_WITH_AES_128_CBC_SHA" + case tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + return "ECDHE_RSA_WITH_AES_256_CBC_SHA" + case tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + return "ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" + case tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + return "ECDHE_RSA_WITH_AES_128_CBC_SHA256" + case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + return "ECDHE_RSA_WITH_AES_128_GCM_SHA256" + case tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + return "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" + case tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + return "ECDHE_RSA_WITH_AES_256_GCM_SHA384" + case tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + return "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" + case tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: + return "ECDHE_RSA_WITH_CHACHA20_POLY1305" + case tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: + return "ECDHE_ECDSA_WITH_CHACHA20_POLY1305" + } + return "unknown tls cipher suite" +} + +func (cs *TLSCipherSuite) fromString(str string) (err error) { + switch strings.Replace(strings.ToUpper(str), "-", "_", -1) { + case "RSA_WITH_RC4_128_SHA": + *cs = TLSCipherSuite(tls.TLS_RSA_WITH_RC4_128_SHA) + case "RSA_WITH_3DES_EDE_CBC_SHA": + *cs = TLSCipherSuite(tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA) + case "RSA_WITH_AES_128_CBC_SHA": + *cs = TLSCipherSuite(tls.TLS_RSA_WITH_AES_128_CBC_SHA) + case "RSA_WITH_AES_256_CBC_SHA": + *cs = TLSCipherSuite(tls.TLS_RSA_WITH_AES_256_CBC_SHA) + case "RSA_WITH_AES_128_CBC_SHA256": + *cs = TLSCipherSuite(tls.TLS_RSA_WITH_AES_128_CBC_SHA256) + case "RSA_WITH_AES_128_GCM_SHA256": + *cs = TLSCipherSuite(tls.TLS_RSA_WITH_AES_128_GCM_SHA256) + case "RSA_WITH_AES_256_GCM_SHA384": + *cs = TLSCipherSuite(tls.TLS_RSA_WITH_AES_256_GCM_SHA384) + case "ECDHE_ECDSA_WITH_RC4_128_SHA": + *cs = TLSCipherSuite(tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) + case "ECDHE_ECDSA_WITH_AES_128_CBC_SHA": + *cs = TLSCipherSuite(tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) + case "ECDHE_ECDSA_WITH_AES_256_CBC_SHA": + *cs = TLSCipherSuite(tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) + case "ECDHE_RSA_WITH_RC4_128_SHA": + *cs = TLSCipherSuite(tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA) + case "ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": + *cs = TLSCipherSuite(tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) + case "ECDHE_RSA_WITH_AES_128_CBC_SHA": + *cs = TLSCipherSuite(tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) + case "ECDHE_RSA_WITH_AES_256_CBC_SHA": + *cs = TLSCipherSuite(tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) + case "ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": + *cs = TLSCipherSuite(tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) + case "ECDHE_RSA_WITH_AES_128_CBC_SHA256": + *cs = TLSCipherSuite(tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) + case "ECDHE_RSA_WITH_AES_128_GCM_SHA256": + *cs = TLSCipherSuite(tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) + case "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": + *cs = TLSCipherSuite(tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + case "ECDHE_RSA_WITH_AES_256_GCM_SHA384": + *cs = TLSCipherSuite(tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) + case "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": + *cs = TLSCipherSuite(tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) + case "ECDHE_RSA_WITH_CHACHA20_POLY1305": + *cs = TLSCipherSuite(tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305) + case "ECDHE_ECDSA_WITH_CHACHA20_POLY1305": + *cs = TLSCipherSuite(tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305) + default: + return fmt.Errorf("invalid tls cipher suite: '" + str + "'") + } + return +} + +func (cs TLSCipherSuite) MarshalText() (data []byte, err error) { + data = []byte(cs.String()) + return +} + +func (cs *TLSCipherSuite) UnmarshalText(data []byte) (err error) { + return cs.fromString(string(data)) +} + +//********** TLSCurve type TLSCurve tls.CurveID +func (c TLSCurve) String() string { + switch tls.CurveID(c) { + case tls.CurveP256: + return "secp256r1" + case tls.CurveP384: + return "secp384r1" + case tls.CurveP521: + return "secp521r1" + case tls.X25519: + return "x25519" + } + return "unknown tls echd curve" +} + +func (c *TLSCurve) fromString(str string) (err error) { + switch strings.ToLower(str) { + case "prime256v1": + fallthrough + case "secp256r1": + *c = TLSCurve(tls.CurveP256) + case "prime384v1": + fallthrough + case "secp384r1": + *c = TLSCurve(tls.CurveP384) + case "prime521v1": + fallthrough + case "secp521r1": + *c = TLSCurve(tls.CurveP521) + case "x25519": + *c = TLSCurve(tls.X25519) + default: + return fmt.Errorf("invalid tls ecdh curve: '" + str + "'") + } + return +} + +func (c TLSCurve) MarshalText() (data []byte, err error) { + data = []byte(c.String()) + return +} + +func (c *TLSCurve) UnmarshalText(data []byte) (err error) { + return c.fromString(string(data)) +} + +//********** TLSSessionTicketKey + type TLSSessionTicketKey [32]byte +func (stk TLSSessionTicketKey) String() string { + return hex.EncodeToString([]byte(stk[:])) +} + +func (stk *TLSSessionTicketKey) fromString(str string) error { + key, err := hex.DecodeString(str) + if err != nil { + return fmt.Errorf("invalid tls session ticket key: %v", err) + } + if len(key) != len(stk) { + return fmt.Errorf("invalid tls session ticket key length: got %d bytes, expected %d bytes", len(key), len(stk)) + } + copy(stk[:], key) + return nil +} + +func (stk TLSSessionTicketKey) MarshalText() (data []byte, err error) { + data = []byte(stk.String()) + return +} + +func (stk *TLSSessionTicketKey) UnmarshalText(data []byte) (err error) { + return stk.fromString(string(data)) +} + +//********** TLSConfig + type TLSConfig struct { CertFile string `json:"certificate"` KeyFile string `json:"certificate-key"` MinVersion TLSProtocolVersion `json:"min-protocol-version"` MaxVersion TLSProtocolVersion `json:"max-protocol-version"` - CipherSuites []TLSCipher `json:"ciphers"` + CipherSuites []TLSCipherSuite `json:"ciphers"` PreferServerCipherSuites bool `json:"prefer-server-ciphers"` CurvePreferences []TLSCurve `json:"ecdh-curves"` - SessionTicketsDisabled bool `json:"session-tickets"` + SessionTickets bool `json:"session-tickets"` SessionTicketKey TLSSessionTicketKey `json:"session-ticket-key"` } @@ -197,23 +442,27 @@ func (t TLSConfig) ToGoTLSConfig() (*tls.Config, error) { return nil, err } - // TODO: generate cfg from t - cfg := &tls.Config{ - Certificates: []tls.Certificate{cert}, - MinVersion: tls.VersionTLS10, - CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256}, - PreferServerCipherSuites: true, - CipherSuites: []uint16{ - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - tls.TLS_RSA_WITH_AES_256_GCM_SHA384, - tls.TLS_RSA_WITH_AES_256_CBC_SHA, - }, + cfg := &tls.Config{Certificates: []tls.Certificate{cert}} + cfg.MinVersion = uint16(t.MinVersion) + cfg.MaxVersion = uint16(t.MaxVersion) + for _, cs := range t.CipherSuites { + cfg.CipherSuites = append(cfg.CipherSuites, uint16(cs)) + } + cfg.PreferServerCipherSuites = t.PreferServerCipherSuites + for _, cp := range t.CurvePreferences { + cfg.CurvePreferences = append(cfg.CurvePreferences, tls.CurveID(cp)) } + cfg.SessionTicketsDisabled = !t.SessionTickets + cfg.SessionTicketKey = [32]byte(t.SessionTicketKey) return cfg, nil } +//********************************************* +//********** SFive Statistics + +//********** SFiveDuration + type SFiveDuration int64 func (d *SFiveDuration) UnmarshalText(data []byte) error { @@ -228,6 +477,8 @@ func (d *SFiveDuration) UnmarshalText(data []byte) error { return nil } +//********** SFiveConf + type SFiveConf struct { Sock string `json:"socket"` Hostname string `json:"hostname"` @@ -237,6 +488,9 @@ type SFiveConf struct { Stream []string `json:"stream"` } +//********************************************* +//********** Configuration + type Config struct { ListenAddr string `json:"listen"` Protocol ProtocolType `json:"protocol"` -- cgit v1.2.3