GNOME Remote Desktop: Headless system-level RDP fails NLA handshake with Windows mstsc — black screen

Bug #2141992 reported by Gerry Burde
12
This bug affects 2 people
Affects Status Importance Assigned to Milestone
GNOME Remote Desktop
Fix Released
Unknown
gnome-remote-desktop (Ubuntu)
Confirmed
Undecided
Unassigned

Bug Description

- Source package: gnome-remote-desktop
  - Release: Ubuntu 25.10
  - Package version: 49.0-0ubuntu1.1
  - Expected: GDM login screen appears via RDP when connecting from Windows mstsc.exe to port 3389
-Actual:Black screen for ~30 seconds then disconnect. Server logs show NLA handshakefailure:nla_server_recv_stream:nla_recv()error:-1 and Connection reset by peer

On Ubuntu 25.10 (GNOME 49, gnome-remote-desktop 49.0), system-level headless RDP via `gnome-remote-desktop` consistently fails NLA (Network Level Authentication) when connecting from Windows 10/11 `mstsc.exe`. The Windows client connects, shows a black screen for ~30 seconds, then disconnects. The GRD server logs show `nla_server_recv_stream: nla_recv() error: -1` and `client authentication failure` on every attempt.

XFCE4 + xrdp on the same machine works perfectly on port 3390, confirming network connectivity and RDP client functionality are not the issue.

## Environment

- **OS**: Ubuntu 25.10 (Questing), kernel 6.17.0-14-generic
- **Hardware**: Hyper-V VM (Microsoft Corporation Virtual Machine), AMD Ryzen 5 7430U
- **GPU**: Virtual — `/dev/dri/card1` only (no card0), no VGA device on lspci
- **No TPM**: GRD falls back to GKeyFile for credential storage
- **No physical display**: Headless server, no monitor attached

### Package versions

| Package | Version |
|---------|---------|
| gnome-remote-desktop | 49.0-0ubuntu1.1 |
| gdm3 | 49.0.1-1ubuntu2.1 |
| gnome-shell | 49.0-1ubuntu1.2 |
| mutter-common | 49.0-2ubuntu5.3 |
| libfreerdp3-3 | 3.16.0+dfsg-2ubuntu0.1 |
| libwinpr3-3 | 3.16.0+dfsg-2ubuntu0.1 |

### GRD configuration

```
$ sudo grdctl --system status --show-credentials
Overall:
    Unit status: active
RDP:
    Status: enabled
    Port: 3389
    TLS certificate: /var/lib/gnome-remote-desktop/rdp-tls.crt
    TLS key: /var/lib/gnome-remote-desktop/rdp-tls.key
    Username: ubuntu
    Password: ubuntu
```

## Steps to reproduce

1. Install Ubuntu 25.10 server in a Ubuntu Multipass Hyper-V VM (headless, no physical display)
2. Install GNOME desktop: `apt-get install -y gdm3 gnome-remote-desktop gnome-shell gnome-session`
3. Generate TLS certificates:
   ```bash
   sudo openssl req -newkey rsa:2048 -nodes \
     -keyout /var/lib/gnome-remote-desktop/rdp-tls.key \
     -x509 -days 365 \
     -out /var/lib/gnome-remote-desktop/rdp-tls.crt \
     -subj "/CN=$(hostname)"
   sudo chown gnome-remote-desktop:gnome-remote-desktop /var/lib/gnome-remote-desktop/rdp-tls.*
   sudo chmod 600 /var/lib/gnome-remote-desktop/rdp-tls.key
   ```
4. Configure system RDP:
   ```bash
   sudo grdctl --system rdp set-tls-cert /var/lib/gnome-remote-desktop/rdp-tls.crt
   sudo grdctl --system rdp set-tls-key /var/lib/gnome-remote-desktop/rdp-tls.key
   sudo grdctl --system rdp set-credentials ubuntu ubuntu
   sudo grdctl --system rdp enable
   sudo systemctl enable --now gnome-remote-desktop.service
   sudo systemctl set-default graphical.target
   ```
5. Verify GDM greeter is running (gnome-shell process under gdm-greeter user) and port 3389 is listening
6. From Windows 10 or 11, open `mstsc.exe`, connect to `<vm-ip>:3389` with username `ubuntu`, password `ubuntu`

### Expected result
GDM login screen appears via RDP, allowing user authentication to a GNOME Wayland session.

### Actual result
Windows RDP client shows a black screen for ~30 seconds, then disconnects. No login screen ever appears.

## Server-side logs

Every connection attempt produces the same NLA failure sequence in `journalctl -u gnome-remote-desktop`:

```
[ERROR][com.freerdp.core.transport] - [transport_read_layer]: BIO_read returned a system error 104: Connection reset by peer
[ERROR][com.freerdp.core.peer] - [transport_read_layer]: ERRCONNECT_CONNECT_TRANSPORT_FAILED [0x0002000D]
[ERROR][com.freerdp.core.nla] - [nla_server_recv_stream]: nla_recv() error: -1
[ERROR][com.freerdp.core.transport] - [transport_accept_nla]: client authentication failure
[ERROR][com.freerdp.api] - [peer_recv_callback_internal]: CONNECTION_STATE_NEGO - rdp_server_accept_nego() fail
[ERROR][com.freerdp.core.transport] - [transport_check_fds]: transport_check_fds: transport->ReceiveCallback() - STATE_RUN_FAILED [-1]
[WARN][com.freerdp.core.rdp] - [rdp_send_deactivate_all]: rdpMcs::userId == 0, skip sending PDU_TYPE_DEACTIVATE_ALL
[ERROR][com.freerdp.core.transport] - [transport_default_write]: BIO_should_retry returned an error: error:80000020:system library::Broken pipe
[RDP] Network or intentional disconnect, stopping session
[DaemonSystem] Aborting handover, removing remote client with remote id /org/gnome/RemoteDesktop/Client/XXXXXXXXXX
[ERROR][com.freerdp.core.peer] - [rdp_set_error_info]: ERRINFO_CB_CONNECTION_CANCELLED [0x00010409]
```

Earlier attempts (before creating `/etc/winpr3/SAM`) also showed:
```
[ERROR][com.winpr.sspi.NTLM] - [ntlm_fetch_ntlm_v2_hash]: Error: Could not find user in SAM database
```

GRD startup consistently shows:
```
Init TPM credentials failed because No TPM device found, using GKeyFile as fallback
```

## Workarounds attempted (all failed)

### 1. SAM file for FreeRDP NTLM auth
Created `/etc/winpr3/SAM` with NTLM hash via `winpr-hash3 -u ubuntu -p ubuntu -f sam`. Eliminated the "SAM database" error but NLA handshake still fails with `Connection reset by peer`.

### 2. TLS certificates generated with winpr-makecert3
Replaced openssl-generated certs with `winpr-makecert3 -rdp -silent` certificates (RDP-specific key usage extensions). No change — same NLA failure.

### 3. Disable/re-enable RDP cycle
```bash
sudo grdctl --system rdp disable
sudo grdctl --system rdp set-credentials ubuntu ubuntu
sudo grdctl --system rdp enable
sudo systemctl restart gnome-remote-desktop
```
No change.

### 4. loginctl enable-linger
Enabled user session lingering: `sudo loginctl enable-linger ubuntu`. No change.

### 5. User-level RDP certificates
Generated separate per-user TLS certificates and configured via `grdctl rdp set-credentials`. Failed with "BIO_new failed for certificate" / "Object does not exist at path /org/freedesktop/secrets/collection/login" (no GNOME keyring in headless context).

### 6. Clean service restart ordering
Stopped both services, restarted GDM first (waited for greeter to fully launch), then started GRD. GRD started cleanly with "RDP server started" — same NLA failure on connection.

### 7. Multiple credential combinations
Tested `rdpuser/changeme`, `ubuntu/ubuntu` — same result regardless of credentials, because the NLA handshake fails before credentials are even checked.

### 8. gsettings for gnome-remote-desktop user
Enabled RDP via gsettings in addition to grdctl:
```bash
sudo -u gnome-remote-desktop dbus-launch gsettings set org.gnome.desktop.remote-desktop.rdp enable true
sudo -u gnome-remote-desktop dbus-launch gsettings set org.gnome.desktop.remote-desktop.rdp view-only false
sudo -u gnome-remote-desktop dbus-launch gsettings set org.gnome.desktop.remote-desktop.rdp tls-cert /var/lib/gnome-remote-desktop/rdp-tls.crt
sudo -u gnome-remote-desktop dbus-launch gsettings set org.gnome.desktop.remote-desktop.rdp tls-key /var/lib/gnome-remote-desktop/rdp-tls.key
```
No change — same NLA failure.

