-
Notifications
You must be signed in to change notification settings - Fork 30.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nodejs runs out of memory trying to connect to HTTPS host with self-signed certificate #37757
Comments
❯ node -v
v15.2.0
❯ cp ~/Downloads/node_https_test.zip .
❯ unzip node_https_test.zip
Archive: node_https_test.zip
inflating: cert.conf
inflating: cert.pem
inflating: https_renew_cert.sh
inflating: index.js
inflating: key.pem
inflating: run.sh
inflating: server.js
❯ export NODE_EXTRA_CA_CERTS="$PWD/cert.pem"
❯ node server.js
^Z
[1] + 9905 suspended node server.js
❯ node index.js
^Z
[2] + 9921 suspended node index.js
❯ fg %node\ server.js
[1] - 9905 continued node server.js
^Z
[1] + 9905 suspended node server.js
❯ fg %node\ index.js
[2] - 9921 continued node index.js
An error Error: unable to verify the first certificate
at TLSSocket.onConnectSecure (node:_tls_wrap:1498:34)
at TLSSocket.emit (node:events:329:20)
at TLSSocket._finishInit (node:_tls_wrap:933:8)
at TLSWrap.ssl.onhandshakedone (node:_tls_wrap:707:12) {
code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
} Can't reproduce. Am I doing something wrong here? |
Looks fine to me. Just did exactly what you did, reproduces the problem for me. Are you running ubuntu? I also tried it on fedora after you answered and then i get the same error you do. |
Yes, Ubuntu. |
I´ve set up a repo with an action to reproduce the issue: https://github.com/nils91/node_https_test.
|
I might have found a workaround: Removing the line
from the cert.conf file and regenerating the certificate using the new config allows node to get a connection. However, that might not be applicable to all use-cases, as some applications can be picky about the |
I forked your repo here and ran some tests on few other versions. In spite of running the test on <--- Last few GCs --->
[1560:0x6003ef0] 85165 ms: Mark-sweep (reduce) 2043.8 (2083.1) -> 2043.4 (2083.8) MB, 1600.2 / 0.0 ms (+ 0.0 ms in 69 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 1880 ms) (average mu = 0.485, current mu = 0.233) [1560:0x6003ef0] 87646 ms: Mark-sweep (reduce) 2044.4 (2083.8) -> 2044.3 (2084.6) MB, 2454.3 / 0.0 ms (average mu = 0.255, current mu = 0.011) allocation failure scavenge might not succeed
<--- JS stacktrace --->
FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory
1: 0xa7f490 node::Abort() [node]
2: 0x9a5c4d node::FatalError(char const*, char const*) [node]
3: 0xc6c2ae v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
4: 0xc6c627 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
5: 0xe360a5 [node]
6: 0xe65633 v8::internal::EvacuateNewSpaceVisitor::Visit(v8::internal::HeapObject, int) [node]
7: 0xe721e6 v8::internal::FullEvacuator::RawEvacuatePage(v8::internal::MemoryChunk*, long*) [node]
8: 0xe5e30f v8::internal::Evacuator::EvacuatePage(v8::internal::MemoryChunk*) [node]
9: 0xe5e588 v8::internal::PageEvacuationTask::RunInParallel(v8::internal::ItemParallelJob::Task::Runner) [node]
10: 0xe503a9 v8::internal::ItemParallelJob::Run() [node]
11: 0xe74170 void v8::internal::MarkCompactCollectorBase::CreateAndExecuteEvacuationTasks<v8::internal::FullEvacuator, v8::internal::MarkCompactCollector>(v8::internal::MarkCompactCollector*, v8::internal::ItemParallelJob*, v8::internal::MigrationObserver*, long) [node]
12: 0xe749b3 v8::internal::MarkCompactCollector::EvacuatePagesInParallel() [node]
13: 0xe74d75 v8::internal::MarkCompactCollector::Evacuate() [node]
14: 0xe874e1 v8::internal::MarkCompactCollector::CollectGarbage() [node]
15: 0xe433a8 v8::internal::Heap::MarkCompact() [node]
16: 0xe44d38 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
17: 0xe482dc v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
18: 0xe0bf3a v8::internal::Factory::AllocateRaw(int, v8::internal::AllocationType, v8::internal::AllocationAlignment) [node]
19: 0xe05444 v8::internal::FactoryBase<v8::internal::Factory>::AllocateRawWithImmortalMap(int, v8::internal::AllocationType, v8::internal::Map, v8::internal::AllocationAlignment) [node]
20: 0xe07540 v8::internal::FactoryBase<v8::internal::Factory>::NewRawOneByteString(int, v8::internal::AllocationType) [node]
21: 0xe0ddfd v8::internal::Factory::NewStringFromUtf8(v8::internal::Vector<char const> const&, v8::internal::AllocationType) [node]
22: 0xc83882 v8::String::NewFromUtf8(v8::Isolate*, char const*, v8::NewStringType, int) [node]
23: 0xbb774e node::crypto::X509ToObject(node::Environment*, x509_st*) [node]
24: 0xbb81e4 node::crypto::GetPeerCert(node::Environment*, std::unique_ptr<ssl_st, node::FunctionDeleter<ssl_st, &SSL_free> > const&, bool, bool) [node]
25: 0xc2b567 node::crypto::TLSWrap::GetPeerCertificate(v8::FunctionCallbackInfo<v8::Value> const&) [node]
26: 0xcd8cbb [node]
27: 0xcda26c [node]
28: 0xcda8e6 v8::internal::Builtin_HandleApiCall(int, unsigned long*, v8::internal::Isolate*) [node]
29: 0x14fa219 [node]
./run.sh: line 5: 1560 Aborted (core dumped) node index.js
Error: Process completed with exit code 134. |
https://github.com/RaisinTen/node_https_test/runs/2140664480?check_suite_focus=true says that the crash was introduced in |
cc @nodejs/crypto |
There, however, was an OpenSSL update in 15.5.0. Perhaps this caused the problem? |
#37889 contains some background on the OpenSSL change that might be related here, as well as a standalone repro. |
Looks like this is the relevant infinite loop: node/src/crypto/crypto_common.cc Line 469 in f00c243
I'm not really familiar enough with the OpenSSL APIs to understand why, though. |
|
I am not sure if this is relevant, but I've verified the behavior change from OpenSSL 1.1.1g to 1.1.1h. With OpenSSL 1.1.1g the connection |
I can confirm this issue shows up on Mac OS 10.15.7 as well, though it just infinite loops for me (haven't let it run long enough to exhaust available memory, but I see it increasing steadily). To make matters worse, Let's Encrypt's official recommendation (which I think is correct) includes the exact thanks for looking into this! |
I was running into this bug and this comment saved me. With a cert that just had |
What steps will reproduce the bug?
When trying to connect to a https-enabled host and using a self-signed certificate provided to node via
NODE_EXTRA_CA_CERTS
node hangs for a few minutes, using more and more memory, until it exits withAllocation failed - JavaScript heap out of memory
. Full stacktrace below.How often does it reproduce? Is there a required condition?
The server needs to be up and the correct server certificate needs to be used.
What is the expected behavior?
I would expect the connection to be made successfully, since the self-signed certificate has been provided to node.
What do you see instead?
Additional information
All files i´ve used to reproduce: node_https_test.zip
https_renew_cert.sh is a script used to generate the key/certificate pair. (Sample certificate and key is also included in the zip, so you don´t have to regenerate them, if you don´t have oppenssl installed)
server.js is the server. Execute with node server.js.
index.js is the client. Started from run.sh
run.sh: Starts the client and sets
NODE_EXTRA_CA_CERTS
. (You need to update the path to the certificate)The text was updated successfully, but these errors were encountered: