lib/tlsutil: Enable TLS 1.3 when available, on test builds (fixes #5065) (#5558)

* lib/tlsutil: Enable TLS 1.3 when available, on test builds (fixes #5065)

This enables TLS 1.3 negotiation on Go 1.12 by setting the GODEBUG
variable. For now, this just gets enabled on test versions (those with a
dash in the version number).

Users wishing to enable this on production builds can set GODEBUG
manually.

The string representation of connections now includes the TLS version
and cipher suite. This becomes part of the log output on connections.
That is, when talking to an old client:

    Established secure connection .../TLS1.2-TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256

and now potentially:

    Established secure connection .../TLS1.3-TLS_AES_128_GCM_SHA256

(The cipher suite was there previously in the log output, but not the
TLS version.)

I also added this info as a new Crypto() method on the connection, and
propagate this out to the API and GUI, where it can be seen in the
connection address hover (although with bad word wrapping sometimes).

* wip

* wip
This commit is contained in:
Jakob Borg 2019-02-26 11:49:02 +01:00 committed by GitHub
parent 722b3fce6a
commit f24676ba5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 4 deletions

View File

@ -709,7 +709,7 @@
<tr>
<th><span class="fas fa-fw fa-link"></span>&nbsp<span translate>Address</span></th>
<td ng-if="connections[deviceCfg.deviceID].connected" class="text-right">
<span tooltip data-original-title="{{ connections[deviceCfg.deviceID].type.indexOf('Relay') > -1 ? '' : connections[deviceCfg.deviceID].type }}">
<span tooltip data-original-title="{{ connections[deviceCfg.deviceID].type.indexOf('Relay') > -1 ? '' : connections[deviceCfg.deviceID].type }} {{ connections[deviceCfg.deviceID].crypto }}>
{{deviceAddr(deviceCfg)}}
</span>
</td>

View File

@ -51,6 +51,7 @@ const (
// From go/src/crypto/tls/cipher_suites.go
var tlsCipherSuiteNames = map[uint16]string{
// TLS 1.2
0x0005: "TLS_RSA_WITH_RC4_128_SHA",
0x000a: "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
0x002f: "TLS_RSA_WITH_AES_128_CBC_SHA",
@ -73,6 +74,16 @@ var tlsCipherSuiteNames = map[uint16]string{
0xc02c: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
0xcca8: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
0xcca9: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
// TLS 1.3
0x1301: "TLS_AES_128_GCM_SHA256",
0x1302: "TLS_AES_256_GCM_SHA384",
0x1303: "TLS_CHACHA20_POLY1305_SHA256",
}
var tlsVersionNames = map[uint16]string{
tls.VersionTLS12: "TLS1.2",
772: "TLS1.3", // tls.VersionTLS13 constant available in Go 1.12+
}
// Service listens and dials all configured unconnected devices, via supported
@ -281,7 +292,7 @@ next:
protoConn := protocol.NewConnection(remoteID, rd, wr, s.model, c.String(), deviceCfg.Compression)
modelConn := completeConn{c, protoConn}
l.Infof("Established secure connection to %s at %s (%s)", remoteID, c, tlsCipherSuiteNames[c.ConnectionState().CipherSuite])
l.Infof("Established secure connection to %s at %s", remoteID, c)
s.model.AddConnection(modelConn, hello)
continue next

View File

@ -27,6 +27,7 @@ type Connection interface {
RemoteAddr() net.Addr
Priority() int
String() string
Crypto() string
}
// completeConn is the aggregation of an internalConn and the
@ -101,6 +102,11 @@ func (c internalConn) Priority() int {
return c.priority
}
func (c internalConn) Crypto() string {
cs := c.ConnectionState()
return fmt.Sprintf("%s-%s", tlsVersionNames[cs.Version], tlsCipherSuiteNames[cs.CipherSuite])
}
func (c internalConn) Transport() string {
transport := c.connType.Transport()
host, _, err := net.SplitHostPort(c.LocalAddr().String())
@ -118,7 +124,7 @@ func (c internalConn) Transport() string {
}
func (c internalConn) String() string {
return fmt.Sprintf("%s-%s/%s", c.LocalAddr(), c.RemoteAddr(), c.Type())
return fmt.Sprintf("%s-%s/%s/%s", c.LocalAddr(), c.RemoteAddr(), c.Type(), c.Crypto())
}
type dialerFactory interface {

View File

@ -574,6 +574,7 @@ type ConnectionInfo struct {
Address string
ClientVersion string
Type string
Crypto string
}
func (info ConnectionInfo) MarshalJSON() ([]byte, error) {
@ -586,6 +587,7 @@ func (info ConnectionInfo) MarshalJSON() ([]byte, error) {
"address": info.Address,
"clientVersion": info.ClientVersion,
"type": info.Type,
"crypto": info.Crypto,
})
}
@ -609,6 +611,7 @@ func (m *model) ConnectionStats() map[string]interface{} {
}
if conn, ok := m.conn[device]; ok {
ci.Type = conn.Type()
ci.Crypto = conn.Crypto()
ci.Connected = ok
ci.Statistics = conn.Statistics()
if addr := conn.RemoteAddr(); addr != nil {

View File

@ -409,9 +409,15 @@ func (f *fakeConnection) RemoteAddr() net.Addr {
func (f *fakeConnection) Type() string {
return "fake"
}
func (f *fakeConnection) Crypto() string {
return "fake"
}
func (f *fakeConnection) Transport() string {
return "fake"
}
func (f *fakeConnection) Priority() int {
return 9000
}

View File

@ -20,6 +20,7 @@ import (
"os"
"time"
"github.com/syncthing/syncthing/lib/build"
"github.com/syncthing/syncthing/lib/rand"
)
@ -69,6 +70,11 @@ var (
func init() {
// Creates the list of ciper suites that SecureDefault uses.
cipherSuites = buildCipherSuites()
if build.IsBeta {
// Append "tls13=1" to GODEBUG before starting TLS, to enable TLS
// 1.3 in Go 1.12.
os.Setenv("GODEBUG", os.Getenv("GODEBUG")+",tls13=1")
}
}
// SecureDefault returns a tls.Config with reasonable, secure defaults set.
@ -84,7 +90,7 @@ func SecureDefault() *tls.Config {
// secure (so the web tells me, don't ask me to explain the
// details).
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
// The cipher suite lists built above.
// The cipher suite lists built above. These are ignored in TLS 1.3.
CipherSuites: cs,
// We've put some thought into this choice and would like it to
// matter.