tcp_tunnel 2.1.0 copy "tcp_tunnel: ^2.1.0" to clipboard
tcp_tunnel: ^2.1.0 copied to clipboard

A minimalistic TCP tunnel library, entirely written in Dart, and equipped with a user-friendly Command Line Interface (CLI) for seamless usage across diverse platforms.

2.1.0 #

  • Security layer for hub-mode connections (opt-in, two independent layers):
    • TLS on the agent↔hub links. The hub can serve its control port over TLS (hub --tls-cert <pem> --tls-key <pem> / TunnelHub.securityContext); each accepted connection is upgraded with SecureSocket.secureServer before its handshake. Agents connect over TLS with publish/connect --tls, trusting a custom CA with --tls-ca <pem> or accepting any certificate (dev only) with --tls-insecure (TunnelServerAgent/TunnelClientAgent.securityContext and onBadCertificate). Encrypts both the control frames and the raw-piped payload as it crosses the network. No new dependency — dart:io TLS.
    • Shared-secret authentication. Agents present a token in their HELLO, constant-time compared by the hub (TunnelHub.authToken, TunnelServerAgent/TunnelClientAgent.authToken); a mismatch is rejected with a REJECT frame. The token is resolved (in priority order) from --token-file <path> (keeps it out of shell history and the process arg list), the TCP_TUNNEL_TOKEN env var, or --token <secret>. The HELLO frame now carries an optional token field; adds constantTimeEquals.
    • Both layers are optional and independent; existing plaintext deployments are unaffected. The hub's control-accept loop now runs in the guarded zone so a stray socket error during a TLS handshake or rejection teardown is logged rather than left unhandled.

2.0.1 #

  • publish can request a public port from the hub (default off): --public-port <n> (fixed), --public-port any / --public-port . (dynamic), or --public (alias for --public-port any). Exposed as TunnelServerAgent.requestPublicPort. If the request cannot be satisfied — the port is already in use by another service/process, it is unallocatable, or a dynamic request reaches a hub started without --map-dynamic — the hub sends a REJECT control frame and publish exits non-zero with the reason (TunnelServerAgent.onPublicPortRejected). Adds FrameType.reject; the HELLO frame now carries the agent's public-port request.
  • Changed --map-dynamic semantics: it no longer auto-allocates a public port for every published service. It now only permits publishers to request a dynamic public port via --public-port any; without the flag such requests are rejected with a reason. Operator-configured dynamic ports (--map svc=.) are unaffected, and a service whose agent requests no port stays in local port mode (TunnelHub.dynamicPublicPorts).

2.0.0 #

  • Hub mode: a single public hub that routes named services from private LANs (NAT-friendly on both ends) to remote consumers, using a pre-warmed pool of parked connections. Two consumer modes share the same hub:
    • Mode 1 — public port mode: the hub binds a public TCP port per service (--map svc=port); plain TCP clients connect directly. The port may be dynamically allocated with --map svc=. (per service) or --map-dynamic (auto-allocate a port for any published service); the chosen port is logged. Dynamic allocation can be constrained to a firewall-friendly range via --port-range start-end (TunnelHub.dynamicPortRange / PortRange).
    • Mode 2 — local port mode: a client agent opens a local listen port and uses the hub purely as a rendezvous (no public per-service port needed).
  • Every CLI command prints a "How to use" block on startup explaining how to publish to / consume from it (the hub block lists allocated public ports).
  • The hub now tells each connecting server agent its service's public port (a WELCOME control frame); publish logs where the service is publicly mapped (or that it is local port mode only). Exposed as TunnelServerAgent.publicPort.
  • New library APIs:
    • lib/src/tcp_tunnel_protocol.dart: length-prefixed control frames (HELLO/ACTIVATE/PING/PONG/READY), encodeFrame/decodeFrame, and FramedConnection (reads frames across fragmented/coalesced TCP reads).
    • lib/src/tcp_tunnel_hub.dart: TunnelHub.
    • lib/src/tcp_tunnel_agent.dart: TunnelServerAgent (publish) and TunnelClientAgent (connect).
  • lib/src/tcp_tunnel_base.dart: added SocketAsync.adopt(FramedConnection) to hand a connection off from the framed handshake to raw piping by reusing the existing single subscription (no re-listen) and replaying leftover bytes.
  • CLI: new hub, publish, and connect modes. Existing local, bridge, and client modes are unchanged.
  • Activation uses an explicit ACTIVATE/READY barrier so server-speaks-first protocols (MySQL/SSH/SMTP banners) work and in-flight keepalive frames never leak into the raw stream.
  • Not included (same posture as before): encryption/TLS, authentication, dynamic public-port allocation, client-specified target addressing.

