π¦ @goodandready/dsh-lanmode
August 31, 2026 Β· View on GitHub
Local Area Network (LAN) Access Enabler, Secure Context Shims, Direct Bridge & Auto-TLS for DeepSeek Harness
π¬π§ English β’ π·πΊ Π ΡΡΡΠΊΠΈΠΉ β’ π¨π³ δΈζθ―΄ζ
β‘ Why DSH Fails Over Local Network (LAN)
By default, modern web browsers and the DeepSeek Harness frontend deliberately restrict access when opened from non-localhost IP addresses (e.g. 192.168.x.x or 10.x.x.x) over plain HTTP:
- π Locked Settings & Models Tabs: The Web UI evaluates the hostname via
isLoopbackHostname. If accessed over LAN, the settings service falls back to in-memory mode: all plugin configuration cards render empty, section states become"unavailable", mutations are discarded before transmission, and the Models page displays "settings are unavailable in this browser". - π₯ Fatal UUID Generation Crash:
crypto.randomUUID()only exists in browser Secure Contexts (HTTPS or localhost). On plain HTTP across LAN, file uploads, tool calls, and session initializations crash instantly. - π Broken Clipboard Copying:
navigator.clipboardis completely disabled by browsers on non-secure origins, breaking all code snippet "Copy" buttons. - ποΈ Microphone & Voice Input Blockade: Browser security engines block
navigator.mediaDevices.getUserMediaon plain HTTP, making voice input viadsh-voiceimpossible on remote mobile phones and tablets. - π‘οΈ Loopback-Only Core API Fencing: Core DSH methods (
/api/settings.*,/api/credentials.*,/api/models.*) strictly reject requests not originating from loopback127.0.0.1.
dsh-lanmode completely resolves all these limitations through non-invasive webServer.tapIndex HTML shims, a smart direct bridge, and auto-generated local TLS certificates.
graph LR
subgraph RemoteDevices [LAN Clients: Phone / Tablet / Laptop]
Client[π± Mobile Safari / π» Remote Laptop: 192.168.1.50] -->|HTTP / LAN HTTPS| Bridge[dsh-lanmode Smart Direct Bridge]
end
subgraph ShimsLayer [tapIndex Injected Client Shims]
Bridge --> Shim1[π Loopback Hostname Bypass: Unlocks Settings & Models]
Bridge --> Shim2[π RFC 4122 crypto.randomUUID Polyfill]
Bridge --> Shim3[π Fallback navigator.clipboard Polyfill]
Bridge --> Shim4[π Auto-TLS: Unlocks WebRTC Microphone for dsh-voice]
end
subgraph HostBackend [DSH Host Core]
Bridge --> HeaderRewrite[Loopback Host/Origin Header Rewriter]
HeaderRewrite --> PrivilegedAPI[Core Settings, Credentials & Models API]
end
subgraph Output [Result]
Shim1 --> FullWeb[β
100% Fully Functional Web UI Across Entire LAN]
Shim2 --> FullWeb
Shim3 --> FullWeb
Shim4 --> FullWeb
PrivilegedAPI --> FullWeb
end
style RemoteDevices fill:#1e1e2e,stroke:#89b4fa,stroke-width:2px,color:#cdd6f4
style ShimsLayer fill:#181825,stroke:#cba6f7,stroke-width:2px,color:#cdd6f4
style HostBackend fill:#11111b,stroke:#a6e3a1,stroke-width:2px,color:#cdd6f4
style Output fill:#181825,stroke:#f38ba8,stroke-width:2px,color:#cdd6f4
β¨ Full Feature Breakdown
1. π Settings & Models Tab Unlocking (lib/shim.js & lib/loopback-source.js)
- Dynamically patches the
isLoopbackclient evaluation on-the-fly insideindex.htmland the JS bundle without modifying core files on disk. - Preserves Real Network Topology: While settings are unlocked for editing, the plugin retains real client origin awareness so file path links are opened on the correct machine (server vs client).
2. π RFC 4122 v4 crypto.randomUUID() Polyfill
- Injects a cryptographically sound UUID generator using
getRandomValues(or fallback pseudo-random generator) when running on plain HTTP, eliminating crashes during file uploads and turn submissions.
3. π Clipboard Copy Fallback
- Injects a seamless fallback using hidden
textareaanddocument.execCommand('copy')so code block copy buttons work flawlessly on mobile browsers without HTTPS.
4. ποΈ Three Operating Modes (lib/mode.js)
direct(Direct Listener): Binds a dedicated port on0.0.0.0, accepts LAN connections, and proxies traffic to the local loopback harness while rewriting headers.proxy(Reverse Proxy Mode): For setups already behind Nginx, Caddy, or Traefik. Does not open extra ports; only injects client shims viawebServer.tapIndex.auto(Smart TCP Auto-Detection): Performs a non-blocking TCP socket knock on startup. If an existing proxy is already serving the port, it operates inproxymode; otherwise, it safely spins up the direct bridge listener.
5. π Auto-Generated Self-Signed TLS for Microphone (lib/tls.js)
- Browsers strictly forbid microphone access (
getUserMedia) on plain HTTP. dsh-lanmodeuses the system'sopensslto generate a local X.509 certificate (valid for 397 days, automatically renewed 30 days before expiration), upgrading LAN connections to HTTPS so voice input viadsh-voiceworks on iPhones, iPads, and Android devices.
6. π‘οΈ CIDR Subnet Filtering & Privileged Protection (lib/access.js, lib/privileged.js, lib/handoff.js)
- CIDR Subnet Filtering: Restrict LAN access to specific IP ranges (e.g.
allowSubnets: ["192.168.1.0/24", "10.0.0.0/8"]). - Privileged API Guard: Controls whether remote clients can mutate credentials and server settings (
allowPrivileged: true/false). - Pairing Handoff Tokens: Secure token-based handshake for new devices.
7. π©Ί Diagnostics & Health Dashboard (lib/health.js)
- Access
GET /dsh-lanmode/healthto view an in-depth diagnostic JSON report:- Operating mode (
directvsproxy); - Network interfaces and bound IP addresses;
- Active shims and TLS certificate expiration status;
- Allowed subnets and privileged route status.
- Operating mode (
8. π URL Query Debugging Switches
?lanmode=offβ Disables all shims completely (reproduces stock locked behavior).?lanmode=invertβ Simulates an external network context directly on localhost for testing.
π¦ Quick Installation
dsh plugin --profile web add @goodandready/dsh-lanmode
Important
Restart DSH Web UI after installation (systemctl --user restart dsh-web) and reload your browser tab.
βοΈ Configuration Reference (settings.yaml)
dsh-lanmode:
enabled: true
mode: auto # 'auto', 'direct', or 'proxy'
directBridge:
enabled: true
port: 3000
host: 0.0.0.0
allowSubnets:
- 192.168.0.0/16
- 10.0.0.0/8
- 127.0.0.1/32
enableTls: false # Enable for HTTPS microphone access
allowPrivileged: true # Allows settings/credentials mutation from LAN
shimLoopback: true
shimRandomUuid: true
shimClipboard: true
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | auto | Operating mode: auto (detect proxy), direct (own listener), or proxy |
directBridge.port | number | 3000 | Port for the direct LAN bridge listener |
allowSubnets | string[] | ["0.0.0.0/0"] | Allowed CIDR IP ranges permitted to connect |
enableTls | boolean | false | Automatically generates local self-signed TLS cert for HTTPS |
allowPrivileged | boolean | true | Permits remote LAN clients to modify settings and API keys |
shimLoopback | boolean | true | Unlocks Settings and Models tabs on non-localhost origins |
shimRandomUuid | boolean | true | Injects RFC 4122 v4 crypto.randomUUID() polyfill |
shimClipboard | boolean | true | Injects navigator.clipboard fallback copy handler |
π License
MIT Β© GooDAnDReaDY