Skip to main content
T

dsh-plugin-phone-access

tensaibishoujomarisa/dsh-plugin-phone-access

Reach this Harness from your phone over a private network: a loopback-preserving gateway with one-time pairing codes, plus a portrait layout for narrow screens.

Install

dsh plugin --profile web add github:tensaibishoujomarisa/dsh-plugin-phone-access

README

dsh-plugin-phone-access

Reach this Harness from your phone over a private network (Tailscale, ZeroTier, Radmin VPN, WireGuard), using one-time pairing codes instead of the launch token the desktop shell consumes for itself. A portrait layout is included for narrow screens.

dsh keeps binding 127.0.0.1. This plugin starts a small gateway on the private network addresses it discovers and rewrites Host / Origin to the loopback authority before forwarding, so the browser trust fence accepts the request without a trustedHosts edit. Removing the bundle restores the previous state.

Before you install: you need a private network

This plugin does not provide one; it opens a pairable door on a network you already have. Tailscale is the only channel it uses by default.

  1. Install Tailscale on the PC (https://tailscale.com/download) and sign in.
  2. Install Tailscale on the phone. No Play Store needed: Tailscale publishes official APKs at https://pkgs.tailscale.com/stable/#android (tailscale-android-universal-<version>.apk, with a .sha256 beside it). Android 8+.
  3. Sign in on the phone with the same account, then turn its switch on.
  4. Both devices should now appear in the Tailscale admin console.

Other overlays (ZeroTier, WireGuard, Radmin VPN) and the plain LAN work too — set scope to private or all; the adapter classifier matches by type, so it will not bind the LAN by accident.

Install

dsh plugin --profile <name> add dsh-plugin-phone-access

Restart the app; a round phone button appears at the bottom right.

First run, five steps

  1. Click the round button.
  2. Read the state it reports:
    • "installed but not connected" → turn the Tailscale switch on. No Harness restart needed; it binds within 30 seconds.
    • "no Tailscale adapter found" → Tailscale is not installed or not signed in.
    • an address is listed → continue.
  3. On the phone, open http://100.x.y.z:19387 from the panel (bookmark it).
  4. Enter the 6-digit pairing code shown on the desktop.
  5. Keep using the same entry point (that bookmark or its home-screen shortcut). That device then stays signed in for 30 days.

Things to know

  1. The PC must not sleep. powercfg /change standby-timeout-ac 0; laptops also powercfg /change standby-timeout-dc 0. A sleeping PC shows only a spinner.
  2. Turning Tailscale off is persistent. tailscale down survives reboots; the panel will say "installed but not connected" until you switch it back on.
  3. Login is per browser context. Pairing in one browser does not carry to another browser or to an in-app webview; each needs its own pairing.
  4. The cookie expires 30 days after pairing, not 30 days after last use.
  5. Clearing browser data or private mode means pairing again.
  6. Phones drop the tunnel when idle. Exempt Tailscale from battery optimisation, or enable "always-on VPN".
  7. Reaching the port means running shell commands on that PC. Do not share the address or the code.
  8. Changing port invalidates the phone bookmark.
  9. Restarting Harness does not break paired devices (the signing secret is persistent).

Security

  • The gateway binds private-network addresses only.
  • Pairing codes are 6 digits, valid 15 minutes, single use, with an 8-attempt lockout. They are shown only on the desktop and in $DSH_HOME/dsh-phone-access.json (mode 600).
  • /pair is answered by the gateway itself, so a stale session cookie can never turn a code submission into a proxied failure.
  • trustedHosts is never modified.
  • Plain HTTP: the overlay network already provides encryption. Nobody's dsh transport is downgraded by this plugin.
  • Anyone who can reach the port can run shell commands through this Harness.

See README.zh.md for the full Chinese documentation, configuration table, and troubleshooting.

Development

verify.mjs runs 63 checks against a live local dsh (it probes 127.0.0.1:19387 and exercises the gateway end to end):

node verify.mjs

It covers the manifest (including a BOM guard), the Host/Origin rewrite that makes the browser trust fence accept a non-loopback origin, the pairing gateway's routing and three refusal reasons, the stale-cookie path, the Host-only status route, the WebSocket upgrade, the portrait layer's CSS scope and click behaviour, and the client module's registration shape. Set DSH_VERIFY_UPSTREAM_PORT if your dsh listens elsewhere.

The package ships no build step: index.js and client.js are the sources.

Related plugins