tls: native pipe / splice between TLS and another native stream or fd
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Anfängerfreundlichkeit
- 30/100
- Issue-Typ
- Feature
- Klarheit
- Größtenteils klar
- Aktivitätsstatus
- Ruhig
- Tech-Stack
- javascript, node.js
- Bereich
- networking, security
Rechercherichtung
Beginne mit TLSWrap und dem bestehenden pipe/splice-Verhalten von net.Socket, das im Issue beschrieben ist, und verfolge dann den Einstiegspunkt der tls.connect-Sitzung. Ermittle vor der Implementierung das Design und die Ownership-Semantik für das Bridging nativer fd. Als abgeschlossen gilt die Arbeit, wenn die Duplex-Weiterleitung ohne JavaScript-Handler pro Chunk auskommt, Backpressure weitergibt, den Sitzungsaufbau beibehält und die genannten Kriterien für Weiterleitung und Benchmarks erfüllt.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
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.
- Vorherrschende Sprache
- JavaScript
- Sterne
- 122k
- Forks
- 39k
- Ø Merge
- 3 T. 22 Std.
- Gemergte PRs (30 T.)
- 245
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Hat eine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus nodejs/node
-
node:internal/inspector/network_http: `TypeError: Missing dataLength` in event when response uses `setEncoding()`Evtl. vergeben @lazerg hat das vor 3 Tagen übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
Maintainer antworten meist innerhalb von 1 Tag
-
[Docs] `process.loadEnvFile()` does not document behaviour when variables already existEvtl. vergeben @Sepandard hat das vor 13 Tagen übernommen. Offendoc
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 90/100
Maintainer antworten meist innerhalb von 1 Tag
-
Stream.prototype.forEach will block in first promise in queue before read more chunkEvtl. vergeben @mmustafasenoglu hat das vor 14 Tagen übernommen. Offendoc
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 65/100
Maintainer antworten meist innerhalb von 1 Tag
-
build
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 88/100
nodejs/node#66076 · 2 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
`TextEncoder.encodeInto()` underfills the destination for some non-ASCII textEvtl. vergeben @XadillaX hat das vor 28 Tagen übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 84/100
nodejs/node#65994 · 2 Kommentare · 2 Reaktionen ·
Maintainer antworten meist innerhalb von 1 Tag
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 62/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 62/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
Maintainer antworten meist innerhalb von 1 Tag
-
documentation good first issue help wanted
Schwierigkeit 1/5 1-3 Stunden Anfängerfreundlichkeit 85/100
zmo2s/agent-toolbox#23 ·
-
[Bug]: [MCP/CLI] Bare loopback IP addresses (127.0.0.1:port) and hosts with ports fail to navigate due to erroneous scheme inferenceEvtl. vergeben @alok-108 hat das heute übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
microsoft/playwright#43263 ·
Maintainer antworten meist innerhalb von 1 Tag