tls: native pipe / splice between TLS and another native stream or fd
Les mainteneurs répondent en général sous 1 jour
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Accessibilité débutants
- 30/100
- Type d'issue
- Fonctionnalité
- Clarté
- Plutôt claire
- Activité
- Calme
- Stack technique
- javascript, node.js
- Domaine
- networking, security
Piste de recherche
Commencez par TLSWrap et le comportement existant de pipe/splice de net.Socket décrit dans l’issue, puis suivez le point d’entrée de la session tls.connect. Déterminez la conception et la sémantique de propriété pour le bridging des fd natifs avant l’implémentation. Le travail est considéré comme terminé lorsque le transfert duplex évite les handlers JavaScript par chunk, propage la contre-pression, préserve l’établissement de la session et respecte les critères indiqués de transfert et de benchmark.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
What is the problem this feature will solve?
net.Socket supports efficient kernel-level forwarding patterns (socket.pipe(), socket.pause()/resume() with native backpressure). There is no TLS equivalent — forwarding cleartext through TLSSocket always goes through the streams layer:
TCP (encrypted) → TLSWrap::ClearOut → JS Readable → user pump → JS Writable → sink
For full-duplex bridges (TLS ↔ TUN fd, TLS ↔ pipe, TLS ↔ another TCP socket), userland must:
- Implement two pumps (encrypt direction + decrypt direction) in JavaScript or duplicate logic in a native addon
- Manually coordinate backpressure (pause/resume, 'drain', TUN poll pause) across heterogeneous endpoints
- Absorb per-chunk copies and event-loop latency from TLSWrap (see related issues on SetImmediate deferral and read copies)
net has splice-style optimizations between fds; TLSWrap sits in the middle with no supported way to wire cleartext directly to a native sink/source while keeping session setup in Node.
This forces ecosystem projects (VPN helpers, transparent proxies, iOS tunnel tooling) to ship custom OpenSSL forwarders instead of composing built-in APIs.
What is the feature you are proposing to solve the problem?
Add native TLS pipe/splice primitives that pump cleartext between an established TLSSocket (or tls.connect session) and another native I/O endpoint without per-chunk JavaScript involvement.
Proposed API (sketch):
import tls from 'node:tls';
import net from 'node:net';
const tcp = await net.connect({ port });
const tlsSocket = await tls.connect({ socket: tcp, ... });
// Duplex: TLS cleartext ↔ numeric fd (TUN, pipe, etc.)
const handle = tlsSocket.spliceTo({
fd: tunFd,
direction: 'duplex', // 'in' | 'out' | 'duplex'
});
handle.start();
await handle.stop(); // idempotent cleanup
// Or one-shot helper:
await tlsSocket.pipeToNative(tunFd, { direction: 'duplex' });
Implementation outline (on TLSWrap):
- Decrypt path (TLS → sink): SSL_read loop → write cleartext to sink fd; on EAGAIN/EWOULDBLOCK, pause uv_read_start on the underlying TCP stream until sink is writable (native backpressure, not socket.pause() in JS).
- Encrypt path (source → TLS): read cleartext from source fd → SSL_write → EncOut → TCP; stall source read when SSL_write or TCP send buffer is full.
- Reuse existing TLSWrap session, handshake, cert/PSK options — only the payload pump is native.
- Clear ownership semantics for fds (caller retains TUN; bridge does not close unless autoClose: true).
Relation to other proposals:
- Lighter-weight than full tls.createBridge() when one side is already a TLSSocket and the other is an fd.
- Complements zero-copy onread for users who still want one direction in JS.
Success criteria:
- Bidirectional MTU-sized forwarding without socket.on('data') handlers.
- Backpressure propagates correctly (no unbounded buffering in pending_cleartext_input_ / userland).
- Benchmark shows lower CPU and event-loop utilization vs. an equivalent JS pump.
What alternatives have you considered?
- socket.pipe(otherSocket) through TLSSocket — Still routes every byte through JS streams; does not splice to raw fds; no TLS-aware backpressure.
- duplex streams + pipeline() — Same V8-boundary and allocation costs; popular but not a performance solution.
- tls.createBridge() (separate proposal) — Higher-level API that may subsume this for fd targets; spliceTo is a narrower addition for users who already have a TLSSocket and want fd bridging only.
- Custom N-API OpenSSL forwarder — Proven in production (e.g. iOS tunnel addons) but duplicates TLSWrap and OpenSSL linkage in every consumer.
- node:child_process + socat/openssl s_client — Operational hack, not embeddable in Node apps.
- Document manual pump patterns only — Insufficient; the gap is missing native wiring in TLSWrap, not developer skill.
- Langage dominant
- JavaScript
- Étoiles
- 122k
- Forks
- 39k
- Merge moyen
- 3 j 22 h
- PR mergées (30 j)
- 244
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de nodejs/node
-
node:internal/inspector/network_http: `TypeError: Missing dataLength` in event when response uses `setEncoding()`Peut-être pris @lazerg l’a pris il y a 4 jours. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
Les mainteneurs répondent en général sous 1 jour
-
[Docs] `process.loadEnvFile()` does not document behaviour when variables already existPeut-être pris @Sepandard l’a pris il y a 14 jours. Ouvertedoc
Difficulté 1/5 Moins d'une heure Accessibilité débutants 90/100
Les mainteneurs répondent en général sous 1 jour
-
Stream.prototype.forEach will block in first promise in queue before read more chunkPeut-être pris @mmustafasenoglu l’a pris il y a 15 jours. Ouvertedoc
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
Les mainteneurs répondent en général sous 1 jour
-
build
Difficulté 1/5 Moins d'une heure Accessibilité débutants 88/100
nodejs/node#66076 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
`TextEncoder.encodeInto()` underfills the destination for some non-ASCII textPeut-être pris @XadillaX l’a pris il y a 28 jours. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
nodejs/node#65994 · 2 commentaires · 2 réactions ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de nodejs/node
Issues similaires
-
chore v2
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
modelcontextprotocol/servers#5115 ·
Les mainteneurs répondent en général sous 1 jour
-
beginner bug good first issue
Difficulté 1/5 Moins d'une heure Accessibilité débutants 85/100
philaconvalley/website#168 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 66/100
druxt/umami.demo.druxtjs.org#527 ·
Les mainteneurs répondent en général sous 9 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 62/100
NuSkooler/enigma-bbs#907 ·
Les mainteneurs répondent en général sous 1 jour
-
documentation good first issue
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100