Closed fourstring closed 7 years ago
I will address only CHACHA20, everything else belongs in a separate ticket:
We use Golang's tls
library. When CHACHA20 and POLY1305 land there, they will be usable in Caddy. Please file a ticket with golang/go. (I guess there already is one.)
Update, here it is: https://github.com/golang/go/issues/6914
Regarding cipher suite selection per platform, that is why the tls handshake exists. It is up to the client to give ciphers they want in order of preference, and the server selects from that list, taking their own preference into account. Caddy's tls does this according to the spec, again using golang's tls library. You can specify cipher for the server to use, but any more complicated requests should go through the go team.
On Sat, Apr 30, 2016 at 7:40 AM, W. Mark Kubacki notifications@github.com wrote:
Closed #798 https://github.com/mholt/caddy/issues/798.
— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub https://github.com/mholt/caddy/issues/798#event-646524390
Reopening this because we're toying around with alternate TLS stacks.
This ticket is not meant for feedback or questions on this or other alternate versions. Email, or start a chat on Gitter for that. We track what's in or not in the official version here.
Thanks for experimenting with it Mark! I'm going to close this now since there's not much actionable for us to do right now. I suppose the best thing to do right now is wait and see when CHACHA20 will be implemented in the Go standard library.
I've a builder ready in case the need arises. Builds my toy versions of Caddy: https://hub.blitznote.com/mark/caddy/builds
chacha20 is available in go standard library.
https://github.com/golang/go/commit/67d8226b4862f0f8deb4dc6fa8617017ecb0f32b
Yep, so Caddy will be able to support it when it's built with the next version of Go.
@mholt I will update Caddy :smile: together with the available curves
Put X25519 first. ;-)
@elcore I already did that while hacking caddy's code. I can send PR :)
Put X25519 first. ;-)
@wmark I don't need to -- It already is :) -- Caddy changes the curves just on preference
diff --git a/caddytls/config.go b/caddytls/config.go
index 92e5729..7c2b692 100644
--- a/caddytls/config.go
+++ b/caddytls/config.go
@@ -456,9 +456,10 @@ var defaultCiphers = []uint16{
// Map of supported curves
// https://golang.org/pkg/crypto/tls/#CurveID
var supportedCurvesMap = map[string]tls.CurveID{
- "P256": tls.CurveP256,
- "P384": tls.CurveP384,
- "P521": tls.CurveP521,
+ "X25519": tls.X25519,
+ "P256": tls.CurveP256,
+ "P384": tls.CurveP384,
+ "P521": tls.CurveP521,
}
const (
diff --git a/caddytls/setup_test.go b/caddytls/setup_test.go
index b630e74..e5445c5 100644
--- a/caddytls/setup_test.go
+++ b/caddytls/setup_test.go
@@ -283,7 +283,7 @@ func TestSetupParseWithKeyType(t *testing.T) {
func TestSetupParseWithCurves(t *testing.T) {
params := `tls {
- curves p256 p384 p521
+ curves x25519 p256 p384 p521
}`
cfg := new(Config)
RegisterConfigGetter("", func(c *caddy.Controller) *Config { return cfg })
@@ -294,11 +294,11 @@ func TestSetupParseWithCurves(t *testing.T) {
t.Errorf("Expected no errors, got: %v", err)
}
- if len(cfg.CurvePreferences) != 3 {
- t.Errorf("Expected 3 curves, got %v", len(cfg.CurvePreferences))
+ if len(cfg.CurvePreferences) != 4 {
+ t.Errorf("Expected 4 curves, got %v", len(cfg.CurvePreferences))
}
- expectedCurves := []tls.CurveID{tls.CurveP256, tls.CurveP384, tls.CurveP521}
+ expectedCurves := []tls.CurveID{tls.X25519, tls.CurveP256, tls.CurveP384, tls.CurveP521}
// Ensure ordering is correct
for i, actual := range cfg.CurvePreferences {
@elcore I already did that while hacking caddy's code. I can send PR :)
@wendigo I did the same :) -- You don't need to
POLL:
Should TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY130
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
be before (Mozilla - 1) or after (Go - 2):
[here - 2 ]
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
[here - 1]
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
Refering to crypto/tls/cipher_suites.go:
// Ciphersuite order is chosen so that ECDHE comes before plain RSA and
// AEADs are the top preference.
So order should be consistent with: https://github.com/golang/go/blob/master/src/crypto/tls/cipher_suites.go#L80
Refering to crypto/tls/cipher_suites.go
@wendigo Thank you, forgot to add it :)
So order should be consistent with: https://github.com/golang/go/blob/master/src/crypto/tls/cipher_suites.go#L80
Okay 👍
A server with AES-NI can serve more connections at a decreased load with AES-NI ciphers than with CHACHA20*. So suites with AES should go first, unless a client sends a CHACHA20 variant as the first in its list.
With Golang 1.8 you'd reorder suites accordingly. https://go-review.googlesource.com/#/c/30790/ https://github.com/wmark/caddy/blob/bf477ab1cce80b908f4593b9310a26c79f1684fe/caddy/https/settings_alttls.go#L139-L153
// isChaCha returns true if the cipher suite uses Salsa/ChaCha20 as cipher.
func isChaCha(suiteID uint16) bool {
switch suiteID {
case 0xcc13, 0xcc14, 0xcca8, 0xcca9, 0xccac:
return true
default:
return false
}
}
// GetConfigForClient =
func PreferChaChaIfFirst(clientHello *tls.ClientHelloInfo) (*tls.Config, error) {
if !isChaCha(clientHello.CipherSuites[0]) {
return nil // first copy of tls.Config, with AES suites at the top
}
// Return the second copy of tls.Config, with CHACHA suites at the top.
// It's safe to set TLSv1.2 as the minimum version here.
}
@wmark It is your code, literally :) -- I give you the honour to implement it
Edit: I could not resist 😄, sorry! -- A virtual 🍰 for you!
Please take a look at https://github.com/elcore/caddy/tree/GetConfigForClient-CHACHA20-POLY1305 -- Especially you @wmark
@elcore That warrants a separate PR. Iff mholt wants you to move this forward, that is.
Keep in mind that:
Then:
tlsConfig.MaxVersion = tlsConfig.MinVersion
only iff max < min
(not in the screenshot, but your branch). You don't want to touch that code again when tls.VersionTLS13
is in.win+R
, type gpedit.msc
. Go to Computer… → Admin… → System… → Internet… → Internet…
and go through the settings.Admin… → Netzwerk… → SSL…
. ;-)@wmark
Not all suites are on by default (for example, CHACHA_OLD if vanilla Go has it, is off by default).
Golang does not support CHACHA_OLD -- So, I do not need it
Some suites are TLSv1.2+ only and won't show when you artificially limit TLS to v1.1.
Just a test to show that the code works 😄
tlsConfig.MaxVersion = tlsConfig.MinVersion only iff max < min (not in the screenshot, but your branch). You don't want to touch that code again when tls.VersionTLS13 is in.
Okay 😄
Hit win+R, type gpedit.msc. Go to Computer… → Admin… → System… → Internet… → Internet… and go through the settings.
I do not want to -- I want to keep everything "vanilla"
Edit: Go to https://github.com/elcore/caddy/tree/GetConfigForClient-CHACHA20-POLY1305 to review
Any progress ?
Yes @bigtan -- We just need to wait for Go 1.8
Let's hope go1.8 will land on Feb 1 :)
We should btw make sure that as soon as we add CHACHA20 with Go 1.8, we also add proper, sane defaults for cfg.CurvePreferences
(it should be [tls.X25519, tls.CurveP256]
) and possibly reorder the defaultCiphers
(some RSA ciphers are ordered before their respective ECDSA ones).
@lhecker Take a look at https://github.com/elcore/caddy/commit/eea4e0eeec7497482ee9a7498ca9bc08957a7cf4 - we might do something like this (but I haven't looked in detail yet, it'll probably change a little bit).
reorder the defaultCiphers (some RSA ciphers are ordered before their respective ECDSA ones).
Really? Which ones? I see ECDSA first for otherwise-equivalent cipher suites.
@elcore How are we doing with curve preferences? They're only used in the config.go and setup.go files of the caddytls package. Does that mean we just use Go's default curve preferences unless the user specifies them?
@mholt @elcore's fork seems to be interesting, but unfortunately I don't quite understand the purpose of it. In my understanding during the TLS handshake the client sends a list of supported ciphers and the server may choose one. And what his fork does is to basically view CHACHA20 as equally good as the best server provided cipher right? So in effect it's the same as if CHACHA20 would simply be the topmost preferred cipher: If the client supports it it's chosen and if not it's not. Or is there otherwise (without the fork's optimization) an additional roundtrip involved?
I see ECDSA first for otherwise-equivalent cipher suites.
Here you can see that AES128 is ordered before AES256 as well as RSA before ECDSA.
Does that mean we just use Go's default curve preferences unless the user specifies them?
Yep.
@lhecker
Here you can see that AES128 is ordered before AES256 as well as RSA before ECDSA.
That's a map, the order there is irrelevant. The ordering in the defaultCiphers list below it is much more important.
As for the rest of @elcore's changes i have yet to look at them -- will do when I'm done with work for the day.
@mholt Ah yes sorry. Let's note this as a coding style issue to save me from the disgrace. 😂
Is the ordering of the defaultCiphers
list okay though?
Oh, right, those could probably be switched now.
@mholt
How are we doing with curve preferences? They're only used in the config.go and setup.go files of the caddytls package. Does that mean we just use Go's default curve preferences unless the user specifies them?
Yes :) (https://golang.org/src/crypto/tls/common.go)
< Go 1.8
var defaultCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521}
> Go 1.8
var defaultCurvePreferences = []CurveID{X25519, CurveP256, CurveP384, CurveP521}
@lhecker
In my understanding during the TLS handshake the client sends a list of supported ciphers and the server may choose one. And what his fork does is to basically view CHACHA20 as equally good as the best server provided cipher right? So in effect it's the same as if CHACHA20 would simply be the topmost preferred cipher: If the client supports it it's chosen and if not it's not. Or is there otherwise (without the fork's optimization) an additional roundtrip involved?
"A server with AES-NI can serve more connections at a decreased load with AES-NI ciphers than with CHACHA20*. So suites with AES should go first, unless a client sends a CHACHA20 variant as the first in its list." @wmark
TLS Client -> Call PreferChaChaIfFirst(ClientHelloInfo)
If the client prefers CHACHA20 e.g. Android devices then move it to the front.
https://blog.cloudflare.com/do-the-chacha-better-mobile-performance-with-cryptography/
Please take into account that until 6th generation chips (Skylake) Intel only enabled AES-NI on high end CPU's.
Thus most consumers nowadays browse the web with a machine that isn't AES-NI capable and doesn't do the reordering trick Android uses. Such clients benefit from ChaCha20, but prefer AES instead.
In order to get around this I propose advertising the ChaCha20 cipher as first one. Like Mozilla recommends.[1]
1: "ChaCha20 is prefered as the fastest and safest in-software cipher, followed by AES128. Unlike the modern configuration, we do not assume clients support AESNI and thus do not prioritize AES256 above 128 and ChaCha20."
@emansom That's already being considered, see https://github.com/mholt/caddy/issues/1375:
Ensure ChaCha20-Poly1305 is prioritized unless there is hardware support for AES-GCM suites
Go 1.8 will also be using this strategy.
In fact, I think I'll close this issue in favor of the other one for tracking this.
@mholt @emansom
Thus most consumers nowadays browse the web with a machine that isn't AES-NI capable and doesn't do the reordering trick Android uses. Such clients benefit from ChaCha20, but prefer AES instead.
It is not easy to balance this out.
On the one hand, you want to reduce the load on the server, on the other hand, you want to reduce the load on the client.
There is no clean solution:
Servers
Clients
I think I misread some of the earlier comments.
Some major CDNs do server preference, but will use ChaCha if it is first in the client's list. TLS 1.3 implementations will tend toward whichever of the two the client wants first. Most/all desktop (and server) hardware has AES-NI (my cheapo DO droplet has it), but most mobile doesn't.
So, to optimize server performance, prefer AES, since it probably has AES-NI support. I wouldn't be opposed to that.
Or we could cater to mobile clients.
I think there are good arguments to both sides. I also think the difference is probably not too much for most people. Let's just stick with preferring AES for now and give the busy server a little breathing room. We can always change this later.
Hello, Thanks for the server software,it is great!And it really simplified my website building. But I think on the platform without AES-NI,AES-GCM will be slow.On such platform,chacha20 is better. So could you support CHACHA20? By the way,BoringSSL support 'Equivalent encryption algorithm group',which can choose between AES and CHACHA20 automaticly according to users' platform.The cipher suites like follow: ECDHE-ECDSA-CHACHA20-POLY1305-SHA384|ECDHE-ECDSA-AES-128-GCM-SHA384:.... When you open the site on PC,cipher suite will use AES,if you use mobilephone,it will use chacha20. Would you support this feature? Thank you!