Commit Graph
6 Commits
Author SHA1 Message Date
Security Fix 361b25a8bd hub: answer the local network only, whichever way a client arrives
The reported bug was the Hub being reachable from outside the local
network when Server + Desktop is active. c33457f guards the Caddy site
for sovransystemsos.local, but the Hub is an application that also
listens on a port of its own (8937), and a check in Caddy does nothing
for a client that never goes through Caddy. Whether a client could reach
the Hub depended on which door it used.

The Hub now asks the question itself. LanOnlyMiddleware is registered
outermost, so a client that is not on this computer or the local network
gets a bare 403 before authentication is considered; it never sees the
login page.

- Local means loopback, 10/8, 172.16/12, 192.168/16, 100.64/10
  (Tailscale and other CGNAT/VPN ranges) and 169.254/16 over IPv4, and
  ::1, fc00::/7 and fe80::/10 over IPv6.
- IPv6 global addresses are not on the list. A global address belonging
  to a laptop on the LAN cannot be told apart from a stranger's by the
  address alone, and 2000::/3 is every public IPv6 address there is.
- ::ffff:a.b.c.d is read as the IPv4 address inside it.
- sovran_systemsOS.hub.extraLanNetworks adds networks (IPv4 or IPv6 CIDR)
  for setups whose own devices use addresses outside those ranges. It is
  checked at build time. The app ignores an entry it cannot parse and
  refuses 0.0.0.0/0 and ::/0: it must never widen its policy by
  guessing, and "everyone" is hub.lanOnly = false, asked for by name.
- sovran_systemsOS.hub.lanOnly (default true) turns the check off.
- The first refusal from each address is logged, naming the option to
  change, so an operator whose own device is refused can find out why.
  The list is capped so a scanner cannot fill the journal or memory.

Behind Caddy the policy applies to the real client, not to Caddy: uvicorn
takes the address from X-Forwarded-For only when the peer is 127.0.0.1.

Checked, not only reviewed:
- The real app with the config.json the module really generates (nix
  eval on the nixpkgs revision flake.lock pins, read back from the
  derivation), on a real socket with the source address chosen per
  request: 127.0.0.1, 192.168/16, 100.64/10 and a declared extra
  network are served; 203.0.113.9, 8.8.4.4 and an address just outside
  the declared /28 get 403 on /login, / and /api/ping. /auto-login still
  answers 303 to loopback and 403 to everyone else.
- With c33457f's Caddy guard in front, an IPv6 client at 2001:db8::9
  passes Caddy (it is inside 2000::/3) and is refused by the Hub; an
  IPv4 stranger has the connection closed by Caddy; a LAN client is
  served.
- hub.extraLanNetworks accepts 203.0.113.0/28, 2001:db8:abcd::/48 and
  bare hosts, and fails the build for /33, 300.1.1.1/8, 0.0.0.0/0, ::/0,
  2001:db8::/129 and junk, with a message that says what to write.

Add tests/test_lan_policy.py and tests/test_hub_lan_only.py, and a note
in SECURITY.md.
2026-10-02 02:24:29 -05:00
Arena.ai Agent c33457fff2 caddy: serve the Hub, RTL and Mempool sites to local clients only
The Hub (sovransystemsos.local), Ride The Lightning (:3051) and Mempool
(:60847) sites are meant for the home network. With ports 80/443
forwarded for public services, Caddy also receives requests from other
clients, so these sites now check the client address as well as the Host
header.

A new snippet, sovran_lan_only, closes the connection unless the client
is on this computer or the local network: private_ranges, 100.64.0.0/10
(Tailscale), 169.254.0.0/16, fe80::/10 and fc00::/7. IPv6 global
addresses (2000::/3) are not filtered: computers on the network often
connect over their own global address, which cannot be told apart from
one on the internet by the address alone. Only the three local sites
import the snippet; the domain sites for public services are unchanged.

Clients with a public IPv4 address on the local network are no longer
served on these sites. The Hub is still available on port 8937.

Checked with Caddy 2.11.4 and the Caddyfile the generator writes: public
IPv4 clients get the connection closed on all three sites, local clients
are served, and the public domain sites answer as before.

Add tests/test_caddy_lan_only.py and a note in SECURITY.md.
2026-10-01 21:43:47 -05:00
Arena.ai Agent 34cfba4282 docs, hub, installer: say Server + Desktop makes the home IP public
Server + Desktop publishes services under the operator's own domain, and
the DNS record for that domain points at the home connection, so anyone
can look up the home IP address. None of the places that offer Server +
Desktop said so.

- README: new section "Server + Desktop and your home IP address" (what
  becomes public, what does not, the alternatives, and what happens
  technically), plus a note on the role table and in the security
  overview.
- SECURITY.md: a matching section, the consequence noted next to "Public
  web services exposed only when enabled by the operator", and the
  supported versions row no longer pins 1.0.x.
- ISO installer: the Server + Desktop role card ends with the warning.
- Hub: the domain setup text (onboarding, feature setup and domain
  reconfiguration share renderDomainNeedsHtml) and the upgrade dialog
  carry the same notice.
- Add tests/test_exposure_guards.py. It fails if one of these places
  loses the notice or the README anchor stops resolving.
2026-10-01 21:43:47 -05:00
Sovran Patch 362fa0b36c refactor: extract bitcoin stack into Sovran_Bitcoin flake input
Decouple the Bitcoin/Lightning modules and packages into the standalone
Sovran_Bitcoin flake, consumed as a NixOS module input.

Deleted (now in Sovran_Bitcoin):
  - modules/bitcoin/          (19 files — vendored nix-bitcoin modules)
  - modules/bitcoinecosystem.nix
  - modules/nwc-wallets.nix
  - modules/mempool.nix
  - packages/{albyhub,mempool,rtl,build-support}/
  - tests/bitcoin-btcpay-hardening.nix

Created:
  - modules/sovran-bitcoin-integration.nix — the OS-specific bridge that
    maps sovran_systemsOS.* options to sovran-bitcoin.* and applies
    Second_Drive paths, operator 'free', forced wallet, firewall 3051,
    and Sovran Hub NWC environment wiring.

Modified:
  - flake.nix — added sovran-bitcoin flake input, updated module imports
  - modules/modules.nix — removed deleted imports
  - modules/core/sovran-hub.nix — version metadata now reads from
    pkgs.sovran-bitcoin.* overlay instead of local packages/
  - tests/test_bitcoin_tor_gossip.py — updated to check integration layer

The sovran_systemsOS.* option namespace is preserved. The Hub, roles,
and custom.nix continue to work unchanged.
2026-08-31 10:17:14 -05:00
naturallaw777 f85f1a2c9f Update Documentation 2026-08-11 12:18:21 -05:00
naturallaw777 501c5abe64 docs: add SECURITY.md detailing security policy and best practices 2026-08-06 14:09:35 -05:00