2

I've followed Scott Hanselman's instructions found this blog post to setup an open-ssh server

in summary I've done the following:

# in WSL2 - install openssh-server
sudo apt install openssh-server

# in WSL2 - check ssh version
ssh -V # -> OpenSSH_8.2p1 Ubuntu-4ubuntu0.4, OpenSSL 1.1.1f  31 Mar 2020

# in WSL2 - generate new host keys
ssh-keygen -t ras -b 4096 -f /etc/ssh/ssh_host_rsa_key
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key

The private keys have permissions set to 600, and the public keys are 644

My sshd_config for your reference

#   $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

Include /etc/ssh/sshd_config.d/*.conf

Port 2222
#AddressFamily any
ListenAddress 0.0.0.0
#ListenAddress ::

#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
#PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#PubkeyAuthentication yes

# Expect .ssh/authorized_keys2 to be disregarded by default in future.
# @amin: Removed second one AuthorizedKeysFile  .ssh/authorized_keys .ssh/authorized_keys2
AuthorizedKeysFile  .ssh/authorized_keys

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
#PermitEmptyPasswords no

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#PrintLastLog yes
#TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

# override default of no subsystems
Subsystem   sftp    /usr/lib/openssh/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
#   X11Forwarding no
#   AllowTcpForwarding no
#   PermitTTY no
#   ForceCommand cvs server

On WSL2 we don't have systemd so I start SSH with service ssh start

Now if I open up Powershell and ssh into my WSL2 using ssh -p 2222 myuser@wsl2ip I face no problems logging in with my password.

Next I copy over my windows public key from Win into WSL2 by running

type $env:USERPROFILE\.ssh\id_rsa.pub | ssh -p 2222 myUser@wsl2 "cat >> .ssh/authorized_keys"

and the contents there look like

ssh-rsa AAAAB3N************O1s= myWinUser@DESKTOP-AE*****

and the permissions in my WSL2 ~/.ssh look like

-rw------- 1   575 Jan 17 14:32 authorized_keys
-rw------- 1    97 Aug 30 11:17 config
-r-------- 1   411 Dec  2  2020 id_ed25519
-rw------- 1   100 Dec  2  2020 id_ed25519.pub
-rw------- 1  3389 Jan 17  2021 id_rsa
-rw-r--r-- 1   749 Jan 17  2021 id_rsa.pub
-rw-r--r-- 1  4866 Oct  7 16:19 known_hosts

, and turn off PasswordAuthentication by setting it to no in WSL2's sshd_config

Anytime I try to login with my ssh key I get

myuser@wsl2ip: Permission denied (publickey)

The same thing happens if I repeat the same process with RSA, RSA4096, or ED25519 keys.

What gives?

4
  • 1
    Post the entire sshd_config. Your key must have the proper permissions. Why did you generate a RSA and ED25519 key which one do you intend to use? Strongly suggest starting over and using the instructions listed here. Are you trying to make your WSL2 instance an OpenSSH Server? Why? Windows has that feature built-in
    – Ramhound
    Commented Jan 18, 2022 at 18:48
  • @Ramhound thanks! I've gone ahead and posted the entire sshd_config I've also mentioned the key permissions. To answer your other questions: 1. I mostly did them here to kinda "prove" that I have a clean setup and eliminate a piece of the puzzle 2. I do actually have SSH working directly into Win as you've mentioned, and am aware I could just run bash.exe but (I know I'm being a baby lol) I want to have these two worlds accessed separately. as for which key I'd like to use, to be honest either is fine, I was trying to provide more options I suppose
    – vvMINOvv
    Commented Jan 18, 2022 at 19:08
  • 1
    Your best bet to diagnose problems like that is to run sshd in debug mode. You will see why the key is rejected. Also, do you know about ssh-copy-id? Chances are, your home dir, .ssh dir or authorized_keys file have invalid permissions. Please provide the output of ls -al ~/.ssh.
    – Daniel B
    Commented Jan 18, 2022 at 19:10
  • @DanielB Thank you so much. Yea I might have misspoken there. ssh-copy-id is basically what I meant. Although it didn't seem like Win has ssh-copy-id so instead I ran something like type $env:USERPROFILE\.ssh\id_rsa.pub | ssh -p 2222 myUser@WLSip "cat >> .ssh/authorized_keys" I'll edit my post to include the ssh directory ls
    – vvMINOvv
    Commented Jan 18, 2022 at 21:40

1 Answer 1

5

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.


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
3
  • 1
    Thank you! 1. I didn't know you could run ssh in debug mode, that was super helpful 2. It turns out all my permissions were right EXCEPT for the actual .ssh folder. The contents were fine, but the directory itself was set to 777 not sure how that happened, that's ludicrous permissions... Thanks again
    – vvMINOvv
    Commented Jan 18, 2022 at 21:54
  • 1
    @vvMINOvv Excellent - Glad we (including those in the comments) helped. Do check back, as I'm working on finishing up my sshd recommendations. I realize if you have things working, then you might not want to switch at this point, but there are some nice features that you can get from it. Commented Jan 18, 2022 at 22:07
  • will do, thanks again
    – vvMINOvv
    Commented Jan 18, 2022 at 22:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .