PowerShell / Win32-OpenSSH

Win32 port of OpenSSH
7.36k stars 757 forks source link

Hyper-V Socket Support (built-in support for hvc.exe ssh command) #2200

Open awakecoding opened 8 months ago

awakecoding commented 8 months ago

Summary of the new feature / enhancement

hvc.exe is a built-in Hyper-V command-line tool with the ability to open an SSH connection over Hyper-V sockets, which are an extension to the regular WinSocket APIs that use the VMBus as a transport, allowing direct host/guest communication. The "hvc.exe ssh" command works by calling ssh.exe from the system (Win32-OpenSSH) with special arguments such that it calls "hvc.exe nc" (a netcat-like command) to open the Hyper-V socket transport and redirect socket input/output to standard input/output which is then used by the parent process. This feature request would be to add support for Hyper-V sockets directly in Win32-OpenSSH instead of using a chain of processes wrapped within the other.

Through experimentation, I have managed to make a proof-of-concept where "ssh" is replaced by "hvc ssh" in Enter-PSSession from PowerShell 7, allowing me to connect to Windows and Linux Hyper-V VMs that have the OpenSSH server configured. The biggest issue preventing this from becoming usable is that while Win32-OpenSSH is used by PowerShell, there are no options to pass a custom replacement command: it expects ssh.exe and nothing else. If we were to officially support Hyper-V sockets directly in Win32-OpenSSH, then PowerShell could leverage it directly without hacks where ssh.exe is replaced by a fake OpenSSH client command.

psdirect-hvc-ssh

In terms of value, this would solve two main problems:

  1. Bring PowerShell 7 "Direct" support for Windows guests
  2. Bring PowerShell 7 "Direct" support for Linux guests

While SSH over Hyper-V sockets is not identical to PowerShell Direct, it would be a good alternative. The VM guest doesn't need functional networking, as listening on the loopback interface from the OpenSSH server should work (the connection appears to be coming from the guest, not the host, because of the VMBus!). There doesn't seem to be interest from the Hyper-V team to improve PSDirect which is unfortunately only supported in Windows guests, using Windows PowerShell. As for Linux PSDirect support, it simply never existed. PowerShell Direct is an awesome feature which can be used to build entire Hyper-V labs using scripts driven from the Hyper-V host.

To open a regular ssh connection to a Hyper-V guest using hvc.exe ssh, it looks like this:

PS C:\> hvc.exe ssh -l Administrator@ad.it-help.ninja IT-HELP-WAC
Administrator@ad.it-help.ninja@hyper-v/it-help-wac's password:

Simple enough, right? If you take a look at the chain of commands and subprocesses in Process Explorer, it's a lot more complicated:

hvc.exe ssh -l Administrator@ad.it-help.ninja IT-HELP-WAC
cmd.exe /c ssh.exe -o ProxyCommand="hvc.exe nc -t vsock,ip --ssh --host-prefix hyper-v/ \"%h\" %p" -o HostName=hyper-v/%h -l Administrator@ad.it-help.ninja IT-HELP-WAC
ssh.exe -o ProxyCommand="hvc.exe nc -t vsock,ip --ssh --host-prefix hyper-v/ \"%h\" %p" -o HostName=hyper-v/%h -l Administrator@ad.it-help.ninja IT-HELP-WAC
hvc.exe nc -t vsock,ip --ssh --host-prefix hyper-v/ "hyper-v/it-help-wac" 22

In the case of Enter-PSSession, the command is different as it uses the "powershell" subsystem, and what you get over standard input/output is actually raw MS-PSRP instead of the regular textual interactive shell. However, the way it works is exactly the same as shown above, and we could support it without having ssh.exe call a chain of subprocesses like that.

This feature request only covers porting the functionality from the "hvc.exe ssh" command to be supported built-in in Win32-OpenSSH, which would require adding support for Hyper-V sockets. The PowerShell integration for a "PowerShell 7 Direct" feature that it would unblock should be tracked as a separate feature request following this one.

eponerine commented 8 months ago

Love this! The usage goes beyond just "setting up labs", but can also be leveraged to fix "broken Linux guests" in Azure with the click of a button (assuming you have local guest creds).