Back to home@Jiachi5533

dsh-remote-gateway

Source-filtered remote gateway for DeepSeek Harness behind an authenticated reverse proxy

Stars
0
Language
JavaScript
Created
Aug 28, 2026
Updated
Aug 28, 2026
GitHub repo

Introduction

DSH Remote Gateway icon

DSH Remote Gateway

A source-filtered gateway for using DeepSeek Harness through an authenticated reverse proxy.

简体中文 · Security · Compatibility

Tests Node.js 22.19 or newer MIT License

DSH Remote Gateway secure remote access

Why

DSH intentionally keeps privileged browser capabilities on loopback. A normal reverse proxy can render the page remotely while settings, plugin bundles, WebSockets, or host directory selection still fail. This plugin provides a narrow compatibility gateway without exposing the internal DSH web server directly.

Features

  • Proxies HTTP, SSE, and WebSocket traffic.
  • Accepts requests only from explicitly listed source IP addresses.
  • Keeps the internal DSH web server bound to 127.0.0.1.
  • Rewrites the upstream Host and Origin to the internal loopback authority.
  • Strips edge authentication and forwarded-client identity headers before requests enter DSH.
  • Patches only the exact dsh-client-connection capability probe; every other plugin bundle is passed through byte-for-byte.
  • Replaces the host-native directory dialog with DSH's in-app filesystem browser, so remote users can choose a workspace on the DSH host.
  • Starts and stops with the DSH plugin lifecycle, so an existing systemd, launchd, or other DSH supervisor also supervises the gateway.

Architecture

Remote browser to loopback DSH architecture

The reverse proxy is the public security boundary. It must provide TLS and authentication. The gateway's source allowlist is defense in depth, not user authentication.

Install

Requirements:

  • DSH web profile
  • Node.js 22.19 or newer
  • A reverse proxy that supports WebSocket forwarding and authentication

Install from GitHub:

dsh plugin --profile web add github:Jiachi5533/dsh-remote-gateway

Then edit the generated remote-gateway entry in ~/.dsh/profiles/web/cordis.patch.yml:

- id: remote-gateway
  name: '@jiachi/dsh-remote-gateway'
  config:
    host: 0.0.0.0
    port: 3080
    allowedSources:
      - 192.0.2.10 # exact LAN address of the reverse proxy
      - 127.0.0.1  # optional local health checks

Restart the DSH web process after the first installation. Configure the reverse proxy to send HTTP and WebSocket traffic to http://DSH_HOST_LAN_IP:3080, and enable HTTPS plus authentication at that proxy.

Never expose port 3080 directly to the internet. Do not add broad network ranges to allowedSources; the current implementation accepts exact IP addresses only.

Configuration

OptionDefaultDescription
host0.0.0.0Gateway listen address.
port3080Gateway listen port. Use 0 only in tests.
allowedSources['127.0.0.1']Exact IPv4 or IPv6 source addresses allowed to connect.

IPv4-mapped addresses are canonicalized, and IPv6 loopback ::1 is treated as 127.0.0.1. The upstream host and port are obtained from DSH itself and cannot be redirected through plugin configuration. Startup fails if the internal DSH web server is not bound to 127.0.0.1.

Allowlisted monitoring systems can check GET /_dsh-remote-gateway/health. It returns 200 ok without contacting the DSH upstream, so it verifies the gateway process and source policy rather than DSH readiness.

Security model

  • TLS and user authentication terminate at your reverse proxy.
  • Only the reverse proxy's LAN address should be allowed at the gateway.
  • The internal DSH web server stays loopback-only.
  • Authorization, Proxy-Authorization, Forwarded, X-Forwarded-*, and X-Real-IP are removed before proxying upstream.
  • A source-IP allowlist does not protect against a compromised reverse proxy or another device that can use the same source address.
  • DSH plugins execute with the DSH process permissions. Review every third-party plugin before installation.

See SECURITY.md for reporting and operational guidance.

Compatibility

ComponentStatus
DSH 0.1.1-rc.2Verified on 2026-08-28
HTTP and SSEVerified
WebSocket upgradeVerified
Settings APIVerified
In-app host directory browserVerified
Existing and future standard Host/Client bundlesPassed through unchanged, except the exact connection module path

The connection compatibility patch is deliberately fail-closed. If a DSH update changes the expected probe, that module returns 502 with an explicit log message instead of silently loading a partly broken remote UI.

Most well-behaved plugins continue to work because their client assets and same-origin requests are transparently forwarded. A plugin may still need its own remote adaptation if it hard-codes localhost, opens a native host dialog, or independently rejects non-loopback browser locations.

Upgrade and removal

Update by re-adding the GitHub source from dsh-market or the CLI, then restart DSH:

dsh plugin --profile web add github:Jiachi5533/dsh-remote-gateway

Remove it with:

dsh plugin --profile web remove @jiachi/dsh-remote-gateway

After removal, delete any remaining remote-gateway, directory-picker-browse, and ui-directory-picker-browse rows that were added by this plugin from the profile patch, then restart DSH.

Troubleshooting

  • 403 forbidden: the TCP source address is not present in allowedSources. Add the reverse proxy's LAN IP, not the remote browser's public IP.
  • 502 ... compatibility probe matched 0 times: the installed DSH client connection module changed. Pin a verified DSH version or open an issue with both version numbers.
  • Page loads but WebSocket fails: enable WebSocket upgrade forwarding in the reverse proxy.
  • Native folder dialog appears: confirm both browse picker rows in cordis.patch.yml are enabled and the native directory-picker row is disabled.
  • New UI plugin is missing: restart DSH after installing the plugin, then hard-refresh the browser.

Development

npm test

The test suite covers source filtering, IPv4-mapped addresses, trust-header rewriting, fail-closed module patching, and byte-preserving proxy behavior for unrelated plugin bundles.

License

MIT