Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PortPatch

PortPatch is a portable desktop application that represents your computer and SSH servers as nodes. Draw a directed edge from the place that accepts a connection to the place that should receive the traffic. Closing the window keeps active routes running in the system tray.

Current version: 0.4.2 - MIT License

PortPatch demo

Features

  • A free-form node graph for your computer and multiple SSH servers
  • Drag node cards to arrange the map; hold Ctrl and drag one node onto another to create a directed route
  • Pan the routing map by dragging its background and zoom around the mouse pointer with the wheel
  • Parallel routes between the same nodes are separated into distinct curved lanes
  • Private keys in ~/.ssh are detected locally when adding a server
  • Local-to-remote, remote-to-local, and remote-to-remote TCP relays
  • SOCKS5 routes in either direction
    • Listen on your computer and use a remote server as the egress
    • Listen on a remote server and use your computer as the egress
    • Listen on server A and use server B as the egress
  • Private key, password, SSH Agent, and Pageant authentication
  • Persistent interface sizing from 80% to 125%
  • SHA-256 SSH host-key verification and pinning
  • Per-route start and stop controls with exponential-backoff reconnection
  • Active connection counts, byte counters, errors, and retry status
  • Password and key-passphrase protection through Electron safeStorage (Windows DPAPI, macOS Keychain, or a Linux secret service such as GNOME Keyring or KWallet)
  • Close to tray, start all, stop all, and quit controls
  • Optional launch at sign-in (Windows Login Items or a Linux XDG autostart entry)
  • Optional restoration of only the routes that the user explicitly left active

Portable distribution

PortPatch is distributed without an installer.

  • Windows: one portable .exe; run it directly from any folder
  • Linux: one AppImage; run chmod +x PortPatch-<version>-linux-x86_64.AppImage once, then execute it directly
  • No administrator access is required for normal use
  • Application settings and encrypted credentials remain in the operating system's per-user application-data directory. They are not written beside the executable. This keeps the executable movable and allows it to run from read-only locations.

Both the Windows executable and the Linux AppImage are published on every tagged release; see Current limitations for exactly what has and has not been verified on Linux, and architecture.md for the underlying findings, including a deliberate sandboxing trade-off in the AppImage build.

Download

Download the latest release for your platform from GitHub Releases: PortPatch-<version>-windows-x64-portable.exe or PortPatch-<version>-linux-x86_64.AppImage. No Node.js, pnpm, installation, or administrator access is required. A .sha256 checksum file is published alongside each release asset, and new releases include GitHub build-provenance attestations. Verification instructions are in releasing.md.

git clone downloads the source code, not compiled release files. Cloning is intended for contributors who want to build or modify PortPatch.

Example routes

Goal Route
Use an LLM on a GPU server at localhost:8000 from your computer My Computer 127.0.0.1:18000 -> GPU Server 127.0.0.1:8000 using TCP
Let a remote server use an LLM on your computer at localhost:8000 Server 127.0.0.1:18000 -> My Computer 127.0.0.1:8000 using TCP
Browse sites that are reachable only from a server My Computer 127.0.0.1:1080 -> Server egress using SOCKS5
Give an offline server access through your computer's network Server 127.0.0.1:1080 -> My Computer egress using SOCKS5
Connect a port on server A to a service on server B Server A bind:port -> Server B host:port using TCP

When a server uses a SOCKS5 route, configure the relevant program to use the proxy:

export ALL_PROXY=socks5h://127.0.0.1:1080
curl https://example.com

For a browser, configure 127.0.0.1:1080 as its SOCKS5 proxy and enable proxy-based DNS resolution when available.

Quick start

  1. Download the portable executable for your platform from GitHub Releases and run it. On Linux, mark the AppImage executable first (chmod +x).
  2. Select Add server, then enter the SSH address, user, and authentication method. For private-key authentication, PortPatch silently selects a recognized key from ~/.ssh; open Private key options only when you need another file or a passphrase. SSH Agent mode uses keys already unlocked in Windows OpenSSH Agent/Pageant, or in an ssh-agent reachable through SSH_AUTH_SOCK on Linux.
  3. Select Test connection, verify the SHA-256 host-key fingerprint, and trust it only if it is correct. PortPatch does not send a password or private key before this confirmation.
  4. Hold Ctrl and drag the node that should accept connections onto the node that should receive the traffic. Drag without Ctrl to rearrange nodes, drag the background to pan, and use the mouse wheel to zoom.
  5. Enter the two ports in the compact editor on the new edge. Open Advanced only when you need to change addresses, route type, exposure consent, or reconnection behavior.
  6. Close the window to keep routes running in the system tray. Use the tray menu, or the power-icon Quit button in the top bar, to quit completely; use the Quit button specifically if your Linux desktop does not display the tray icon (see Current limitations).

