block / block/buzz

NIP-98 auth validates the signed URL against a single base address — blocks serving a relay on more than one hostname

Open
#4,953 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

### Environment

- Self-hosted relay via `deploy/compose`, `compose.caddy.yml` with Caddy terminating TLS in front of the relay
- Relay image `ghcr.io/block/buzz:sha-318fbf8`

### Summary

NIP-98 HTTP Auth validation appears to compare the signed request URL against a single configured base address. That makes it impossible to serve one relay over more than one address, even when routing is otherwise working.

### Reproduction

1. Bring up a relay whose configured address is an internal one (e.g. a private network address).
2. Put it behind a reverse proxy on a public hostname, rewriting `Host` so community routing resolves (see the separate issue about community host binding).
3. Unauthenticated endpoints now work over the public hostname — `/` and `/_readiness` both return 200.
4. Any authenticated call fails, **including from a valid roster member**:

```
HTTP 401
NIP-98: NIP-98 HTTP Auth verification failed: URL mismatch:
event has `https://public.example.com/query`,
expected `http://10.0.0.1:3001/query`
```

The same member, same key, works normally against the internal address. A fresh non-member key correctly gets `403 relay_membership_required` on the internal path, so membership enforcement itself is fine.

### Why a proxy-level fix does not work

NIP-98 signs the full request URL client-side. Rewriting `Host` at the proxy cannot change a signature that was already computed, so the mismatch is structural rather than a misconfiguration — the proxy can make routing agree, but not auth.

### Question / proposal

`.env.example` suggests `BUZZ_DOMAIN`, `RELAY_URL` and `BUZZ_MEDIA_BASE_URL` are all meant to derive from one public hostname, and I could not find a separate "bind host" vs "public base URL" concept.

Would you accept a PR adding an **allow-list of acceptable base URLs** for NIP-98 verification (env-configurable, defaulting to current behaviour)? That would let a relay serve an internal and a public address simultaneously without weakening validation — the signature still has to match one of the explicitly configured origins.

If there is already an intended way to do this, I would rather use that. Happy to test a patch either way.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.