Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cipher Suite and Start up fixes #2772

Closed
wants to merge 16 commits into from
2 changes: 2 additions & 0 deletions dnscrypt-proxy/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,8 @@ func (config *Config) loadSource(proxy *Proxy, cfgSourceName string, cfgSource *
dlog.Infof("Downloading [%s] failed: %v, using cache file to startup", source.name, err)
}
proxy.sources = append(proxy.sources, source)
proxy.xTransport.keepCipherSuite = true
proxy.xTransport.rebuildTransport()
return nil
}

Expand Down
121 changes: 59 additions & 62 deletions dnscrypt-proxy/xtransport.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ type XTransport struct {
http3 bool
tlsDisableSessionTickets bool
tlsCipherSuite []uint16
keepCipherSuite bool
CSHandleError int
proxyDialer *netproxy.Dialer
httpProxyFunction func(*http.Request) (*url.URL, error)
tlsClientCreds DOHClientCreds
Expand All @@ -93,6 +95,8 @@ func NewXTransport() *XTransport {
useIPv6: false,
tlsDisableSessionTickets: false,
tlsCipherSuite: nil,
keepCipherSuite: false,
CSHandleError: 0,
keyLogWriter: nil,
}
return &xTransport
Expand Down Expand Up @@ -216,40 +220,33 @@ func (xTransport *XTransport) rebuildTransport() {
}
tlsClientConfig.Certificates = []tls.Certificate{cert}
}

if xTransport.tlsDisableSessionTickets || xTransport.tlsCipherSuite != nil {
if xTransport.tlsDisableSessionTickets {
tlsClientConfig.SessionTicketsDisabled = xTransport.tlsDisableSessionTickets
if !xTransport.tlsDisableSessionTickets {
tlsClientConfig.ClientSessionCache = tls.NewLRUClientSessionCache(10)
tlsClientConfig.ClientSessionCache = nil
} else {
tlsClientConfig.ClientSessionCache = tls.NewLRUClientSessionCache(10)
}
if xTransport.tlsCipherSuite != nil && len(xTransport.tlsCipherSuite) > 0 && xTransport.keepCipherSuite == true {
var tls13 = "198 199 4865 4866 4867 4868 4869 49332 49333"
var only13 = 0
var SuitesCount = 0
for _, expectedSuiteID := range xTransport.tlsCipherSuite {
check := strconv.Itoa(int(expectedSuiteID))
if strings.Contains(tls13 , check) {
SuitesCount += 1
}
only13 += 1
}
if xTransport.tlsCipherSuite != nil {
tlsClientConfig.PreferServerCipherSuites = false
if only13 != SuitesCount {
tlsClientConfig.CipherSuites = xTransport.tlsCipherSuite

// Go doesn't allow changing the cipher suite with TLS 1.3
// So, check if the requested set of ciphers matches the TLS 1.3 suite.
// If it doesn't, downgrade to TLS 1.2
compatibleSuitesCount := 0
for _, suite := range tls.CipherSuites() {
if suite.Insecure {
continue
}
for _, supportedVersion := range suite.SupportedVersions {
if supportedVersion != tls.VersionTLS13 {
for _, expectedSuiteID := range xTransport.tlsCipherSuite {
if expectedSuiteID == suite.ID {
compatibleSuitesCount += 1
break
}
}
}
}
}
if compatibleSuitesCount != len(tls.CipherSuites()) {
dlog.Notice("Explicit cipher suite configured - downgrading to TLS 1.2")
tlsClientConfig.MaxVersion = tls.VersionTLS12
dlog.Info("Explicit cipher suite configured downgrading to TLS 1.2")
tlsClientConfig.MaxVersion = tls.VersionTLS12
if xTransport.CSHandleError < 2 {
xTransport.CSHandleError += 1
}
}
} else {
tlsClientConfig.MaxVersion = tls.VersionTLS13
}
transport.TLSClientConfig = &tlsClientConfig
if http2Transport, err := http2.ConfigureTransports(transport); err != nil {
Expand Down Expand Up @@ -382,10 +379,8 @@ func (xTransport *XTransport) resolveUsingResolvers(
for i, resolver := range resolvers {
ip, ttl, err = xTransport.resolveUsingResolver(proto, host, resolver)
if err == nil {
if i > 0 {
dlog.Infof("Resolution succeeded with resolver %s[%s]", proto, resolver)
resolvers[0], resolvers[i] = resolvers[i], resolvers[0]
}
dlog.Infof("Resolution succeeded with resolver %s[%s]", proto, resolver)
resolvers[0], resolvers[i] = resolvers[i], resolvers[0]
break
}
dlog.Infof("Unable to resolve [%s] using resolver [%s] (%s): %v", host, resolver, proto, err)
Expand All @@ -412,24 +407,16 @@ func (xTransport *XTransport) resolveAndUpdateCache(host string) error {
if xTransport.mainProto == "tcp" {
protos = []string{"tcp", "udp"}
}
if xTransport.ignoreSystemDNS {
if xTransport.internalResolverReady {
for _, proto := range protos {
foundIP, ttl, err = xTransport.resolveUsingResolvers(proto, host, xTransport.internalResolvers)
if err == nil {
break
}
if xTransport.internalResolverReady {
for _, proto := range protos {
foundIP, ttl, err = xTransport.resolveUsingResolvers(proto, host, xTransport.internalResolvers)
if err == nil {
break
}
} else {
err = errors.New("Service is not usable yet")
dlog.Notice(err)
}
} else {
foundIP, ttl, err = xTransport.resolveUsingSystem(host)
if err != nil {
err = errors.New("System DNS is not usable yet")
dlog.Notice(err)
}
err = errors.New("Service is not usable yet")
dlog.Notice(err)
}
if err != nil {
for _, proto := range protos {
Expand All @@ -446,9 +433,15 @@ func (xTransport *XTransport) resolveAndUpdateCache(host string) error {
}
}
}
if err != nil && xTransport.ignoreSystemDNS {
if err != nil && xTransport.ignoreSystemDNS == false {
dlog.Noticef("Bootstrap resolvers didn't respond - Trying with the system resolver as a last resort")
foundIP, ttl, err = xTransport.resolveUsingSystem(host)
if err != nil {
err = errors.New("System DNS error")
dlog.Notice(err)
}
}else if err != nil && xTransport.ignoreSystemDNS == true {
dlog.Noticef("Bootstrap resolvers didn't respond and we are ignoring system dns")
}
if ttl < MinResolverIPTTL {
ttl = MinResolverIPTTL
Expand All @@ -470,9 +463,10 @@ func (xTransport *XTransport) resolveAndUpdateCache(host string) error {
} else {
dlog.Errorf("no IP address found for [%s]", host)
}
}else{
xTransport.saveCachedIP(host, foundIP, ttl)
dlog.Debugf("[%s] IP address [%s] added to the cache, valid for %v", host, foundIP, ttl)
}
xTransport.saveCachedIP(host, foundIP, ttl)
dlog.Debugf("[%s] IP address [%s] added to the cache, valid for %v", host, foundIP, ttl)
return nil
}

Expand Down Expand Up @@ -548,27 +542,30 @@ func (xTransport *XTransport) Fetch(
start := time.Now()
resp, err := client.Do(req)
rtt := time.Since(start)
var statusCode int
if resp != nil {
statusCode = resp.StatusCode
}
if err == nil {
if resp == nil {
err = errors.New("Webserver returned an error")
} else if resp.StatusCode < 200 || resp.StatusCode > 299 {
err = errors.New(resp.Status)
}
} else {
dlog.Debugf("HTTP client error: [%v] - closing idle connections", err)
xTransport.transport.CloseIdleConnections()
}
statusCode := 503
if resp != nil {
statusCode = resp.StatusCode
}
if err != nil {
dlog.Debugf("HTTP client error: [%v]", err)
dlog.Debugf("[%s]: [%s]", req.URL, err)
if xTransport.tlsCipherSuite != nil && strings.Contains(err.Error(), "handshake failure") {
if xTransport.tlsCipherSuite != nil && xTransport.keepCipherSuite == true {
dlog.Warnf(
"TLS handshake failure - Try changing or deleting the tls_cipher_suite value in the configuration file",
"TLS handshake failure with cipher suite: %v - Try changing or deleting the tls_cipher_suite value in the configuration file",
xTransport.tlsCipherSuite,
)
xTransport.tlsCipherSuite = nil
if strings.Contains(err.Error(), "handshake failure") || strings.Contains(err.Error(), "tls: error decoding message") {
if xTransport.CSHandleError == 1 {
xTransport.CSHandleError += 1
xTransport.keepCipherSuite = false
}
}
xTransport.rebuildTransport()
}
return nil, statusCode, nil, rtt, err
Expand Down