OlmschenkEarth logo

NAS IDE SSH set up for Windows

This tutorial is designed to set up the JetBrains IDEs, running on Windows, to have a good connection to the NASA NAS servers. It should be largely applicable to other IDEs as well. In this setup, we create an SSH configuration that pipes SSH traffic through the Windows Subsystem for Linux (WSL) SSH client, but makes that configuration envokable from the regular Windows SSH client.

Reasoning for the workaround

If you just want it to work but don’t care why we need to do something special to get it to work, you can skip this section.

NAS uses a non-standard gateway server SSH command. That is, for the Secure Front End server (sfe) that you need to jump through to get to other NAS servers, NAS chose to make their own special commands that must be used on that intermediate jump server, rather than using existing, standard SSH jump commands. During this non-standard command, input is also requested from the user (they are prompted for an RSA OTP).

JetBrains uses SSHJ, an programmatic SSH library, internally for its SSH connections. Due to the non-standard NAS SSH jump server commands, the SSH connection requires a shell command. This results in us dropping out of SSHJ and calling the default SSH client on the system. SSHJ is designed to give programmatic access to SSH, not to provide arbitrary access to shell interfaces. So, to allow the RSA OTP password prompt to be visible to the user, we need to tell the default system SSH client to provide this prompt via a separate method. OpenSSH (the default SSH client on most systems), allows for the setting of an arbitrary program that will be called in the event that a user prompt is required. This “askpass” program is usually just a small GUI prompt popup program.

On macOS and Linux, just setting this askpass program during the special intermediate server command would be sufficient. Unfortunately, Windows’ default SSH client causes additional issues in this case. The Windows OpenSSH client, contrary to other OpenSSH clients, does not provide multiplexing support. Multiplexing support allows a single connection to be made to an SSH host, and then multiple virtual connections can be established through that one real connection. JetBrains takes advantage of this to open several virtual connections in the background while doing various tasks. Even on Windows, this isn’t normally a problem, because SSHJ provides its own multiplexing. However, because NAS uses a non-standard command, we switch from SSHJ to the system SSH client. Without multiplexing, this results in a huge number of RSA OTP prompts.

The workaround used here is to take advantage of the WSL SSH client. Since this is running the Linux version of OpenSSH, it does have multiplexing. So in this tutorial, we will make sure the WSL SSH client is setup properly to with an askpass program, then create a wrapper that the default Windows SSH client can use to direct traffic through that WSL client.

If NAS switches to standard SSH jump client commands, no special configuration of any sort is needed (as everything would stay within SSHJ). If the Windows version of OpenSSH implements multiplexing, the simpler workaround used on macOS and Linux can be used (which is just adding an askpass program). However, the combination of these requires a the more complex workaround here. That said, it’s not terribly complex and works nicely once set up.

Obtaining a WSL distro

You’ll need a distro installed for WSL. This tutorial will use Ubuntu, but most distros should be fine. You can list installed distros using

wsl --list

To install Ubuntu, use

wsl --install Ubuntu

The rest of the tutorial assumes you are working in your default WSL instance. You can adjust this to work in a secondary WSL if needed.

Setting up the WSL SSH configuration

Note

We’re about to edit your OpenSSH config file (usually stored at ~/.ssh/config). It’s a good idea to make a backup of this file first in case something goes wrong. I usually copy it and append the date (e.g., ~/.ssh/config_yyyy_mm_dd).

This assumes you have already completed the NAS SSH passthrough tutorial, and therefore have already added your SSH public key to the NAS servers.

Within your WSL instance, you’ll need to have a ~/.ssh (keep in mind, this is the one within your Linux home directory, not the Windows home directory). This may have been created previously. Here, we’ll setup pfe to have the required configuration, but other NAS front-ends are similar. In your ~/.ssh/config file, add

Host sfe
    User golmsche
    ForwardAgent yes
    Hostname sfe6.nas.nasa.gov
    IdentityFile ~/.ssh/nasa_nas

Host sfe sfe?.nas.nasa.gov
    ControlMaster          auto
    ControlPath            ~/.ssh/master-%r@sfe:%p
    ControlPersist         1
    ServerAliveInterval     5m
    User golmsche
    ForwardAgent yes
    Hostname sfe6.nas.nasa.gov
    IdentityFile ~/.ssh/nasa_nas

Host sfe sfe?.nas.nasa.gov sup*.nas.nasa.gov
    LogLevel                info
    ProxyCommand            none

Host pfe pfe-last pfe.nas.nasa.gov pfe-last.nas.nasa.gov
    User golmsche
    HostKeyAlias            pfe20.nas.nasa.gov
    Port                    29810
    ForwardAgent yes
    IdentityFile ~/.ssh/nasa_nas
    ProxyCommand            /usr/bin/env SSH_ASKPASS_REQUIRE=force SSH_ASKPASS=/home/golmschenk/.ssh/askpass_error_on_cancel_wrapper.sh ssh -a -oCompression=no sfe ssh-balance %h

You will need to replace golmsche with your NAS username, golmschenk with your WSL username, and nasa_nas with the name of your NAS private SSH key file. Notably, in this configuration, we are always passing the key agents along with the key files, and we are adding the ASKPASS environment variables during the ProxyCommand.

In the above configuration, we reference an askpass script that should be called. Create that script at ~/.ssh/askpass_error_on_cancel_wrapper.sh, and inside it put

#!/bin/bash
result=$(ssh-askpass "$@")
if [ $? -ne 0 ] || [ -z "$result" ]; then
	exit 1
fi
echo "$result"

This script still expects ssh-askpass to be installed. On Ubuntu, you can install that with

sudo apt update
sudo apt install ssh-askpass ssh-askpass-gnome

You’ll also need your NAS SSH key to be in ~/.ssh (probably duplicated from your Windows .ssh directory).

Lastly, make sure all the file permissions are correct. The ~/.ssh/askpass_error_on_cancel_wrapper.sh script needs to be excutable (if needed, run chmod +x on it). And the .ssh directory and it’s contents need to follow standard SSH file permissions.

Setting up the Windows SSH configuration

JetBrains will be using the Windows SSH configuration file. So we still need a small wrapper on the Windows side to tell that SSH configuration to use the WSL configuration. This is relatively simple though. In your Windows .ssh/config file add

Host pfe_through_wsl
    Hostname localhost
    User golmsche
    IdentityFile ~/.ssh/nasa_nas
    ForwardAgent yes
    Port 22
    HostKeyAlias pfe20.nas.nasa.gov
    ProxyCommand wsl ssh -W localhost:22 pfe

Again, replace golmsche with your NAS username and nasa_nas with the name of your NAS private SSH key file. Again, you need the private key file to exist in both the Windows and WSL .ssh directories. This host uses the WSL configuration to connect all the way to PFE. Then, the Windows SSH client just treats that existing connection as being on the localhost. We still need the credentials in the Windows SSH configuration, because ProxyCommand only creates a transport layer through WSL, while still SSH protocol running through the Windows SSH client.

Using the connection

Your connection should now be set up. As a quick test, from a new Windows terminal, you should be able to use ssh pfe_through_wsl. You should get a single RSA OTP prompt. While that connection is open, if you open another terminal and again connect with ssh pfe_through_wsl, it should connect without asking for another RSA OTP.

Similarly, you can now use the pfe_through_wsl host as your target host for the JetBrains IDEs. If no existing connection is open, it will ask for the RSA OTP a single time. JetBrains will hold open the connection, and any other connections through the IDE will not require another RSA OTP.