2015 11 03 cygwin sshd - hanyong/note GitHub Wiki

windows 下安装 cygwin 和 sshd

由于习惯了 linux 命令行,我在 windows 下一般会安装一个 cygwin 环境,为了能够使用 ssh 登录机器,同时还会安装上 sshd 服务。

cygwin 经过这么多年的发展,已经日趋成熟,安装配置也相对简单。 下载运行安装程序,默认安装路径为 "C:\cygwin",我一般会改成 "D:\cygwin", 通常我会把 cygwin 安装程序本身和安装包下载也放到这个目录。 安装镜像选择一个国内速度较快的源,我一般用 ustc http://mirrors.ustc.edu.cn/ 。 软件包选择界面搜索一下 ssh,选上 openssh 服务器和客户端。 其他软件包按需选择,vim, wget, curl, tar, find, git 等这些常用的都可以选上,然后一路 next 即可完成安装。

我通常会将 cygwin 下驱动器前缀从 "/cygdrive" 修改为 "/",这样使用 "/c", "/d" 就可以访问 C 盘 D 盘。 并将 "/home" 目录定位到 "D:\home",这样我删除 cygwin 整个目录重装时我保存到 home 目录的东西不会丢。 即将 "/etc/fstab" 文件内容修改如下:

none / cygdrive binary,posix=0,user 0 0
D:/home /home ntfs binary,posix=0,user 0 0

安装完成后各种客户端工具就可以使用了,但 sshd 服务还要再额外配置一下, 配置过程也相对简单,cygwin 提供了一个配置脚本 ssh-host-config,需要注意的是要以超级管理员 (Administrator) 权限运行这个脚本。 以超级管理员权限打开一个 cygwin 终端,运行 ssh-host-config,有几个配置项,基本上一路 yes 就可以了, 除了 CYGWIN 环境变量留空,cyg_server 用户是否改名选 no,设置一个密码,我一般随意设置一个简单的 "abc123"。 这个密码会在随后的脚本输出中明文打出,有点坑爹,所以不要输入敏感密码。 配置脚本会在系统中创建一个 sshd 用户和一个 cyg_server 用户,安装一个名为 sshd 的服务。 这个服务会在下次启动电脑时自动启动,或者使用 "net start sshd" 或 "cygrunsrv --start sshd" 手动启动。 之后 ssh 使用本机用户名密码就可以远程登录机器了。

最近因为在 vps 上重装了 windows/ubuntu 双系统, cygwin 和 ubuntu 生成的 ssh host key 不一样,导致切换系统后 ssh 登录总会报错。 既然是一台机器一个IP一个域名,那么应该使用相同的 key, 看了下 cygwin 和 ubuntu host key 文件个数和名字都一样,只是文件路径稍微有点差异 (ubuntu 下多了一层 ssh 子目录)。 打算直接用 ubuntu 的 host key 覆盖 cygwin,ubuntu 下操作如下:

rsync -av /etc/ssh/ssh_host_* /d/cygwin/etc/

操作完切回 windows 后发现 sshd 服务无法启动了,"net start sshd" 启动服务失败,没说什么原因。 google 了一下貌似说是一些目录的权限问题。 因为中间我切换过用户,不知道是不是用户切换导致权限问题, 不去研究了,直接将 cygwin 下所有目录和文件删除重装,将 host key 拷回去,再重新配置 ssh-host-config,结果还是不行。 甚至重装系统再重装 cygwin 搞了下还是不行。 因为 D 盘跟 C 盘不在一个磁盘,我都有点怀疑是不是 D 盘文件系统权限有点问题了。 直接在 C 盘重装了一次,这次不做任何自定义配置了,结果可以了,sshd 服务配置启动 ok 了。

在 windows 下复制粘贴把 host key 拷过去覆盖,结果报错说无法覆盖,突然想到应该是 host key 的权限问题, 查看 cygwin 默认生成的 host key 文件权限是这样的:

$ ls -l /c/cygwin/etc/ssh_host_*
-rw------- 1 cyg_server Administrators  668 十一  3 19:33 /c/cygwin/etc/ssh_host_dsa_key
-rw-r--r-- 1 cyg_server Administrators  616 十一  3 19:33 /c/cygwin/etc/ssh_host_dsa_key.pub
-rw------- 1 cyg_server Administrators  227 十一  3 19:33 /c/cygwin/etc/ssh_host_ecdsa_key
-rw-r--r-- 1 cyg_server Administrators  188 十一  3 19:33 /c/cygwin/etc/ssh_host_ecdsa_key.pub
-rw------- 1 cyg_server Administrators  419 十一  3 19:33 /c/cygwin/etc/ssh_host_ed25519_key
-rw-r--r-- 1 cyg_server Administrators  108 十一  3 19:33 /c/cygwin/etc/ssh_host_ed25519_key.pub
-rw------- 1 cyg_server Administrators 1675 十一  3 19:33 /c/cygwin/etc/ssh_host_rsa_key
-rw-r--r-- 1 cyg_server Administrators  408 十一  3 19:33 /c/cygwin/etc/ssh_host_rsa_key.pub

