Windows远程桌面配置-有网的地方都可访问家里的电脑

啰嗦的话放在最后,先上干货。
这篇文章仅为自己记录参考,方便以后新电脑重新配置。有的步骤如果不懂,不会过多解释。

需求

家里无法申请到公网ip,但是买了腾讯云/阿里云等的服务器有公网ip。希望通过配置,实现家中的电脑在有电有网的情况下,可以让任何其他有网络的地方都可以远程连接到家里的电脑。 且当遇到网络波动或故障时,在网络恢复后也能很快重新提供远程访问的能力。

参考

为了实现这一点,参考了一下几篇文章:
https://zhuanlan.zhihu.com/p/400086370
http://www.huangwenchao.com.cn/2016/10/windows-ssh-socks.html
https://blog.csdn.net/chg1226/article/details/117903288
下文很多内容,来自这三篇中内容的整合(后文不再特意说明某部分内容来自哪里),以及自己找的资料,让远程访问的能力更加完善,不会轻易挂掉无法重启。

准备

1 windows10 专业版
一般买电脑激活的都是windows10 家庭版。远程电脑的功能在专业版上,但是现在专业版限制只能企业来购买。所以个人只能去某宝十来块就可以解决。
2 云服务器
腾讯云/阿里云等可以购买云服务器,并且提供了公网ip
3 windows电脑下载 Cygwin
下载OpenSSH AutoSSH cygrunsrv
4 另一个设备用于测试
另一台电脑测试能否远程访问家里的电脑
或者安卓设备安装微软提供的官方app,测试远程访问家里的电脑
https://docs.microsoft.com/zh-cn/windows-server/remote/remote-desktop-services/clients/remote-desktop-clients
因为微软将app放到谷歌商店了,所以国内手机要使用就要找到apk文件,然后进行安装。可以从 apkpure 网站找一下。

详细步骤

激活windows 10专业版

某宝买然后找客服,按照步骤来就行了。

开启远程桌面功能

开始菜单 > 设置 > 系统 > 远程桌面”中启用远程桌面


启用远程桌面

安装Cygwin 安装OpenSSH AutoSSH cygrunsrv

进官网 https://www.cygwin.com/ 安装,进入傻瓜模式安装。注意,在选择安装包时,它会默认选中一些安装包,但是缺少OpenSSH,AutoSSH以及cygrunsrv。可以在左上角搜索下关键字,找到后,选择该条目的版本,它就会在后续安装时安装这个版本的包。
如果真的忘记这一步了,也没有关系。安装完 Cygwin 后,再次双击安装程序,一步一步走,走到选择安装包的那一步会发现刚才默认安装的包,程序都检测到安装好了,不会再次进行安装,因此只要我们选择自己想要的包,选择好版本,然后点击下一步,就可以安装新选择的包。

如果在执行 Cygwin 时遇到报错,考虑可能要右键图标,然后“以管理员身份运行”打开,就不会报错了。

SSH配置

以下命令在windows的cmd中运行

mkdir %userprofile%\.ssh

mklink /J "D:\mySoftWare\Cygwin\home\xzxz\.ssh" "%userprofile%\.ssh"

其中,第二个命令中的 D:\mySoftWare\Cygwin\home\xzxz\.ssh 你可以找到自己安装的 Cygwin 的安装目录,然后可以发现在该目录下有一个home文件夹,下面一般只有一个用户,假设我的用户叫做xzxz,最后加上 \.ssh即可。我的路径就是这么拼凑出来的。

这个命令的意思是, Cygwin 中用户xzxz下的 .ssh 文件实际上是链接到 windows 中的 %userprofile%\.ssh。也就是 Cygwin 中的 ssh 配置用的都是 windows系统的ssh配置。
两边都可以修改各自的.ssh文件,修改后对两边都生效。

以下命令在Cygwin中执行

ssh-keygen

ssh-copy-id -p 22 xxx@111.222.333.444