### 9. Full ezone.co.uk guide
Followed the complete guide from https://www.ezone.co.uk/blog/working-headless-rdp-with-gnome-remote-desktop-on-ubuntu-25-10.html including system + user certificates, loginctl enable-linger, and both system and user grdctl configuration. User-level `grdctl rdp set-credentials` fails with "Object does not exist at path /org/freedesktop/secrets/collection/login" (no GNOME keyring available in headless SSH session). Same NLA failure on connection.

## Additional context

### GDM greeter does launch successfully
After fixing a separate nsswitch.conf issue (kanidm NSS module blocking `gdm-greeter` DynamicUser resolution — fixed by adding `systemd` to the passwd NSS chain), the GDM greeter launches correctly:

```
$ ps -ef | grep gnome-shell
gdm-gre+ 1168728 ... /usr/bin/gnome-shell # greeter is running
```

GDM debug logs confirm full greeter lifecycle:
```
Gdm: GdmSessionWorker: state ACCREDITED
Gdm: GdmSessionWorker: state SESSION_OPENED
pam_unix(gdm-launch-environment:session): session opened for user gdm-greeter(uid=60578)
```

### xrdp works on same machine
XFCE4 + xrdp on port 3390 works perfectly from the same Windows client, confirming:
- Network path is clear
- Windows RDP client is functional
- Unix password authentication works (`ubuntu/ubuntu`)

### The connection appears to partially establish
The Windows client briefly connects (shows black), the `update_read_refresh_rect` warning appears in logs (client is sending refresh requests), then GRD aborts the handover after ~30 seconds. This suggests the RDP transport connects but NLA never completes, so the display handover to the GNOME compositor never happens.

### Server supports only NLA Security
One log entry shows: `server supports only NLA Security` followed by `Protocol security negotiation failure`. There is no `grdctl` option to disable NLA or allow fallback to RDP Security or TLS Security, which means Windows clients that fail NLA have no alternative path.

## Related bugs

