caddy: v2.7.x: panic when TLS-SNI is received for an unknown domain
caddy v2.7.2 installed via the apt repository:
Aug 03 08:55:31 proxy caddy[1163492]: panic: runtime error: invalid memory address or nil pointer dereference
Aug 03 08:55:31 proxy caddy[1163492]: [signal SIGSEGV: segmentation violation code=0x1 addr=0x30 pc=0x903750]
Aug 03 08:55:31 proxy caddy[1163492]: goroutine 57 [running]:
Aug 03 08:55:31 proxy caddy[1163492]: github.com/caddyserver/certmagic.(*Config).getCertDuringHandshake(0xc000543520, {0x1f09a88, 0xc000194008}, _, _)
Aug 03 08:55:31 proxy caddy[1163492]: github.com/caddyserver/certmagic@v0.19.1/handshake.go:378 +0x1390
Aug 03 08:55:31 proxy caddy[1163492]: github.com/caddyserver/certmagic.(*Config).GetCertificateWithContext(0xc000543520, {0x1f09a88, 0xc000194008}, 0xc000543450)
Aug 03 08:55:31 proxy caddy[1163492]: github.com/caddyserver/certmagic@v0.19.1/handshake.go:84 +0xbff
Aug 03 08:55:31 proxy caddy[1163492]: github.com/caddyserver/certmagic.(*Config).GetCertificate(0xc000138ee0?, 0xc0001dc1b0?)
Aug 03 08:55:31 proxy caddy[1163492]: github.com/caddyserver/certmagic@v0.19.1/handshake.go:50 +0x2a
Aug 03 08:55:31 proxy caddy[1163492]: github.com/caddyserver/caddy/v2/modules/caddytls.(*ConnectionPolicy).buildStandardTLSConfig.func1(0xc000543450)
Aug 03 08:55:31 proxy caddy[1163492]: github.com/caddyserver/caddy/v2@v2.7.2/modules/caddytls/connpolicy.go:232 +0x14f
Aug 03 08:55:31 proxy caddy[1163492]: github.com/quic-go/qtls-go1-20.(*config).getCertificate(0xc0008d7800, 0xc000543450)
Aug 03 08:55:31 proxy caddy[1163492]: github.com/quic-go/qtls-go1-20@v0.3.0/common.go:1086 +0x42
Aug 03 08:55:31 proxy caddy[1163492]: github.com/quic-go/qtls-go1-20.(*serverHandshakeStateTLS13).pickCertificate(0xc000631be8)
Aug 03 08:55:31 proxy caddy[1163492]: github.com/quic-go/qtls-go1-20@v0.3.0/handshake_server_tls13.go:415 +0x66
Aug 03 08:55:31 proxy caddy[1163492]: github.com/quic-go/qtls-go1-20.(*serverHandshakeStateTLS13).handshake(0xc000631be8)
Aug 03 08:55:31 proxy caddy[1163492]: github.com/quic-go/qtls-go1-20@v0.3.0/handshake_server_tls13.go:60 +0x53
Aug 03 08:55:31 proxy caddy[1163492]: github.com/quic-go/qtls-go1-20.(*Conn).serverHandshake(0xc00053d180, {0x1f09a50, 0xc000562fa0})
Aug 03 08:55:31 proxy caddy[1163492]: github.com/quic-go/qtls-go1-20@v0.3.0/handshake_server.go:53 +0x188
Aug 03 08:55:31 proxy caddy[1163492]: github.com/quic-go/qtls-go1-20.(*Conn).handshakeContext(0xc00053d180, {0x1f09af8, 0xc0001753e0})
Aug 03 08:55:31 proxy caddy[1163492]: github.com/quic-go/qtls-go1-20@v0.3.0/conn.go:1540 +0x3ce
Aug 03 08:55:31 proxy caddy[1163492]: github.com/quic-go/qtls-go1-20.(*Conn).HandshakeContext(0xc00005dfd0?, {0x1f09af8?, 0xc0001753e0?})
Aug 03 08:55:31 proxy caddy[1163492]: github.com/quic-go/qtls-go1-20@v0.3.0/conn.go:1480 +0x25
Aug 03 08:55:31 proxy caddy[1163492]: created by github.com/quic-go/qtls-go1-20.(*QUICConn).Start
Aug 03 08:55:31 proxy caddy[1163492]: github.com/quic-go/qtls-go1-20@v0.3.0/quic.go:179 +0xcf
Might be related to https://github.com/golang/go/issues/61639 ?
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 4
- Comments: 86 (49 by maintainers)
Good thinking! In fact there is:
tls.Config.GetCertificatealso passes in aClientHelloInfo. I feel really stupid for missing this 😔. For some reason I thought thattls.Config.GetConfigForClientwould be the only place, and didn’t even bother checking. This means we’ll need to wrapGetCertificateas well, equivalent to what we do in https://github.com/quic-go/quic-go/pull/4001/files#diff-c1eebd1c52f66da524b99c57f22669500f22784ae80475fbf2b786bc0d1ba278.Fix coming later today. This will be included in the v0.37.2 patch release.
@W0n9 A fix for both panics is in the works, and will be included in the v0.37.2 release.
Okay! I have a way to replicate it.
Simple config:
Run with
./caddy run --config Caddyfileas normal.(I’m using non-standard ports and turning off admin because I have another Caddy instance running already)
Making a request for the wrong SNI (i.e.
foo.localhostwhen Caddy only haslocalhost) with this command (container with a custom curl with http3 support, because it’s the easiest way for me to try http3 reliably):@marten-seemann hopefully that should be enough for you to be able to do some
fmt.Printf()tracing and such?Stacktrace with Go 1.21 if it helps at all (i.e. using stdlib TLS stack instead of qtls):
Baader–Meinhof phenomenon 😉
I did a quick test as well:
2.7.2 fails but the updated build works.
Hi guys, can you please test with https://github.com/quic-go/quic-go/pull/4016. I’d like to get confirmation that this actually works before cutting yet another patch release again.
I have tried caddy 2.7.3, it fixed for me👍
Testing my server with
curl -v https://google.com --connect-to google.com:443:MY_SERVER_IP:443 --http3-onlyCaddy crash: 2.7.2 built with
xcaddy build --with github.com/caddyserver/cache-handler --with github.com/caddyserver/replace-responseWorks: 2.7.2 built with
xcaddy build --with github.com/caddyserver/cache-handler --with github.com/caddyserver/replace-response --with github.com/quic-go/quic-go=github.com/quic-go/quic-go@280054c@mholt Ah, I understand what you were asking now. Following the earlier example with Docker and curl-http3 (substituting for
justdanz/curl-http3because I’m on arm64), I tried with Caddy v2.7.2 as a control and it did indeed crash.I then tried with
GOOS=linux GOARCH=arm64 ./xcaddy build --with github.com/caddy-dns/cloudflare --with github.com/quic-go/quic-go=github.com/quic-go/quic-go@280054cand there is no crash after several minutes of running. I hope this is helpful.Thanks @marten-seemann, I can confirm my reproduce case from https://github.com/caddyserver/caddy/issues/5680#issuecomment-1664889820 is fixed by https://github.com/quic-go/quic-go/pull/4016.
I think the panic @W0n9 reported is a separate issue though. I don’t know how to replicate that problem. A new issue should probably be opened for that.
Fix is ready at https://github.com/quic-go/quic-go/pull/4014.
Right, I should not stay up this late, was just focusing on watching the errors, thats from the server and not cloudflare, so all good.
You don’t have a certificate for the raw IP, so that is expected and only logged with level debug.
Oh, as I just checked again I got handshake error now?
{“level”:“debug”,“ts”:1691191817.8557942,“logger”:“http.stdlib”,“msg”:“http: TLS handshake error from 192.168.1.26:56616: no certificate available for ‘192.168.1.4’”}
For whatever its worth, I tested on windows as well and I no longer receive TLS handshake error spam after building with
xcaddy build master --with github.com/caddy-dns/cloudflare --with github.com/caddyserver/transform-encoder --with github.com/WeidiDeng/caddy-cloudflare-ip --with github.com/quic-go/quic-go=github.com/quic-go/quic-go@280054cExcellent, thank you both!
@marten-seemann We now have numerous confirmations of the patch working, so I’m confident with your fix. 💯 Thank you thank you.
Awesome, thank you. Confirmations of the fix from anyone else experiencing the issue would be valuable as we await the patch release! 💯
I’ll try to get a fix out for the recursive
GetConfigForClient/GetCertificatesome time tonight.@marten-seemann Dang, there’s still a code path we’re missing.
@RainmakerRaw Thank you so much for trying it out. Sorry to keep you up 😅 Get some good sleep, hopefully we’ll have it figured out soon.
@mholt Sorry Matt it’s 2am here, I only just saw this by chance. Compiling now…
Yeah, I hate bugs like this as it happened to me twice on one box and zero times on my other box. Same build process, identical config minus 2 different site names.
and since those 2, I’ve tried restarting ~30 times and I can’t get it to reproduce.
lmk if there’s anything you need from the quic-go side. I’ll be holding off on cutting the RSA patch release until we’ve reached a conclusion here.
Oh sorry, one second, I forgot I downgraded my phoenix back back to the older version, let me update it and reproduce.
Here are the two:
and
My config is small I think as I only use the security plugin to do SSO auth and that protects my site.
I wasn’t doing anything specific to generate as the automatic SSL renewal would kick in and that would produce the error as it happened right after startup.
Oh, we built with Go 1.20.6 though 🤔 did we need to build with 1.20.7?
Edit: Nevermind that shouldn’t have mattered according to the changes in https://github.com/golang/go/issues?q=milestone%3AGo1.20.7