Aaron's Blog

在wsl下安装使用sshd全攻略.md

wsl是微软对Windows Linux Subsystem的官方叫法。安装wsl后,通过bash来启动这个子系统,然后可以安装ssh。在我的windows发行版上,启用了wsl以后,ssh就默认存在了。但要真正使用起来,还要注意以下几点。

sshd-config

最重要的配置是这两项:

1
2
3
UsePrivilegeSeparation no #因为wsl没有实现chroot
PasswordAuthentication yes
ListenAddress 0.0.0.0 #这一项在我的发行版里缺省为注释行。

为安全起见,我将listen address由0.0.0.0改成了127.0.0.1。

关掉原生的ssh server

较新的windows版本自带了一个ssh server,也监听在22端口。你可以通过power shell来查看这项服务:

1
2
3
4
5
6
PS C:\Users\yangy> Get-Service -Name ssh*
Status Name DisplayName
------ ---- -----------
Stopped SshBroker SSH Server Broker
Stopped SshProxy SSH Server Proxy

这是显示关闭以后的状态。这个服务必须关掉,不然wsl的ssh service是无法启动起来的。在windows服务里找到这两个服务:

启动和调试

  1. 首先以/usr/sbin/sshd -d的方式启动服务。-d表明是以调试方式启动的服务,这种情况下,错误会显示在控制台上。在我的电脑上,不存在/var/log/secure日志文件,所以无法以传统linux的方式来做troubleshooting。
  2. 在另一个bash窗口中输入 ssh username@localhost -v。可以使用-v -vv, -vvv来加重输出日志的详细程度。在我的电脑上出现过connection closed的错误,查看sshd -d窗口的输出,提示No supported key exchange algorithms。这是因为在sshd_config中这一段中指定的key文件不存在:
    1
    2
    3
    4
    5
    # HostKeys for protocol version 2
    HostKey /etc/ssh/ssh_host_rsa_key
    HostKey /etc/ssh/ssh_host_dsa_key
    HostKey /etc/ssh/ssh_host_ecdsa_key
    HostKey /etc/ssh/ssh_host_ed25519_key

这种情况下需要用ssh-keygen来生成这些文件:

1
2
3
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key

  1. 如果以上步骤通过,那么现在可以使用下述方法启动:
    1
    sudo service ssh --full-restart

要注意即使以这种方法启动ssh server,它仍然只是在存在bash窗口时的一个子服务。一旦最后一个bash窗口关闭,这个ssh server也就关闭了,显然这不是我们想要的。接下来看看怎么将ssh server以windows服务或者后台进程来运行。

运行为windows后台进程

当前WSL并不支持ssh server作为服务运行。我们需要借助windows计划任务和脚本,使得在windows启动时自动运行这一服务。

1
2
set ws=wscript.createobject("wscript.shell")
ws.run "C:\Windows\System32\bash.exe -c 'sudo /usr/sbin/sshd -D'",0

将这个文件存为vbs,并在计划任务中添加一个启动任务,触发器设置为系统启动时。
上述脚本存在一个问题,就是执行sudo时,会提示输入密码,而这时又无法拿到用户的输入。要解决这一问题,需要允许sudo在没有密码的情况下执行命令。

在bash窗口中运行sudo visudo:

1
2
#includedir /etc/sudoers.d
$username ALL=(ALL) NOPASSWD: /usr/sbin/sshd -D

这里的$username即wsl子系统中的一个用户名。我使用了安装wsl时给出的一个用户名。