- [LP #2089611](https://bugs.launchpad.net/bugs/2089611) — RDP blank screen on Ubuntu 24.04, Confirmed, unassigned
- [LP #1983199](https://bugs.launchpad.net/bugs/1983199) — Unable to connect to Ubuntu RDP remote desktop
- [RH #2189376](https://bugzilla.redhat.com/show_bug.cgi?id=2189376) — GRD cannot connect with Windows 10/11 RDP client, CredSSP error (closed EOL)
- [GNOME Discourse](https://discourse.gnome.org/t/gnome-rdp-black-screen-ubuntu-24-04-1/23502) — GNOME RDP black screen discussion

## Suggested fixes

1. **Allow security negotiation fallback**: Add a `grdctl` option to allow TLS or RDP security in addition to NLA, so clients that fail NTLM can still connect
2. **Fix NTLM/NLA with GKeyFile credentials**: When TPM is unavailable and credentials are stored in GKeyFile, ensure FreeRDP's server-side NTLM can resolve them during the NLA handshake
3. **Document headless VM setup**: The interaction between GDM DynamicUser, nsswitch.conf, and GRD system mode is undocumented and breaks in non-trivial configurations

Revision history for this message
Gerry Burde (gerry9000) wrote :
Gerry Burde (gerry9000)
description: updated
Gerry Burde (gerry9000)
Changed in gnome-remote-desktop:
importance: Undecided → Unknown
status: New → Unknown
Changed in gnome-remote-desktop:
status: Unknown → New
Revision history for this message
Gerry Burde (gerry9000) wrote : Debdiff: fix mstsc handover negotiation (4 bugs)

Attaching debdiff for gnome-remote-desktop 49.0-0ubuntu1.2

Revision history for this message
Gerry Burde (gerry9000) wrote : SRU Justification

SRU Justification:

[Impact]
Windows mstsc.exe cannot complete an RDP session to GNOME Remote Desktop
49.0 on headless VMs. Four issues in the RDP handover flow prevent the
connection from succeeding.

[Test Plan]
1. Install gnome-remote-desktop 49.0-0ubuntu1.2
2. Connect from Windows using mstsc.exe to the VM's IP on port 3389
3. Enter credentials at GDM login screen
4. Verify desktop appears after login
5. Disconnect, wait >60 seconds, reconnect — verify handover still works
6. Test with FreeRDP client (Remmina/xfreerdp) — verify RDSTLS still works

[Where Problems Could Occur]
- TLS fallback in SYSTEM mode slightly lowers the authentication barrier
  (unauthenticated clients can see GDM prompt, same as physical access)
- RefuseManualStop=yes prevents systemctl stop on the handover service
  (admins must use systemctl kill instead)
- Retry loop generates lightweight D-Bus traffic every 2s until handover
  succeeds (logged at debug level only)

[Other Info]
Patch: d/p/lp-2141992-fix-mstsc-handover-negotiation.patch
Upstream issue: https://gitlab.gnome.org/GNOME/gnome-remote-desktop/-/issues/244
PPA with fix: ppa:gerry9000/grd-mstsc-fix

Changed in gnome-remote-desktop:
status: New → Fix Released
Revision history for this message
Gerry Burde (gerry9000) wrote : Updated debdiff for gnome-remote-desktop 49.0-0ubuntu1.3 (two-phase retry fix)

Updated debdiff (0ubuntu1.3): fixes retry limit causing permanent handover daemon death (Bug 5, self-inflicted). Replaces hard 30-retry limit with two-phase retries. Tested with mstsc.exe (TLS and RDSTLS paths) and sdl3freerdp. PPA updated: ppa:gerry9000/grd-mstsc-fix

Revision history for this message
Gerry Burde (gerry9000) wrote :

With further research, the root cause has been traced to gnome-settings-daemon rather than gnome-remote-desktop. The PPA (ppa:gerry9000/grd-mstsc-fix) and earlier debdiffs resolve the observed connection failures but do so by adding retry logic in gnome-remote-desktop's handover daemon -- working around the symptom rather than fixing the cause.

The actual bug is in gsd-sharing-manager.c: when sharing_status goes OFFLINE, assigned services are unconditionally stopped, killing the handover daemon while the system RDP daemon still needs it. The fix is a one-line guard checking system_service_running before stopping. This matches the existing guard already present in the start path.

Fix submitted upstream: https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/merge_requests/474 (targeting gnome-49, closes #931). Attaching corrected debdiff for gnome-settings-daemon 49.0-1ubuntu3.1.

Revision history for this message
Gerry Burde (gerry9000) wrote :

gnome-settings-daemon 49.0-1ubuntu3.1 debdiff

Simon Poirier (simpoir)
tags: added: dcr-freezer
Revision history for this message
Launchpad Janitor (janitor) wrote :

Status changed to 'Confirmed' because the bug affects multiple users.

Changed in gnome-remote-desktop (Ubuntu):
status: New → Confirmed
Revision history for this message
Matthew Hiltner (data8504) wrote :

I’d like to report what appears to be the same underlying issue in a somewhat different environment, in case it helps confirm the scope of the bug.

I’m seeing the same overall failure pattern with GNOME Remote Login on Ubuntu 25.10, even though my setup differs from the original report in a few ways.

My environment is:

 - Ubuntu 25.10 on the remote host
 - GNOME Remote Desktop in system/Remote Login mode
 - gnome-remote-desktop 49.0-0ubuntu1.1
 - gdm3 49.0.1-1ubuntu2.1
 - gnome-settings-daemon 49.0-1ubuntu3
 - gnome-shell 49.0-1ubuntu1.2
 - mutter 49.0-2ubuntu5.3
 - libfreerdp3-3 3.16.0+dfsg-2ubuntu0.1

The important difference is that I am not using Windows mstsc, and I am not using an Ubuntu Server style headless install. This is a normal Ubuntu desktop machine, and I reproduced the problem with both:

 - Apache Guacamole / guacd
 - a direct FreeRDP client (xfreerdp)

That seems important because it suggests the problem is not specific to mstsc, and also not specific to Guacamole. In my case, taking Guacamole out of the equation entirely did not change the behavior.

What I observe is:

 - RDP authentication succeeds
 - the remote host starts the GDM remote login / greeter path
 - then the connection stalls and is eventually cancelled
 - gnome-remote-desktop-daemon logs:
     - Aborting handover, removing remote client
     - ERRINFO_CB_CONNECTION_CANCELLED [0x00010409]

During repeated failures, I also see GDM/greeter side effects such as stale gdm-greeter / Xwayland processes and eventually errors like “Failed to create an X lock file”, but after cleaning those up and retrying from a clean state, the original handover failure still happens. So those look like secondary fallout, not the primary cause.

I realize my environment differs from the original report, but the reason I think this is likely the same root cause is:

 - the package versions line up closely
 - the failure occurs after authentication, during the GNOME Remote Login handover
 - it reproduces with multiple independent RDP clients
 - restarting services, rebooting, and re-enabling Remote Login did not resolve it

So from my perspective, this looks broader than “mstsc against Ubuntu Server headless,” and more like a general regression in the GNOME Remote Login handover path on this package set.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.