From 01b63814441f6a20c0337bc3875978a40f45c59c Mon Sep 17 00:00:00 2001 From: holdmysocks <1349908+holdmysocks@users.noreply.github.com> Date: Fri, 2 Oct 2026 11:44:32 -0400 Subject: [PATCH] Forward UDP from the tailnet for Remote Play The console's Remote Play service uses UDP 9295, 9296, 9297 and 9302 next to TCP 9295. tsnet has no catch-all for UDP, so the daemon now listens on the ports in the new udpPorts setting (those four by default) on its tailnet addresses and relays them to localhost. The UDP relay is shared with the local forwards. --- README.md | 47 +++++++++-- docs/BUILDING.md | 2 +- docs/TECHNICAL.md | 7 ++ docs/status-page.png | Bin 56627 -> 61260 bytes probe-c/rpprobe.c | 39 +++++++++ tsd/config.go | 6 ++ tsd/inboundudp.go | 95 ++++++++++++++++++++++ tsd/inboundudp_test.go | 85 ++++++++++++++++++++ tsd/localforward.go | 146 ++------------------------------- tsd/main.go | 36 +++++++++ tsd/status.html | 1 + tsd/udprelay.go | 178 +++++++++++++++++++++++++++++++++++++++++ tsd/web.go | 8 +- 13 files changed, 502 insertions(+), 148 deletions(-) create mode 100644 probe-c/rpprobe.c create mode 100644 tsd/inboundudp.go create mode 100644 tsd/inboundudp_test.go create mode 100644 tsd/udprelay.go diff --git a/README.md b/README.md index 78a553a..1895559 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,9 @@ Puts a jailbroken PS5 on your [Tailscale](https://tailscale.com) network. - **Reach the console from anywhere.** FTP, the payload loader, web tools: whatever listens on the console is available at its tailnet address from your other Tailscale devices. +- **Remote Play over Tailscale.** Play the PS5 from anywhere with a Remote + Play client, at the console's tailnet address, with no port forwarding on + your router. - **Stream games to the console over Tailscale.** A Moonlight client on the PS5 (such as ProsperoLight) can connect to a Sunshine host on your tailnet. - **Home screen icon** that opens its status page. @@ -82,9 +85,35 @@ want, for example FTP on 2121 or the payload loader on 9021. - Every TCP port that something on the console listens on is forwarded. Ports with no listener refuse the connection. -- UDP is not forwarded in this direction. -- To keep a port off the tailnet, add it to `blockedPorts` in the - [configuration](#configuration). +- UDP ports have to be listed, in `udpPorts` in the + [configuration](#configuration). The default list is Remote Play's. +- To keep a TCP port off the tailnet, add it to `blockedPorts`. + +### Remote Play + +The console's own Remote Play service is reachable at its tailnet address, so +a Remote Play client on any of your Tailscale devices can connect from +anywhere. Any client that lets you enter the console's address works. + +1. On the console, enable Remote Play (Settings > System > Remote Play). +2. Register your Remote Play client with the console as usual. This is + easiest at home on the same network; see the client's documentation. +3. In the client, add the console manually with its **tailnet address** + (shown on the status page). +4. Connect. + +Tested and working with Chiaki, and with Asobi on iOS and Android. + +How it works: Remote Play uses TCP 9295 and UDP 9295, 9296, 9297 and 9302. +The TCP port is forwarded like any other; the daemon listens on the UDP +ports on the console's tailnet addresses and relays them to the service. + +Notes: + +- The video passes through the daemon, which runs at the lowest priority so + that it never takes time from a game. Under a demanding game that may show + as stutter. +- Waking the console from rest mode does not work: nothing is running then. ### The status page @@ -159,6 +188,7 @@ optional. Restart Tailscale (send the payload again) to apply edits. "forwards": [ {"proto": "tcp", "listen": "127.0.0.1:8096", "target": "my-nas:8096"} ], + "udpPorts": [9295, 9296, 9297, 9302], "blockedPorts": [], "verbose": false } @@ -173,6 +203,7 @@ optional. Restart Tailscale (send the payload again) to apply edits. | `controlURL` | A coordination server other than Tailscale's. | | `sunshineHost` | The Sunshine host; set from the status page. | | `forwards` | Extra local forwards: `proto` is `tcp` or `udp`, `listen` a localhost address, `target` a tailnet host and port. | +| `udpPorts` | The console's UDP ports reachable from the tailnet. Default `[9295, 9296, 9297, 9302]` (Remote Play). `[]` turns inbound UDP off. | | `blockedPorts` | Local TCP ports that are never exposed to the tailnet. | | `verbose` | Put Tailscale's own log in the main log as well. | @@ -214,9 +245,10 @@ Two things are left to do by hand: ## Security - The status page and its controls are unauthenticated. -- All listening TCP ports on the console become reachable from your tailnet, - including the payload loader, which runs anything sent to it. Use Tailscale - ACLs if other people share your tailnet. +- All listening TCP ports on the console, and the UDP ports in `udpPorts`, + become reachable from your tailnet. That includes the payload loader, which + runs anything sent to it. Use Tailscale ACLs if other people share your + tailnet. - The local forwards and the proxy listen on `127.0.0.1` only and are not exposed to the tailnet. @@ -232,6 +264,9 @@ starting again after a reboot with the saved login, reaching the console over the tailnet, a ProsperoLight stream from a Sunshine host through the forward, the HTTP proxy, the home screen icon. +Remote Play through the tailnet address works with Chiaki and with Asobi on +iOS and Android. + Not tested: rest mode, Uninstall on a console, other firmware versions, coordination servers other than Tailscale's. diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 31ba7a2..52e1a5a 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -52,7 +52,7 @@ These folders are not in the repository. ```powershell # daemon payload: C launcher + Go program -> out\tailscale.elf -.\tools\build-payload.ps1 -GoDir tsd -Name tailscale -Version 0.3.0 +.\tools\build-payload.ps1 -GoDir tsd -Name tailscale -Version 0.4.0 # installer -> out\tailscale-installer.elf (embeds out\tailscale.elf) .\tools\build-installer.ps1 diff --git a/docs/TECHNICAL.md b/docs/TECHNICAL.md index 792cf9d..e693cda 100644 --- a/docs/TECHNICAL.md +++ b/docs/TECHNICAL.md @@ -27,6 +27,13 @@ specification. - Inbound: tsnet's fallback TCP handler pipes each tailnet connection to `127.0.0.1:`. It dials the local port before accepting, so ports with no listener are refused properly. +- Inbound UDP (`inboundudp.go`): tsnet has no catch-all for UDP, so the ports + in `udpPorts` are listened on with `tsnet.Server.ListenPacket` on the + node's tailnet addresses and relayed to `127.0.0.1`. The default list is + PS5 Remote Play's (9295, 9296, 9297, 9302); its service answers clients + that arrive from loopback. Both UDP directions share `udprelay.go`: one + connection to the target per client address, dropped after two idle + minutes. - Outbound: local forwards (`localforward.go`) listen on localhost and relay TCP and UDP to a tailnet host through `tsnet.Server.Dial`. UDP is relayed per client address with an idle timeout. The Sunshine setting is a preset diff --git a/docs/status-page.png b/docs/status-page.png index e0fce8f522b0ab5fdbef74c80e849c9eadae14f2..9d5ecc88290df9f7003f4d5e1d2aa69e7bfbe594 100644 GIT binary patch literal 61260 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%0D+& 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%0AM0 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 Aod5s; literal 56627 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 diff --git a/probe-c/rpprobe.c b/probe-c/rpprobe.c new file mode 100644 index 0000000..bde4ce9 --- /dev/null +++ b/probe-c/rpprobe.c @@ -0,0 +1,39 @@ +/* Ask the console's Remote Play service for its discovery reply over + * loopback, to confirm it answers clients that arrive from 127.0.0.1 (which + * is how the daemon's UDP relay reaches it). Read-only. */ + +#include +#include +#include + +#include +#include +#include +#include + +int +main(void) { + static const char req[] = "SRCH * HTTP/1.1\ndevice-discovery-protocol-version:00030010\n"; + struct sockaddr_in addr = {0}; + struct timeval tv = {3, 0}; + char buf[1024]; + int fd = socket(AF_INET, SOCK_DGRAM, 0); + ssize_t n; + + setvbuf(stdout, 0, _IONBF, 0); + addr.sin_family = AF_INET; + addr.sin_port = htons(9302); + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + sendto(fd, req, sizeof(req) - 1, 0, (struct sockaddr *)&addr, sizeof(addr)); + n = recv(fd, buf, sizeof(buf) - 1, 0); + if (n <= 0) { + printf("discovery via 127.0.0.1:9302: no reply\n"); + } else { + buf[n] = 0; + buf[strcspn(buf, "\r\n")] = 0; + printf("discovery via 127.0.0.1:9302: %s\n", buf); + } + close(fd); + return 0; +} diff --git a/tsd/config.go b/tsd/config.go index a6b9321..44037ea 100644 --- a/tsd/config.go +++ b/tsd/config.go @@ -5,6 +5,7 @@ import ( "errors" "io/fs" "os" + "slices" ) // config is read from /data/tailscale/config.json. Every field is optional. @@ -28,6 +29,10 @@ type config struct { // Forwards are extra local forwards: a localhost port on the console // relayed to a host on the tailnet. Forwards []forwardRule `json:"forwards,omitempty"` + // UDPPorts lists the console's UDP ports that are reachable from the + // tailnet. The default is what PS5 Remote Play uses. An empty list turns + // inbound UDP off. + UDPPorts []uint16 `json:"udpPorts"` // BlockedPorts lists local TCP ports that are never exposed to the tailnet. BlockedPorts []uint16 `json:"blockedPorts,omitempty"` // Verbose turns on Tailscale's own (very chatty) logging. @@ -39,6 +44,7 @@ func defaultConfig() config { Hostname: "ps5", WebAddr: ":8090", HTTPProxyAddr: "127.0.0.1:8118", + UDPPorts: slices.Clone(remotePlayUDPPorts), } } diff --git a/tsd/inboundudp.go b/tsd/inboundudp.go new file mode 100644 index 0000000..5c8f942 --- /dev/null +++ b/tsd/inboundudp.go @@ -0,0 +1,95 @@ +package main + +import ( + "context" + "net" + "net/netip" + "slices" + "strconv" + "sync" +) + +// Inbound UDP: tailnet devices reaching UDP services on the console. +// +// TCP needs no configuration, because tsnet asks about every incoming +// connection and it can be passed to localhost on the spot. UDP has no such +// hook, so the ports have to be listed and listened on, on the console's +// tailnet addresses. The default list is what PS5 Remote Play uses. + +// remotePlayUDPPorts are the UDP ports of the console's Remote Play service: +// registration (9295), the stream (9296), the connection test (9297) and +// discovery (9302). Its session port, TCP 9295, is covered by the TCP +// forwarding. +var remotePlayUDPPorts = []uint16{9295, 9296, 9297, 9302} + +// udpExposer keeps a set of the console's UDP ports reachable on its tailnet +// addresses. +type udpExposer struct { + // listen opens a UDP socket on a tailnet address + // (tsnet.Server.ListenPacket). + listen func(network, addr string) (net.PacketConn, error) + logf func(format string, args ...any) + // targetHost is where the console's services are reached. + targetHost string + + mu sync.Mutex + addrs []netip.Addr + ports []uint16 + stops []func() + active []uint16 +} + +// update makes ports reachable on addrs, replacing whatever was exposed +// before. It does nothing if neither has changed. +func (e *udpExposer) update(addrs []netip.Addr, ports []uint16) { + e.mu.Lock() + defer e.mu.Unlock() + if slices.Equal(addrs, e.addrs) && slices.Equal(ports, e.ports) { + return + } + for _, stop := range e.stops { + stop() + } + e.stops, e.active = nil, nil + e.addrs, e.ports = slices.Clone(addrs), slices.Clone(ports) + + for _, port := range ports { + target := net.JoinHostPort(e.targetHost, strconv.Itoa(int(port))) + ok := false + for _, addr := range addrs { + network := "udp4" + if addr.Is6() { + network = "udp6" + } + listenAddr := netip.AddrPortFrom(addr, port).String() + stop, err := startUDPRelay(udpRelayConfig{ + name: "udp " + listenAddr, + listen: func() (net.PacketConn, error) { return e.listen(network, listenAddr) }, + dial: func(ctx context.Context) (net.Conn, error) { + var d net.Dialer + return d.DialContext(ctx, "udp", target) + }, + logf: e.logf, + }) + if err != nil { + e.logf("udp %s: %v", listenAddr, err) + continue + } + e.stops = append(e.stops, stop) + ok = true + } + if ok { + e.active = append(e.active, port) + } + } + if len(e.active) > 0 { + e.logf("UDP ports reachable from the tailnet: %v", e.active) + } +} + +// activePorts returns the ports currently exposed. +func (e *udpExposer) activePorts() []uint16 { + e.mu.Lock() + defer e.mu.Unlock() + return slices.Clone(e.active) +} diff --git a/tsd/inboundudp_test.go b/tsd/inboundudp_test.go new file mode 100644 index 0000000..e694844 --- /dev/null +++ b/tsd/inboundudp_test.go @@ -0,0 +1,85 @@ +package main + +import ( + "net" + "net/netip" + "strconv" + "testing" + "time" +) + +// The exposer must relay datagrams arriving on a "tailnet" socket to the same +// port on the target host and bring the replies back to the sender. +func TestUDPExposer(t *testing.T) { + // The console's service: echoes with a prefix. + service, err := net.ListenPacket("udp", "127.0.0.1:0") + if err != nil { + t.Fatal(err) + } + defer service.Close() + go func() { + buf := make([]byte, 2048) + for { + n, from, err := service.ReadFrom(buf) + if err != nil { + return + } + service.WriteTo(append([]byte("ps5:"), buf[:n]...), from) + } + }() + port := uint16(service.LocalAddr().(*net.UDPAddr).Port) + + // Stand-in for tsnet: "listening on the tailnet address" is a loopback + // socket on some other port, whose address the test then sends to. + listening := make(chan net.Addr, 4) + var asked []string + e := &udpExposer{ + targetHost: "127.0.0.1", + logf: t.Logf, + listen: func(network, addr string) (net.PacketConn, error) { + asked = append(asked, network+" "+addr) + pc, err := net.ListenPacket("udp", "127.0.0.1:0") + if err == nil { + listening <- pc.LocalAddr() + } + return pc, err + }, + } + tailnetIP := netip.MustParseAddr("100.64.0.5") + e.update([]netip.Addr{tailnetIP}, []uint16{port}) + defer e.update(nil, nil) + + want := "udp4 100.64.0.5:" + strconv.Itoa(int(port)) + if len(asked) != 1 || asked[0] != want { + t.Fatalf("listened on %v, want [%s]", asked, want) + } + if got := e.activePorts(); len(got) != 1 || got[0] != port { + t.Fatalf("activePorts = %v", got) + } + + client, err := net.Dial("udp", (<-listening).String()) + if err != nil { + t.Fatal(err) + } + defer client.Close() + for _, msg := range []string{"SRCH", "again"} { + client.Write([]byte(msg)) + buf := make([]byte, 100) + client.SetReadDeadline(time.Now().Add(5 * time.Second)) + n, err := client.Read(buf) + if err != nil || string(buf[:n]) != "ps5:"+msg { + t.Fatalf("%q: got %q, %v", msg, buf[:n], err) + } + } + + // Unchanged input must not reopen anything. + e.update([]netip.Addr{tailnetIP}, []uint16{port}) + if len(asked) != 1 { + t.Errorf("update with the same addresses and ports listened again: %v", asked) + } + // An empty port list turns it off. + e.update([]netip.Addr{tailnetIP}, nil) + if got := e.activePorts(); len(got) != 0 { + t.Errorf("activePorts after clearing = %v", got) + } +} diff --git a/tsd/localforward.go b/tsd/localforward.go index 771b8ce..876c645 100644 --- a/tsd/localforward.go +++ b/tsd/localforward.go @@ -7,7 +7,6 @@ import ( "net" "strconv" "sync" - "sync/atomic" "time" ) @@ -152,144 +151,11 @@ func (f *forwarder) serveTCP(c net.Conn, r forwardRule) { pipe(c, up) } -// UDP flows that have been silent this long are forgotten. -const udpIdleTimeout = 2 * time.Minute - -// udpFlow is the relay state for one local client address. -type udpFlow struct { - out chan []byte // datagrams from the client waiting to go upstream - lastSeen atomic.Int64 -} - -func (fl *udpFlow) touch() { fl.lastSeen.Store(time.Now().UnixNano()) } - -func (fl *udpFlow) idle() bool { - return time.Since(time.Unix(0, fl.lastSeen.Load())) > udpIdleTimeout -} - func (f *forwarder) startUDP(r forwardRule) (stop func(), err error) { - pc, err := net.ListenPacket("udp", r.Listen) - if err != nil { - return nil, err - } - var ( - mu sync.Mutex - current = pc - closed bool - flows = map[string]*udpFlow{} - ) - socket := func() (net.PacketConn, bool) { - mu.Lock() - defer mu.Unlock() - return current, closed - } - - go func() { - buf := make([]byte, 65535) - for { - sock, stopped := socket() - if stopped { - return - } - n, from, err := sock.ReadFrom(buf) - if err != nil { - if _, stopped := socket(); stopped { - return - } - // Like TCP listeners, a UDP socket can die when the - // PS5's network is reconfigured. Open a new one. - f.logf("forward %v: %v; reopening", r, err) - sock.Close() - time.Sleep(time.Second) - if reopened, err := net.ListenPacket("udp", r.Listen); err == nil { - mu.Lock() - if closed { - reopened.Close() - } else { - current = reopened - } - mu.Unlock() - } - continue - } - - key := from.String() - mu.Lock() - fl := flows[key] - if fl == nil { - fl = &udpFlow{out: make(chan []byte, 256)} - flows[key] = fl - go f.serveUDPFlow(r, fl, from, socket, func() { - mu.Lock() - if flows[key] == fl { - delete(flows, key) - } - mu.Unlock() - }) - } - mu.Unlock() - - fl.touch() - select { - case fl.out <- append([]byte(nil), buf[:n]...): - default: // upstream is not keeping up; UDP may drop - } - } - }() - - return func() { - mu.Lock() - closed = true - current.Close() - mu.Unlock() - }, nil -} - -// serveUDPFlow relays one client's datagrams to the target and the replies -// back, until the flow goes quiet or the forward is stopped. -func (f *forwarder) serveUDPFlow(r forwardRule, fl *udpFlow, client net.Addr, socket func() (net.PacketConn, bool), done func()) { - defer done() - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) - up, err := f.dial(ctx, "udp", r.Target) - cancel() - if err != nil { - f.logf("forward %v: %v", r, err) - return - } - defer up.Close() - - // Replies: target -> client. - go func() { - buf := make([]byte, 65535) - for { - up.SetReadDeadline(time.Now().Add(udpIdleTimeout)) - n, err := up.Read(buf) - if err != nil { - var ne net.Error - if errors.As(err, &ne) && ne.Timeout() && !fl.idle() { - continue - } - return - } - fl.touch() - if pc, closed := socket(); !closed { - pc.WriteTo(buf[:n], client) - } - } - }() - - idle := time.NewTicker(udpIdleTimeout / 4) - defer idle.Stop() - for { - select { - case b := <-fl.out: - if _, err := up.Write(b); err != nil { - return - } - case <-idle.C: - if _, closed := socket(); closed || fl.idle() { - return - } - } - } + return startUDPRelay(udpRelayConfig{ + name: "forward " + r.String(), + listen: func() (net.PacketConn, error) { return net.ListenPacket("udp", r.Listen) }, + dial: func(ctx context.Context) (net.Conn, error) { return f.dial(ctx, "udp", r.Target) }, + logf: f.logf, + }) } diff --git a/tsd/main.go b/tsd/main.go index 7f5f49a..b0da42a 100644 --- a/tsd/main.go +++ b/tsd/main.go @@ -11,9 +11,11 @@ import ( "context" "fmt" "net" + "net/netip" "os" "os/signal" "path/filepath" + "slices" "strings" "sync" "syscall" @@ -105,6 +107,7 @@ type daemon struct { srv *tsnet.Server lc *local.Client fwd *forwarder + udp *udpExposer mu sync.Mutex state string // ipn backend state, e.g. "NeedsLogin", "Running" @@ -174,8 +177,10 @@ func (d *daemon) run() error { ctx, cancel := context.WithCancel(context.Background()) defer cancel() + d.udp = &udpExposer{listen: d.srv.ListenPacket, logf: d.logf, targetHost: "127.0.0.1"} go d.watch(ctx) go d.recoverLogin(ctx) + go d.exposeUDP(ctx) sigc := make(chan os.Signal, 1) signal.Notify(sigc, syscall.SIGTERM, syscall.SIGINT) @@ -214,6 +219,37 @@ func (d *daemon) localForwardRules() []forwardRule { return append(sunshineRules(d.cfg.SunshineHost), d.cfg.Forwards...) } +// exposeUDP keeps the configured UDP ports listening on the console's tailnet +// addresses. Those are only known once Tailscale is connected and can change, +// so they are checked periodically. +func (d *daemon) exposeUDP(ctx context.Context) { + ticker := time.NewTicker(5 * time.Second) + defer ticker.Stop() + for { + d.mu.Lock() + running := d.state == "Running" + ports := slices.Clone(d.cfg.UDPPorts) + d.mu.Unlock() + if running { + var addrs []netip.Addr + v4, v6 := d.srv.TailscaleIPs() + for _, a := range []netip.Addr{v4, v6} { + if a.IsValid() { + addrs = append(addrs, a) + } + } + if len(addrs) > 0 { + d.udp.update(addrs, ports) + } + } + select { + case <-ctx.Done(): + return + case <-ticker.C: + } + } +} + // tsnetLogf receives tsnet's messages for the user. While it waits for a // login it repeats the same line every few seconds, which would drown the // log, so a message is only logged again when it changes. diff --git a/tsd/status.html b/tsd/status.html index f931cc8..e2d1c09 100644 --- a/tsd/status.html +++ b/tsd/status.html @@ -161,6 +161,7 @@ async function refresh() { if (s.ips.length) row(dl, 'Tailnet address', s.ips.join(', '), true); if (s.tailnet) row(dl, 'Tailnet', s.tailnet); if (s.proxy) row(dl, 'HTTP proxy', s.proxy, true); + if (s.ips.length) row(dl, 'Reachable from tailnet', 'every open TCP port' + (s.udpPorts.length ? '; UDP ' + s.udpPorts.join(', ') + ' (Remote Play)' : '')); const health = $('health'); health.replaceChildren(...(s.health || []).map(h => { const li = document.createElement('li'); li.textContent = h; return li; })); diff --git a/tsd/udprelay.go b/tsd/udprelay.go new file mode 100644 index 0000000..85ae667 --- /dev/null +++ b/tsd/udprelay.go @@ -0,0 +1,178 @@ +package main + +import ( + "context" + "errors" + "net" + "sync" + "sync/atomic" + "time" +) + +// A UDP relay sits between a listening socket and a target. Every client +// address that sends to the socket gets its own connection to the target, so +// the target's replies find their way back to the right client. It is used in +// both directions: console apps to a tailnet host (local forwards) and +// tailnet devices to a service on the console (inbound UDP). + +// UDP flows that have been silent this long are forgotten. +const udpIdleTimeout = 2 * time.Minute + +type udpRelayConfig struct { + name string + // listen opens the socket clients send to. It is called again if the + // socket fails, which on the PS5 happens when the network is + // reconfigured. + listen func() (net.PacketConn, error) + // dial opens the connection to the target for one client. + dial func(ctx context.Context) (net.Conn, error) + logf func(format string, args ...any) +} + +// udpFlow is the relay state for one client address. +type udpFlow struct { + out chan []byte // datagrams from the client waiting to go to the target + lastSeen atomic.Int64 +} + +func (fl *udpFlow) touch() { fl.lastSeen.Store(time.Now().UnixNano()) } + +func (fl *udpFlow) idle() bool { + return time.Since(time.Unix(0, fl.lastSeen.Load())) > udpIdleTimeout +} + +type udpRelay struct { + cfg udpRelayConfig + + mu sync.Mutex + sock net.PacketConn + closed bool + flows map[string]*udpFlow +} + +// startUDPRelay opens the listening socket and relays until stop is called. +func startUDPRelay(cfg udpRelayConfig) (stop func(), err error) { + sock, err := cfg.listen() + if err != nil { + return nil, err + } + r := &udpRelay{cfg: cfg, sock: sock, flows: map[string]*udpFlow{}} + go r.readLoop() + return r.stop, nil +} + +func (r *udpRelay) stop() { + r.mu.Lock() + defer r.mu.Unlock() + r.closed = true + r.sock.Close() +} + +// socket returns the current listening socket and whether the relay has been +// stopped. +func (r *udpRelay) socket() (net.PacketConn, bool) { + r.mu.Lock() + defer r.mu.Unlock() + return r.sock, r.closed +} + +func (r *udpRelay) readLoop() { + buf := make([]byte, 65535) + for { + sock, stopped := r.socket() + if stopped { + return + } + n, from, err := sock.ReadFrom(buf) + if err != nil { + if _, stopped := r.socket(); stopped { + return + } + r.cfg.logf("%s: %v; reopening", r.cfg.name, err) + sock.Close() + time.Sleep(time.Second) + if reopened, err := r.cfg.listen(); err == nil { + r.mu.Lock() + if r.closed { + reopened.Close() + } else { + r.sock = reopened + } + r.mu.Unlock() + } + continue + } + + key := from.String() + r.mu.Lock() + fl := r.flows[key] + if fl == nil { + fl = &udpFlow{out: make(chan []byte, 256)} + r.flows[key] = fl + go r.serveFlow(key, fl, from) + } + r.mu.Unlock() + + fl.touch() + select { + case fl.out <- append([]byte(nil), buf[:n]...): + default: // the target is not keeping up; UDP may drop + } + } +} + +// serveFlow relays one client's datagrams to the target and the replies +// back, until the flow goes quiet or the relay is stopped. +func (r *udpRelay) serveFlow(key string, fl *udpFlow, client net.Addr) { + defer func() { + r.mu.Lock() + if r.flows[key] == fl { + delete(r.flows, key) + } + r.mu.Unlock() + }() + + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + up, err := r.cfg.dial(ctx) + cancel() + if err != nil { + r.cfg.logf("%s: %v", r.cfg.name, err) + return + } + defer up.Close() + + // Replies: target -> client. + go func() { + buf := make([]byte, 65535) + for { + up.SetReadDeadline(time.Now().Add(udpIdleTimeout)) + n, err := up.Read(buf) + if err != nil { + var ne net.Error + if errors.As(err, &ne) && ne.Timeout() && !fl.idle() { + continue + } + return + } + fl.touch() + if sock, stopped := r.socket(); !stopped { + sock.WriteTo(buf[:n], client) + } + } + }() + + idle := time.NewTicker(udpIdleTimeout / 4) + defer idle.Stop() + for { + select { + case b := <-fl.out: + if _, err := up.Write(b); err != nil { + return + } + case <-idle.C: + if _, stopped := r.socket(); stopped || fl.idle() { + return + } + } + } +} diff --git a/tsd/web.go b/tsd/web.go index 7dd7107..2427371 100644 --- a/tsd/web.go +++ b/tsd/web.go @@ -46,7 +46,9 @@ type statusInfo struct { // SunshineHost and Forwards describe the local forwards. SunshineHost string `json:"sunshineHost"` Forwards []string `json:"forwards"` - Uptime int64 `json:"uptimeSeconds"` + // UDPPorts are the console's UDP ports reachable from the tailnet. + UDPPorts []uint16 `json:"udpPorts"` + Uptime int64 `json:"uptimeSeconds"` } func (d *daemon) serveWeb(ln net.Listener) { @@ -139,6 +141,10 @@ func (d *daemon) handleStatus(w http.ResponseWriter, r *http.Request) { } info.SunshineHost = d.cfg.SunshineHost d.mu.Unlock() + info.UDPPorts = []uint16{} + if d.udp != nil { + info.UDPPorts = append(info.UDPPorts, d.udp.activePorts()...) + } info.Forwards = []string{} for _, r := range d.fwd.rules() { info.Forwards = append(info.Forwards, r.String())