Files
netbird/client/cmd/rdp_windows.go
Claude c5186f1483 [client] Add RDP token passthrough for passwordless Windows Remote Desktop
Implement sideband authorization and credential provider architecture for
passwordless RDP access to Windows peers via NetBird.

Go components:
- Sideband RDP auth server (TCP on WG interface, port 3390/22023)
- Pending session store with TTL expiry and replay protection
- Named pipe IPC server (\\.\pipe\netbird-rdp-auth) for credential provider
- Sideband client for connecting peer to request authorization
- CLI command `netbird rdp [user@]host` with JWT auth flow
- Engine integration with DNAT port redirection

Rust credential provider DLL (client/rdp/credprov/):
- COM DLL implementing ICredentialProvider + ICredentialProviderCredential
- Loaded by Windows LogonUI.exe at the RDP login screen
- Queries NetBird agent via named pipe for pending sessions
- Performs S4U logon (LsaLogonUser) for passwordless Windows token creation
- Self-registration via regsvr32 (DllRegisterServer/DllUnregisterServer)

https://claude.ai/code/session_01C38bCDyYzLgxYLVwJkcUng
2026-04-11 17:15:42 +00:00

35 lines
754 B
Go

//go:build windows
package cmd
import (
"fmt"
"os/exec"
log "github.com/sirupsen/logrus"
)
// launchRDPClient launches the native Windows Remote Desktop client (mstsc.exe).
func launchRDPClient(peerIP string) error {
mstscPath, err := exec.LookPath("mstsc.exe")
if err != nil {
return fmt.Errorf("mstsc.exe not found: %w", err)
}
cmd := exec.Command(mstscPath, fmt.Sprintf("/v:%s", peerIP))
if err := cmd.Start(); err != nil {
return fmt.Errorf("start mstsc.exe: %w", err)
}
log.Debugf("launched mstsc.exe (PID %d) connecting to %s", cmd.Process.Pid, peerIP)
// Don't wait for mstsc to exit - it runs independently
go func() {
if err := cmd.Wait(); err != nil {
log.Debugf("mstsc.exe exited: %v", err)
}
}()
return nil
}