Foreword

DSH’s web process binds only to 127.0.0.1 by default, and its Host trust fence for /api returns 403 for all requests from non-loopback sources (to prevent DNS-rebinding / cross-origin). Access exposed through an frp tunnel is therefore blocked. DSH itself does not provide a login/password layer for public visitors. Enabling --trusted-host directly only “creates a gap in the fence for public IPs”; it is not authentication.

The dsh-web-auth plugin merges the fence and authentication into a proper architecture: it is a loopback reverse proxy running inside the DSH web process, providing token login and session management for DSH Web exposed via frp/tunnels.

Plugin Introduction

dsh-web-auth is the public authentication gate for DSH Web. The plugin runs inside the DSH process, forwards requests to the local DSH Web by reverse proxy, and handles Token login and HttpOnly session Cookies.

Core Features

  • Reverse proxy to DSH Web
  • Token login authentication
  • HttpOnly session Cookies (12 hours by default, with sliding renewal)
  • Supports the X-DSH-Auth header, allowing scripts or tools to access without Cookies
  • WebSocket pass-through
  • Rate limiting for consecutive failures from the same source IP (10 failures trigger a 10-minute limit)

Installation and Enablement

Install the repository into a specified profile using the plugin command:

dsh plugin --profile web add <git repository URL>

After installation, you need to add dsh-web-auth to dsh.profile.bundles in the profile’s package.json:

"dsh": {
  "profile": {
    "bundles": [
      "@deepseek-ai/dsh-base",
      "@deepseek-ai/dsh-web-app",
      "dsh-web-auth"
    ]
  }
}

Then generate the token file:

openssl rand -hex 32 > ~/.dsh/web-auth-token

Configuration and Behavior

The plugin provides a rich set of configuration options, all of which are optional:

key Default Description
gateHost 127.0.0.1 Bind address for the gate
gatePort 3081 Listening port for the gate (frpc should point here)
targetHost 127.0.0.1 Address of DSH web
targetPort 3080 Fallback port for DSH web (at runtime, webServer.port takes precedence)
token — Directly inline the token
tokenFile web-auth-token Token file name (relative to $DSH_HOME) or absolute path
sessionTtlMinutes 720 Session cookie lifetime (minutes, with sliding renewal)
maxFails 10 Number of consecutive failures from the same source IP that triggers rate limiting
failWindowMs 600000 Rate limiting window (milliseconds)

The request flow is as follows:

public internet → frp tunnel → 127.0.0.1:3081 (gate, token login) → 127.0.0.1:3080 (DSH web, Host=loopback → gate allows the request)

The specific behavior is as follows:

  • Unauthenticated browser GET page: 302 redirect to the /__dsh-auth__/login login page.
  • Unauthenticated access to /api, static assets, or WebSocket upgrade: returns 401.
  • Login page POST /__dsh-auth__/login (with a token field, JSON or urlencoded): on success, issues an HttpOnly session Cookie and 302 redirects back to the original path.
  • Request includes X-DSH-Auth: <token> header: allows cookieless access.
  • POST /__dsh-auth__/logout: clears the Cookie.
  • 10 consecutive failures from the same source IP: triggers a 10-minute rate limit.

Use Cases and Notes

  • Zero external dependencies: uses only Node.js built-in modules; requires Node.js >= 18.
  • Fail Closed mechanism: if the token cannot be found, the gate does not start and the public entry point is unavailable, but the DSH core is not affected.
  • Deployment dependency: must be used with frpc so that the localPort for dsh-web points to gatePort (3081).

Ecosystem Background

The DeepSeek Harness (DSH) philosophy is “everything is a plugin.” This plugin is maintained by ChinaBoy0618 under the MIT license. For more details, visit the plugin directory or the GitHub repository.