From fa4cf9ea8d3e145d585f1c8ca5705f4615fb0769 Mon Sep 17 00:00:00 2001 From: Kiko Date: Thu, 5 Nov 2026 00:37:46 +0000 Subject: [PATCH 1/2] Add docs/remote-access.md: Tailscale and Headscale options (untested) Co-Authored-By: Claude Sonnet 5.5 --- docs/remote-access.md | 179 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 docs/remote-access.md diff --git a/docs/remote-access.md b/docs/remote-access.md new file mode 100644 index 0000000..5fe8f43 --- /dev/null +++ b/docs/remote-access.md @@ -0,0 +1,179 @@ +# Remote access: iPad to a Sunshine host on restrictive wifi + +**Status: planning document. Every step below is untested.** Nothing here has been run +against the real host, iPad, or network. Doc claims are cited; anything not found in the +cited docs is marked *unverified*. Nothing in this repo changes: this is a design note. + +## Problem + +Moonlight (this client) streams from a Sunshine host (called **Raven** here) over several +TCP and UDP ports. The target situation is an iPad on managed wifi that blocks those +ports, with no mobile data fallback. The usual escape is an overlay VPN whose traffic +looks like ordinary HTTPS. Only outbound TCP 443 is assumed to work. + +Sunshine's base port is 47989 and other ports are offset from it +([Sunshine configuration](https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2configuration.html)). +That page does not list the offsets; read the exact list from Sunshine's config UI. Pairing +uses the Sunshine web UI (default `https://:47990`, PIN page) +([Sunshine getting started](https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2getting__started.html)). +The web UI is LAN-only by default (`origin_web_ui_allowed: lan`); a tailnet address is not +the LAN, so pairing may need that setting changed or must be done on the LAN first. +*Unverified: whether tailnet source addresses count as `lan`.* + +## What the overlay must carry + +Moonlight video/audio/input are UDP. Tailscale and Headscale carry arbitrary IP inside +WireGuard, so UDP flows unchanged. When no direct path exists, the WireGuard packets +travel inside a TCP/HTTPS connection to a DERP relay. + +## Option A: Tailscale (hosted control plane, Tailscale DERP) + +### How it behaves on a 443-only network + +- Outbound requirements: TCP 443 for coordination and DERP; UDP 41641 and UDP 3478 only + improve direct connections. If only 443 is allowed, "connectivity still works" via + relays, but not as fast as peer-to-peer + ([Tailscale firewall ports](https://tailscale.com/kb/1082/firewall-ports)). +- Every connection starts relayed and then tries to upgrade to direct; DERP is the + fallback when direct fails. Relayed traffic is end-to-end WireGuard encrypted + ([connection types](https://tailscale.com/kb/1257/connection-types)). +- Tailscale warns DERP has limited quality of service and lower throughput. Its sample + `tailscale ping` output shows DERP at roughly 40 to 280 ms. Those are examples, not + predictions for this site. + +### Steps (all untested) + +1. Create or identify the tailnet and its owner (see Open Questions). +2. Install Tailscale on Raven; sign in to that tailnet. +3. Install the Tailscale iOS app on the iPad; sign in to the same tailnet. *Unverified: + whether the managed iPad's profile permits installing a VPN app or creating a VPN + configuration. This is the first likely blocker.* +4. In the Tailscale admin console or `tailscale status` on Raven, note Raven's tailnet IP + (`100.x.y.z`) or MagicDNS name. +5. On the LAN beforehand if possible, pair Moonlight with Raven normally. If pairing over + the tailnet: in Moonlight, add the host manually by tailnet IP; enter the PIN in + Sunshine's web UI. +6. Start a stream over the tailnet; check with `tailscale ping raven` (on any tailnet + device) whether the path is `direct` or `via DERP(...)`. +7. If relayed and unplayable, lower Moonlight resolution, FPS and bitrate first. + +### Latency limits when relayed + +Relayed means TCP-in-the-middle for UDP-like traffic: head-of-line blocking on loss, an +extra round trip through the nearest DERP region, and a throughput ceiling. Expect +playable desktop and slow-paced use, not guaranteed competitive-game latency. *No +measurement exists for this site; measure with `tailscale ping` and a trial stream.* + +## Option B: self-hosted Headscale on Yggdrasil behind 443 + +Headscale is an open-source reimplementation of the Tailscale control server; the +official Tailscale iOS app can point at it +([Apple clients](https://headscale.net/stable/usage/connect/apple/): account menu, +"Use custom coordination server", enter the `https://` URL). + +### Needs Eureka's approval first + +Nothing below is done until Eureka approves each item: + +- A new public hostname and DNS record for the control server. +- A public TLS certificate for it, and where TLS terminates. +- A new daemon (Headscale) on Yggdrasil and who deploys and survives it (Idunn + authority applies; this doc does not choose). +- Public exposure of 443 for this hostname, and possibly UDP 3478 (see below). +- A relay choice: reuse Tailscale's public DERP map (the iPad still reaches Tailscale's + relays on 443), or run Headscale's embedded DERP. +- Who may register nodes, and key expiry policy. + +### Minimal configuration shape (untested; read the example config for your release tag +before use, per [config docs](https://headscale.net/stable/ref/configuration/)) + +- `server_url`: the public `https://` hostname on 443. +- `listen_addr`: loopback or internal only; reverse proxy in front. +- TLS cert/key paths left empty when a proxy terminates TLS (Headscale then logs + `listening without TLS`, which is expected) + ([reverse proxy](https://headscale.net/stable/ref/integration/reverse-proxy/)). +- `trusted_proxies` set to the proxy address. +- A sqlite database path, a noise private key path, IP prefixes, and a DNS block as in the + shipped example config. +- `derp.urls`: keep Tailscale's default map for the first trial. Removing it makes the + embedded server a single point of failure + ([DERP](https://headscale.net/stable/ref/derp/)). +- Optional: `derp.server.enabled: true` plus `ipv4`/`ipv6`, `verify_clients: true`. + +### Proxy constraints from the docs + +- The proxy must support WebSockets: the control protocol upgrades via POST with + `Upgrade: tailscale-control-protocol`. Cloudflare proxies and Tunnels are unsupported. +- Port summary: tcp/443 public; tcp/80 only for built-in Let's Encrypt HTTP-01; udp/3478 + public if embedded DERP is enabled; tcp/50443 only for gRPC remote control; tcp/9090 + not public ([requirements](https://headscale.net/stable/setup/requirements/)). +- STUN for embedded DERP needs udp/3478, which an HTTPS reverse proxy cannot carry. On a + 443-only client network STUN is blocked anyway, so DERP-over-443 is the path that + matters. *Unverified: the docs do not say whether the embedded DERP's HTTPS endpoint + works behind a reverse proxy.* Simplest trial: leave Tailscale's DERP map in place. +- The reverse-proxy page is community maintained and may be outdated. + +### Exposure added + +One new public HTTPS hostname fronting a control plane; optionally a public relay and UDP +3478. Raven and the iPad gain no inbound ports; Sunshine ports stay on the tailnet. The +tailnet's ACLs should restrict the iPad to Raven's Moonlight ports only +(*unverified in this environment; ACL syntax differs between Headscale versions*). + +## Failure ladder + +Run top to bottom, stopping at the first success. Everything is untested. + +1. Home/LAN: confirm Moonlight streams to Raven with no overlay (baseline). +2. Tailscale on both devices at the LAN: confirm tailnet IP works, `tailscale ping` is + direct. +3. iPad on the restrictive wifi, Tailscale connected: does the app reach "Connected"? + If not: is VPN installation or profile blocked by management (stop; this is policy, + not network), or is 443 to the control plane filtered or TLS-intercepted? +4. `tailscale ping raven` from the iPad's side (use another tailnet device, or app + status): `direct` is best, `via DERP` means relay. +5. Relayed but stream stutters: lower bitrate, resolution, FPS; try H.264 over HEVC if the + iPad decoder is struggling (decode, not network, may be the limit). +6. Control plane reachable but no DERP: network may TLS-intercept or block Tailscale + domains. Option B with a hostname that is not a known Tailscale domain is the next step. +7. Wifi blocks everything but ordinary web browsing, and VPN apps are policy-blocked: + neither option works. Fall back to a browser-based path or a different network. + +## A or B + +| Question | A: Tailscale hosted | B: Headscale on Yggdrasil | +|---|---|---| +| Time to first test | Hours | Days (approvals, DNS, TLS, deploy) | +| New public exposure | None | Hostname, cert, daemon, maybe UDP 3478 | +| Works if network blocks Tailscale domains | No | Possibly (own hostname) | +| Works if network only does 443 | Yes, relayed | Yes, relayed, via Tailscale DERP or own | +| Control-plane ownership | Tailscale account holder | Eureka / GameCult | +| Latency when relayed | Tailscale DERP regions | Same, or own DERP region if run | +| Ongoing work | None | Upkeep, updates, backups | +| Recommended | Try first | Only if A fails at ladder step 3 or 6 | + +## Open Questions + +- Where does Raven sit on the network (same LAN as the iPad's home, behind carrier NAT, + behind a router that can forward ports, wired or wifi)? It decides whether direct + connections are plausible at all. +- Who holds the tailnet account for Option A (individual, org, shared), and who can add + devices and edit ACLs? +- Does the iPad's management policy allow a third-party VPN app? Nothing else matters if + not. +- Is any measurement available of latency from the restrictive network to the nearest + DERP region? +- If Option B is chosen: does Eureka want Headscale in the Yggdrasil deployment model, and + who owns it? + +## Sources + +- +- +- +- +- +- +- +- +- -- 2.47.3 From 634c72c5fbe139fc8d0aca2836c1da23d3e7c952 Mon Sep 17 00:00:00 2001 From: Kiko Date: Thu, 5 Nov 2026 10:51:02 +0000 Subject: [PATCH 2/2] docs: remote access conditions, Wireguard-only Sunshine, jailbroken iPad Co-Authored-By: Claude Sonnet 5.5 --- docs/remote-access.md | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/docs/remote-access.md b/docs/remote-access.md index 5fe8f43..723654f 100644 --- a/docs/remote-access.md +++ b/docs/remote-access.md @@ -4,6 +4,36 @@ against the real host, iPad, or network. Doc claims are cited; anything not found in the cited docs is marked *unverified*. Nothing in this repo changes: this is a design note. +## Conditions in force + +Set by Eureka (who holds the Wireguard network and Yggdrasil). They bound every option +below; an option that cannot meet them is out. + +- **Raven's Sunshine host is a yes in principle only if** it is bound to the Wireguard + interface and paired by Meta, and never exposed (no public or LAN-wide listener, no + port forward). *Untested and unverified: how to bind Sunshine to one interface. This + doc has not found a Sunshine setting for it; check the Sunshine configuration page and + the host firewall before relying on either.* +- **Minds get no access to the iPad** until Meta gives its Yggdrasil address and says yes. + Nothing here is to be run from, or opened on, Yggdrasil before that. Option B below is + a design only. +- **Pairing is Meta's act**, not a Mind's. + +## Client device + +The iPad has no App Store and runs an old jailbroken iOS (Taurine). The fork reaches it +through TrollStore, not the App Store. Consequences, none of them tested: + +- Step 3 of Option A ("install the Tailscale iOS app") and the Headscale "custom + coordination server" path both assume the App Store app. *Unverified: whether any + Tailscale or Wireguard client can be installed on this iPad, and whether it runs on that + iOS version.* This is now the first likely blocker, ahead of any management profile. +- *Unverified: whether a VPN client installed via TrollStore can create a VPN + configuration on a Taurine device.* A Wireguard client on the iPad is the natural fit + for the conditions above, and it is equally untested. +- Whether this fork builds for that iOS version is a build question for the + `gamecult/ios14-build` branch, not settled here. + ## Problem Moonlight (this client) streams from a Sunshine host (called **Raven** here) over several @@ -45,7 +75,7 @@ travel inside a TCP/HTTPS connection to a DERP relay. 1. Create or identify the tailnet and its owner (see Open Questions). 2. Install Tailscale on Raven; sign in to that tailnet. -3. Install the Tailscale iOS app on the iPad; sign in to the same tailnet. *Unverified: +3. Install a Tailscale client on the iPad (no App Store there; see Client device); sign in to the same tailnet. *Unverified: whether the managed iPad's profile permits installing a VPN app or creating a VPN configuration. This is the first likely blocker.* 4. In the Tailscale admin console or `tailscale status` on Raven, note Raven's tailnet IP @@ -159,7 +189,7 @@ Run top to bottom, stopping at the first success. Everything is untested. connections are plausible at all. - Who holds the tailnet account for Option A (individual, org, shared), and who can add devices and edit ACLs? -- Does the iPad's management policy allow a third-party VPN app? Nothing else matters if +- Can any VPN client be installed on the Taurine iPad at all (App Store absent, TrollStore only)? Does its management policy allow a third-party VPN app? Nothing else matters if not. - Is any measurement available of latency from the restrictive network to the nearest DERP region? -- 2.47.3