Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

- Add opt-in single-folder sharing to Share This Mac with security-scoped bookmark persistence, negotiated `FSH1` browsing, bounded native and browser download/upload streams, strict realpath containment, 512 MiB file and 256 KiB chunk limits, root-local temporary uploads with atomic rename and teardown cleanup, and host-controlled remote writes.
- Add a pure-Go Windows Crabfleet Connect backend with synchronized GDI BitBlt primary-display capture, full-frame RGBA dirty updates, SendInput absolute pointer, wheel, and keyboard injection, active-layout shortcuts, Unicode and legacy X11 keysym text mapping, retry-safe teardown, and amd64/arm64 cross-build proof, while deferring DXGI, multi-monitor, per-monitor-DPI, packaging, and real-hardware validation.
- Add the Crabfleet Connect foundation with a shared Go RFB 3.8 host core, per-run VNC-DES authentication, Tight/JPEG and client-side cursor/input support, a CI-safe synthetic backend, and a Linux X11 MIT-SHM/XFixes/XTest backend plus cross-compiled CLI, while documenting deferred codecs, Wayland, ARD, audio, and hardware validation.
- Harden Share This Mac tailnet identity resolution with stable multi-IPv4 selection and candidate exposure, MagicDNS-free hostname fallback, actionable backend-state and malformed-status errors, and an explicit unsupported IPv6-only listener result.
- Add a default-off Share This Mac Remote Desktop-permission experiment with persisted Privacy Settings selection, live ScreenCaptureKit capability polling, direct System Settings guidance, and unchanged Screen Recording defaults for macOS 26 capture-indicator research.
Expand Down
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -430,22 +430,26 @@ Full documentation available at [docs.crabfleet.ai](https://docs.crabfleet.ai):
- [API](https://docs.crabfleet.ai/api) – REST and WebSocket APIs
- [Spec](https://docs.crabfleet.ai/spec) – Complete product specification

## Crabfleet Connect for Linux
## Crabfleet Connect for Linux and Windows

`crabfleet-connect` is the first cross-platform host foundation for sharing a
Linux machine to the native macOS viewer or browser client. It provides a Go
RFB 3.8 server, a fresh per-run VNC password, Tight/JPEG frames, client-side
cursor updates, remote input, a synthetic test backend, and a Linux X11
MIT-SHM/XFixes/XTest backend. The X11 backend cross-compiles in CI but has not
been validated on physical Linux hardware yet.
Linux or Windows machine to the native macOS viewer or browser client. It
provides a Go RFB 3.8 server, a fresh per-run VNC password, Tight/JPEG frames,
client-side cursor updates, remote input, a synthetic test backend, a Linux X11
MIT-SHM/XFixes/XTest backend, and a pure-Go Windows backend using synchronized
GDI `BitBlt` primary-display capture plus `SendInput`. The Windows key path
combines virtual keys for named keys and active-layout shortcuts with Unicode
text injection and canonical legacy X11 keysym conversion. Both native paths
cross-compile, but neither has been validated on physical target hardware yet.

The CLI listens on loopback by default because VNC-DES does not encrypt RFB
traffic. Remote use requires an explicit `--bind` on an already protected
private path.

This increment does not provide ARD host authentication, H.264 or HEVC
encoding, Wayland/PipeWire capture, multi-group XKB input, audio, clipboard
synchronization, or service packaging. See
encoding, Wayland/PipeWire capture, Windows DXGI Desktop Duplication,
Windows multi-monitor or per-monitor-DPI support, multi-group XKB input, audio,
clipboard synchronization, or service packaging. See
[`cmd/crabfleet-connect/README.md`](cmd/crabfleet-connect/README.md)
for the exact boundary and run command.

Expand Down
11 changes: 9 additions & 2 deletions cmd/crabfleet-connect/README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
# Crabfleet Connect foundation

`crabfleet-connect` is the first Linux host foundation for sharing a machine to Crabfleet's macOS viewer or browser client.
`crabfleet-connect` is the cross-platform host foundation for sharing a Linux or Windows machine to Crabfleet's macOS viewer or browser client.

Real in this increment:

- RFB 3.8 server handshake and direct-listener VNC-DES authentication with an eight-character per-run share password; Security None is never offered.
- Tight/JPEG full-frame updates, client-side cursor pseudo-encodings, pointer/key input, strict protocol bounds, bounded sessions, and idempotent teardown.
- A pure-Go synthetic capture/input backend used by tests and as an explicit fallback.
- A Linux X11 backend implemented with MIT-SHM `XShmGetImage` capture, XFixes cursor images, and XTest input with key-level modifier mapping. It compiles for Linux; it has not been validated on physical Linux hardware in this track. Multi-group XKB layouts fail closed to the synthetic fallback rather than risking incorrect input.
- A pure-Go Windows backend implemented with synchronized GDI `BitBlt` primary-display capture and `SendInput` for absolute pointer, wheel, virtual-key shortcut, and layout-independent Unicode text input. Its named-key table and canonical legacy X11 keysym conversion are tested on every platform, and the host cross-builds as amd64 and arm64 PE executables. It has not been run on physical Windows hardware in this track.

Deferred:

- ARD host authentication. Type 30 remains in the Track H-compatible security offer but fails closed; VNC-DES type 2 is the working MVP.
- H.264/HEVC hardware encoding, Wayland/PipeWire capture, multi-group XKB input, audio, clipboard synchronization, packaging/service installation, and real-hardware validation.
- H.264/HEVC hardware encoding, Wayland/PipeWire capture, Windows DXGI Desktop Duplication, Windows multi-monitor and per-monitor-DPI support, multi-group XKB input, audio, clipboard synchronization, packaging/service installation, and real-hardware validation.

Run:

```sh
go run ./cmd/crabfleet-connect --display :0 --port 5900
```

On Windows, omit `--display`; the native backend captures the primary display:

```powershell
go run ./cmd/crabfleet-connect --port 5900
```

The process prints its per-run share password and listener address. If native capture cannot initialize, it says why and uses the synthetic test pattern. Use `--synthetic` to force that backend. The listener defaults to `127.0.0.1` because VNC-DES authenticates but does not encrypt the RFB session. Use `--bind` to select a private interface only when the network path is already protected, such as through an authenticated tunnel; `--bind 0.0.0.0` is an explicit insecure exposure.
16 changes: 14 additions & 2 deletions cmd/crabfleet-connect/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"net"
"os"
"os/signal"
"runtime"
"strconv"
"strings"
"syscall"
Expand Down Expand Up @@ -68,7 +69,7 @@ func run(ctx context.Context, arguments []string, stdout, stderr io.Writer) erro
}
hostname, err := os.Hostname()
if err != nil || hostname == "" {
hostname = "Linux"
hostname = runtime.GOOS
}
server, err := rfb.NewServer(rfb.ServerConfig{Session: rfb.SessionConfig{
Backend: backend,
Expand All @@ -95,7 +96,7 @@ func selectBackend(forceSynthetic bool, display string, stderr io.Writer) (conne
if !forceSynthetic {
backend, err := connect.NewPlatformBackend(display)
if err == nil {
return backend, "Linux X11 (MIT-SHM capture + XTest input)", nil
return backend, nativeBackendDescription(), nil
}
fmt.Fprintf(stderr, "Native capture unavailable (%v); using synthetic test pattern.\n", err)
}
Expand All @@ -106,6 +107,17 @@ func selectBackend(forceSynthetic bool, display string, stderr io.Writer) (conne
return backend, "synthetic test pattern", nil
}

func nativeBackendDescription() string {
switch runtime.GOOS {
case "linux":
return "Linux X11 (MIT-SHM capture + XTest input)"
case "windows":
return "Windows GDI BitBlt capture + SendInput"
default:
return "native capture + input"
}
}

func generateSharePassword() (string, error) {
const alphabet = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789"
const length = 8
Expand Down
27 changes: 16 additions & 11 deletions docs/macos-native-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,26 +63,31 @@ full UTF-8 text with servers that negotiate it; against servers without the
extension, standard cut text must encode losslessly as ISO-8859-1 and
unsupported text is rejected instead of silently becoming empty data.

## Linux Connect foundation
## Linux and Windows Connect foundation

The native viewer can also connect directly to the first
`crabfleet-connect` Linux host foundation. That Go host speaks RFB 3.8 with a
fresh per-run VNC-DES password, Tight/JPEG full-frame updates, client-side
cursor rectangles, and pointer/key input. Its synthetic backend provides the
portable CI and protocol-test path. The Linux-only backend implements X11
capture with MIT-SHM `XShmGetImage`, cursor images with XFixes, and input with
XTest; it cross-compiles for amd64 and arm64 but has not been exercised on
physical Linux hardware in this increment.
`crabfleet-connect` Linux and Windows host foundation. That Go host speaks RFB
3.8 with a fresh per-run VNC-DES password, Tight/JPEG full-frame updates,
client-side cursor rectangles, and pointer/key input. Its synthetic backend
provides the portable CI and protocol-test path. The Linux backend implements
X11 capture with MIT-SHM `XShmGetImage`, cursor images with XFixes, and input
with XTest. The pure-Go Windows backend captures the primary display into RGBA
frames with synchronized GDI `BitBlt` and injects absolute pointer, wheel, and
keyboard input with `SendInput`; named keys and active-layout shortcuts use
virtual keys, while text uses Unicode injection plus canonical legacy X11
keysym conversion. Both native paths cross-compile for amd64 and arm64. Neither
has been exercised on physical target hardware in these increments.

The Connect listener defaults to loopback because VNC-DES does not encrypt RFB
traffic. A remote listener requires an explicit private bind on a separately
protected network path.

The Linux host still advertises the direct-listener ARD security type for wire
The Connect host still advertises the direct-listener ARD security type for wire
compatibility, but ARD host authentication fails closed and viewers must select
VNC password authentication. H.264/HEVC encoding, Wayland/PipeWire, audio,
multi-group XKB input, clipboard synchronization, service packaging, and
real-hardware validation remain follow-up work.
Windows DXGI Desktop Duplication, Windows multi-monitor and per-monitor-DPI
support, multi-group XKB input, clipboard synchronization, service packaging,
and real-hardware validation remain follow-up work.

## Wake-on-LAN

Expand Down
2 changes: 1 addition & 1 deletion internal/connect/platform_other.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !linux
//go:build !linux && !windows

package connect

Expand Down
7 changes: 7 additions & 0 deletions internal/connect/platform_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//go:build windows

package connect

func NewPlatformBackend(string) (Backend, error) {
return NewWindowsBackend()
}
Loading