1.0.2 #

  • lib/src/tcp_tunnel_base.dart:

    • Added end-to-end backpressure: SocketAsync now owns its stream subscription and pauses reading until the destination's flush completes, preventing unbounded memory growth when one peer is slower than the other.
    • Connection failures no longer hang: SocketAsync.unresolved closes on a failed connect, and close() now always notifies onClose even when the socket was never resolved.
    • Tunnel.connectAsync: a failed target connection now closes the tunnel (and fires onClose) instead of hanging forever.
    • Removed a dead Socket.handleError(...) handler whose result was discarded; error handling lives in the subscription's onError.
    • Added Tunnel.pair(SocketAsync, SocketAsync) factory; withSockets and targetPort now delegate to it.
    • Tunnel.targetPort now returns Future<Tunnel?> and destroys the inbound socket when the target connection fails.
    • Verbose data logging now logs byte counts instead of latin1-decoding payloads; removed the now-unused dart:convert import.
  • bin/tcp_tunnel.dart:

    • Fixed _withFlag to correctly detect single-dash flags.
    • _parseMaxTunnels: added lower bound check to ensure minimum value of 1.
    • Added graceful shutdown: SIGINT/SIGTERM now close active servers and tunnels before exiting (SIGTERM skipped on Windows).
  • lib/src/tcp_tunnel_bridge.dart:

    • Changed _server1 and _server2 fields to nullable ServerSocket?.
    • Added null-aware calls to _server1?.close() and _server2?.close() in close().
    • Queues now hold SocketAsync instances; a queued socket that closes before being paired is evicted via onClose and skipped during pairing, so it is never paired into a dead tunnel.
  • lib/src/tcp_tunnel_server.dart:

    • Changed _server field to nullable ServerSocket?.
    • Added null-aware call to _server?.close() in close().
    • Updated to the nullable Tunnel.targetPort result (logs only on success).
  • pubspec.yaml:

    • Updated test dependency from ^1.31.0 to ^1.31.1.
  • test/tcp_tunnel_test.dart:

    • Rewrote tests extensively:
      • Added utility functions freePort(), _wait().
      • Added RecordingServer helper class to record socket data.
      • Added echoServer helper for echoing data.
      • Added comprehensive tests for:
        • TunnelLocalServer forwarding data one and both directions.
        • Multiple concurrent clients support.
        • TunnelBridge connecting queued sockets, FIFO pairing, and close idempotency.
        • Tunnel.withSockets relaying data and close notification.
        • Full chain integration test with bridge, client tunnel, and local server.
        • Connection failures firing onClose for connect and connectAsync.
        • connectAsync lazy connect (target connects only after first remote data).
        • Backpressure: large payload (4 MiB) transferred byte-for-byte.
        • TunnelBridge eviction of a queued socket closed before pairing.
        • CLI usage smoke test.
        • connectAsync forwarding the first (triggering) data to the target and bidirectional round-trip with onReady completing.
        • TunnelBridge buffering data sent while a socket is queued, isolating many concurrent pairs, and tearing down a peer when one side closes.
        • TunnelLocalServer dropping the client when the target is unreachable.
        • onStart callback, verbose data path, and custom targetHost.
        • Edge cases: half-close drain, zero-length writes, reverse-direction relay, large bidirectional transfer, and SocketAsync state getters.
      • Removed old redirectLocalPort, bridgePorts, and clientTunnel helper functions.
      • Improved test reliability with explicit waits and socket flushes.

1.0.2+ #

  • bin/tcp_tunnel.dart:

    • Added support for verbose flag in CLI.
    • Added support for loop flag and --max-tunnels option in client mode.
    • Added structured logging using package:logging.
    • Updated _configureLogging to always configure logging with level ALL if verbose, otherwise INFO.
    • Changed default logging level in _configureLogging from ALL to INFO.
    • Refactored main logic to _run with verbose and loop parameters.
    • Added _withFlag helper to parse boolean flags.
  • Client mode:

    • Added support for parallel connections with a new _parseParallels method.
    • Run multiple client tunnels in parallel based on the parsed parallel count.
    • Managed multiple tunnels with _tunnels list and recursive connection logic in client mode.
  • Argument parsing:

    • Added _parseParallels to parse concurrency-related flags (--concurrency, --parallel, --parallels) with clamping between 2 and max tunnels.
    • Refactored argument parsing into _parseArgInt helper method used by _parseMaxTunnels and _parseParallels.
  • lib/src/tcp_tunnel_base.dart:

    • Added guarded zone support with Tunnel.zoneGuarded and Tunnel.runGuarded.
    • Added onReady future to Tunnel to notify when tunnel is fully established.
    • Added connectAsync factory for two-phase lazy connection (remote connect → first data → target connect).
    • Updated connect factory to complete onReady after both sockets connect.
    • Updated targetPort and withSockets factories to complete onReady.
    • Added verbose parameter to Tunnel constructors and logging on close.
    • Improved internal connection and ready notification logic.
  • lib/src/tcp_tunnel_bridge.dart:

    • Added verbose parameter to TunnelBridge.
    • Tunnel creation now passes verbose flag.
    • Added logging on tunnel connection when verbose enabled.
  • lib/src/tcp_tunnel_server.dart:

    • Added verbose parameter to TunnelLocalServer.
    • Tunnel creation now passes verbose flag.
    • Added logging on new tunnel connection when verbose enabled.

1.0.1 #

  • Updated SDK constraint to >=3.10.0 <4.0.0.
  • Updated dependencies:
    • logging to ^1.3.0
    • lints to ^6.1.0
    • dependency_validator to ^5.0.5
    • test to ^1.31.0
  • Added executable entry for tcp_tunnel in pubspec.yaml.
  • Changed module type in tcp_tunnel.iml from JAVA_MODULE to WEB_MODULE.
  • bin/tcp_tunnel.dart:
    • Fixed trailing comma in _runModeClient parameters.
  • lib/src/tcp_tunnel_base.dart:
    • Improved code style in SocketAsync and Tunnel classes.
  • lib/tcp_tunnel.dart:
    • Removed library name declaration (library tcp_tunnel;) to default unnamed library.

1.0.0 #

  • Initial version.
8
likes
160
points
149
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A minimalistic TCP tunnel library, entirely written in Dart, and equipped with a user-friendly Command Line Interface (CLI) for seamless usage across diverse platforms.

Repository (GitHub)
View/report issues

License

BSD-3-Clause (license)

Dependencies

logging

More

Packages that depend on tcp_tunnel