pieterlouw / caddy-net

Proxy server type for Caddy server (https://github.com/mholt/caddy)
Apache License 2.0
66 stars 11 forks source link

TLS support is broken #6

Closed RX14 closed 6 years ago

RX14 commented 6 years ago

With the caddyfile:

proxy :6697 google.com:80 {
  host znc.rx14.co.uk
  tls self_signed
}

Using the v0.10.6 binary:

Activating privacy features... done.
[INFO] Proxying from  :6697  ->  google.com:80
Done proxying: 172.18.0.2:6697 172.18.0.2:40078
$ openssl s_client -host localhost -port 6697 < /dev/null
CONNECTED(00000005)
depth=0 O = Caddy Self-Signed
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 O = Caddy Self-Signed
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/O=Caddy Self-Signed
   i:/O=Caddy Self-Signed
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIBajCCARGgAwIBAgIRAL8EUXZpkCkAw29YRtduN0swCgYIKoZIzj0EAwIwHDEa
MBgGA1UEChMRQ2FkZHkgU2VsZi1TaWduZWQwHhcNMTgwMjA1MjMxOTQzWhcNMTgw
MjEyMjMxOTQzWjAcMRowGAYDVQQKExFDYWRkeSBTZWxmLVNpZ25lZDBZMBMGByqG
SM49AgEGCCqGSM49AwEHA0IABEaDr6IJ1EJrW05ZzdeNA1DAhcyfMGB/xcEq9Ay+
4uUthLtTGGiRWzL3JqlS4obnyHSurBWy+yD3ToshRZP2jLejNDAyMA4GA1UdDwEB
/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHREEBDACggAwCgYIKoZI
zj0EAwIDRwAwRAIgc8Wh/+Cq57W/2B0kuHTMtvTQKAQ0hMaPhu93zyacW0sCIAQ9
6VllSBsQv1dCVVl20o7hHt4of/NVmX59k/6RNtaW
-----END CERTIFICATE-----
subject=/O=Caddy Self-Signed
issuer=/O=Caddy Self-Signed
---
No client certificate CA names sent
Peer signing digest: SHA384
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 753 bytes and written 269 bytes
Verification error: unable to verify the first certificate
---
New, TLSv1.2, Cipher is ECDHE-ECDSA-AES256-GCM-SHA384
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-ECDSA-AES256-GCM-SHA384
    Session-ID: D5EFECF89EB51CC305A7C7FCCEB87BEFF66E721F7FC76B30EDD85C2AB98E20E2
    Session-ID-ctx:
    Master-Key: FA04535FDDD30F767039382D4EED06AFEACDD29D109A795DAEF6DEC5E13F47A8F0FA0E135FED98376297B1BCE333A832
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket:
    0000 - c2 80 77 50 cb 40 22 e3-11 0e ce f4 88 ea 38 8c   ..wP.@".......8.
    0010 - 64 fb 48 01 9c 37 be 4b-0e 95 13 88 90 06 4a ca   d.H..7.K......J.
    0020 - 91 ec c7 84 1a a1 4b 18-23 83 95 cf ff 45 27 9b   ......K.#....E'.
    0030 - cd 1d 69 0e fd 84 42 47-ba 39 13 cd 5b 4e 1e a3   ..i...BG.9..[N..
    0040 - fb 8a e3 8e 43 55 4a 27-a8 df 0f fd 8b f2 0f 30   ....CUJ'.......0
    0050 - 33 6a 42 0b 09 58 ea 41-7d e9 9e 9d 1b e6 bb 65   3jB..X.A}......e
    0060 - 84 1b 75 6d 13 c6 23 9b-b8 a6 f1 f9 00 e7 c8 3f   ..um..#........?
    0070 - ed b8 f1 44 a9 73 d1 ca-                          ...D.s..

    Start Time: 1517872786
    Timeout   : 7200 (sec)
    Verify return code: 21 (unable to verify the first certificate)
    Extended master secret: no
---
DONE

On v0.10.10

2018/02/05 23:20:29 [NOTICE] There is already a certificate loaded for , so certificate for [ ] will not service that name
2018/02/05 23:20:29 [NOTICE] There is already a certificate loaded for , so certificate for [] will not service that name
2018/02/05 23:20:29 [NOTICE] There is already a certificate loaded for , so certificate for [] will not service that name
Activating privacy features... done.
[INFO] Proxying from  :6697  ->  google.com:80
Done proxying: 172.18.0.2:6697 172.18.0.2:40090
$ openssl s_client -host localhost -port 6697 < /dev/null
CONNECTED(00000005)
140132566949824:error:1408F10B:SSL routines:ssl3_get_record:wrong version number:ssl/record/ssl3_record.c:252:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 5 bytes and written 176 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1517872831
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: no
---

I have attempted to bisect this bug, but found it impossible due to the inability to run bisections over the whole GOPATH. I can check out github.com/mholt/caddy at v0.10.6, add the plugin, and build but it fails just the same as v0.10.10. I suspect something has changed between august 2017 and now in the myriad of repositories in $GOPATH. Since there's no way to bisect all of these, i'm stuck using the v0.10.6 binary with no way to debug and no way to even reproduce the binary. I'm more than a little disappointed in the go tooling.

pieterlouw commented 6 years ago

Hi @RX14 ,

I'm not sure if this problem might be related to an issue in caddytls (https://github.com/mholt/caddy/pull/2015). I had to make changes in the plugin as well: (https://github.com/pieterlouw/caddy-net/issues/5). This change will be merged into version 0.10.11 of Caddy which is scheduled to be released when Go 1.10 is released.

Pieter

mholt commented 6 years ago

@RX14

Since there's no way to bisect all of these, i'm stuck using the v0.10.6 binary with no way to debug and no way to even reproduce the binary. I'm more than a little disappointed in the go tooling.

That sounds more like a limitation in git tooling; Caddy vendors its dependencies, so all its code lives in a single repo.

Make sure you are in fact building what you think you are building (use go run build.go to get correct version information when you run caddy -version - very helpful).

That said, 0.10.11 does drastically change and improve the TLS certificate loading, so give that branch a try (as Pieter suggests)!

RX14 commented 6 years ago
$ ./caddy -version
Caddy 0.10.6 (+e7f08bf Fri Feb 16 21:18:51 UTC 2018)
 1 file changed, 1 insertion(+)
caddy/caddymain/run.go

$ ./caddy -plugins
Server types:
  http
  net

Caddyfile loaders:
  short
  flag
  default

Other plugins:
  http.basicauth
  http.bind
  http.browse
  http.errors
  http.expvar
  http.ext
  http.fastcgi
  http.gzip
  http.header
  http.index
  http.internal
  http.limits
  http.log
  http.markdown
  http.mime
  http.pprof
  http.proxy
  http.push
  http.redir
  http.request_id
  http.rewrite
  http.root
  http.status
  http.templates
  http.timeouts
  http.websocket
  net.host
  shutdown
  startup
  tls
  tls.storage.file

$ cat /tmp/Caddyfile
proxy :6697 google.com:80 {
  host znc.rx14.co.uk
  tls self_signed
}

$ ./caddy -type net -conf /tmp/Caddyfile
Activating privacy features... done.
[INFO] Proxying from  :6697  ->  google.com:80
WARNING: File descriptor limit 1024 is too low for production servers. At least 8192 is recommended. Fix with "ulimit -n 8192".
Done proxying: [::1]:6697 [2001:630:e4:4220:1e4d:70ff:fe62:3491]:59452

$ openssl s_client -host localhost -port 6697 < /dev/null
CONNECTED(00000005)
140196474408896:error:1408F10B:SSL routines:ssl3_get_record:wrong version number:ssl/record/ssl3_record.c:252:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 5 bytes and written 176 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1518816069
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: no
---

whereas with the official v0.10.6 binary from my docker container:

$ ./caddy -version
Caddy 0.10.6

$ ./caddy -plugins
Server types:
  http
  net

Caddyfile loaders:
  short
  flag
  default

Other plugins:
  http.basicauth
  http.bind
  http.browse
  http.errors
  http.expvar
  http.ext
  http.fastcgi
  http.gzip
  http.header
  http.index
  http.internal
  http.limits
  http.log
  http.markdown
  http.mime
  http.pprof
  http.proxy
  http.push
  http.redir
  http.request_id
  http.rewrite
  http.root
  http.status
  http.templates
  http.timeouts
  http.websocket
  net.host
  shutdown
  startup
  tls
  tls.dns.gandi
  tls.storage.file

$ ./caddy -type net -conf /tmp/Caddyfile
Activating privacy features... done.
[INFO] Proxying from  :6697  ->  google.com:80
WARNING: File descriptor limit 1024 is too low for production servers. At least 8192 is recommended. Fix with "ulimit -n 8192".
Done proxying: [::1]:6697 [2001:630:e4:4220:1e4d:70ff:fe62:3491]:57484

$ openssl s_client -host localhost -port 6697 < /dev/null
CONNECTED(00000005)
depth=0 O = Caddy Self-Signed
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 O = Caddy Self-Signed
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/O=Caddy Self-Signed
   i:/O=Caddy Self-Signed
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIBajCCARCgAwIBAgIQHcXpPwbLqWq+TkRaL8LadTAKBggqhkjOPQQDAjAcMRow
GAYDVQQKExFDYWRkeSBTZWxmLVNpZ25lZDAeFw0xODAyMTYyMTMwMTBaFw0xODAy
MjMyMTMwMTBaMBwxGjAYBgNVBAoTEUNhZGR5IFNlbGYtU2lnbmVkMFkwEwYHKoZI
zj0CAQYIKoZIzj0DAQcDQgAEzQ8DKu4Md/z+4g2sRZMOlKqNAQ9moiztYPDE2Yrl
kTA7UYXguESXSasRY0N70zqzux3IyzQXQWyxdrqyc5IcjKM0MDIwDgYDVR0PAQH/
BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAsGA1UdEQQEMAKCADAKBggqhkjO
PQQDAgNIADBFAiAo4fnxkSr4ZEjj4U2h+Kanm58PwAWpw5daNtdiqME+ngIhAO27
2i+vJ7O+y5ljk/APtEnNSZIthRZKaqdU6WqvLsd2
-----END CERTIFICATE-----
subject=/O=Caddy Self-Signed
issuer=/O=Caddy Self-Signed
---
No client certificate CA names sent
Peer signing digest: SHA384
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 755 bytes and written 269 bytes
Verification error: unable to verify the first certificate
---
New, TLSv1.2, Cipher is ECDHE-ECDSA-AES256-GCM-SHA384
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-ECDSA-AES256-GCM-SHA384
    Session-ID: 0D3A77315ED43EDFE48F51CE4C8D745C1BD75D19B4D078E72E703A3912A121AC
    Session-ID-ctx:
    Master-Key: 24DFEB88436D68D4049995BF92EB8C1CB5FC7DAD01BA1E0A3F3780E88DE881BCC6F125A69AD98A72055EA396AB14112E
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket:
    0000 - c5 9c 9b 01 47 06 a9 a5-63 cf ff 55 e0 8b 6c 74   ....G...c..U..lt
    0010 - bc f8 10 2a be 69 12 b2-db d7 5d 49 11 ce 71 4e   ...*.i....]I..qN
    0020 - 80 d7 c6 ec 47 f7 77 35-01 aa b4 ea 7c d2 b5 3a   ....G.w5....|..:
    0030 - 78 d6 98 44 7e 68 39 5e-9f fa c5 4e c2 36 d3 13   x..D~h9^...N.6..
    0040 - 58 d9 a6 e5 0d 94 44 a6-e4 7f 2a 63 53 d7 4b d2   X.....D...*cS.K.
    0050 - 63 72 15 91 bc e5 a7 30-5a d7 a0 d4 57 47 d6 f9   cr.....0Z...WG..
    0060 - 8f cf 12 43 67 eb 22 1d-ff 71 24 f3 49 16 ff 0d   ...Cg."..q$.I...
    0070 - b3 d8 89 7c 2f 89 ee 51-                          ...|/..Q

    Start Time: 1518816612
    Timeout   : 7200 (sec)
    Verify return code: 21 (unable to verify the first certificate)
    Extended master secret: no
