Foreword¶
DeepSeek Harness (DSH) web service listens only on the localhost loopback address by default and strictly validates the Host and Origin headers: only requests from 127.0.0.1 can invoke privileged interfaces like settings.*, credentials.*, and host.listDirectory. While the page can be opened, these interfaces return 403.
Common approaches involve using SSH port forwarding, Caddy, frp, ngrok, or Cloudflare Tunnel to expose the web UI to the public network or LAN. After passing through a generic tunnel, the hostname in the request headers changes to a public domain, causing Harness’s trust checks to fail. Some solutions only add password authentication without rewriting headers, leaving privileged APIs still inaccessible; some LAN plugins lack authentication and are unsuitable for public exposure.
This article introduces dsh-full-remote: a reverse proxy with token authentication inserted between the tunnel and Harness web service. It rewrites Host/Origin to the loopback address while replacing Harness’s original trust checks with an independent access control layer.
What Is This¶
dsh-full-remote is a plugin for DeepSeek Harness, maintained by JUANWANG-BUAA, and listed in awesome-dsh-plugin. The npm package name is also dsh-full-remote, current version 0.3.8, licensed under MIT, and requires Node.js ^22.19 or >=24.
The plugin starts a reverse proxy (default 127.0.0.1:3081) in front of the Harness web service (default 127.0.0.1:3080). After remote browsers connect to the proxy via a tunnel, the proxy validates access tokens or device sessions, rewrites request headers, and forwards HTTP, SSE, and WebSocket traffic, enabling privileged APIs like settings, credentials, and directory browsing to function properly in remote scenarios.
What Problem Does It Solve¶
| Approach | Result |
|---|---|
Generic tunnels (SSH forwarding, Caddy, binding to 0.0.0.0) |
Page loads; settings.* / credentials.* / host.listDirectory return 403 |
| Unauthenticated LAN plugins | Available on LAN; unsuitable for public exposure |
| Password-only authentication without header rewriting | Request authenticated, but privileged API still blocked |
dsh-full-remote works by rewriting Host and Origin to 127.0.0.1 before forwarding, allowing Harness’s trust checks to pass. Since rewriting bypasses Harness’s original remote client checks, the plugin establishes its own access control layer using tokens, device sessions, optional approval, and audit logs.
Core Features¶
Privileged APIs Remain Accessible¶
After proxy forwarding, the following interfaces are no longer blocked by 403 errors during remote access:
settings.describe/update/replace/mutatecredentials.describe/set/unsethost.listDirectory/pickDirectory/openPathagentPreset.*,llm.discoverModels
Access Control¶
- Access Token: 192-bit token stored in a state file with mode
0600; viewable and rotatable in the local panel. - Per-device Sessions: Each login creates independent device credentials with only hashes persisted; the panel allows renaming, revoking devices, and displays login IPs and recent access IPs.
- First-Access Approval (Optional): New devices wait on the page and require approval from the local panel to proceed.
- Mobile Invitations: Connect via QR codes or one-time links (single-use, 15-minute expiration); links do not contain long-term tokens. Retries from the same IP browser within 60 seconds reuse the original device session, avoiding duplicate logins due to tunnel instability.
- Login Protection: Fixed delay and IP-based lockout on failed logins; optional CIDR allowlist to restrict remote IPs.
- Forwarded IP Recognition: Optional
trustForwardedForextracts the real client IP from the rightmost value ofX-Forwarded-Forfrom trusted local tunnels;CF-Connecting-IPis a Cloudflare-specific option.
Operations & Audit¶
- Fence Self-Check: Probes
settings.describeusing the same Host/Origin rewriting as the proxy to confirm the proxy chain is operational. - JSONL Audit Logs: Records events such as logins, approvals, revocations, token rotations, start/stop, and WebSocket open/reject; the panel allows viewing recent events and exporting JSON; logs auto-rotate after 8 MB, retaining one history generation.
- Protocol Support: Forwards HTTP, SSE, and WebSocket; compressible HTTP responses (HTML/JS/CSS/JSON/SVG, ≥1 KB) support gzip; SSE and WebSocket are not compressed.
- Other: Runtime-adjustable listen address with auto-rollback on binding failure; optional local TLS (
tlsCertFile/tlsKeyFile); health check endpoint/_dsh_reverse_proxy/healthz; WebSocket upgrade failures rate-limited by IP.
Optional Cloudflare Quick Tunnel¶
The plugin can temporarily start a Cloudflare quick tunnel, generating a QR code for mobile scanning. Existing SSH, frp, ngrok, Tailscale, or cloudflared tunnels can also point to the proxy target address displayed in the panel. Quick tunnels are optional and temporary, not a hosted production deployment solution.
Installation & Enablement¶
Install and start under the DSH web profile:
dsh plugin --profile web add dsh-full-remote
dsh --profile web
After installation, open the Settings → Reverse proxy panel to manage the proxy.
Typical Usage¶
Quick Remote Access¶
- In Settings → Reverse proxy, click Start proxy to launch the reverse proxy.
- Click Start Cloudflare quick tunnel and scan the generated QR code. The invitation link is one-time and does not contain a long-term access token.
- After entering the token or completing device approval on the mobile or remote browser, the full web UI becomes usable, including settings, credentials, and directory operations.
Using Existing Tunnels¶
In controlled networks, Cloudflare quick tunnels are unnecessary. Simply point SSH, frp, ngrok, Tailscale, or cloudflared tunnels to the local proxy address displayed in the panel (default 127.0.0.1:3081).
Request Flow¶
flowchart LR
A[Mobile or Remote Browser] --> B[Public Tunnel<br>cloudflared / ngrok / frp / SSH]
B --> C[dsh-full-remote<br>127.0.0.1:3081<br>Authentication + Header Rewriting]
C --> D[DeepSeek Harness Web<br>127.0.0.1:3080]
- The remote browser connects to the plugin listener via a public tunnel.
- Requests must carry an access token, a valid one-time invitation, or an existing device session; unauthenticated requests never reach the backend.
- The proxy rewrites
Host/Originto the loopback address, removes untrusted headers, and forwards to the Harness web service.
Use Cases & Considerations¶
Who Is This For
- Users needing to remotely operate DSH web UI from a mobile phone or another device, with access to privileged functions like settings, credentials, and directory browsing.
- Those with existing SSH, frp, ngrok, Tailscale, or other tunnels who want to enable remote access without modifying Harness source code.
- Environments requiring per-device session management, login event auditing, or manual approval for first-time access.
Precautions Before Use
- The plugin runs with the permissions of the current
dshprocess. Before installation, review the source code and SECURITY.md to understand the security model. - Before exposing the listener to the public network, configure tokens, device approval, or CIDR allowlists; quick tunnels are for temporary debugging only, not production deployment.
- Header rewriting replaces Harness’s original remote trust checks; access control relies entirely on the plugin’s authentication layer.
- For compatibility with other DSH plugins, refer to compatibility.md in the repository.
Links¶
- SkillHub Directory: dsh-full-remote
- GitHub Repository: JUANWANG-BUAA/dsh-full-remote
- npm Package: dsh-full-remote
Following these steps, dsh-full-remote condenses the remote access issue of “page loads but privileged API returns 403” into a reverse proxy solution with token gating, per-device session management, and audit logging.