而之前重装 cygwin 时 windows 复制粘贴过去的 host key 文件权限是这样的:

$ ls -l /d/cygwin-bak3/etc/ssh_host_*
-rwxr-xr-x 1 cyg_server Administrators  668 六月 27 03:03 /d/cygwin-bak3/etc/ssh_host_dsa_key
-rwxr-xr-x 1 cyg_server Administrators  597 六月 27 03:03 /d/cygwin-bak3/etc/ssh_host_dsa_key.pub
-rwxr-xr-x 1 cyg_server Administrators  227 六月 27 03:03 /d/cygwin-bak3/etc/ssh_host_ecdsa_key
-rwxr-xr-x 1 cyg_server Administrators  169 六月 27 03:03 /d/cygwin-bak3/etc/ssh_host_ecdsa_key.pub
-rwxr-xr-x 1 cyg_server Administrators  399 六月 27 03:03 /d/cygwin-bak3/etc/ssh_host_ed25519_key
-rwxr-xr-x 1 cyg_server Administrators   89 六月 27 03:03 /d/cygwin-bak3/etc/ssh_host_ed25519_key.pub
-rwxr-xr-x 1 cyg_server Administrators 1679 六月 27 03:03 /d/cygwin-bak3/etc/ssh_host_rsa_key
-rwxr-xr-x 1 cyg_server Administrators  389 六月 27 03:03 /d/cygwin-bak3/etc/ssh_host_rsa_key.pub

发现问题后,在 D 盘重装 cygwin,配置好 sshd 服务后再使用 cp 命令拷贝 host key 过去覆盖:

cp /d/cygwin-bak2/etc-bak/ssh_host_* /etc/

使用 cp 不带任何参数,避免修改目标文件的权限,再重启 sshd 服务发现是 ok 的。

随后又发现一个问题,可以使用密码登录,但无法使用 publickey 登录。 客户端 ssh 添加 "-v" 参数打印连接认证过程没发现什么问题。 初步怀疑也是文件权限问题,但看了下 ".ssh/authorized_keys" 文件权限没什么问题。 尝试看看服务端日志,在 "/var/log/" 目录下找到一个 "sshd.log" 文件,可是是空的,没任何内容, 修改 sshd_config 文件把 LogLevel 调到最低的 DEBUG3 级别,"sshd.log" 文件还是空没任何内容。 google 了一下说 sshd 默认日志会打到 syslog,而在 windows 下就是 windows event log。 windows event log 什么鬼?不知道怎么看。 又说 sshd 有个参数 "-e",可以把调试日志打到标准错误 stderr, 而看了下 "cygrunsrv --help","/var/log/" 目录下的服务日志实际上就是服务进程标准输出和标准错误的重定向文件。 这么说只要启动 sshd 时添加一个 "-e" 参数,就可以在 "/var/log/sshd.log" 看到日志。 可是 sshd 是作为一个服务安装的,直接运行不行,也是报文件权限问题。 解决办法就是重新安装下 sshd 服务,在其运行时添加下 "-e" 参数,再重新启动服务。

停止并删除 sshd 服务:

cygrunsrv --stop sshd
cygrunsrv --remove sshd

看一下 ssh-host-config 脚本,查到安装 sshd 服务的命令用法,简化之后的命令如下:

cygrunsrv --install sshd -p /usr/sbin/sshd -u cyg_server -w abc123 -a "-D -e"

恢复 sshd_config 配置,默认日志级别是 INFO。 重启服务之后果然在 "/var/log/sshd.log" 看到日志:

Server listening on 0.0.0.0 port 22.
Authentication refused: bad ownership or modes for directory /home/hanyong/.ssh
Authentication refused: bad ownership or modes for directory /home/hanyong/.ssh
Connection closed by 42.120.74.99 [preauth]
Authentication refused: bad ownership or modes for directory /home/hanyong
Authentication refused: bad ownership or modes for directory /home/hanyong
Connection closed by 42.120.74.99 [preauth]
Accepted publickey for hanyong from 42.120.74.99 port 32992 ssh2: RSA SHA256:6uEGyyw8lW/UciF999xuouorcTd+bV1C8KD6YisPyAo

开始报 ".ssh" 目录权限问题,设置 "chmod 700 .ssh",修正后报 "$HOME" 目录权限问题,设置 "chmod 755 ~", 之后使用 publickey 登录 ok。

修复问题后重新安装 sshd 服务去掉 "-e" 参数,恢复默认配置。 停掉所有 sshd 进程 (断开所有 ssh 连接), 执行 cygrunsrv --remove sshd 删除服务, 再重新运行 ssh-host-config,是否覆盖配置选择 no, 重新安装服务即可.