---
DONE

I copied the binary out of the docker container with docker cp and executed it in the same directory with the same caddyfile with the same environment.

And here's my diff for adding the plugin that's reported in ./caddy -version:

$ git diff | tee /dev/null
diff --git a/caddy/caddymain/run.go b/caddy/caddymain/run.go
index 81f97f2..a33e928 100644
--- a/caddy/caddymain/run.go
+++ b/caddy/caddymain/run.go
@@ -35,6 +35,7 @@ import (

        "github.com/mholt/caddy/caddytls"
        // This is where other plugins get plugged in (imported)
+       _ "github.com/pieterlouw/caddy-net/caddynet"
 )

 func init() {

Doesn't look like a reproducible build to me, unless the tls.dns.gandi plugin somehow fixed this (unlikely). Could also be a bug/change in the Go standard library, but I find that also somewhat unlikely.

RX14 commented 6 years ago

Just tested on the latest master of caddy with the issue5 branch of caddy-net and I can reproduce the issue. Doesn't look like it's fixed by the new changes.

RX14 commented 6 years ago

Oup, my bad, I forgot to checkout an older version of caddy-net. It appears I can reproduce the good version now. Definitely c9a147e68de24d4e7756e1fcda1924c925f84f94 caused this issue. Sorry for the commotion.

pieterlouw commented 6 years ago

Hi @RX14 , Thanks for the in depth investigation. Are you saying that caddy-net don't enable any type of tls since https://github.com/pieterlouw/caddy-net/commit/c9a147e68de24d4e7756e1fcda1924c925f84f94 ?

RX14 commented 6 years ago

I'm saying that the tls handshake is broken since that commit (see openssl output). I haven't tried using a http client to test if it responds to unencrypted http, I just didn't think of it.

pieterlouw commented 6 years ago

Hi @RX14 ,

I managed to duplicate and find the bug on my side. This has been fixed. Thanks again for great error reporting.

Pieter

RX14 commented 6 years ago

Thanks, can confirm this is fixed!

mholt commented 6 years ago

Yay! Pieter, you're awesome. Thanks to everyone who participated in this.