这两个命令是用于免密登录云端服务器用的。其中第二个命令中的 xxx@111.222.333.444 xxx 指的是登录云端服务器的用户名是什么,这个名字在你购买云服务器时就配置了登录用户和密码。而 111.222.333.444 指的时云服务器的公网ip,同样是在购买时,在购买商的控制台都可以看到这些信息。

这两步完成后,其实就意味着在Cygwin中可以免密登录云服务器了。而由于Cygwin的ssh配置其实和windows的是同一个,因此在windows中也可以免密登录云服务器了。可以通过下面的命令分别在 Cygwin 以及 windows系统的cmd中测试是否可以免密登录。

ssh xxx@111.222.333.444

将windows的ssh.exe同样link到Cygwin的bin目录中
与上面的找目录的方式一致,找到 D:\mySoftWare\Cygwin\bin 中,查看里面必须含有 autossh.exe 以及 ssh.exe。我遇到的情况是:我通过Cygwin安装了autossh,因此bin目录中有autossh.exe,但是没找到ssh.exe,因此将 windows 的ssh.exelink到这个目录了。如果你有ssh.exe可以不用管这一步,Link命令与上面类似,如下:

mklink  "D:\mySoftWare\Cygwin\bin\ssh.exe" "C:\Windows\System32\OpenSSH\ssh.exe"

云服务器配置

登录云服务器中,编辑云主机的/etc/ssh/sshd_config文件,找到 GatewayPorts 这个配置,一般是被注释掉的,打开它,然后配置其值是 yes。

GatewayPorts  yes

重启 sshd 服务

sudo service sshd restart

同时,在购买云服务器的提供商,如腾讯云/阿里云的控制台,将3389端口放行。以腾讯云为例,云服务器配置系统中找到“安全组”,可以摸索下,腾讯云默认提供了常用端口的放行规则。使用这个“一键放通”就好了。


腾讯云的配置

windows电脑的配置

在 %userprofile%.ssh 下新建一个 config 文件,填写以下内容:

Host myhost
  Hostname 111.222.333.444
  Port 22
  User xxx
  IdentityFile ~/.ssh/id_rsa
  RemoteForward 3389 localhost:3389
  ServerAliveInterval 100

在 Cygwin 中测试下:

ssh myhost

上面的命令会免密登录云服务器中。输入 exit 退出云服务器。会返回 Cygwin
继续测试 autossh

export AUTOSSH_DEBUG=1
autossh -M 4000 myhost

autossh --help可以看到该命令可以通过环境变量调整日志。
上面的第一个命令是设置一个临时环境变量,让autossh命令执行时,打印debug日志,便于调试问题。
第二个命令则是在云服务器开了一个家里的windows电脑桌面的3389端口,如果从其他地方的机器连接这个3389端口,流量会导到云服务器后面那台家里的windows电脑。

测试远程登录

此时,使用另一台电脑或者安装了apk的安卓设备,测试远程登录。其中ip输入的是云服务器的公网ip。而登录信息就是你家里电脑的登录名和密码。如果不知道登录名是什么,可以进入windows“设置”,然后搜索“账户”,选择找到的“管理你的账户”或者“你的账户信息”均可。


账户

可以看到,如果是管理员用户的话,下图中绿色部分的内容就是登录名。


登录名-管理员

或者,对于普通的本地用户,下图中马赛克部分的内容就是登录名。
登录名-本地用户

把autossh做成系统服务

打开一个有系统管理员权限的cmd,输入下面的命令:

cygrunsrv -I AutoSSH --path D:\mySoftWare\Cygwin\bin\autossh.exe -a "-M 4000 myhost -N" -e AUTOSSH_DEBUG=1 -e AUTOSSH_LOGFILE=/var/log/autossh.log -e AUTOSSH_NTSERVICE=1

