Skip to main content
added 5746 characters in body
Source Link
NotTheDr01ds
  • 23.6k
  • 6
  • 70
  • 112
  • First, the most likely reason for it failing is as Ramhound mentioned in the comments -- Key permissions. You just mentioned copying over the private key from Windows to ~/.ssh/authorized_keys, but you didn't mention changing the permissions. Try:

    chmod 600 ~/.ssh/authorized_keys
    
  • Hopefully, that will work, but if it doesn't, try:

    sudo service ssh stop
    sudo mkdir /run/sshd
    sudo chmod 0755 /run/sshd
    sudo /usr/sbin/sshd -d
    

    That will run sshd in the foreground with additional debugging. Hopefully that will tell you why the key is being denied.


Preferred Method of Enabling SSH into WSL2

The page you linked to in your question is the one that says:

DO NOT DO THE INSTRUCTIONS IN THIS POST until you have read the FOLLOW UP THE EASY WAY how to SSH into Bash and WSL2 on Windows 10 from an external machine and made the right decision for YOU!

So I'd be curious why you selected the older, port-forwarding method over the alternative that he proposes for setting the Windows OpenSSH shell to the bash.exe (outdated info, but still works) command.

Regardless, I (and others) feel there's a much better alternative to either of Hanselman's techniques.

Advantages of this method:

  • No port forwarding required
  • Minimal firewall work needed since it relies on Windows services
  • Works even if you have multiple WSL distributions installed
  • Works with sshfs, scp, sftp, Ansible, and any app or service that requires a real SSH connection.

The summary is that:

  • We rely on WSL2's ability to forward "localhost" connections on Windows to WSL (a.k.a. localhost forwarding).
  • We use Windows OpenSSH server as a JumpHost to the WSL2 OpenSSH server.

The initial setup for this is the same as for Hanselman's "easy method". Start by enabling the Windows OpenSSH server on port 22.

  • As before(Especially for future readers) I recommend simply following the Microsoft docs for the latest information, saving this postbut I'm copying the relevant commands in here so thatas well. From PowerShell:

    # Sounds like you had the Client already installed, at least
    Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 
    Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
    
    Start-Service sshd
    Set-Service -Name sshd -StartupType 'Automatic'
    
    # Confirm the Firewall rule is configured. It should be created automatically by setup. Run the following to verify
    if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue | Select-Object Name, Enabled)) {
        Write-Output "Firewall Rule 'OpenSSH-Server-In-TCP' does not exist, creating it..."
        New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
    } else {
        Write-Output "Firewall rule 'OpenSSH-Server-In-TCP' has been created and exists."
    }
    
  • Recommended if you haveare an Administrator on your Windows install -- Edit C:\Program Data\ssh\sshd_config and comment out the following lines:

    #Match Group administrators
    #       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
    
  • While you are editing that information while, I continueassume you will want to write up the alternative methodset:

    PasswordAuthentication no
    
  • By default, Windows OpenSSH looks for enabling sshC:\Program Data\ssh\administrators_authorized_keys (see this question). By commenting these lines out, you will use your %userprofile%\.ssh\authorized_keys instead.

  • Add your public key to %userprofile%\.ssh\authorized_keys. Make sure that permissions are restrictive per this answer (or related answers).

  • Confirm that you can log to Windows OpenSSH from WSL using your key:

    ssh -i <path_to_private_key> "${HOSTNAME}.local"
    

At this point, you really have terminal access to WSL2 through Windows OpenSSH already.

From any machine on the network:

ssh -t <windows_host_or_ip> wsl

This will simply run the wsl command after the connection to Windows.

That works for shell access, but if you need "real" ssh access to WSL for Andible, sshfs, sftp, scp, etc., then read on ...

Next (for anyone else reading this) configure OpenSSH in WSL. You've done this part already. And port 2222 is a good option.

Copy over your public key to ~/.ssh/authorized_keys (already done for you) and make sure your permissions are correct (as mentioned above).

If you haven't already, add your private key to ssh-agent via:

eval $(ssh-agent) # under Linux
ssh-add <path_to_key

