Local https works with `curl` but not `wget`?

local https works with curl but not wget ?

1. Output of caddy version

$ caddy version
v2.5.2 h1:eCJdLyEyAGzuQTa5Mh3gETnYWDClo1LjtQm2q9RNZrs=

2. How I run Caddy

$ brew install caddy
$ caddy run

a. System environment

$ sw_vers
ProductName: macOS
ProductVersion: 12.5
BuildVersion: 21G72

b1. Commands that succeed

opening a browser

$ open https://localhost:443/health

200_CADDYPROXY_OK

curl

$ curl https://localhost:443/health

200_CADDYPROXY_OK

b2. Commands that fail

wget

$ wget https://localhost:443/health

--2022-08-18 18:29:24--  https://localhost/health
Resolving localhost (localhost)... ::1, 127.0.0.1
Connecting to localhost (localhost)|::1|:443... connected.
ERROR: cannot verify localhost's certificate, issued by ‘CN=Caddy Local Authority - ECC Intermediate’:
  Unable to locally verify the issuer's authority.
To connect to localhost insecurely, use `--no-check-certificate'

http - eg. httpie https://httpie.io/

$ http https://localhost:443/health

http: error: SSLError: HTTPSConnectionPool(host='localhost', port=443): Max retries exceeded with url: /health (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)'))) while doing a GET request to URL: https://localhost:443/health

c. Service/unit/compose file

n/a, running natively

d. My complete Caddy config

http://localhost:80 {
  log

  respond /health 200_CADDYPROXY_OK

  reverse_proxy /example https://example.com:443 {

    trusted_proxies private_ranges
    transport http {
      tls_insecure_skip_verify
    }
  }
}

https://localhost:443 {
  log
  tls internal

  respond /health 200_CADDYPROXY_OK

  reverse_proxy /example https://example.com:443 {

    trusted_proxies private_ranges
    transport http {
      tls
      tls_server_name example.com
    }
  }
}

3. The problem I’m having

I want to understand how caddy works with TLS in order to move on to more complex setups, so I would like to know why the wget option fails here. I would also like to know how curl is succeeding… is it not checking certs?

4. curl -v versus wget -vd output

$ wget -vd https://localhost:443/health

DEBUG output created by Wget 1.21.3 on darwin21.3.0.

Reading HSTS entries from /Users/kai/.wget-hsts
URI encoding = ‘UTF-8’
Converted file name 'health' (UTF-8) -> 'health' (UTF-8)
--2022-08-18 18:38:01--  https://localhost/health
Resolving localhost (localhost)... ::1, 127.0.0.1
Caching localhost => ::1 127.0.0.1
Connecting to localhost (localhost)|::1|:443... connected.
Created socket 5.
Releasing 0x000060000372fce0 (new refcount 1).
Initiating SSL handshake.
Handshake successful; connected socket 5 to SSL handle 0x00007fb1b2809400
certificate:
  subject:
  issuer:  CN=Caddy Local Authority - ECC Intermediate
ERROR: cannot verify localhost's certificate, issued by ‘CN=Caddy Local Authority - ECC Intermediate’:
  Unable to locally verify the issuer's authority.
To connect to localhost insecurely, use `--no-check-certificate'.
Closed 5/SSL 0x00007fb1b2809400
$ curl -v https://localhost:443/health

*   Trying 127.0.0.1:443...
* Connected to localhost (127.0.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: [NONE]
*  start date: Aug 18 19:09:02 2022 GMT
*  expire date: Aug 19 07:09:02 2022 GMT
*  subjectAltName: host "localhost" matched cert's "localhost"
*  issuer: CN=Caddy Local Authority - ECC Intermediate
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7f7999011400)
> GET /health HTTP/2
> Host: localhost
> user-agent: curl/7.79.1
> accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 200
< server: Caddy
< content-length: 17
< date: Thu, 18 Aug 2022 22:38:07 GMT
<
* Connection #0 to host localhost left intact

200_CADDYPROXY_OK

5. What I already tried

A shorter Caddyfile produces similar results, eg.

https://localhost:443 {
  log
  respond /health 200_CADDYPROXY_OK
}

curl is verifying the cert.

I think it’s just that wget isn’t using the right trust store on your system. I don’t use a mac, so I couldn’t really say why.

FYI, you don’t need to specify :443 if you’re using https:// and you don’t need to specify :80 when using http://. Those ports are implicit for those schemes, in both Caddy and all HTTP clients.

You only need this if you have another proxy in front of Caddy. If you’re making requests directly to Caddy, you should remove this.

I don’t think you need this. What you should have though is header_up Host {upstream_hostport}. It would look like this:

reverse_proxy /example* https://example.com {
	header_up Host {upstream_hostport}
}
1 Like

Gotcha, thanks @francislavoie I think that “curl is doing the right thing here” is good enough for me, I can just move forward using curl as my primary test case

1 Like

This topic was automatically closed after 30 days. New replies are no longer allowed.