命令中的路径根据自己的安装情况替换下。
这个命令会在 windows 系统的服务中创建一个名叫 AutoSSH 的服务。你可以打开Cygwin,然后进入 /var/log/ 目录中找到 autossh.log 。查看该服务的运行情况。如果遇到问题,会有debug日志打印到这个文件中。
我遇到的问题是无法在 Cygwin/bin 目录中找到 ssh.exe。这个问题在上文中通过link到windows的ssh.exe已经解决了。

你可以在windows 10系统的左下角,输入 “服务” 两个字,然后选择下图的图标打开服务。


windows服务

可以找到 AutoSSH 这个新建的服务。


AutoSSH服务

在这里,你可以手动的 启动/停止/重启动 这个服务。
至此,我们使用 autossh 可在网络不稳定时以及ssh超时后重新连接。同时将其做成了系统服务。

但是我们还是需要手动启动,并且一旦家里网络不稳定,导致断网,即便后续网络恢复正常,也有可能遇到远程访问家里的电脑也无法正常工作了。
这是因为有的时候,网络正常后,autossh可以发现并且尝试重连,但是云服务器对我们配置的 4000 3389端口还保持着监听,因此autossh也会在日志中打印报错信息。虽然在经过30~40分钟的超时重试后,最终autossh还是会放弃旧连接,建立新连接。但是时间太长了,我们想尽可能减少无法访问的时间。
所以,我们需要实现自动化:

  • 开机并且连接网络后就自动启动该服务,即便不登陆任何用户
  • 网络中断一段时间后,如果网络恢复了,就重启该服务,并将云服务器中对 4000 和 3389端口的监听进程kill掉。以便网络恢复后可以通过autossh与云服务器建立新的连接

自动化

windows wifi自动连接

如果是有线网不用考虑这个问题。
如果是无线网络,在设置中搜索“管理已知网络”


搜索-管理已知网络

然后点击


点击-管理已知网络

选中你常用的wifi,点击“属性”
点击-属性

将wifi自动连接的开关打开
wifi自动连接

设置成功后,在电脑开机时,到了用户登录页面,即便不登陆,也会自动发现并连接网络。

开机自启动服务

windows系统左下角,输入“任务计划程序”,点击进入。

任务计划程序

点击“创建任务”,见下图:
点击创建任务

在“常规”这个页面中,对照上图填写。其中注意一定要选择 不管用户是否登录都要运行,然后勾选中 使用最高权限运行
切换到“触发器”页面,按照下图4个步骤,比照图片操作好:
触发器配置

切换到“操作”页面
这个页面填写任务被触发时,要执行哪些命令。
如下图所示,会执行2个命令:先停止AutoSSH服务,然后再启动AutoSSH服务。
因此要先新建一个停止的命令,再新建一个启动的命令,就如同下图这样的上下的关系。
下图以新建一个停止的命令为例进行配置。启动命令的步骤与它类似,只是填写的参数稍有不同,都在下图体现了。
执行的命令

切换到“条件”页面
AutoSSH服务只有在wifi连接时才能提供远程桌面访问的能力。因此要配置成下图这样的条件。
条件配置

切换到“设置”页面
按照下图进行设置即可
设置页面

至此,开机后,即便不登录用户,等自动连接到网络后,就会自动开启AutoSSH服务,提供远程桌面访问的能力。
你可以此时重启电脑试一下。

网络故障恢复后执行脚本

如上文所述,当遇到网络故障后,我们就无法远程访问家里的电脑了,等网络恢复后,有的时候,即便我们使用autossh可以在网络恢复后尝试重新连接云服务器,但是由于云服务器还使用网络故障前的进程监听4000和3389端口,因此网络恢复后,autossh尝试重新连接云服务器也会失败。通过上文创建windows服务时的脚本,我们指定了autossh的日志文件位置,我们可以打开Cygwin,进入 /var/log 查看AutoSSH.log日志,会发现有如下报错:

Warning: remote port forwarding failed for listen port 4000
Warning: remote port forwarding failed for listen port 3389
日志

