Looking at some aspects of Remote Desktop & trying to create a more current general reference of several issues, including:
- Can you get Google Credential Provider for Windows (GCPW) working on with Windows Server 2022 and Remote Desktop?
- How does Guacamole work with Remote Desktop?
- What happens if Network Layer Authentication (NLA) is on or off?
- How does the Remote Desktop app for Android/Chromebook work in different scenarios?
I am currently trying to resolve a small issue where some of our users need to work with a particular type of Adobe Acrobat form, built with an old form system called XFA.
XFA allows users to create forms that can be submitted directly from within Acrobat Reader. You can send these forms out, have your users fill out some information, and hit submit, all from within the comfort of their own Reader, and it will shoot the information to you electronically.
This sounds like a very handy feature, but it comes with one caveat – it only works in copies of Reader on Windows and Mac OS. Any other version of Reader won’t work. So you can’t complete XFA forms on Linux, Android, Chromebooks, or iOS.
Firefox have made some effort to support XFA forms, but the particular forms we are working with – which come from a shipping line – don’t work. Some of the form interface elements simply won’t load (e.g., a select dropdown populated with some items) and then ultimately it can’t submit. I don’t blame Firefox for this – it looks like supporting XFA would be a pretty major project, and given the last update to it was in 2012, it feels like something of a technological dead end.
Unfortunately, at my workplace, about 50% of our staff are using Chromebooks. Fortunately, only a few people need to deal with the XFA forms. We’d rather not move them to Windows – Chromebooks suffice for literally everything else they need to do, and we’re not really set up to be a Windows org. Trying to get a multi-billion dollar shipping line with established workflows built around decades-old technology has not proven to be an easy thing to do, so we’re left with solving this problem ourselves.
So I set about trying to find some alternatives to moving everyone to Windows for an edge case. The first thing that came to mind – we can just have a shared Windows machine that everyone can jump into to fill out these forms? Easy! Dust off hands, problems solved.
It turns out it’s not that easy. Here is why:
- First of all the Remote Desktop application on Chromebooks -which is the Android version from the Play Store – seems to be a bit garbage. It works, to some degree, but it has a long list of complaints raised about it continually disconnected and generally not working properly. This makes me a bit nervous about deploying it and having people rely on it for mission-critical stuff.
- There’s no really easy way to put a file on a Remote Desktop server if you’re not connecting in from Windows – if you’re a Windows client, you can just copy/paste the file directly from one desktop to another. Chromebook users can’t do that, & we don’t want to have to worry about users logging into their various accounts on the Windows server just to put a single PDF on there, as they’d have to remember to logout. (Just leaving a whole separate Windows machine in the office has these difficulties, compounded by the fact that people work from home so it’s not always available).
- The main activity they need to do is filling out these forms, which is mainly done by copying and pasting data from a web site into the PDF. Copy/pasting seems a bit suspect in RDP from the Chromebook – sometimes it seems to not work. It would simply not be viable to present this as an option and tell our users they can’t copy and paste with 100% reliability.
To try to work around some of these problems I looked at a few different things and had many adventures. I have summarised these below:
Remote Desktop with GCPW on Windows Server 2022
I had hoped Remote Desktop on a Windows server with the Google Credential Provider for Windows installed might fix things. This should mean that users can log in with their Google Workspace accounts and have access to their usual profile stuff, including their files. This would make the file sharing stuff a lot easier, and ensure they have access to their browser profile as well, which might help move things around.
But this has a few problems. For one, GCPW is not even supported on Windows Server. However, a bit of websearching shows that it does work, but not without some headaches.
The main headache has to do with the security and encryption used by modern Windows Server RDP. It uses this thing called NLA (Network Level Authentication), which is the thing in the RDP client that prompts for your user credentials before you’ve connected to the server. Without NLA, you first connect to the desktop of the remote machine, and then log in as usual.
With NLA, GCPW doesn’t work, because the server doesn’t have the opportunity to start the Google authentication login dialog flow.
But! You can disable NLA. That should fix it, right?!
Kind of. Disabling NLA is a two-sided thing – you need to disable it on the server, and on the client. To disable NLA on the server, you go to Settings -> Remote Desktop -> Advanced Settings, and uncheck the NLA checkbox:
That will fix the server side. But you also need to set the client to not use NLA.
But this is not something you can do in mstsc.exe (the Windows RDP client)!There is no option you can check to disable NLA, so even with NLA disabled, the client will still prompt you when you start the connection.
Fortunately I stumbled across this random gist which explains the solution – you need to save a .rdp file, and edit it to add the following line:
enablecredsspsupport:i:0
(It turns out Microsoft do have this documented, but I could only find it once I already new the above magic setting.)
With that option set in my .rdp file, I was able to connect to the desktop of the server and see the GCPW login.
Logging in will take you through the normal Google login flow, but after authenticating, you might get an error – GCPW will create the user account after auth, but (unless you’ve already configured your Windows server to allow everyone RDP access) that user will probably not be in the RDP user group. Fixing this requires manually adding that user into the Remote Desktop users group, which is easy:
- Open the Users/Groups control panel: Start -> Run ->
lusrmgr.msc
- Click on the Users and look for the newly created GCPW user. Their username will be something like
%firstname%_%email_domain_bit%
– e.g. if your email address is david@example.com, the username will be something likedavid_example
- Double click/open that user, select “Member of” tab, and add to “Remote Desktop Users” group.
Once that is done you should be able to log in with your Google account as normal.
(Note: I re-imaged this machine and installed it again from scratch to make sure it worked the same way a second time. It didn’t. On the second time, when I tried to log in with the GCPW setup, I got the message “Your administrator doesn’t allow you to sign in with this account”. Fortunately Google are all over this message and have a FAQ addressing it – the fix is to simply add the registry key HKEY_LOCAL_MACHINE\Software\Google\domains_allowed_to_login
with a string value of your Google Workspace domain. I don’t know why the GCPW installer did this correctly the first time, but not the second time?!)
Once this was working I thought I was pretty much done – now, to just get this going from a Chromebook! (Like an idiot, I didn’t think about the Chromebook aspect of this before I started.)
It turns out the Remote Desktop app available for Chromebook (at the time of writing, it is v10.0.19.1290) does not support connecting without NLA. There is no client option to disable the NLA authentication flow. You can copy over a .rdp file and open it, but it still prompts as if NLA is enabled, so my guess is the current version of RD for Android simply requires NLA for all connections.
(There was a version of the Remote Desktop app (version 8) which, just because it was older, may have worked for NLA-less connections. Based on the comments in the current RD app on the Play Store, version 8 was superior in a lot of respects, so who knows. Unfortunately it is no longer available from the Play Store, but a lot of people seem to be downloading it from random places as a .apk to keep using it -which says a lot.)
So – connecting from Chromebooks directly using GCPW doesn’t seem like an option. What else can we try?
Windows Server 2022 Remote Desktop Web Client
I vaguely remembered that Windows users could Remote Desktop from a web interface, so maybe I could set that up?
This was a wild adventure. It’s not just a checkbox you can click to turn on the web client. First of all, you need to install the Remote Desktop Services feature.
This is a huge process and comes with its own lengthy instructions. I won’t go into all the problems and hassles because they’re kind of out of scope, but I’ll mention a few of the main things that popped up.
- You can’t install the Remote Desktop Services – as far as I can tell – unless your Windows Server is part of a domain. This can be an old school domain or a newfangled Azure Active Directory thing. I set it up as a normal domain so I didn’t have to muck around with Azure.
- To do this you need to add the Active Directory Domain feature – Server Manager -> Role based or Feature based -> Add Active Directory Domain Services.
- This failed for me with a random error, “Windows Server 2016: One or several parent features are disabled so current feature can not be enabled. Error: 0xc004000d”. I found this random blog post from 2018 which had some arcane PowerShell solution, which I’ll reproduce here for posterity:
- Open an elevated PowerShell prompt and enter the following to check if the .NET Framework Feature is installed:
- Get-WindowsFeature Net-Framework-Features
- Then enter:
- Get-WindowsFeature Net-Framework-Features | Remove-WindowsFeature
- Finally repeat the first command to check the feature has been removed:
- Get-WindowsFeature Net-Framework-Features
- Restart the server.
- Restart-Computer
- I have no idea what this does, but it fixed the problem for me, and I was able to install Active Directory Domain Services.
- Once the server was now in a domain, I was able to blather my way through the install process for Remote Desktop Services. I used this guide as a basis.
- Once that is done, you need to do another completely insane manual PowerShell process, but this one is part of the official Microsoft documentation: Set up the Remote Desktop web client for your users. This also had some problems:
- You’ll need to update to the latest PowerShell version first. The article doesn’t mention it but it doesn’t work with the default PowerShell installed on Windows Server 2022 at least.
- Step one is “On the RD Connection Broker server, obtain the certificate used for Remote Desktop connections”. I wasn’t quite sure what this meant, but figured out it means just open “Manage user certificates” tool, look for the Remote Desktop category, and export the certificate in there. There was only one for me; I picked the first export option and saved it as a .cer file.
- Step 6 is importing that certificate via. The instructions say: “Next, run this cmdlet with the bracketed value replaced with the path of the .cer file that you copied from the RD Broker”. It should say “… replaced with the full absolute path” – I kept getting random PowerShell errors (
'Exception calling ".ctor" with "1" argument'
kind of thing). You can also run it with no parameter, and it will prompt you for the path
A brief segue – RemoteApps!
After all that, I kind of forgot what I was doing because I discovered these things called “RemoteApps” – basically, a way to let people Remote Desktop into a specific app! I started playing around with them as I thought this might be a neat compromise – people could just RD directly into Acrobat Reader and wouldn’t even need to deal with all of the rest of the experience!
Unfortunately this seemed a bit painful as it meant I still needed to figure out a way to get these PDFs onto the server in a place where the Acrobat process could access them.
Anyway, RemoteApps looked cool and worked perfectly once they were set up, ignoring the other problems, so that is something I’ll be coming back to.
Guacamole – an open source Apache project supporting Remote Desktop
I had recently heard about Guacamole, which looked interesting as a piece in this puzzle – perhaps it would solve one or more of the problems.
It was a real chore to get running. The documentation is great in some parts but confusing and contradictory in others. I started with the recommended Docker process in the hope that it would avoid compiling from source and mucking around with Linux too much, but I ran into a ton of problems with the Docker setup:
- The Docker version seems to have a hard requirement of one of the authentication modules, like MySQL. Some of the older documentation refers to a “noauth” solution (and LLMs will uselessly suggest this is an option) but lots of trial and error and reading docs and support tickets finally led me to the conclusion that with the Docker version there is no way to do this without an auth layer.
- Setting up MySQL is something I’ve done a million times, but not with Docker. My first experience sucked because the Docker instructions for MySQL seem wrong – the official image instructions say you can connect to the mysql CLI tool, but that flat out didn’t work for me, so I had to muck around trying to get that working. (I imagine Docker pros won’t have this issue but it was annoying that the most basic default instructions failed.)
- The RDP server I want to connect to is on our Tailscale tailnet. The Docker container can’t access the tailnet without setting up the Tailscale sidecar. This looks like a decent solution but I am not familiar or confident enough with Docker to bother mucking around with it.
So, deep sigh, let’s try compiling from source.
This turned out to be utterly painless and very fast. The biggest issue I had was deploying the .war file for the client – I set up a new Debian box, which installs Tomcat 10 by default. Everything looked like it was working, but I would just get random errors trying to load the Guacamole client.
I eventually discovered that this is just a basic compatibility issue with Tomcat 10. It’s frustrating that this info isn’t front and centre in the Guacamole documentation (or maybe it is and I just missed it).
I downgraded the box to Debian 11 and tried again with Tomcat 9 and it worked perfectly first go.
I ran into a few small issues that could be documented a bit better. I’ll summarise some things if you don’t want to read all the docs:
- First and most importantly, you do not need to set up a MySQL server for authentication, or any of the other authentication types. It will work fine out of the box with the basic authentication provided by the user-mapping.xml file
- You need to create a /etc/guacamole directory. Download the example user- mapping.xml file from their Github repo.
- Modify the XML file as required to test it out. I’d recommend testing with the default built in accounts (e.g., USERNAME2 / PASSWORD) to start with just to make sure you can log in to the Guacamole interface and the RDP connections are working as expected.
- Define your own connection(s). Note that the hashed passwords need to be generated with
echo -n [password] | sha256sum
, not justecho
. - I struggled to get NLA-less connections going. The Guacamole documentation references NLA and no NLA repeatedly so I was sure it was possible but I couldn’t find the right combination of parameters. Eventually I figured it out through trial and error, so here it is:
<connection name="acrobatbox">
<protocol>rdp</protocol>
<param name="hostname">8.8.8.8</param>
<param name="port">3389</param>
<param name="security">tls</param>
<param name="disable-auth">true</param>
<param name="ignore-cert">true</param>
<param name="resize-method">display-update</param>
<param name="normalize-clipboard">windows</param>
</connection>
- The key bits in the above are setting security to tls and disable-auth to true – this is the magic combination to disable NLA on the client side.
Once that was done, I finally had an RDP connection working via Guacamole which respected the need for no NLA, so I could log into the desktop with GCPW – success, right?!
Well, no. It turns out that Guacamole is a great piece of software which works amazingly well and covers a lot of ground, but unfortunately kind of sucks to use if one of your main requirements is using the clipboard a lot.
The way the clipboard in Guacamole works is… weird. The details are in the documentation, which, had I read before embarking on this journey, I might have not bothered.
The basic gist of it is you have a menu available when you’re connected to the server via Guacamole. In that menu is a text area. You can use that text area to move information back and forth between the two systems.
This is obviously not a great user experience. It must come up a lot, because it’s mentioned in their FAQ under a question that is approximately “why don’t you just make the clipboard work?”
The answer there implies though that it does work, at least as long as you’re using a modern browser that supports Clipboard API. I was testing with latest Chrome so figured I’d be OK, but it still wasn’t working.
Some more investigation revealed the problem: Chrome will only allow access to the clipboard if you’re accessing it via HTTPS. I set up an nginx proxy in front of it and tried again in a new browser – this time it actually prompted with with a browser notification to allow access to the clipboard, and it worked as expected, with the usual bi-directional clipboard flow working pretty much perfectly. The one exception to this is the login screen, where you can’t copy/paste the password, which is a small frustration, but probably manageable for most users.