谁都不想天天带着厚重的游戏本出去,更何况某些高性能的服务器或者台式机等设备根本带不出去,于是有了远程桌面和SSH之类功能,前者在远程设备中连接另一台Windows电脑的桌面,后者则访问另一台电脑的终端命令行。
但是,中国的网络环境大家都懂的,大部分电脑都没有公网IP,对于既有移动需求又有远程桌面需求的电脑来说,IP也时常会变换。能不能有一个有固定公网IP的云主机,来作为中转,将流量转到被连接的主机上呢?
于是我们有了FRP。FRP可以进行内网穿透,具体来讲,就是我们上面所说的事情。
fatedier/frp
FRP由两部分组成,分别是服务端和客户端,前者是有公网IP的那台机器,后者是由于各种原因需要被穿透的那台机器。
在看下面的内容之前,建议先了解一下 端口号 的概念。
搭建FRP服务端
我们需要一台有固定公网IP的机器来搭建FRP,常为云主机。建议选择中国大陆网络连接比较顺畅的服务器,以保证较低的延迟。
首先从 FRP release 页面下载适合你服务端机器的包,一般是amd64,Linux还是Windows依你服务器端的系统决定。解压,然后将它传到你的服务器上;如果你对命令行足够熟悉,也可以直接用 wget 命令在服务器上下载解压。
然后,进入FRP的路径,修改frps.ini,基础的结构如下:
[common]
bind_port = xxxx # 服务端与客户端之间通信所用的端口
dashboard_port = xxxx # 网页控制台的端口号,你没有域名的话可以使用 “服务器 ip: 这个端口号” 来访问控制台
token = xxxxx # 客户端连接到服务端的密码
dashboard_user = xxxx # 网页控制台的用户名
dashboard_pwd = xxxx # 网页控制台的密码
vhost_http_port = xxxx # HTTP 协议端口
vhost_https_port = xxxx # HTTPS 协议端口
1
2
3
4
5
6
7
8
[common]
bind_port = xxxx # 服务端与客户端之间通信所用的端口
dashboard_port = xxxx # 网页控制台的端口号,你没有域名的话可以使用 “服务器 ip: 这个端口号” 来访问控制台
token = xxxxx # 客户端连接到服务端的密码
dashboard_user = xxxx # 网页控制台的用户名
dashboard_pwd = xxxx # 网页控制台的密码
vhost_http_port = xxxx # HTTP 协议端口
vhost_https_port = xxxx # HTTPS 协议端口
server_port是服务端与客户端通信使用的端口,而下一部分提到的remote_port是外界连接至服务端的哪个端口,相当于连接到客户端的local_port。
按需设置即可,注意端口不要冲突了。这些数字可能都会用到,也别忘了。完成之后,输入命令 ./frps -s frps.ini 来启动服务端。推荐使用nohup命令来实现后台运行:nohup ./frps -s frps.ini $。不会有人用Windows Server吧?
搭建完成之后,访问 “你的服务器IP: 控制台端口号” 来访问网页控制台,并用先前设置的控制台用户名和密码登录,这里你就可以看到你的FRP服务器信息了。
此外,你也可以使用 Sakura Frp ,它是预先搭建好的一系列FRP服务器,你可以免费使用,但它的带宽等有一定的限制,如果想追求更好的体验,最好还是自行使用国内的服务器搭建。
搭建FRP客户端
由客户端决定要和FRP服务端建立几个连接,各个连接分别转发哪个端口,以及应该如何转发。
在将任何东西暴露于公网之前,我建议:
做好适当的防护措施,防止攻击;
先在局域网下测试连接通过,排除客户端本身设置问题造成的麻烦。
仍然是从上面的release页面下载对应于你客户端机器系统的压缩包,客户端和服务端是同包的。解压之后编辑frpc.ini,基本结构如下:
[common]
server_addr = xxx # 你服务端的地址,可以用域名或者 IP 地址,这里不加端口号。
server_port = xxx # 服务端与客户端通信所用的端口号
token = xxx # 客户端连接到服务端的密码
[xxx] # 这一套配置文件的名称,可以自定义,一套配置文件建立一个连接,一个 ini 可以有多套
type = tcp # 通信所用的协议,支持 TCP、UDP、HTTP、HTTPS 等协议的转发,要与实际通信协议配套
local_ip = 127.0.0.1 # 本地需要暴露到互联网上的 IP 地址,理论上也可以是同一个局域网的,本机的话就是 127.0.0.1 或者 localhost
local_port = xxx # 本地需要暴露到互联网上的端口号
remote_port = xxx # 服务端可以将什么端口映射为你本地的端口
use_compression = xxx # 是否启用压缩,值为 true 或者 false,启用则占用两边 CPU 资源
use_encryption = xxx # 是否加密,同上
1
2
3
4
5
6
7
8
9
10
11
12
[common]
server_addr = xxx # 你服务端的地址,可以用域名或者 IP 地址,这里不加端口号。
server_port = xxx # 服务端与客户端通信所用的端口号
token = xxx # 客户端连接到服务端的密码
[xxx] # 这一套配置文件的名称,可以自定义,一套配置文件建立一个连接,一个 ini 可以有多套
type = tcp # 通信所用的协议,支持 TCP、UDP、HTTP、HTTPS 等协议的转发,要与实际通信协议配套
local_ip = 127.0.0.1 # 本地需要暴露到互联网上的 IP 地址,理论上也可以是同一个局域网的,本机的话就是 127.0.0.1 或者 localhost
local_port = xxx # 本地需要暴露到互联网上的端口号
remote_port = xxx # 服务端可以将什么端口映射为你本地的端口
use_compression = xxx # 是否启用压缩,值为 true 或者 false,启用则占用两边 CPU 资源
use_encryption = xxx # 是否加密,同上
更详细的配置可以参考文末附录的官方文档。然后输入命令 ./frpc -c frpc.ini,就可以启动客户端服务了。
你可以打开上述的服务端网页控制台,来检查一下连接是否成功。
Windows系统的特别提示
鉴于很多人使用的是Windows系统,这里特别提醒一下:需要使用cmd或者PowerShell等终端来启动,不能直接双击frpc.exe,并且命令窗口关闭之后就会停止运行。
那么怎么去除碍眼的命令行,还让它一直后台运行呢?少数派的文章中提出,可以写一个batch脚本,来实现这个效果:
@echo off
if "%1" == "h" goto begin
mshta vbscript:createobject("wscript.shell").run("""%~nx0""h",0)(window.close)&&exit
:begin
cd X:\xxx rem 这个路径改为 frpc.exe 的位置
frpc -c frpc.ini
exit
1
2
3
4
5
6
7
@ echo off
if " %1 " == "h" goto begin
mshta vbscript:createobject("wscript.shell" ).run(""" %~nx0 ""h" ,0)(window.close)&& exit
: begin
cd X:\xxx rem 这个路径改为 frpc.exe 的位置
frpc -c frpc.ini
exit
如果你没有Visual Studio Code等代码编辑器,你也可以将这段内容复制到记事本里,另存为一个文本文档,然后将文件扩展名改成. bat,是一样的效果。
现在,双击这个bat文件,就可以启动后台服务了;在任务管理器中找到frpc.exe,结束它,就能将它关闭。你还可以使用 “计划任务” 功能实现FRP的开机启动。至于Linux用户,这些步骤大同小异,请参考上一节的nohup命令。
远程连接WSL 2子系统
正如我开头提到的,相信很多人都拥有高性能但不太好移动的计算机,而为了方便日常生产生活,这台计算机常装有Windows系统。有些工作实在是没必要用远程桌面完成,只需要SSH连接终端就可以了,这时使用SSH连接WSL子系统内的Linux bash终端,就可以随时轻易利用强大的算力了。下面以Windows 10 21H1上的Ubuntu 20.04.2 LTS为例。
需要特别注意的是,WSL2系统本身是并不能直接SSH连接的。要解决这个问题,首先要重装一个 “正常的”OpenSSH”:
sudo apt-get remove openssh-server
sudo apt-get install openssh-server
1
2
sudo apt-get remove openssh-server
sudo apt-get install openssh-server
然后还需要编辑一下sshd_config文件,使其允许使用密码接入SSH,当然如果你能够把所有设备的公钥全都加进去,倒也可以不用用户名和密码…… 毕竟这是要暴露到公网上的东西,我甚至更推荐使用RSA公钥验证。
如果你需要密码登录,则用sudo提权后使用文本编辑器编辑 /etc/ssh/sshd_config 文件。我这里推荐使用Visual Studio Code(前面加code或者code-insiders,需要Windows宿主系统上装有vscode),或者GNU Nano(前面加nano),当然如果你是大佬也可以用Vim之类的工具。打开之后,将PasswordAuthentication后面的no改为yes即可。
然后下载Linux AMD64版本的FRP包,修改frpc.ini如下:
[common] # 这个和上面同理
server_addr = xxx
server_port = xxx
token = xxx
[WSL_ssh] # 这个名称可以自定义
type = tcp # SSH 协议建立在 TCP 的基础上,所以填 TCP
local_ip = 127.0.0.1
local_port = 22 # 本地 SSH 端口默认为 22,当然你可以改,也建议改一下,记得同步修改 SSH 配置
remote_port = xxxx # 服务端映射的端口
1
2
3
4
5
6
7
8
9
10
[common] # 这个和上面同理
server_addr = xxx
server_port = xxx
token = xxx
[WSL_ssh] # 这个名称可以自定义
type = tcp # SSH 协议建立在 TCP 的基础上,所以填 TCP
local_ip = 127.0.0.1
local_port = 22 # 本地 SSH 端口默认为 22,当然你可以改,也建议改一下,记得同步修改 SSH 配置
remote_port = xxxx # 服务端映射的端口
运行服务,你就可以远程连接到WSL 2了,注意端口号的变化。使用命令 ssh -oPort=remote_port user@server_addr 来连接客户端的SSH。
ref.
使用 frp 进行内网穿透 - 少数派 (sspai.com)
文档 | frp (gofrp.org)
使用 ssh 工具连接到 ubuntu on windows(wsl) - 简书 (jianshu.com)