Node reverse proxy API says TLS certificate expired

1. The problem I’m having:

A few months ago I developed and deployed a small web app and it has been working fine. I haven’t used it for a few weeks until the other day when I noticed it wasn’t working. I checked the logs and the node based API is gives an error that the TLS certificate is expired. – The TLS certs are not expired, it is using auto provisioning from Lets Encrypt

The curious thing in my mind is that this was all working fine and no changes or updates have been done to the server or code since it was working awhile back.

To resolve this problem I’ve tried:

  • Doing a system update and restart of the server.
  • Delete the TLS certs from ~/.local/share/caddy/certificates they they are re-provisioned.
  • Upgrade from Node 18 LTS to Node 20 LTS

None of those have worked so I’m not sure where to look next.

2. Error messages and/or full log output:

Caddy log

2023/12/03 15:56:26.525	ERROR	http.log.error.log0	EOF	{"request": {"remote_ip": "2a02:ab88:7:8a80::9bb1", "remote_port": "39676", "client_ip": "2a02:ab88:7:8a80::9bb1", "proto": "HTTP/3.0", "method": "GET", "host": "reburner.io", "uri": "/api/auth/magic_link/request/mr.burns+reburner@skware.org", "headers": {"Accept": ["application/json, text/plain, */*"], "Referer": ["https://reburner.io/"], "Sec-Fetch-Site": ["same-origin"], "Dnt": ["1"], "Sec-Ch-Ua-Platform": ["\"Linux\""], "Accept-Language": ["en-US,en;q=0.6"], "Sec-Gpc": ["1"], "Sec-Fetch-Dest": ["empty"], "Accept-Encoding": ["gzip, deflate, br"], "Sec-Fetch-Mode": ["cors"], "Sec-Ch-Ua": ["\"Brave\";v=\"119\", \"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\""], "Sec-Ch-Ua-Mobile": ["?0"], "User-Agent": ["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"]}, "tls": {"resumed": false, "version": 772, "cipher_suite": 4865, "proto": "h3", "server_name": "reburner.io"}}, "duration": 0.394615607, "status": 502, "err_id": "i5med47sw", "err_trace": "reverseproxy.statusError (reverseproxy.go:1265)"}
2023/12/03 15:56:26.526	ERROR	http.log.access.log0	handled request	{"request": {"remote_ip": "2a02:ab88:7:8a80::9bb1", "remote_port": "39676", "client_ip": "2a02:ab88:7:8a80::9bb1", "proto": "HTTP/3.0", "method": "GET", "host": "reburner.io", "uri": "/api/auth/magic_link/request/mr.burns+reburner@skware.org", "headers": {"Dnt": ["1"], "Sec-Ch-Ua-Platform": ["\"Linux\""], "Accept-Language": ["en-US,en;q=0.6"], "Sec-Fetch-Site": ["same-origin"], "Sec-Gpc": ["1"], "Sec-Fetch-Dest": ["empty"], "Accept-Encoding": ["gzip, deflate, br"], "Sec-Ch-Ua": ["\"Brave\";v=\"119\", \"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\""], "Sec-Ch-Ua-Mobile": ["?0"], "User-Agent": ["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"], "Sec-Fetch-Mode": ["cors"], "Accept": ["application/json, text/plain, */*"], "Referer": ["https://reburner.io/"]}, "tls": {"resumed": false, "version": 772, "cipher_suite": 4865, "proto": "h3", "server_name": "reburner.io"}}, "bytes_read": 0, "user_id": "", "duration": 0.394615607, "size": 0, "status": 502, "resp_headers": {"Date": ["Sun, 03 Dec 2023 15:56:26 GMT"], "Server": ["Caddy"]}}

Node JS error

Dec 03 15:56:26 reburner.io systemd[1]: reburner-api.service: Failed with result 'exit-code'.
Dec 03 15:56:26 reburner.io systemd[1]: reburner-api.service: Main process exited, code=exited, status=1/FAILURE
Dec 03 15:56:26 reburner.io node[825475]: Node.js v20.10.0
Dec 03 15:56:26 reburner.io node[825475]: }
Dec 03 15:56:26 reburner.io node[825475]:   command: 'CONN'
Dec 03 15:56:26 reburner.io node[825475]:   code: 'ESOCKET',
Dec 03 15:56:26 reburner.io node[825475]:     at ssl.onhandshakedone (node:_tls_wrap:871:12) {
Dec 03 15:56:26 reburner.io node[825475]:     at TLSSocket._finishInit (node:_tls_wrap:1085:8)
Dec 03 15:56:26 reburner.io node[825475]:     at TLSSocket.emit (node:events:514:28)
Dec 03 15:56:26 reburner.io node[825475]:     at TLSSocket.onConnectSecure (node:_tls_wrap:1674:34)
Dec 03 15:56:26 reburner.io node[825475]: Error: certificate has expired
Dec 03 15:56:26 reburner.io node[825475]:             ^
Dec 03 15:56:26 reburner.io node[825475]:             triggerUncaughtException(err, true /* fromPromise */);
Dec 03 15:56:26 reburner.io node[825475]: node:internal/process/promises:289
Dec 03 15:55:29 reburner.io systemd[1]: Started Reburner.io API server.

3. Caddy version:

4. How I installed and ran Caddy:

a. System environment:

Caddy v2.7.5
Node 20.10.0
Archlinux
Everything is a systemd service except for Caddy which I start manually after a restart.

b. Command:

cd /srv/http
caddy start

c. Service/unit/compose file:

d. My complete Caddy config:

/srv/http/Caddyfile

reburner.io {
	encode gzip

	handle /api/* {
		reverse_proxy localhost:8181
	}

	handle {
		root * /srv/http/reburner.io/web-ui/dist
		file_server
		try_files {path} /index.html
	}

	log {
		level DEBUG
	}
}

5. Links to relevant resources:

Adding the NODE_TLS_REJECT_UNAUTHORIZED=0 environment variable has resolved the problem but doesn’t really seem to be the correct solution so I’ll be looking into it more.

I don’t think this has anything to do with Caddy. It’s probably your Node app making HTTP requests to some other server, and that server has an expired certificate.

No, you didn’t solve any problem, you just turned off all security that TLS offers. Now, anyone could perform a man-in-the-middle attack between your Node server and whatever else it tries to connect to.

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