feat: add revtunnel reverse-tunnel plugin#802
Open
tg123 wants to merge 10 commits into
Open
Conversation
Register an SSH reverse tunnel with `ssh -R` and let anyone holding the returned GUID + ed25519 private key connect through sshpiper back to a host reachable from the registrar. - Register-side auth: none (embedded SSH server in-process) - Connect-side auth: publickey only (GUID as username) - Session stores: memory:// (default) and file://<dir> - Idle timeout: 2h with 5min sweep interval - Includes unit tests, in-process integration test, and e2e test - Added goreleaser build entries for the new plugin Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new revtunnel plugin that lets a user register an SSH reverse tunnel (ssh -R ...) and distribute a generated GUID + ed25519 keypair so other users can connect back through sshpiperd to a host reachable only from the registrar.
Changes:
- Introduces
plugin/revtunnelimplementation: embedded register-side SSH server, GUID/key issuance, connect-side pubkey validation, and forwarded-tcpip channel bridging. - Adds session persistence options (
memory://andfile://<dir>) with unit + in-process integration tests. - Adds end-to-end coverage and wires the plugin into GoReleaser artifacts.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| plugin/revtunnel/main.go | Plugin entrypoint, CLI flags, and idle-sweeper loop. |
| plugin/revtunnel/plugin_config.go | Implements sshpiper callbacks (register/connect flows + CreateConn). |
| plugin/revtunnel/server.go | Embedded SSH server for registrations; GUID/key generation and output formatting. |
| plugin/revtunnel/registry.go | In-memory live registry + optional persisted record lookup. |
| plugin/revtunnel/registry_test.go | Unit tests for registry behavior and concurrent safety. |
| plugin/revtunnel/store.go | Parses --session-store into a concrete store implementation. |
| plugin/revtunnel/store_memory.go | In-memory session store implementation. |
| plugin/revtunnel/store_file.go | File-backed session store with per-GUID JSON records. |
| plugin/revtunnel/store_test.go | Unit tests for memory/file stores and openSessionStore. |
| plugin/revtunnel/integration_test.go | In-process integration test driving full register→connect flow via callbacks. |
| plugin/revtunnel/README.md | Usage and operational documentation for the new plugin. |
| e2e/revtunnel_test.go | Docker-compose E2E test covering registration + connect through tunnel. |
| .goreleaser.yaml | Adds plugin_revtunnel build + archive + snap entries. |
…fe GUID validation
- Remove store.Put from Lookup/Touch to avoid excessive I/O on file stores - Keep LastActivity in-memory only (persisted on Put/Delete) - Rewrite README to match actual auth model (pubkey-based, no issued key) - Update examples README output format to match actual plugin output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…, block on pendingKeys - Move close(guidCh) after wg.Wait() to prevent send-on-closed-channel panic - Dial first in dialConnWithKey, enqueue key only on success (no orphaned keys) - Block with timeout on pendingKeys read instead of non-blocking default - Update examples/revtunnel/README.md output format to match actual plugin output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace pendingKeys channel with sync.Map keyed by remote address to prevent key/session mis-correlation under concurrent registrations - Use non-blocking send on guidCh to avoid hanging handleGlobalRequests when the session has already exited - Throttle channelConn.Touch to once per 30s to avoid mutex contention on high-throughput SSH sessions (SCP/SFTP) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Register an SSH reverse tunnel with
ssh -Rand let anyone holding the returned GUID + ed25519 private key connect through sshpiper back to a host reachable from the registrar.How it works
ssh -R 0:<host>:<port> <user>@sshpiper— plugin issues a GUID + ed25519 keypair to the registrar's session.ssh -i id_revtunnel <guid>@sshpiper— plugin verifies pubkey, opens aforwarded-tcpipchannel on the registrar's connection, and the daemon does a normal SSH handshake to<host>:<port>as<user>.Features
memory://(default, lost on restart) orfile://<dir>(one JSON per GUID, atomic write)ssh -R 0:...(RFC 4254 §7.1 compliance)Testing
registry_test.go,store_test.go)integration_test.go)e2e/revtunnel_test.go)-raceFiles
plugin/revtunnel/— plugin implementation + READMEe2e/revtunnel_test.go— end-to-end test.goreleaser.yaml— addedplugin_revtunnelbuild/archive/snap entries