Remote desktop connectors - BYUHPC/7lbd GitHub Wiki

Why are connectors necessary?

One of the main security features of 7lbd is that all job processes run in a network namespace with no external routes. This means that every process running in a 7lbd Open OnDemand job has a completely separate network stack, set up by the spank_iso_netns plugin exclusively for that job. These network stacks are 100% independent from one another, each with its own interfaces, routing tables, nft/iptables rulesets, etc. They do not share any elements with the host’s operating system network stack.

In our 7lbd network namespaces, we do not set up any external routes for network traffic to get in or out of a job’s network namespace. Consequently, there is absolutely no way for any cluster or internet traffic to communicate with these job processes, and no job process can reach out to any network or internet resource. This means there is no email, no Internet, no DNS, no Active Directory—nothing. The only possible network connectivity for 7lbd job processes is to contact other processes within the same job. These include our Windows VM, a guacd container, a samba server, and the specially designed connectors provided with 7lbd. There are three connectors that specifically allow remote desktop access to the Windows VM running in the namespace: a Guacamole Connector, a noVNC connector for admins, and an oodproxy mTLS connector for direct RDP access.

7lbd Connectors(1)

How do the connectors work?

To understand how 7lbd connectors work, we first need to understand how file descriptors work in Linux. Whenever Linux opens a file, socket, or pipe, the process that calls the "open" command stores a reference to that item in what is known as a file descriptor table. Each entry in the file descriptor table contains an integer, followed by additional information to describe the location of the open resource. The most important behavior of file descriptors for our discussion is that when a process forks, the child process inherits the parent's file descriptor table. That means that the child process can access all files, sockets or pipes that the parent process had open.

In the case of our 7lbd Slurm job, the spank_iso_netns plugin opens three sockets on our public network interface and binds an available port to each. The Spank plugin then retrieves the file descriptor numbers associated with these open ports. Next, the network namespace is created for the job, and all processes started by the job inherit the file descriptor table from the Spank plugin. That means when the Open OnDemand job launches the VM along with the three remote desktop connectors, all of these processes inherit the same file descriptor table.

There is no way for a process created inside the 7lbd network namespace to open a socket that can talk outside the namespace. Sockets are subject to the network stack under which they are created, and the network stack inside the 7lbd namespace has no external routes. This is why our 7lbd remote desktop connectors are not programmed to open a socket and listen on an address and port; instead, they are programmed to listen on an inherited file descriptor. Because these file descriptors are inherited from a process created before the network namespace was established, they retain full access to the external network.

For example, consider the following standard Node.js code to open a socket on port 3000.

server.listen(3000, '0.0.0.0', () => { console.log('Server is listening on port 3000.'); }); 

If this code were to be run inside a 7lbd job in the network namespace, the listener could only be accessed by other job processes. That is why the ISO NETNS Spank plugin opens the needed sockets and binds them to ports before the network namespace is created.

Now, consider the server.listen() command below. In this instance, another process has already opened the socket and bound it to a port; the actual listen call has already been run by the spank_iso_netns plugin. In the code below, we are simply helping the "server" object know where the existing socket lives by providing it with a valid file descriptor. If that inherited file descriptor points to a socket that was created outside of the network namespace, then it will be able to communicate externally.

server.listen({ fd: myFd }, () => { 
  console.log('Server is listening using the provided file descriptor.'); 
});

These connectors are the only processes inside the network namespace that are programmed to listen on file descriptors; all other software running inside the job uses traditional network configurations and does not know how to communicate via a file descriptor. This design allows us to maintain complete control over network traffic—all traffic must pass through our connectors.

The Three Connectors

This card shows an example job run by an administrator with all three connectors enabled. Normally, the VNC Console would not be exposed to regular users. If connectors are disabled, their connection buttons will not be present on the card. Note that for the “RDP” option, there is a drop-down menu to choose which client software to use for RDP. This option is available only for Linux clients. Windows clients will use the native MSTSC software, and there is currently no support for the TLS Proxy on a Mac (we do not have a Mac to develop the browser plugin on).

7lbd_card

Guacamole VM Console oodproxy RDP
guac_thumbnail vm_console_thumnail oodproxy_rdp_thumnail
Guacamole demo
Web-based RDP for speed and convenience
VM Console demo
Web-based VNC console for administrators
oodproxy RDP demo
Direct RDP access through a custom proxy

1. Guacamole-Based Web RDP (Browser-Based RDP)

Guacd Connector Architecture

Description:
This solution provides a browser-based RDP (Remote Desktop Protocol) connection to Windows-based VMs. Users simply open their browser, click on the Open OnDemand job card, and view the Windows desktop—no additional software is required on their local machine. While it leverages Apache Guacamole’s underlying code, this is not a full Guacamole installation; instead, a custom, streamlined server-side application is built and installed specifically for this environment.

Key Points:

  • User Setup: No additional user-side software installation is required.
  • Server Setup: Requires building some server-side code and installing the Open OnDemand 7lbd application.
  • Integration: Uses the standard Open OnDemand reverse proxy with no additional configuration changes, similar to other web-based Open OnDemand apps (e.g., JupyterLab, VSCode).
  • Ideal Use Case: General desktop access to Windows VMs with no client installation or additional server components.
  • Performance and Features: Performance is nearly equivalent to that of a dedicated RDP client; however, some features such as audio may not be configured.

2. VNC Through noVNC (Web-Based Console Access)

VNC Console Connector Architecture

Description:
VNC through noVNC provides direct access to the VM’s console, similar to sitting at the VM’s own monitor. This method is particularly useful for system administrators who need to troubleshoot boot issues or interact with the VM at a low level.

Key Points:

  • User Setup: No additional user-side software is required; access is provided through a web browser.
  • Server Setup: Requires installing the 7lbd Open OnDemand app with no modifications to the Open OnDemand configuration.
  • Integration: Uses the existing websockify and reverse proxy infrastructure, similar to other noVNC-based Open OnDemand apps (e.g., MATLAB).
  • Ideal Use Case: Troubleshooting and low-level maintenance of VMs.
  • Performance: There may be noticeable mouse lag; not recommended for general use.

3. oodproxy mTLS (FreeRDP, Remmina, MSTSC)

oodproxy mTLS Architecture

Description:
The oodproxy mTLS connector allows Remmina, FreeRDP, or MSTSC to connect directly to the VM via RDP.

Key Points:

  • User Setup: Requires an RDP client such as FreeRDP, Remmina, or MSTSC on Microsoft Windows, and additionally requires the installation of stunnel and a script launcher to manage the connections.
  • Server Setup: Involves installing and configuring a custom proxy server, BYU's oodproxy on a server with a public IP address.
  • Performance and Features: Performance and features depend on the RDP client used for connection.
⚠️ **GitHub.com Fallback** ⚠️