(Note: Windows also supports ssh-add. Just make sure the "OpenSSH Authentication Service" is running).

At this point, you can use the Windows host as your JumpHost like so:

ssh -J <windows_host_or_ip> -p 2222 localhost

This connects to the Windows OpenSSH server (on port 22) which then turns around and connects to localhost:2222, which is your WSL2 instance.

As mentioned, this will now work for scp, sshfs, etc.


Optionally:

This technique has one "side-effect", in that localhost is stored as the same "known host" regardless of which port or jump host you use to connect. So if you do connect to multiple WSL instances in this way, ssh will start complaining about potential man-in-the-middle issues.

The best way to avoid this (and simplify things in general) is to create a Host entry in ~/.ssh/config. Let's say your Windows host name is bubblegum and your WSL distro is ubuntu. Add the following to ~/.ssh/config:

Host bubblegum_ubuntu  # Can be whatever you want
Hostname localhost
User <username> # If needed
Port 2222
ProxyJump bubblegum
UserKnownHostsFile ~/.ssh/known_hosts_bubblegum_ubuntu

That will redirect the known_host entry to a file that is only used for that particular host.

It also means that you can now:

ssh bubblegum_ubuntu
scp bubblegum_ubuntu:/home/username/filename .
sftp bubblegum_ubuntu
sshfs bubblegum_ubuntu:/ /mountpoint
  • First, the most likely reason for it failing is as Ramhound mentioned in the comments -- Key permissions. You just mentioned copying over the private key from Windows to ~/.ssh/authorized_keys, but you didn't mention changing the permissions. Try:

    chmod 600 ~/.ssh/authorized_keys
    
  • Hopefully, that will work, but if it doesn't, try:

    sudo service ssh stop
    sudo mkdir /run/sshd
    sudo chmod 0755 /run/sshd
    sudo /usr/sbin/sshd -d
    

    That will run sshd in the foreground with additional debugging. Hopefully that will tell you why the key is being denied.

  • As before, saving this post here so that you have that information while I continue to write up the alternative method for enabling ssh.

  • First, the most likely reason for it failing is as Ramhound mentioned in the comments -- Key permissions. You just mentioned copying over the private key from Windows to ~/.ssh/authorized_keys, but you didn't mention changing the permissions. Try:

    chmod 600 ~/.ssh/authorized_keys
    
  • Hopefully, that will work, but if it doesn't, try:

    sudo service ssh stop
    sudo mkdir /run/sshd
    sudo chmod 0755 /run/sshd
    sudo /usr/sbin/sshd -d
    

    That will run sshd in the foreground with additional debugging. Hopefully that will tell you why the key is being denied.


Preferred Method of Enabling SSH into WSL2

The page you linked to in your question is the one that says:

DO NOT DO THE INSTRUCTIONS IN THIS POST until you have read the FOLLOW UP THE EASY WAY how to SSH into Bash and WSL2 on Windows 10 from an external machine and made the right decision for YOU!

So I'd be curious why you selected the older, port-forwarding method over the alternative that he proposes for setting the Windows OpenSSH shell to the bash.exe (outdated info, but still works) command.

Regardless, I (and others) feel there's a much better alternative to either of Hanselman's techniques.

Advantages of this method:

  • No port forwarding required
  • Minimal firewall work needed since it relies on Windows services
  • Works even if you have multiple WSL distributions installed
  • Works with sshfs, scp, sftp, Ansible, and any app or service that requires a real SSH connection.

The summary is that:

  • We rely on WSL2's ability to forward "localhost" connections on Windows to WSL (a.k.a. localhost forwarding).
  • We use Windows OpenSSH server as a JumpHost to the WSL2 OpenSSH server.

