远程唤醒并使用无公网IP的电脑

因为全球IPv4地址的短缺,现在家庭宽带用户一般都没有公网 IP,就算动态的公网 IP 也没有。这样,远程使用家里电脑就不像原来那么容易了。这里分享一种低成本的远程唤醒并使用无公网IP电脑的思路和具体代码,供有一定电脑基础的朋友参考。(演示视频《手机内网穿透远程桌面》: https://space.bilibili.com/1744354915/channel/seriesdetail?sid=417246 )

一、方案概述
使用一部 Android 手机作为远程远程唤醒的中介设备,Android 版本5.0 或以上,运行内存至少 2G,与被唤醒电脑置于同一局域网。唤醒时需要一部有公网 IP 的电脑,且这台电脑的对外端口是自己可以控制的,这台电脑可以与客户端电脑是同一电脑。主要思路是在手机上安装 Termux,Termux 内安装 ssh 服务器和局域网唤醒工具,并布置一段 ssh 反向连接代码,把 那部有公网 IP 电脑的特定端口反向转发到 ssh 服务器和被唤醒电脑的远程服务(如桌面)端口。这样,通过那台公网电脑就可以进入 Android 手机内调用其中的唤醒工具来唤醒局域网中的电脑了。详情如下。

二、设置有公网IP的那台电脑
一)、安装 Linux 接受 Android 手机和唤醒客户端的连接。Android 手机会把这台 Linux 电脑上的特定端口反向连接到自身的 ssh 服务器远程访问端口和被唤醒的电脑的远程桌面连接端口。然后,访问这台公网电脑的特定端口就可以访问 Android 手机和被唤醒电脑了。
二)、这里使用 Debian 10,安装 openssh-server 用于上面的远程连接。假设公网 IP 为1.2.3.4,开放的端口这里假设为 22、8022、3389,为了减少复杂性,都使用默认的端口设置。端口 22 用于访问这台公网电脑的 ssh 服务器,8022 用于访问访问中转用的 Android 手机里的 ssh 服务器,3389 用于访问被唤醒电脑的 Windows 远程桌面。
三)、这台公网电脑可以一直开着,也可以需要的时候再开,Android 手机里的连接脚本会在公网电脑开启后自动连接上并转发需要的端口。
四)、公网电脑可以选用各大厂商的云服务器,也可以是你正在使用的客户端里安装的一台 Linux 虚拟机。在一些云服务器厂商有个别的型号不用销毁实例,可以有停机不收费的选项,按量付费,正好可以用于偶尔连接一下被唤醒电脑的情况,使用完毕选择停机不收费关机就行了。
五)、如果要有良好的操作远程被唤醒电脑的体验,尤其是比如远程电脑上CAD制图,建议带宽至少10M。普通的远程操作1M带宽也行。一些按量付费的云电脑可以最大设置到100M的带宽。你可以根据自己的需要多测试一下选择适合的带宽。

三、设置被远程唤醒的局域网电脑
这个问题在网上提及的比较多,大家稍一搜索就会了。这里只说3个要点:
一)、被远程唤醒的电脑必须是通过与路由器直接连接的有线网卡。
二)、在主板的 BIOS 设置中开启网卡远程唤醒功能,各种主板的设置项稍有不同,可以在里面找一下或参考主板说明。笔记本电脑有的没有相关选项,一般默认是开启了的。
三)、在操作系统里设置一下与路由器相连的有线网卡,开启远程唤醒功能。记下网卡的 MAC 地址备用。这里假设是:00:11:22:33:44:55。
四)、开启需要远程访问的端口,如 Windows 远程桌面的 3389 端口。另外,得让本机的防火墙允许外部访问3389端口。