这时,如果登录云服务器,通过 sudo netstat -anpt | grep 4000 查找pid,然后kill掉该进程即可恢复远程访问能力。查找4000端口和查找3389端口找到的pid是一样的,因此这里就以查找4000端口为例进行说明了。

为了解决这一问题,我们需要一个脚本,该脚本可以周期性的运行,判断网络状态。如果发现网络由坏变好,就去云服务器删除旧的pid,然后重启windows服务AutoSSH。
其中,周期性的运行脚本是windows任务计划程序可以做到的事情,我们刚才也刚刚创建了一个电脑启动且联网后启动AutoSSH服务的任务计划程序。而另一个关键是编写一个脚本,可以后台运行上述判断及相关命令。

脚本
在云服务器中的脚本

通过ssh命令进入云服务器,如:

ssh xxx@111.222.333.444

因为已经配置好免密登录了,所以可以直接登进去。
进入后,请确认命令 netstat 是可以执行的。如果报错说找不到/不认识这个命令,你可以通过百度将netstat这个命令安装上。
进入当前用户目录,命令: cd ~,然后新建文件,命令:vi kill_old_remote_process.sh
将下面的内容填充到sh文件中:

#! /bin/bash
pid_4000=$(echo your_password| sudo -S netstat -anpt | grep 4000 | grep sshd | head -n 1 | awk '{printf $7}'| cut -d/ -f1)
echo $pid_4000
if [ -n "$pid_4000" ]
then
        kill -9 $pid_4000
else
        echo "4000 and 3389 port is not started"
fi

你需要将上面的your_password换成登录云服务器的密码。保存并退出。
这个脚本的作用是,通过netstat查找端口4000的进程id,如果存在的话就kill它,如果不存在正好。

最后,将这个文件设置为可执行文件,粗暴的命令:chmod u+x kill_old_remote_process.sh

在windows电脑的脚本

在D盘新建一个 remote_desk 的文件夹,用于保存脚本相关的文件。一定要是这个名字,因为和下面的脚本内容有关系,如果你可以修改脚本,可以自己找一个地方新建文件夹。
新建一个文件: check_net.bat ,并填充以下内容

@echo off
ping www.baidu.com
if errorlevel 1 (
    echo net disconnect. will create net_block file.
    @echo>"D:\remote_desk\net_block"
)else (
    echo net well! check net_block file exist or not!
    if exist D:\remote_desk\net_block ( 
        echo find net_block file, will delete it. Then kill previous pid in cloud server. Then stop service, finally start service.
        del /f /s /q D:\remote_desk\net_block
        ssh xxx@111.222.333.444 "bash ~/kill_old_remote_process.sh"
        cygrunsrv -E AutoSSH
        cygrunsrv -S AutoSSH
    )else ( 
      echo not find net_block file, will do nothing
    )
)

这个脚本的作用是通过ping百度,确认当前网络是否有问题。
如果有问题,就在文件夹下创建一个net_block文件。
如果没问题,代表网络是好的,此时有2种可能:

  • 网络刚刚从故障恢复为可用
  • 网络一直都可用

而判断这两种情况的关键,就是net_block文件。如果该文件存在,则说明上次运行该脚本时,还是网络有故障的,现在网络恢复了。
而这,正是上文说的,当网络由故障恢复正常后,需要kill掉云服务器上的进程,然后本地windows的AutoSSH服务重启下。
因此脚本中这部分的逻辑就是:

  • 删除net_block文件,这样下次运行即便网络也是通畅的,也因为缺少net_block文件,就能知道这不是网络刚刚恢复为可用,因此不用执行复杂的逻辑。
  • 云服务器kill以前的进程
  • 本地windows的AutoSSH服务重启

同目录下,再新建一个 check_net.vbs 的文件,填充以下内容:

CreateObject("WScript.Shell").Run "cmd /c D:/remote_desk/check_net.bat",0

