Skip to content

feat: add revtunnel reverse-tunnel plugin#802

Open
tg123 wants to merge 10 commits into
masterfrom
feat/reverse-tunnel-plugin
Open

feat: add revtunnel reverse-tunnel plugin#802
tg123 wants to merge 10 commits into
masterfrom
feat/reverse-tunnel-plugin

Conversation

@tg123

@tg123 tg123 commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Summary

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.

How it works

  1. Register: ssh -R 0:<host>:<port> <user>@sshpiper — plugin issues a GUID + ed25519 keypair to the registrar's session.
  2. Connect: ssh -i id_revtunnel <guid>@sshpiper — plugin verifies pubkey, opens a forwarded-tcpip channel on the registrar's connection, and the daemon does a normal SSH handshake to <host>:<port> as <user>.

Features

  • Register-side auth: none (embedded SSH server in-process)
  • Connect-side auth: publickey only (GUID as username)
  • Session stores: memory:// (default, lost on restart) or file://<dir> (one JSON per GUID, atomic write)
  • Idle timeout: 2h (5min sweep)
  • Pseudo-port allocation for ssh -R 0:... (RFC 4254 §7.1 compliance)

Testing

  • Unit tests (registry_test.go, store_test.go)
  • In-process integration test (integration_test.go)
  • E2E docker-compose test (e2e/revtunnel_test.go)
  • All pass with -race

Files

  • plugin/revtunnel/ — plugin implementation + README
  • e2e/revtunnel_test.go — end-to-end test
  • .goreleaser.yaml — added plugin_revtunnel build/archive/snap entries

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>
Copilot AI review requested due to automatic review settings June 16, 2026 03:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/revtunnel implementation: embedded register-side SSH server, GUID/key issuance, connect-side pubkey validation, and forwarded-tcpip channel bridging.
  • Adds session persistence options (memory:// and file://<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.

Comment thread plugin/revtunnel/server.go
Comment thread plugin/revtunnel/server.go
Comment thread plugin/revtunnel/server.go Outdated
Comment thread plugin/revtunnel/server.go Outdated
Comment thread plugin/revtunnel/store_file.go Outdated
Copilot AI review requested due to automatic review settings June 16, 2026 08:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 8 comments.

Comment thread e2e/revtunnel_test.go Outdated
Comment thread plugin/revtunnel/server.go Outdated
Comment thread plugin/revtunnel/plugin_config.go
Comment thread plugin/revtunnel/server.go
Comment thread plugin/revtunnel/README.md Outdated
Comment thread plugin/revtunnel/README.md Outdated
Comment thread plugin/revtunnel/README.md Outdated
Comment thread examples/revtunnel/README.md

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 7 comments.

Comment thread plugin/revtunnel/server.go
Comment thread plugin/revtunnel/server.go Outdated
Comment thread e2e/revtunnel_test.go Outdated
Comment thread plugin/revtunnel/registry.go
Comment thread plugin/revtunnel/registry.go Outdated
Comment thread plugin/revtunnel/README.md Outdated
Comment thread examples/revtunnel/README.md
Copilot AI review requested due to automatic review settings June 16, 2026 08:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 8 comments.

Comment thread plugin/revtunnel/server.go
Comment thread plugin/revtunnel/server.go
Comment thread plugin/revtunnel/server.go Outdated
Comment thread plugin/revtunnel/server.go
Comment thread plugin/revtunnel/plugin_config.go
Comment thread plugin/revtunnel/plugin_config.go
Comment thread plugin/revtunnel/README.md
Comment thread examples/revtunnel/README.md
tg123 and others added 2 commits June 16, 2026 02:05
- 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>
Copilot AI review requested due to automatic review settings June 16, 2026 09:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 18 changed files in this pull request and generated 3 comments.

Comment thread plugin/revtunnel/server.go
Comment thread plugin/revtunnel/server.go Outdated
Comment thread plugin/revtunnel/plugin_config.go
- 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants