TL;DR: Here's the Link:

I use RDP a lot and had some scripts to let me launch lots of RDP sessions without having to enter my random-generated passwords over and over. I wasn't happy with how I was handling those passwords so I've made it more secure using gpg and KeePassXC. Last night I made it compatible with Windows and MSTSC which will be uploaded here shortly once it's cleaned up a bit.

Basically I'll click a shortcut for whatever host, which runs my launcher. I get prompted for my GPG passphrase, which reads from an encrypted file containing my KeePassXC passphrase, which is then used to retrieve the user password for launching the RDP session.

Gpg-agent uses a cache-TTL to "hold the door open" for 10 minutes by default, so I can launch a bunch of sessions and only type my passphrase once.


- gpg client and running gpg-agent (gpg4win, etc) with a private key set up, etc.
- cygwin if you're running Windows
- KeePassXC (or some other key-store that has a command-line interface
to query the database. In the beginning I was just using the gpg file
with user/password pairs, so that works too)

The tool has a few neat features:

- If run from the command line with no arguments, it will prompt for user/pass/host/domain, good for one-off sessions to machines I won't log into much. That's great since I spend all my time in terminal windows and this stops me having to go back and forth to the mouse and keyboard while entering credentials.

- If launched with -b, it prompts you for information for a one-off connection, but will also build a new shortcut launcher from a template. So like for the first connection to a machine you know you're going to use a lot. (Linux/Mac only)

- Automatically tunnel sessions over ssh. This means I can launch RDP sessions on my Mac and they'll seamlessly proxy through my work laptop to the VPN.

For tunneling, I am taking an arbitrary range of 200 ports and incrementing them based on what's currently listening. If there's already a process listening on port 6201, then try 6202 etc until there's an open one. So I can easily open 20-30 ssh tunneled sessions each with its own ssh process which will close down when the RDP window closes. 200 is "probably overkill", which means it might just be barely enough in the real world.

The launcher shortcut mechanics are a bit different on my Linux and Mac machines so I split the -b script builder piece out based on OS. On Linux, I use KDE/Plasma, and so I generate these as KDE desktop files which look like this:

#!/usr/bin/env xdg-open
[Desktop Entry]
Exec=/home/xrayspx/bin/rdplauncher.sh -h it-host.xrayspx.com -d xdomainx -u xrayspx

On the Mac side, I use shell scripts with the extension .rdp (which conflicts with Microsoft's client, but I don't care since I never use their client anyway). Those just launch using Terminal, so it does pop a terminal for a fraction of a second, but I really don't have a problem with that. To get the Terminal window to close (and I do associate these files with Terminal.app specifically rather than iTerm2), open Terminal.app, go to the Terminal menu -> Settings -> Profiles (tab) -> "Basic" or whatever profile is your default -> Shell (tab). Choose what action to take when the shell exits. I have it set to "Close if the shell exited cleanly" and "ask before closing" set to "only if there are processes other than the login shell..."

The launcher for that looks like:

#! /bin/bash
rdplauncher.sh -h host.xrayspx.com -d xdomainx -u xrayspx &

I generate those from the KDE .desktop files with a command like this:

for host in $(ls | grep "\.desktop$" | awk -F ".desktop" '{print $1}'); do cmd=$(grep Exec $host.desktop | awk -F "xrayspx/bin/" '{print $2}'); echo "\!#/bin/zsh" >> $host.rdp; echo "$cmd &" >> $host.rdp; done

That creates .rdp files in the same directory as the .desktop files, so now they can be moved around, have chmod set, etc.

If I call it with AppleScript or Automator instead of a bash script as above, none of the password retrieval process works. I think it short circuits and sends the output back to the AppleScript rather than the bash script which ran the command. If I can get that working that would be ideal.

The mechanics on Windows are similar to the Mac method. a .bat file which launches the bash script via Cygwin:

C:\cygwin64\bin\mintty.exe -w hide -e /bin/bash -l -c '/home/user/bin/rdplauncher.sh -h host -u username -d domain'

On Windows at least the Cygwin window it creates is hidden from the user, so that's nice.