这是因为 .bat 类型的文件,如果作为任务计划程序的命令执行文件,会出现黑窗口(也就是cmd的命令窗口),从而打扰当前正在使用电脑的人。因此这个vbs脚本就是隐藏这个窗口的。

新建任务计划程序 任务

与上文类似,进入任务计划程序,点击创建任务
”常规“页面
配置如下图。一般我们以登录的用户创建任务时,运行任务时,请使用下列用户账户的值是当前电脑的登录用户名。如果你测试后发现该用户没有足够的权限,那么可以像下图一样,配置为Administrators

常规页面配置

配置为Administrators的步骤:
点击更改用户或组,在弹出的窗口中,选择左下角的高级,在弹出的窗口中,选择右侧的按钮立即查找,然后双击下图箭头所指的用户

双击用户

注意不要双击错了,这两个就差了最后的字母s,我们需要双击的是带s的这个。
双击后,会返回上一个窗口,这时候点击确定

”触发器“页面
红色方框框起来的需要按照图片进行配置。

触发器配置页面

这样,就会在每天中,每间隔5分钟执行该任务。

”操作“页面
按照下图进行配置。其中需要注意,如果你把脚本放到其他地方,需要在这里确定脚本的路径是对的。

操作页面配置

”条件“页面
按照下图配置

配置

”设置“页面
按照下图配置

配置

保存该任务。

整体测试

至此,我们的配置全部完成。可以全流程走一遍,测试下各类情况下的表现。
1 重启电脑
电脑重启后,不输入密码,即不登录任何用户。可以看到此时右下角是有网络标志的,稍等一会会自动连上wifi。
而根据我们配置的第一个任务,会在电脑启动并且有网络时,即便没有登录,也会开启AutoSSH服务,提供远程桌面访问的能力。
所以,此时我们可以远程登陆下,测试结果预期是可以登录的。

2 验证网络波动 - 断网 -> 周期性任务执行 -> 联网 -> 周期性任务执行
对应超过5分钟的断网情况。
断掉网络连接,此时再次尝试远程登录,预期是无法成功的。
等待5分钟以上,让周期性任务可以执行一次,它会发现网络故障的问题,并创建 net_block 文件。
然后再恢复网络连接,等待周期性任务再次被执行,发现此时网络恢复了,根据脚本的命令会删除云服务器的旧的进程然后重启windows的AutoSSH服务。就可以继续提供正常的远程桌面访问能力了。

3 验证网络波动 - 断网 -> 等待/var/log/AutoSSH.log显示ssh报错日志 -> 联网 -> 周期性任务执行
对应3~5分钟的断网情况。
一开始断网后,观察日志没有立刻反馈有问题,估计是有超时设置。等了一会后,发现日志显示:

client_loop: send disconnect: Connection reset
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 752
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh exited with error status 255; restarting ssh
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: expired child, returning 1
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (404 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 0
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 2)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 753
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 753
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[753]: child of 751 execing /usr/bin/ssh
ssh: connect to host myhost port 22: Unknown error
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 753
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh exited with error status 255; restarting ssh
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: expired child, returning 1
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (600 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 1
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 3)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 754
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 754
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[754]: child of 751 execing /usr/bin/ssh
ssh: connect to host myhost port 22: Unknown error

一直重复这样的报错日志,说明它在努力尝试。
多次尝试后,就有了异常日志

Warning: remote port forwarding failed for listen port 4000
Warning: remote port forwarding failed for listen port 3389

根据之前积累的日志中的数据,发现就这样多次尝试,并且日志报错提示30、40分钟后,下一次尝试就成功了。下面是完整的日志。