Select the ? button at any time to review the map controls.

Background tray behavior

By default, closing the window keeps active routes running. Open PortPatch again from its system tray icon, or use the tray menu to stop routes and quit the application. If the tray icon is unavailable, run the same portable executable or AppImage again to bring the existing window back.

PortPatch continues running in the system tray

The SSH server must permit the required forwarding through AllowTcpForwarding. A restrictive server may return an error such as administratively prohibited. Its GatewayPorts policy also controls the actual exposure of remotely bound ports.

The default local bind address, 127.0.0.1, accepts connections only from the same computer. Non-loopback local listeners and every remote-node listener require explicit exposure consent. An SSH server with GatewayPorts yes can expose even a requested 127.0.0.1 listener on every interface, so review the server configuration and firewall. The current SOCKS5 listener does not provide user authentication.

Development

Node.js and pnpm are required.

pnpm install
pnpm icons
pnpm test
pnpm start

Regenerate the README demos with pnpm demo and pnpm demo:tray.

Build the portable Windows executable:

pnpm dist:win

The output is written to release/PortPatch-<version>-windows-<arch>-portable.exe.

Build the Linux AppImage (must be built and tested on Linux):

pnpm install
pnpm dist:linux

The output is written to release/PortPatch-<version>-linux-<arch>.AppImage. Running the resulting AppImage, or pnpm icons/pnpm start, may fail with a setuid_sandbox_host error inside containers or sandboxes that disable unprivileged user namespaces; set ELECTRON_DISABLE_SANDBOX=1 in that case (packaging itself, i.e. pnpm dist:linux, does not need it, since it never launches Electron).

How it works

Each edge is modeled as two operations instead of an SSH command string:

  1. Open a TCP listener on the source node.
  2. For each connection, dial the target from the destination node and relay both streams.

When the source is remote, PortPatch uses SSH forwardIn. When the target is remote, it uses SSH forwardOut. The same model therefore handles conventional local and reverse forwarding as well as server-A-to-server-B routing. See the architecture document for details.

Current limitations

  • Only TCP and SOCKS5 CONNECT are supported; UDP is not supported.
  • Each server must currently be reachable directly over SSH from the computer running PortPatch. ProxyJump import is planned for a later version.
  • PortPatch relays both SSH streams for remote-to-remote routes, so the application must remain running.
  • SOCKS5 is a per-application proxy, not a VPN or transparent TUN interface for all server traffic.
  • Windows executables are not Authenticode-signed and may trigger a Microsoft Defender SmartScreen warning. PortPatch does not use a self-signed certificate because it would not establish a trusted publisher identity on another computer.
  • The Linux AppImage builds and runs, and has been confirmed working by a person on real Ubuntu 24.04/GNOME/X11 hardware, but not yet on any other distribution, KDE, or a Wayland session; see architecture.md for the underlying findings on sandboxing and tray behavior.
  • On GNOME, the system tray icon requires the "AppIndicator and KStatusNotifierItem Support" extension. It ships pre-installed on Ubuntu but is not enabled by default in every session, and is not installed at all on stock Fedora Workstation; without it, the tray icon is silently never shown. With the extension active, the icon has been confirmed to render correctly (see architecture.md). Use the top bar Quit button (or the tray menu, if visible) to fully close PortPatch either way.
  • If no Linux secret-storage backend (GNOME Keyring/libsecret or KWallet) is available, PortPatch blocks saving new passwords and key passphrases instead of using Electron's weak basic_text persistence. Install gnome-keyring (or KWallet on KDE), or use SSH Agent authentication.

About

Visual SSH port routing for desktop. Connect local and remote nodes to build TCP and SOCKS forwarding paths.

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages