WIP: feat(tsconnect/wasm): add upgradeTLS to wrapped conns #14

Draft
codinget wants to merge 1 commits from feat/conn-upgrade-tls into webnet
Owner

Adds an upgradeTLS method to the conn objects returned by dial/accept, wrapping the existing net.Conn with crypto/tls in place — the explicit upgrade needed for STARTTLS (SMTP) and AUTH TLS (FTPS).

  • tlsClientConfigFromJS factored out of dialTLS (behavior unchanged); when no default server name is available (the upgrade case) it requires serverName unless insecureSkipVerify is set.
  • upgradeTLS(opts) on wrapped conns: client mode uses the same options as dialTLS (serverName, insecureSkipVerify, caCerts); server mode via isServer: true with certPem/keyPem (same parsing as listenTLS).
  • Returns a new wrapped conn sharing the same underlying net.Conn; the old handle must not be used afterward. On handshake failure the conn is closed.

Consumed by the corresponding @webnet/transport / @webnet/tsconnect PR on the webnet repo, which provides the in-place RawTransport.upgradeTls semantics one layer up.

Adds an `upgradeTLS` method to the conn objects returned by `dial`/accept, wrapping the existing `net.Conn` with `crypto/tls` in place — the explicit upgrade needed for STARTTLS (SMTP) and AUTH TLS (FTPS). - `tlsClientConfigFromJS` factored out of `dialTLS` (behavior unchanged); when no default server name is available (the upgrade case) it requires `serverName` unless `insecureSkipVerify` is set. - `upgradeTLS(opts)` on wrapped conns: client mode uses the same options as `dialTLS` (`serverName`, `insecureSkipVerify`, `caCerts`); server mode via `isServer: true` with `certPem`/`keyPem` (same parsing as `listenTLS`). - Returns a new wrapped conn sharing the same underlying `net.Conn`; the old handle must not be used afterward. On handshake failure the conn is closed. Consumed by the corresponding `@webnet/transport` / `@webnet/tsconnect` PR on the webnet repo, which provides the in-place `RawTransport.upgradeTls` semantics one layer up.
codinget added 1 commit 2026-07-06 14:40:56 +02:00
Adds an upgradeTLS method to the conn objects returned by dial/accept,
wrapping the existing net.Conn with crypto/tls in place (STARTTLS /
FTPS AUTH TLS style). Client mode reuses the dialTLS options
(serverName, insecureSkipVerify, caCerts), now factored into
tlsClientConfigFromJS; server mode takes isServer with certPem/keyPem.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfRgMke8p7QDxD5QM5thxH
codinget added the
Agent
Fable
Agentic
labels 2026-07-06 14:41:13 +02:00
Author
Owner

Reviewed alongside webnet/webnet#63 (the consumer of upgradeTLS). The Go side here looks correct in isolation, but flagging for context: the new wrapConn(tlsConn) returned by upgradeTLS (around line 1484 in cmd/tsconnect/wasm/wasm_js.go) leaves the old wrapConn's read/write closures alive, still bound to the plain net.Conn that tls.Client/tls.Server now uses internally. That's fine as long as the JS caller strictly stops using the old handle the instant it calls upgradeTLS — but webnet/webnet#63's ipn.ts Conn.upgradeTls doesn't actually enforce that (it doesn't mark itself in-flight during the handshake), so a concurrent read()/write() from the JS side can still reach the old handle and race the handshake on the same fd. Posted the detailed finding and suggested fix on webnet#63; no action needed here unless you want to harden this side too (e.g. by having the old wrapConn's closures start erroring once superseded).

Reviewed alongside webnet/webnet#63 (the consumer of upgradeTLS). The Go side here looks correct in isolation, but flagging for context: the new `wrapConn(tlsConn)` returned by `upgradeTLS` (around line 1484 in cmd/tsconnect/wasm/wasm_js.go) leaves the *old* wrapConn's read/write closures alive, still bound to the plain `net.Conn` that `tls.Client`/`tls.Server` now uses internally. That's fine as long as the JS caller strictly stops using the old handle the instant it calls upgradeTLS — but webnet/webnet#63's `ipn.ts Conn.upgradeTls` doesn't actually enforce that (it doesn't mark itself in-flight during the handshake), so a concurrent read()/write() from the JS side can still reach the old handle and race the handshake on the same fd. Posted the detailed finding and suggested fix on webnet#63; no action needed here unless you want to harden this side too (e.g. by having the old wrapConn's closures start erroring once superseded).
This pull request is marked as a work in progress.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/conn-upgrade-tls:feat/conn-upgrade-tls
git checkout feat/conn-upgrade-tls
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: webnet/tailscale#14