client_loop: send disconnect: Connection reset
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 752
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh exited with error status 255; restarting ssh
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: expired child, returning 1
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (404 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 0
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 2)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 753
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 753
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[753]: child of 751 execing /usr/bin/ssh
ssh: connect to host myhost port 22: Unknown error
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 753
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh exited with error status 255; restarting ssh
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: expired child, returning 1
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (600 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 1
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 3)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 754
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 754
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[754]: child of 751 execing /usr/bin/ssh
ssh: connect to host myhost port 22: Unknown error
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 754
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh exited with error status 255; restarting ssh
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: expired child, returning 1
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (600 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 2
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 4)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 755
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 755
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[755]: child of 751 execing /usr/bin/ssh
ssh: connect to host myhost port 22: Unknown error
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 755
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh exited with error status 255; restarting ssh
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: expired child, returning 1
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (600 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 3
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 5)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 756
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 756
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[756]: child of 751 execing /usr/bin/ssh
ssh: connect to host myhost port 22: Unknown error
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 756
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh exited with error status 255; restarting ssh
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: expired child, returning 1
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (600 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 4
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 6)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 757
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 757
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[757]: child of 751 execing /usr/bin/ssh
ssh: connect to host myhost port 22: Unknown error
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 757
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh exited with error status 255; restarting ssh
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: expired child, returning 1
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (600 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 5
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 7)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 758
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 758
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[758]: child of 751 execing /usr/bin/ssh
ssh: connect to host myhost port 22: Unknown error
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 758
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh exited with error status 255; restarting ssh
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: expired child, returning 1
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (600 secs left)
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 6
2022/04/16 23:13:29 D:\mySoftWare\Cygwin\bin\autossh[751]: sleeping for grace time 2 secs
2022/04/16 23:13:31 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 8)
2022/04/16 23:13:31 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 759
2022/04/16 23:13:31 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 759
2022/04/16 23:13:31 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:13:31 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:13:31 D:\mySoftWare\Cygwin\bin\autossh[759]: child of 751 execing /usr/bin/ssh
ssh: connect to host myhost port 22: Unknown error
2022/04/16 23:13:31 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 759
2022/04/16 23:13:31 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh exited with error status 255; restarting ssh
2022/04/16 23:13:31 D:\mySoftWare\Cygwin\bin\autossh[751]: expired child, returning 1
2022/04/16 23:13:31 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (600 secs left)
2022/04/16 23:13:31 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 7
2022/04/16 23:13:31 D:\mySoftWare\Cygwin\bin\autossh[751]: sleeping for grace time 8 secs
2022/04/16 23:13:39 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 9)
2022/04/16 23:13:39 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 760
2022/04/16 23:13:39 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 760
2022/04/16 23:13:39 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:13:39 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:13:39 D:\mySoftWare\Cygwin\bin\autossh[760]: child of 751 execing /usr/bin/ssh
ssh: connect to host myhost port 22: Unknown error
2022/04/16 23:13:39 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 760
2022/04/16 23:13:39 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh exited with error status 255; restarting ssh
2022/04/16 23:13:39 D:\mySoftWare\Cygwin\bin\autossh[751]: expired child, returning 1
2022/04/16 23:13:39 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (600 secs left)
2022/04/16 23:13:39 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 8
2022/04/16 23:13:39 D:\mySoftWare\Cygwin\bin\autossh[751]: sleeping for grace time 18 secs
2022/04/16 23:13:57 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 10)
2022/04/16 23:13:57 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 761
2022/04/16 23:13:57 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 761
2022/04/16 23:13:57 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:13:57 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:13:57 D:\mySoftWare\Cygwin\bin\autossh[761]: child of 751 execing /usr/bin/ssh
ssh: connect to host myhost port 22: Unknown error
2022/04/16 23:13:57 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 761
2022/04/16 23:13:57 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh exited with error status 255; restarting ssh
2022/04/16 23:13:57 D:\mySoftWare\Cygwin\bin\autossh[751]: expired child, returning 1
2022/04/16 23:13:57 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (600 secs left)
2022/04/16 23:13:57 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 9
2022/04/16 23:13:57 D:\mySoftWare\Cygwin\bin\autossh[751]: sleeping for grace time 32 secs
2022/04/16 23:14:29 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 11)
2022/04/16 23:14:29 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 762
2022/04/16 23:14:29 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 762
2022/04/16 23:14:29 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:14:29 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:14:29 D:\mySoftWare\Cygwin\bin\autossh[762]: child of 751 execing /usr/bin/ssh
Warning: remote port forwarding failed for listen port 4000
Warning: remote port forwarding failed for listen port 3389
2022/04/16 23:24:29 D:\mySoftWare\Cygwin\bin\autossh[751]: received SIGALRM (end-of-life 0)
2022/04/16 23:24:44 D:\mySoftWare\Cygwin\bin\autossh[751]: timeout polling to accept read connection
2022/04/16 23:24:44 D:\mySoftWare\Cygwin\bin\autossh[751]: port down, restarting ssh
2022/04/16 23:24:44 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:24:44 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 0
2022/04/16 23:24:44 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 12)
2022/04/16 23:24:44 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 763
2022/04/16 23:24:44 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 763
2022/04/16 23:24:44 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:24:44 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:24:44 D:\mySoftWare\Cygwin\bin\autossh[763]: child of 751 execing /usr/bin/ssh
Warning: remote port forwarding failed for listen port 4000
Warning: remote port forwarding failed for listen port 3389
channel 2: open failed: connect failed: Connection refused
eceived SIGALRM (end-of-life 0)
2022/04/16 23:35:00 D:\mySoftWare\Cygwin\bin\autossh[751]: timeout polling to accept read connection
2022/04/16 23:35:00 D:\mySoftWare\Cygwin\bin\autossh[751]: port down, restarting ssh  这时候可以远程连接了
2022/04/16 23:35:00 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:35:00 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 0
2022/04/16 23:35:00 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 13)
2022/04/16 23:35:00 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 764
2022/04/16 23:35:00 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 764
2022/04/16 23:35:00 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:35:00 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/16 23:35:00 D:\mySoftWare\Cygwin\bin\autossh[764]: child of 751 execing /usr/bin/ssh
2022/04/16 23:45:00 D:\mySoftWare\Cygwin\bin\autossh[751]: received SIGALRM (end-of-life 0)
2022/04/16 23:45:00 D:\mySoftWare\Cygwin\bin\autossh[751]: connection ok
2022/04/16 23:45:00 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 764
2022/04/16 23:45:00 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/16 23:45:00 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs

4 验证网络波动 - 断网 -> 联网 -> 周期性任务
对应断网在3分钟内快速恢复的情况。
断掉网络连接,然后快速进行网络连接。模拟网络故障然后快速恢复的情况。
此时周期性的任务不要被触发执行,根据周期性任务的配置,是从每天的00:00:05秒开始每隔5分钟执行一次,因此只要掌握好断网的时间点就可以。
同时需要观察在 /var/log/autossh.log 中没有异常日志打印。
此时,经过验证,网络恢复后可以正常远程访问,在Cygwin的/var/log/AutoSSH.log中也没有看到异常日志。

问题

上面根据断网时长分为了3类:0 ~ 3分钟,3 ~ 5分钟,超过5分钟。
其中断网 3 ~ 5 分钟的情况等待的时间最长。是因为断网 3 ~ 5 分钟,有可能周期性任务没有被触发,从而无法感知到本次断网,就无法主动进行重启操作。只能依赖autossh的自动重连机制。而这个重连机制,经过测试,大约需要30 ~ 40分钟才会确认连接不可用,进行重新连接。所以,运气不好的情况下,可能家中的网络早已恢复,但是我们在外地还需要30 ~ 40分钟后,等待autossh重新建立新连接后,才能连接上。

改进

针对这个问题,有一个改进的方案:
我们在外地,无法干预家中的电脑,但是可以干预云服务器。
经过测试发现,在家中电脑有网络的情况下,无论当前远程访问可不可用,如果手动执行云服务器上的 kill_old_remote_process.sh 脚本。autossh下一次尝试时,在 Cygwin 的 /var/log/AutoSSH.log 文件中可以看到日志:

channel 2: open failed: connect failed: Connection refused
eceived SIGALRM (end-of-life 0)
2022/04/17 00:27:45 D:\mySoftWare\Cygwin\bin\autossh[751]: timeout polling to accept read connection
2022/04/17 00:27:45 D:\mySoftWare\Cygwin\bin\autossh[751]: port down, restarting ssh
2022/04/17 00:27:45 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/17 00:27:45 D:\mySoftWare\Cygwin\bin\autossh[751]: checking for grace period, tries = 0
2022/04/17 00:27:45 D:\mySoftWare\Cygwin\bin\autossh[751]: starting ssh (count 23)
2022/04/17 00:27:45 D:\mySoftWare\Cygwin\bin\autossh[751]: ssh child pid is 785
2022/04/17 00:27:45 D:\mySoftWare\Cygwin\bin\autossh[751]: check on child 785
2022/04/17 00:27:45 D:\mySoftWare\Cygwin\bin\autossh[751]: clear alarm timer (0 secs left)
2022/04/17 00:27:45 D:\mySoftWare\Cygwin\bin\autossh[751]: set alarm for 600 secs
2022/04/17 00:27:45 D:\mySoftWare\Cygwin\bin\autossh[785]: child of 751 execing /usr/bin/ssh

可以发现,autossh知道该连接不可用了,直接新建一个连接。节省了后续autossh超时重试的时间。

这样,我们在外地,发现远程访问超过5分钟无法成功。可以尝试登录云服务器。手动执行 kill_old_remote_process.sh 脚本,然后等待并重试即可。

在电脑肯定开机的前提下,我们在外地尝试多次,超过5分钟都无法远程访问,那么原因只有2个:
1 断网超过5分钟,目前仍然没有恢复
2 断网3 ~ 5分钟,家庭网络恢复了,但是因为autossh的超时重试机制需要30 ~ 40分钟,因此目前仍然不能访问。

此时,我们在云服务器手动执行 kill_old_remote_process.sh 脚本,分别对其的影响是:
1 断网超过5分钟的情况:没有任何影响。
因为断网超过5分钟,周期性任务肯定是感知到断网的情况了,不管我们现在有没有手动执行云服务器的脚本,等后面来网了之后,周期性任务也会执行windows脚本删除云服务器上的进程。
这种情况下,即便我们手动执行云服务器的脚本,也不会恢复和远程访问。需等待家庭的网络恢复,然后运行下一次周期性任务时,会发现网络由坏变好了,就会重启服务。
2 断网3~5分钟的情况:可以帮助快速恢复。
因为此时家庭有网了,只是autossh的超时重连机制导致没有立即重连。所以我们手动在云服务器执行脚本删除进程,等下一次autossh尝试时,就会放弃重试,而是新建立连接。
这样就不用等待30~40分钟,而是等待下一次autossh的连接尝试,即可恢复。

总结

经过上面的配置之后。只要提前把家里的电脑插上电开机。就会在启动且联网后(即便不登陆任何用户)提供远程访问的能力。
如果在外地远程访问连续超过5分钟都无法连上网。就登录云服务器,手动执行 kill_old_remote_process.sh 脚本。然后等待一段时间后就可以进行远程访问了。

如果是真的长时间断网,那么等待的时间很长,需要家中来网了,且下一次周期性任务执行后,才可以远程访问。最长的等待时间是:等待家中来网的时间+5分钟(周期性任务的执行周期),最短的等待时间是:等待家中来网的时间(周期性任务的执行时间点正好卡在来网的时候执行了)

如果是家里已经来网了,那就是autossh超时重连机制造成的无法远程访问,我们手工执行脚本后,需要等待下一次autossh尝试连接,根据日志总结的经验,最长需要等待10分钟才能等来autossh下一次尝试。最短就立即生效了(删除后,正好autossh尝试重连,就直接去建立新连接了。)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容