在某些场景下,我们需要在外远程访问家中的电脑。例如,最近过年回家时,有些服务需要远程查看,因此我折腾了使用 FRP 远程访问家中 Mac 的方法,还有远程唤醒电脑的 WakeOnLan 方案。
使用 FRP 和 WakeOnLan 远程电脑的方法
本文的大纲如下:
- 如何使用 FRP 远程
- FRP 远程的体验
- FRP 的安全性和 TLS 抓包
- WakeOnLan 的需求
- WakeOnLan 的配置
- 最后
如何使用 frp 远程
FRP 的远程访问逻辑非常简单。由于家庭宽带通常不提供公网 IP(目前申请公网 IP 通常需要额外付费,具体方式需咨询运营商),因此需要通过服务器进行网络中转。
配置的过程中使用的是安全地暴露内网服务方式,这里简称为 stcp,使用的版本是v0.61.0。
Mac 自带的远程访问方式为 VNC,需要打开「设置」,「共享」,「屏幕共享」,并且打开「允许使用密码控制屏幕」。
服务端 frps 的配置为 frps.toml
,启动命令为 ./frps -c frps.toml
1 | bindPort = 7100 # 服务器监听端口 |
在深圳的机器上,运行 FRP 客户端配置文件 frpc.toml
如下,启动命令为 ./frpc -c frpc.toml
。
1 | serverAddr = "xxx" # 服务器域名 |
在外电脑运行 frpc 配置为 frpc.toml
,启动命令为 ./frpc -c frpc.toml
1 | serverAddr = "xxx" # 服务器域名 |
启动之后,打开 macos 自带的「屏幕共享」软件,按照配置连接127.0.0.1:6000
,输入账号密码即可远程使用。
FRP 远程的体验
macOS 的远程使用的协议是 VNC 协议,相比于 Windows 的 RDP 协议体验会差一些。由于 macOS 的复杂动效和高分辨率,会很卡,把 macOS 的分辨率调整为 1080P,开启系统设置中的「减弱动态效果」,但是微信打开图片依然有渐变的动画,其他更深层次的优化设置没去研究了。
找了一下相关的帖子,例如 Mac 上最流畅不卡的远程控制另外一台 Mac 的方法是什么?和求远程 mac 的最佳方式。在原生的 VNC 协议上,想要获得较好的体验就得加带宽,4Mbps 的带宽都很难获得较好的体验,最近云厂商出了峰值 200Mbps 的服务器体验会稍微好一点。其他类似 teamviewer 和向日葵之类的软件就没有去尝试了。
在「屏幕共享」连接成功后,点击顶部状态栏的「编辑」菜单,选择「使用共享的剪切板」,这样可以方便地在两台机器之间复制粘贴内容。文件传输方面,把文件拖动到目标电脑的「访达」目录即可。
FRP 的安全性和 TLS 抓包
另外对于 FRP 的安全性进行了简单的探究。
- 部署在公网服务器上的 FRP 服务如何不被别人盗用?
在服务器的配置文件中设置了auth.token = "xxx" # 服务器验证密码
来保证不知道 auth.token 的用户无法使用。 - FRP 协议传输数据的过程中是否有加密处理?
在以前讨论里有流量被嗅探 #3193相关的讨论。在 2023 年 6 月,FRP v0.50.0 默认使用了 tls 协议来进行加密,但是在 frps 随机生成的证书没有校验,做到这个程度已经差不多了。如果要进一步提升安全性,就自己配置证书。
我通过抓包也看到在三次握手完成之后,就开始走 TLS 协议。
WakeOnLan 的需求
原本到这里应该就结束了,让电脑永不休眠就可以了。然而我给电脑用上了「小米智能插座 3」,发现电脑在正常空跑的情况,在留存 Chrome、微信和 QQ 的情况下,功耗一般在 55-70w 之间。
如果是休眠状态,电脑功耗仅需要 3W。值得一提的是,我买了 Macmini M4,即使空跑也只有 3W 的功耗,苹果是真的省电。
按照 60w 的功率计算,一天大概需要 1.44 度电,按照 7 毛一度电,一天的电费需要 1 元,一年就是 365 元。
1 | 60*24/1000=1.44度 |
啥都不干需要消耗这么多电力,这显然不太合理。虽说可以设置电脑连接电源时自动启动,通过智能插座来远程控制开关电源,但是这样做不满足我的需求。于是我使用 WakeOnLan(网络唤醒) 技术来唤醒休眠中的电脑。
WakeOnLan 的配置
WakeOnLan 的原理很简单,就是网卡监听收到的包,如果是特殊内容的魔术包就唤醒操作系统。目前绝大多数电脑都支持通过 WakeOnLan 来唤醒。 以我的 PC 为例,在 BIOS 中设置 PICE-E 和 Intel CNVi 为 Enable 状态即可。
设置好之后就需要从另外一个设备来唤醒,我尝试了使用群晖和路由器都可以办到,由于路由器一直跑并且不休眠的,所以最终选择使用路由器。我问了 AI 来生成一个唤醒的程序,给代码稍作改动就达到目的,我将代码和编译出来的执行程序都放到了 github 上的 wakeonlan_go。
我的路由器是红米 AX6000,在路由器中执行命令可以看到基础系统是 openwrt,询问 AI 得知应该使用 linux 的 arm64 进行编译。
1 | # cat /etc/os-release |
首先将文件拷贝到路由器的 /tmp
目录,然后将其移动到 /data
目录下。在命令行中执行以下命令即可唤醒电脑。
1 | # 这里的 ip 我填的是,192.168.31.255,需要填写电脑所在的局域网的广播地址,家用路由器的 ip 一般是 192.168.1.x 这里广播地址应该填写 192.168.1.255 |
到这里局域网的唤醒就已经成功了。还需要在外网也能访问路由器的命令行来执行命令,将路由器的 ssh 也是用 frp 的 stcp 模式进行内网穿透。这里要注意的是如何让路由器用守护进程的方式运行 frp,我找 AI 也问了脚本,创建文件 frp-service,给执行权限。
1 | #!/bin/sh /etc/rc.common |
就可以通过 /data/frp-service start
命令来启动服务在后台运行了。需要注意的是除了 /data 目录下的文件,其他文件都会在路由器重启时被重置。这里还有个稍微不爽的点是在唤醒后需要等 30 秒左右远程桌面才能重新连上。
最后
本文的需求只是暴露 TCP 服务,直接暴露 TCP 到公网容易被各种暴力破解扫描,所以使用了 FRP 提供的 STCP 方式。如果只需要暴露 http 服务,那么再走 nginx 类的方向代理程序使用 https 对外提供服务比较安全,具体可以看很多年前写过的使用 Frp 内网穿透进行开发。
由于我只用了 macOS 的远程访问,FRP 在 windows 上设置开机启动和守护进程的方式不太一样,有朋友尝试后也完成了设置,可以看看Windows 设置 frpc 开机自动启动(不管用户是否登陆都要运行)
由于现在已经满足了我的需求,比较流行的异地组网,如 headscale 或者 tailscale 的方案没有继续深入研究了。