Skip to content

When using Tailscale/remote access into the webtop, the Hermes dashboard cannot be reached. Agent recommends a Nginx fix #46

Description

@weechcwc

SKILL: dashboard-remote-proxy

Trigger: Use when the dashboard service (bound to loopback) rejects remote access (e.g., via Tailscale/VPN) with a 400 Invalid Host header error.

Goal: Allow secure, authenticated-proxy access to a locally-bound dashboard service without compromising the dashboard's internal Host header security checks.

Rationale
The dashboard service implements a security check for the Host header to prevent DNS rebinding or unauthorized cross-origin requests. It strictly validates that incoming requests use a trusted hostname (usually localhost or 127.0.0.1).

When a user accesses the dashboard via a remote IP (e.g., 100.x.x.x:9119), the browser sends Host: 100.x.x.x, causing the dashboard to reject the request with 400 Invalid Host header.

Instead of disabling the dashboard's internal security, we introduce a lightweight Nginx reverse proxy layer that intercepts the request and rewrites the header to localhost before forwarding it to the dashboard.

Implementation (Nginx)

The following configuration should be placed in /etc/nginx/conf.d/dashboard.conf:

nginx
server {
listen 9119;
server_name _;

location / {
    # Proxy to the dashboard service on loopback
    proxy_pass http://127.0.0.1:9009;

    # CRITICAL: Rewrite Host header to satisfy dashboard security check
    proxy_set_header Host localhost;

    # Forward real client info for logging/audit
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    # Pass through WebSockets
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

}

Verification Protocol
To verify the fix works as intended, execute the following from the host:

  1. Test Direct Loopback:
    curl -I http://127.0.0.1:9119/
    Expected: HTTP 200 OK

  2. Test Spoofed Host (Remote Access Simulation):
    curl -I -H "Host: 100.92.9.40" http://127.0.0.1:9119/
    Expected: HTTP 200 OK (The Nginx proxy correctly rewrites the header, masking the spoofed Host)

Pitfalls & Notes

  • Avoid Socat: Do not use socat for this bridge. socat performs a raw stream forward and cannot modify HTTP headers. Nginx is required for the proxy_set_header manipulation.
  • WebSocket Compatibility: If the dashboard relies on WebSockets, ensure the proxy passes the Upgrade and Connection headers (as shown in the config snippet above).
  • Security: This implementation relies on the dashboard process itself to handle authentication for the incoming request, even if the proxy itself is open on the port.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions