2019.12.5 更新:内网穿透还有更简单、更好的实现方法,具体看文末
# 前言
平时带一台轻薄的笔记本,打开远程家里/寝室里的台式,进行远程桌面,在有网速保证的前提下,既能获得笔记本的轻便型,也能获得台式电脑的强大性能,更能最大化笔记本的续航,更重要的是可以在同一台机器上进行办公、开发,无需资料同步。是很不错的选择。
我体验过的几款远程桌面软件里,
- Teamviewer 是一个很优秀的选择;
- 向日葵免费版有 300kbps 的限速,几乎等于不能用;
- Anydesk 国内网速太慢,不可用;
- 应急的话,还可以用 QQ 的远程协助。(用 QQ 的远程协助启动 Teamviewer 的远程协助)
除了以上选择以外,其实微软自带了远程桌面 mstsc
。在局域网内你就可以通过远程 *.*.*.*:3389
(你的电脑 ip)体验到远程桌面,体验同样是相当不错的,几乎和 Teamviewer 是一样的(所以一般的同学就可以直接选 Teamviewer 了)。
但是,如果在外网体验的话,就不大好了。原因是,你在外网里找不到被远程端的 ip 地址(未经强调,本文所有 ip 指 ipv4,此处是因为 ipv6 在中国还没普及)。
# NAT 及内网穿透的原理
ip 是一台机器在互联网上的唯一地址,可以通过你的机器 ip,从互联网的任何一端找到你的机器。
然而, ipv4 的数量是极其有限的,只有 256*256*256*256=4294967296 四十亿个(想想现在地球多少人口)。
而且还有很多 ip 是保留的,不能作为互联网里的 ip。
现在的 ip 地址已经快要用完了。
因此,聪明的运营商们想了一个办法,可以用一个设备,把他的一个 ip,下发为一万个 ip(当然,远不止这么多)。
这种方法叫 NAT(Network Address Translation,网络地址转换)。
好处是 ip 够用了,另外还具有防火墙的功能;坏处是,转换过的 ip 是不能在互联网上直接访问到的,而且还是动态变化的。你就不能直接靠输入 ip 来实现远程内网 ip。(所以互联网上能直接访问到的 ip 又叫公网 ip)
但是,你想想,肯定是会有方法的,要是你的电脑和一个有公网 ip 的电脑建立了联系,要想访问你的电脑,就可以通过找到这个 ip,让公网 ip 电脑转发一下数据到你的电脑上,你就可以内网以外的地方访问到内网设备了(实现的这个结果叫内网穿透)!
这便是转发/反向代理,内网穿透的一种实现。
2019.12.5 更新:另一种实现是 P2P,你的内网电脑和想要访问内网的电脑同时连接一台公网服务器,这台公网服务器就在你的两台电脑之间建立了一个 P2P 的联系,接下来,你的电脑就不需要再经过公网服务器的中转,直接访问内网电脑了。但这种方法只适用于 UDP 协议,不适用于 TCP 协议。ZeroTier 即是用这种方法实现的。
内网穿透需要一台有公网的电脑,最简单的办法,就是去租一个服务器。而实现转发数据、内网穿透的软件也有不少,如 frp (opens new window)、ngrok 等等。
(以下两段复制自 使用 Shadowsocks 搭建回国代理)
# 租服务器
首先,去租一个阿里云或腾讯云的服务器。
推荐的服务器有:
服务器名 | 规格 | 配置 | 价格 | 备注 |
---|---|---|---|---|
阿里云服务器 ECS (opens new window) | 突发性能实例 t6 | 2核2G40G,流量按量付费0.8元/G | 54元/月,550元/年,1033元/3年,1375元/5年 | 偶尔用一下frp、博客访问,推荐突发性能实例 |
腾讯云服务器 CVM (opens new window) | 标准型SA2 | 1核2G50G,200M,流量按量付费0.8元/G | 45元/月,453元/年,819元/3年,1365元/5年 | 带A的是AMD CPU,性能差不多但会便宜很多 AMD YES |
阿里云学生机 (opens new window) | 轻量应用服务器 | 2核2G60G,带宽5M,1T流量包 | 30元/3月,100元/年 | 仅限学生新用户 |
腾讯云学生机 (opens new window) | 轻量应用服务器 | 1核2G50G,带宽5M,1T流量包 | 27元/3月,108元/年 | 仅限学生(25岁以下免认证) |
如果搭建服务器是用来反向代理+远程桌面的,对带宽就会有需求,最好在 5M 以上。这里推荐的两个非学生机都是流量按量付费,好处是带宽可以拉到100兆或更高,偶尔使用反向代理也不会消耗太多流量,算下来可能比固定带宽还便宜;如果不需要大带宽的,可以考虑阿里云/腾讯云的轻量应用服务器和上面两款的固定带宽版。
系统推荐使用 Debian 或 Ubuntu。
然后租了服务器会给 ip 地址(下面为方便叙述,设为 39.1.2.3
)和密码。
# ssh 远程登录
注意阿里云的服务器要开放防火墙的端口,不然连不上!!!!!!!!
作者就是被这个坑了一下午还没弄好。上面需要开放 22
端口,协议选 tcp
。
在本地 wsl(或自行百度 ssh 的方法)使用 ssh -p22 root@39.1.2.3
登录远程服务器。
# 下载并配置 frp
参考链接:https://www.hostloc.com/thread-463360-1-1.html
本地和远程下载 frp (opens new window) 的压缩包,然后解压。
注意下对应系统的最新的包,而不是复制粘贴下面的命令(我遇到 i/o deadline reached
什么的奇奇怪怪的错误就是因为下的 0.9.0
版本的)。
服务器端的命令:
wget https://github.com/fatedier/frp/releases/download/v0.29.0/frp_0.29.0_linux_amd64.tar.gz
tar -zxvf frp_0.29.0_linux_amd64.tar.gz
cp -r frp_0.29.0_linux_amd64 /etc/frps
rm -f frpc frpc_full.ini frpc.ini
frp 的压缩包中同时包含了 server 服务器版本 frps
和 client 客户端版本 frpc
。服务器可以删除 frpc
相关文件,客户端(被远程的电脑)可以删除 frps
相关文件。
然后配置服务器的 frps.ini
和客户端的 frpc.ini
。
服务端 frps.ini
一行即可,指明客户端连入的端口:
bind_port = 7000
客户端 frpc.ini
要复杂一点。
[common]
server_addr = 39.1.2.3 # 这里是 vps 的 ip
server_port = 7000
[rdp]
type = tcp
local_ip = 127.0.0.1
local_port = 3389 # 本地的 Remote Desktop 对应端口
remote_port = 5200 # 服务器接收 Remote Desktop 信息的端口,可以改
几个端口解释一下:
- 首先,服务器启动
- 客户端启动访问服务器的 7000 端口,建立内网穿透
- 远程的设备访问服务器的 5200 端口,服务器即把数据转发给客户端的 3389 端口,即可远程桌面
注意开放服务器防火墙 tcp 7000 和 5200 端口!!!! 我被这后面这个坑了一个小时。明明配置好了,就是连不上,原来是服务器没开端口。
另外还需要配置一下客户端的远程桌面方面的设置,这个比较常见,在 控制面板-系统-(侧边栏)远程设置-(单选框)允许远程连接到此计算机
。
# 启动 frp 及守护进程
服务器 /etc/frp/frps -c /etc/frp/frp.ini
,客户端 frpc.exe -c frpc.ini
。
启动以后,要是有什么问题,建议检查端口开放和 frp 版本是否为最新,然后再百度。(对我各被坑了一个小时)
如果没什么问题,就可以测试远程桌面了。
注意,远程桌面连接的时候可能会提示密码错误(即使你密码输入正确了)。
这大概是个 bug,原因是你远程那边登录使用的不是密码(而是 PIN)。说不定是个为了安全的 feature 呢
解决方法是,远程端那边需要想办法注销账户,然后用密码登录,这边再远程就没有说明问题了。
要是可以正常使用,就可以准备守护进程了。
# 服务端后台运行
服务端使用 nohup /etc/frp/frps -c /etc/frp/frps.ini & &> /dev/null
使 frp 后台运行。
可能会看到 ignore input
之类的警告,不用管,Ctrl+C
退出前台即可,此时 ssserver
正在后台运行。
# 客户端开机运行
下面的方法二选一。
客户端需要开机后台启动 frpc
,可以把 vbs 脚本放在 Startup 目录。
新建一个文本文档,加入下面两行脚本代码,并改名为
startup-frpc.vbs
,复制到C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
下。
(假设 frpc.exe
和 frpc.ini
都在 c:\frp\
目录)
set ws=WScript.CreateObject("WScript.Shell")
ws.Run "c:\frp\frpc.exe -c c:\frp\frpc.ini",0
也可以用 任务计划
,用 GUI 设定一下就行。具体百度吧,不难。
额外说一句,在设置任务计划时,需要注意的是,
- 在
属性-常规-安全选项
,中,选择不管用户是否登录都要运行
,同时可以选择使用最高权限运行
。(保存的时候需要输入账户的密码) 触发器
选在系统启动时
操作
选启动程序
,命令为wscript
,参数为"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\startup-frpc.vbs"
。(你也可以把这个 vbs 放在别的目录,然后把这个目录修改为对应的目录)
为了防止意外,可以在远程的电脑上安装额外的临时的远程桌面解决方案如 Teamviewer 或 QQ 以应急。
# 客户端守护进程
2019.12.5 更新:如果正确的配置启动命令以后,应该不会出现问题。所以也可以选择上面的配置。不过我还是选择的下面的配置。
但是有些时候还是会有蜜汁启动不了。即使我设了启动命令 + 任务计划,仍然必须要登录以后才会启动 frpc
(而不是在开机后登陆前就启动了)。因此我并不推荐开机自启的方法,而是用这种进程守护的功能。
于是我打算搞一个进程守护,任务计划每一分钟启动一次,检测 frpc
是否正在运行,否则后台启动 frpc
。
为此我需要以下文件(都放在 D:\Documents\Tools\frp\
):
- vbs 脚本,让命令行程序在后台运行的最简单的实现方法。内容如下:
set ws=createobject("wscript.shell")
ws.run"D:\Documents\Tools\frp\frpc-daemon.bat",0,ture
frpc-daemon.bat
脚本,因为 bat 检测进程最为方便。vbs 也可以检测进程,但是按网上 Google 到的方法都只能检测会话名为 Console 的进程,对于任务计划启动的 Services 进程是检测不到的,再加上我不会 vbs,于是采用的是vbs+bat
的方法。
bat 内容如下:
set frppath=D:\Documents\Tools\frp
tasklist | find "frpc" || %frppath%\frpc.exe -c %frppath%\frpc.ini
- 任务计划。
常规部分,选择“不管用户是否登录都要运行”,不要勾选“不存储密码”。
触发器部分,选择 一次
,时间默认,然后勾上 重复任务间隔
设为 1 分钟。
操作部分,启动程序 wscript
,添加参数为 "D:\Documents\Tools\frp\frpc-daemon.vbs"
(你的 frpc-daemon.vbs
路径,带引号)。
虽然这种方法会占用一点点 CPU(实际上占用的很少很少),但是真的非常推荐,配置好以后,要是哪天手滑关了 frpc,问题也不大,几分钟以后就会启动。并且配置好以后,也会开机自启,非常好用,推荐。
# 番外:为 RDP 使用 UDP 协议
远程桌面应该使用 TCP 还是 UDP 协议呢?
抛去网上的一堆 TCP/UDP 枯燥难懂的定义,我找到了这个问答 (opens new window)。
大概意思就是,UDP 只传输数据,不执行校验等命令。也就是说,较 TCP,
- UDP 有更低的延迟(不执行命令)
- UDP 牺牲了稳定性(不能防丢包等)
在 Windows 8 中,微软已经在 UDP 协议上启用了 RDP 协议。
至于是否使用 UDP,还是看自己(还有当地的网络情况)。
如果想要使用 frp
通过 UDP 协议传输,需要把客户端 frpc.ini
配置的部分再抄一遍,把 type
改为 UDP 即可。
[common]
server_addr = 39.1.2.3 # 这里是 vps 的 ip
server_port = 7000
[rdp]
type = tcp
local_ip = 127.0.0.1
local_port = 3389 # 本地的 Remote Desktop 对应端口
remote_port = 5200 # 服务器接收 Remote Desktop 信息的端口,可以改
[rdp-udp]
type = udp
local_ip = 127.0.0.1
local_port = 3389
remote_port = 5200
如果想禁用 UDP,一个方案是把 frpc.ini
的 UDP 部分删掉;也可以通过(在两个设备)组策略关掉远程桌面使用 UDP 的
选项,在组策略的以下位置:
计算机配置/Windows 设置/管理模板/Windows 组件/远程桌面服务/远程桌面会话主机/连接/选择 RDP 传输协议
# 部分错误及解决方案
# frps 和 frpc 无法连接
- 如果客户端无法连接通过 frpc 连接到服务器,可能是服务器没有开放防火墙的对应端口;
- 如果显示
i/o deadline reached
等奇奇怪怪的错误,检查一下 frps 和 frpc 是不是最新版。
# frp 建立,但无法远程桌面
可能是服务器没有开放防火墙的对应端口。
# mstsc 字体模糊
关闭根据网络调整质量
,可改为256kbps-2M
,然后开启平滑字体。
如果仍然无效,可能需要远程登录成功、退出以后重新登录。
2019.11.30 更新:如果网络不好,这个真的没法解决,只能选择将就着用,或者换 Teamviewer。
# mstsc 和 Teamviewer 打开文件资源管理器时卡顿(更新于 2019.10.21)
必然发生,每次都会卡 5 秒左右。
在远程的电脑是 Win10 1903 时,两款软件都会出现这样的问题;升级到 1909 后,问题均消失。
大概 Teamviewer 也调用了 Windows mstsc 的 api 吧,然后 mstsc 出锅了。
# 后记
利用 frp,还可以进行一些骚操作:把自己的电脑当做云盘(比云服务提供的大)、配合 Shadowsocks 和学校寝室的电脑搭建校园网的代理。总之,几个东西的搭配,就能搞很多东西出来了。
# 内网穿透的其他方案
内网穿透还有其他实现方案,如果使用 P2P 的方案,这样所有流量就不用跑服务器转一圈了,而是两台电脑的流量直连,不会受限于两台电脑连接服务器的速度,也不会消耗服务器的流量。
引用知乎上 iittttt 用户的总结 (opens new window),目前用的较多的方案有:
项目名 | 开/闭源 | P2P/非P2P | 免费/收费 | |
---|---|---|---|---|
n2n | 开源 | P2P | 免费 | 服务器较少,暂停开发 |
ngrok | 分版本开源 | 非P2P | 免费或收费 | 官方服务器被墙 |
反向ssh | 开源 | 非P2P | 免费 | |
TeamViewer | 闭源 | P2P | 免费或收费 | |
Hamachi | 闭源 | P2P | 免费或收费 | |
花生壳 | 闭源 | 非P2P | 免费或收费 | 免费限速 |
除此之外,推荐(100 台设备以下)免费的 ZeroTier (opens new window),能够开机自启。使用带 GUI 的客户端来进行配置,配置过程参考这篇博客 (opens new window)。不过缺点是,没有加入的设备,必须要安装客户端配置以后才能使用(frp
只用配置服务器和内网设备,其他设备即可通过端口直接访问)。