四、设置作为远程唤醒中介的 Android 手机
一)、设置手机无线连接到同一局域网的路由器,且一直保持无线连接状态,注意设置手机的亮屏时间尽可能长,可能有助于保持无线连接。因为这部手机设置好后就丢在那里不会再动,建议一直连着充电器。
二)、在 Android 手机上安装 Termux 终端模拟器(https://termux.com/)。Termux 可以运行 Linux 程序,并且不必获取手机的 root 权限。最新版本的 Termux 0.114 (https://f-droid.org/packages/com.termux/)需要 Android 7.0 及以上版本。这里有一篇关于 Termux 的中文文档供参考:Termux 高级终端安装使用配置教程(https://www.sqlsec.com/2018/05/termux.html)。然后在 Termux 里面安装一些必须的 Linux 程序:openssh、screen、perl 、wol 等。用 passwd 命令设置一下密码。在 termux 里面执行 sshd 开启 ssh 服务器远程访问。然后,在电脑上连接 Android 手机里的 Termux,添加我们需要的连接脚本。Termux 的 ssh 服务端口为 8022。关键的代码如下:

ssh -p 22 -R 8022:localhost:8022 -R 3389:192.168.1.101:3389 mdx@1.2.3.4

执上述代码后,Termux 的 ssh 客户端会把远程主机 1.2.3.4 上的 8022 和 3389 端口转发到其自身内的 ssh 服务器的端口 8022 和处于同一局域网内 192.168.1.101的3389远程桌面端口。这样,在有互联网的任一台电脑上,通过 ssh 客户端连接到那台有公网IP的主机1.2.3.4 的 8022 端口,就进入了 Android 手机的 Termux 里面。在 Termux 里执行 wol -i 192.168.1.255 -p 9 00:11:22:33:44:55 就会唤醒对应后面网卡MAC所在的主机。然后,在任一电脑上使用远程桌面客户端连接 1.2.3.4 的 3389 端口就可以访问被唤醒的那台电脑的桌面了。
三)、如果你只有 Android 5、6的废弃手机,那么你可以安装旧版的 Termux 0.83 ( https://www.apkmirror.com/apk/fredrik-fornwall/termux/termux-0-83-release/ ),不过里面的软件不会更新,可能会有一些旧软件造成的安全问题。另外,你也可以使用另一款 Android 手机上的 Linux 发行版模拟器 UserLAnd (https://f-droid.org/zh_Hans/packages/tech.ula/ ),它当前的新版本 2.7.3 可以运行在 Android 5 及以上。

五、实际脚本
一)、脚本要点:
1、Termux 里使用 screen 终端让自动连接脚本在后台运行;
2、Termux 里循环检测 ssh 连接的状态,在服务器上线的情况下可以及时自动重连;
3、Termux 里在 ssh 连接中,可以使用密钥对自动连接,在连接卡死的情况下,用 timeout 命令强制结束连接并重新连接;
4、Termux 里可以杀掉公网IP服务器里疑似卡死的 ssh 连接并重新连接。
二)、Android 手机 Termux 里的 4 个脚本,均放在目录 data/data/com.termux/files/usr/bin/applets/ 下面:
1、名称:su2,作用:主启动脚本,打开 Termux 后执行它就能启动断线重连程序

#!/data/data/com.termux/files/usr/bin/bash
termux-wake-lock
sshd
screen -dmS su2 -t u2 u2
screen -X -S su2 screen -t op
exit 0

2、名称:u2,作用:实际连接脚本

#!/data/data/com.termux/files/usr/bin/bash
export TZ='Asia/Chongqing'
pub_ip=1.2.3.4
pub_home=/home/user
loc_ip=192.168.1.101

while true; do
  echo "Now is: $(date)"
  echo "check if reversed ssh to pub work..."
  timeout --preserve-status 60 \
    ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
    -p 8022 user@${pub_ip} ls ${HOME}/vtt.txt
  if [[ "$?" -ne "0" ]]; then
    timeout 60 \
      ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
      -p 22 user@${pub_ip} ${pub_home}/bin/killrssh
    [[ -n "$(screen -list | grep 's2t')" ]] && screen -X -S s2t quit
    screen -dmS s2t -t ssh2te \
      ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
      -p 22 -R 8022:localhost:8022 -R 3389:${loc_ip}:3389 user@${pub_ip}
  fi
  sleep 10s
done

exit 0

3、名称:tu2,作用:进入查看 screen 的各终端

#!/data/data/com.termux/files/usr/bin/bash
screen -dr -S su2 -p u2
exit 0

4、名称:wakeit,作用,唤醒同一局域网的电脑

#!/data/data/com.termux/files/usr/bin/sh
wol -i 192.168.1.255 -p 9 00:11:22:33:44:55
exit 0

三)、有公网IP服务器里的1个杀掉疑似卡死 ssh 连接的脚本名称:killrssh,作用:杀掉疑似卡死 ssh 连接的脚本

#!/bin/bash
rpid=$(sudo netstat -tpln | grep '0.0.0.0:8022' | awk '{print $7}' | cut -d '/' -f 1)
if [[ -n "${rpid}" ]]; then
  echo "reversed ssh pid is: ${rpid}"
  kill -9 ${rpid}
  echo "`date`: killed reversed ssh pid: ${rpid}." | tee -a ${HOME}/bin/killrssh.log
else
  echo "no reversed ssh process of port 8022"
fi
exit 0

另外,为了使用管理员权限执行 netstat 而不输入密码,使用 sudo visudo 编辑器加入如下代码:

user     ALL=NOPASSWD: /bin/netstat

注意,这里的 user 和上面脚本里的 user 用户名均需要换成你自己的。
上述方案我已经成功运行数月,稳定有效。如果你已经布置了远程使用电脑的方案,也可以把这套方案作为第一或第二方案,增加远程使用电脑的稳定性。欢迎感兴趣的朋友使用交流。需要的朋友也可以考虑购买我的“学习日记小店”的收费服务( https://xxrjxd.taobao.com/ )。

发表评论

电子邮件地址不会被公开。 必填项已用*标注