The initial setup for this is the same as for Hanselman's "easy method". Start by enabling the Windows OpenSSH server on port 22.

  • (Especially for future readers) I recommend simply following the Microsoft docs for the latest information, but I'm copying the relevant commands in here as well. From PowerShell:

    # Sounds like you had the Client already installed, at least
    Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 
    Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
    
    Start-Service sshd
    Set-Service -Name sshd -StartupType 'Automatic'
    
    # Confirm the Firewall rule is configured. It should be created automatically by setup. Run the following to verify
    if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue | Select-Object Name, Enabled)) {
        Write-Output "Firewall Rule 'OpenSSH-Server-In-TCP' does not exist, creating it..."
        New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
    } else {
        Write-Output "Firewall rule 'OpenSSH-Server-In-TCP' has been created and exists."
    }
    
  • Recommended if you are an Administrator on your Windows install -- Edit C:\Program Data\ssh\sshd_config and comment out the following lines:

    #Match Group administrators
    #       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
    
  • While you are editing that, I assume you will want to set:

    PasswordAuthentication no
    
  • By default, Windows OpenSSH looks for C:\Program Data\ssh\administrators_authorized_keys (see this question). By commenting these lines out, you will use your %userprofile%\.ssh\authorized_keys instead.

  • Add your public key to %userprofile%\.ssh\authorized_keys. Make sure that permissions are restrictive per this answer (or related answers).

  • Confirm that you can log to Windows OpenSSH from WSL using your key:

    ssh -i <path_to_private_key> "${HOSTNAME}.local"
    

At this point, you really have terminal access to WSL2 through Windows OpenSSH already.

From any machine on the network:

ssh -t <windows_host_or_ip> wsl

This will simply run the wsl command after the connection to Windows.

That works for shell access, but if you need "real" ssh access to WSL for Andible, sshfs, sftp, scp, etc., then read on ...

Next (for anyone else reading this) configure OpenSSH in WSL. You've done this part already. And port 2222 is a good option.

Copy over your public key to ~/.ssh/authorized_keys (already done for you) and make sure your permissions are correct (as mentioned above).

If you haven't already, add your private key to ssh-agent via:

eval $(ssh-agent) # under Linux
ssh-add <path_to_key

(Note: Windows also supports ssh-add. Just make sure the "OpenSSH Authentication Service" is running).

At this point, you can use the Windows host as your JumpHost like so:

ssh -J <windows_host_or_ip> -p 2222 localhost

This connects to the Windows OpenSSH server (on port 22) which then turns around and connects to localhost:2222, which is your WSL2 instance.

As mentioned, this will now work for scp, sshfs, etc.


Optionally:

This technique has one "side-effect", in that localhost is stored as the same "known host" regardless of which port or jump host you use to connect. So if you do connect to multiple WSL instances in this way, ssh will start complaining about potential man-in-the-middle issues.

The best way to avoid this (and simplify things in general) is to create a Host entry in ~/.ssh/config. Let's say your Windows host name is bubblegum and your WSL distro is ubuntu. Add the following to ~/.ssh/config:

Host bubblegum_ubuntu  # Can be whatever you want
Hostname localhost
User <username> # If needed
Port 2222
ProxyJump bubblegum
UserKnownHostsFile ~/.ssh/known_hosts_bubblegum_ubuntu

That will redirect the known_host entry to a file that is only used for that particular host.

It also means that you can now:

ssh bubblegum_ubuntu
scp bubblegum_ubuntu:/home/username/filename .
sftp bubblegum_ubuntu
sshfs bubblegum_ubuntu:/ /mountpoint
Source Link
NotTheDr01ds
  • 23.6k
  • 6
  • 70
  • 112

A few thoughts:

  • First, the most likely reason for it failing is as Ramhound mentioned in the comments -- Key permissions. You just mentioned copying over the private key from Windows to ~/.ssh/authorized_keys, but you didn't mention changing the permissions. Try:

    chmod 600 ~/.ssh/authorized_keys
    
  • Hopefully, that will work, but if it doesn't, try:

    sudo service ssh stop
    sudo mkdir /run/sshd
    sudo chmod 0755 /run/sshd
    sudo /usr/sbin/sshd -d
    

    That will run sshd in the foreground with additional debugging. Hopefully that will tell you why the key is being denied.

  • As before, saving this post here so that you have that information while I continue to write up the alternative method for enabling ssh.