Certificate not accepted by wget

Running Apache on a CentOS self-administered server (ie, I have ssh access). After suitable configuration changes to httpd/conf.d/ssl.conf, my new LE certificate is recognized and accepted by Apache HTTPS. It is recognized by wget, but not accepted.

    # wget -v -O - https://blackdog.straight8.com/admin
    --2019-02-05 10:59:51--  https://blackdog.straight8.com/admin
    Resolving blackdog.straight8.com... 216.218.245.194
    Connecting to blackdog.straight8.com|216.218.245.194|:443... connected.
    ERROR: cannot verify blackdog.straight8.com's certificate, issued by `/C=US/O=Let\'s  Encrypt/CN=Let\'s Encrypt Authority X3':
    Unable to locally verify the issuer's authority.
    To connect to blackdog.straight8.com insecurely, use `--no-check-certificate'.

Is there some further configuration I have to employ?

You should also include the Let’s Encrypt intermediate certificate in your webserver SSL configuration.

Unfortunately, you don’t include the information about which ACME client you’ve used. If you have used certbot, you should use add chain.pem from the /live/ directory of /etc/letsencrypt/ to your Apache configuration in SSLCertificateChainFile directive.

Edit: update using the chain.pem file as the Apache version is <2.4.8. Thanks @mnordhoff :stuck_out_tongue:

1 Like

The server is sending your certificate, but it also needs to send the Let’s Encrypt Authority X3 intermediate certificate. Web browsers will sometimes compensate; wget doesn’t.

https://www.ssllabs.com/ssltest/analyze.html?d=blackdog.straight8.com&hideResults=on

Since you’re using Apache 2.4.6, you have to add an SSLCertificateChainFile directive pointing to a file containing the intermediate certificate(s).

For example, if you’re using Certbot, it’s the chain.pem file, so you’d set something like “SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem”.

1 Like

Thanks guys. Progress. I am now able to retrieve the relevant content via wget on a secure channel (HTTPS) from a second CentOS server located on the same router (but not equipped with an LE certificate, yet). My local Mac Mojave client is able to retrieve the same content via Apache HTTPS and via wget on an insecure channel (HTTP), but is unable to retrieve the content via wget on a secure channel. Error message as above. Most important, the final target JAVA process is unable to retrieve the content on a secure channel (but is able to do so on an insecure channel). There must be some additional configuration that I am missing.

BTW, I used certbot and yum on my CentOS server to create the certificate, per the instructions provided by LE.

If there is, it would have to be with the JAVA client (and the trusted root store it uses).

I installed the certificate (after conversion to a DER file) into the Java keystore on the CentOS server, and verified it. I don’t know what else to do. Are you suggesting that the Java client (on the Mac) needs configuration?

The exact same error message?

As a comparison, can your Mac wget and Java clients download other websites using Let's Encrypt certificates, like https://letsencrypt.org/?

Can they download websites that use other CAs?

It's possible that they're old and don't trust Let's Encrypt, or that they're not configured to trust any CA.

From my MacOS Mojave bash shell:

% wget -v -O - https://letsencrypt.org/
–2019-02-05 13:13:55-- https://letsencrypt.org/
Resolving letsencrypt.org… 2600:1406:2c:18f::ce0, 2600:1406:2c:187::ce0, 23.72.183.124
Connecting to letsencrypt.org|2600:1406:2c:18f::ce0|:443… connected.
ERROR: cannot verify letsencrypt.org’s certificate, issued by /C=US/O=Let\'s Encrypt/CN=Let\'s Encrypt Authority X3': Unable to locally verify the issuer's authority. ERROR: certificate common namewww.letsencrypt.org’ doesn’t match requested host name letsencrypt.org'. To connect to letsencrypt.org insecurely, use–no-check-certificate’.

% wget -v -O - https://www.letsencrypt.org/
–2019-02-05 13:17:14-- https://www.letsencrypt.org/
Resolving www.letsencrypt.org… 2600:1406:2c:187::ce0, 2600:1406:2c:18f::ce0, 23.72.183.124
Connecting to www.letsencrypt.org|2600:1406:2c:187::ce0|:443… connected.
ERROR: cannot verify www.letsencrypt.org’s certificate, issued by /C=US/O=Let\'s Encrypt/CN=Let\'s Encrypt Authority X3': Unable to locally verify the issuer's authority. To connect to www.letsencrypt.org insecurely, use–no-check-certificate’.

Something’s not right with your wget.
[and maybe also with the underlying crypto system]

The first attempt shows that it only accepts names that are in the common name field.
[not accepting names that are in the SAN field as a match]

The second attempt shows that it doesn’t trust the issuing root.

Perhaps your wget is outdated and can be updated to a newer version.

That was an excellent idea. I used wget only out of (ancient) habit. My MacOS is up-to-date, but that doesn’t apply to third-party tools like wget; the version on my Mac is from 2010!

So, I tried curl, which is up-to-date. Sure enough, curl had no problem with any of the URLs discussed above. So I removed wget; I’ll use curl instead. Now I just have to figure out why the (up-to-date) java app on the Mac isn’t able to download the secure content. Thanks for all the help.

1 Like

For what it’s worth, wget didn’t support Subject Alternative Names until 2011. Older wget will have a lot of problems connecting to HTTPS stuff. (For that and probably other reasons.)

Java’s trust store only added the root CA Let’s Encrypt uses (DST Root CA X3) a couple years ago; it wouldn’t be shocking if you had an older version.

1 Like

Good info. My problem is that if all of my clients (read: game players) have to update Java on their PCs… well, it isn’t going to happen. :frowning:

Yeah. :slightly_frowning_face:

DST Root CA X3 has mostly excellent support, but it was only added to Java’s default trust store in 2016.

https://www.oracle.com/technetwork/java/javase/8u101-relnotes-3021761.html

If it’s your software, you should be able to do anything. I’m not sure what the correct procedure is (technically or ethically), but you could add DST Root CA X3 to the trust store when the software is installed, or use a custom trust store, or a different trust store, or something like that.

But there’s a good argument for using a different CA for servers aimed at a wide range of Java clients.

In my up-to-date Java 11 keystore, I see

letsencryptisrgx1 [jdk], Nov 30, 2017, trustedCertEntry,
Certificate fingerprint (SHA-256): _ELIDED_

Adding the intermediate certificates to the Apache configuration made certificates resolve correctly. Is there an equivalent way to add the intermediate certificates to the Java configuration? I’ve done some searching, but I don’t really know what is useful and not.

You must not trust the intermediates (because they may change at any time), but the roots as suggested by @mnordhoff .

What part of your Java application actually makes outbound SSL connections? It’s probably not a fantastic idea to override the trust store of the entire JVM, especially if it’s somebody else’s PC, but for most libraries (like Apache HttpClient) there are some straightforward ways to pass in custom trust material (like the DST Root CA X3 and ISRG X1 roots).

Edit: if this is a game client where you control the the files and the startup script for the game, you can ship an up-to-date truststore (such as from a recent version of Java) with your game client and include it in the startup script:

  • -Djavax.net.ssl.trustStore specifies the truststore file to use to validate certificates.
  • -Djavax.net.ssl.trustStorePassword specifies the passphrase to access the truststore file.
3 Likes

Well, I’m in over my head here, and I certainly don’t want to screw it up, even though it’s my machine.

I do not have control over the game clients (Minecraft).

The Java server requires that the Java client download resourcepacks that are stored on the web server (same physical server as the game server, although that isn’t a requirement), under server control.

At present, the clients can download the resource packs via a web browser (now that Apache is configured correctly) or via curl, but the Java keystore seems to be missing vital pieces. I don’t know how to get the root data into the Java keystore. I can run either Java 1.8.0.191 (old default installation) or Java 11.0.2 (latest from Oracle), but both are equally deficient in this respect.

Does your scenario seem to match this one: https://minecraft.curseforge.com/projects/letsencryptcraft ?

I don’t necessarily recommend installing that Minecraft mod, but it basically loads the Let’s Encrypt X3 intermediate and applies it to the in-memory trust store. Ignoring that it adds the intermediate instead of the root (:frowning_face:), it seems in theory to do what you need.

Well, that link certainly contains a succinct description of the problem. But I don’t want to run a modded server, so that isn’t going to work for me. Now if they would make a comparable Spigot plugin…

And as is so often the case in the Minecraft world, their latest version is for 1.12.2, whereas I am running 1.13.2 (and 1.14 is due to drop any day).

I wonder if I could just grab the lets-encrypt-x3-cross-signed.der and import it into the server Java keystore.

Rooting around in the Mac Java control panel, I was able to find the 1.8.0_202 update (cleverly, the file name does not include “202”), and reset MC client to use it. Now the certificate chain is recognized.

Thanks everyone for suggestions and patience.

2 Likes