前言

由于之前一直在cpolar做的内网穿透,这网站是国内的网站,导致每次在外连树莓派都要跳转到国内,再跳转回欧洲,卡的不行,于是乎在经历过大概3-4个月的妥协之后,不打算再妥协了,毕竟以后打算用树莓派连接家里面各个终端,这要是每次都从欧洲转会国内,再转回欧洲,这也太卡了。于是乎打算自己做内网穿透,在对比了多个内网穿透工具后,选择了frp,其Github官方文档

2024年3月9日,进行了关于新版本frp v0.54.0的更新

正文

1. 下载frp文件

现在frp的最新版本是v0.39.1,下载地址。但是,我们发现frp有很多版本,不同CPU架构有不同的版本;在每一个下载包里面都包含了客户端和服务端所需的文件,由于我们服务端和客户端很有可能是不同的CPU架构,所以分别下载对应适合的就可以。然而,怎么又去查CPU架构呢?我们通过命令dpkg --print-architecture。如下图,
我们通过查询发现客户端的CPU架构是armhf,也就是arm32位
Screen Shot 20220309 at 12.32.44 AM.png
而服务端的架构是amd64,也就是amd64位。
Screen Shot 20220309 at 12.34.12 AM.png
所以我们分别下载frp_0.39.1_linux_arm.tar.gz给客户端,frp_0.39.1_linux_amd64.tar.gz给服务端。将文件上传到客户端和服务端的形式,萝卜白菜各有所爱,我这里比较倾向于直接用scp上传,具体命令为scp -r localfile.txt username@xxx.xxx.xxx.xxx:~/dir,这里的localfile.txt为你想上传的文件,username为客户端/服务端的用户,xxx.xxx.xxx.xxx为客户端/服务端所在的ip地址,后面跟的~/dir为具体上传目录路径,此处~表示当前用户所在的根目录,更具体的介绍请看[5] SSH 连接、远程上传下载文件
在下载并且分别将对应CPU架构的frp文件上传到客户端和服务端之后呢,我们通过sudo tar xvf filename.tar.gz命令解压~,这里的filename为上传的frp文件的名字,我这里为frp_0.39.1_linux_armfrp_0.39.1_linux_amd64,分别对应客户端和服务端。
如图,客户端和服务端都分别成功解压。
客户端:
Screen Shot 20220309 at 12.41.58 AM.png
服务端:
Screen Shot 20220309 at 12.41.11 AM.png

2. 配置ini文件

在一切都上传完毕呢,我们需要分别对客户端和服务端进行配置,毕竟如果不配置,我们怎么能让我们的客户端/服务端连在一起呢,对吧,= -=~~。

2.1 客户端的配置(frpc.ini)

修改 frpc.ini 如下,frpc的c意味着client

[common]
server_addr = xxx.xxx.xxx.xxx
server_port = 7000

[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
custom_domains = xxx.seanzou.com

这里有几个需要注意的,首先是[common]里面

  1. server_addr就是我们内网穿透之后能用于公网链接的ip地址;
  2. server_port就是和服务端绑定的端口bind_port。

由于我们需要的是ssh,所以我们对[ssh]进行配置,

  1. type为tcp,local_ip为本地ip也就是127.0.0.1,也就是以后我们通过公网+这个端口就能自动转发到我们的客户端上面;
  2. local_port由于是ssh,所以是22端口;
  3. remote_port为我们通过公网ip地址连接的端口;
  4. custom_domains为我们的ip通过DNS解析后的域名,设置了此项我们之后就可以直接通过域名进行访问了

2.2 服务端的配置(frps.ini)

修改 frps.ini 如下,frps的s意味着server

[common]
bind_port = 7000

这里的[common]只有一个parameter,因为我们这里只用ssh,所以比较简单

  1. bind_port是用于和客户端的port进行连接,毕竟我们不需要任何web服务应用,只需要ssh连接,所以仅仅用一个bind_port就足够了。

3. 开启服务

3.1 运行服务(不能断开远程连接)

我们首先,分别服务端运行命令./frps -c ./frps.ini,客户端运行命令./frpc -c ./frpc.ini,发现客户端和服务端都能正常运行,也能通过另一台主机成功通过服务端的域名+配置的端口成功访问到客户端。
服务端:
Screen Shot 20220309 at 1.00.25 AM.png
客户端:
Screen Shot 20220309 at 1.00.42 AM.png
成功访问:
Screen Shot 20220309 at 1.01.29 AM.png

3.2 运行服务(no hang up)

由于此刻我们只要断开远程连接,服务便会自动挂断,所以为了防止这种事情发生呢,我们需要把他设置为断开远程服务也能成功自己运行的。
这样命令就会变成在在服务端运行命令nohup ./frps -c ./frps.ini &,客户端运行命令nohup ./frpc -c ./frpc.ini &

3.3 运行服务(开机自启)

但其实这还不够,我们想要他们能够开机自动启动怎么办呢?

  1. 我们可以发现服务端的frp_0.39.1_linux_amd64.tar.gz解压之后可以看到一个 systemd 目录,将其中的 frps.service 文件复制到服务器的 /etc/systemd/system/ 目录下,并修改 ExecStart=/usr/local/frp/frps -c /usr/local/frp/frps.ini,这里的frps目录为自己的frp所在目录
    具体frps.service配置信息:
[Unit]
Description=Frp Server Service
After=network.target

[Service]
Type=simple
User=nobody
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/frp/frps -c /usr/local/frp/frps.ini

[Install]
WantedBy=multi-user.target

然后输入命令nohup ./frps -c ./frps.ini,会有如下显示:
Screen Shot 20220309 at 1.23.10 AM.png
我们查看一下7000端口是否已经被使用:
Screen Shot 20220309 at 1.23.52 AM.png
发现成功,yes~ 然后设置开机自动启动命令sudo systemctl enable frps记得要把frps.service 文件复制到服务器的 /etc/systemd/system/ 目录下哦!
Screen Shot 20220309 at 1.26.35 AM.png
然后开启服务吧!运行命令sudo systemctl start frps
Screen Shot 20220309 at 1.28.23 AM.png
然后开始出发,设置客户端!

  1. 客户端的配置其实和服务端基本一摸一样,首先,将客户端frp_0.39.1_linux_arm.tar.gz的frpc.service文件复制到客户端的/etc/systemd/system/目录下,并修改ExecStart=/usr/local/frp/frpc -c /usr/local/frp/frpc.ini 和 ExceReload=/usr/local/frp/frpc -c /usr/local/frp/frpc.ini,这里的frps目录为自己的frp所在目录
    具体frpc.service配置信息:
[Unit]
Description=Frp Server Service
After=network.target

[Service]
Type=simple
User=nobody
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/frp/frpc -c /usr/local/frp/frpc.ini
ExceReload=/usr/local/frp/frpc -c /usr/local/frp/frpc.ini

[Install]
WantedBy=multi-user.target

然后设置开机自动启动命令sudo systemctl enable frpc记得要把frpc.service 文件复制到服务器的 /etc/systemd/system/ 目录下哦!
Screen Shot 20220309 at 1.37.29 AM.png
然后开启服务吧!运行命令sudo systemctl start frpc
Screen Shot 20220309 at 1.38.05 AM.png
我们使用命令lsof -i:[port],查看一下6000和7000端口是否已经被使用:
Screen Shot 20220309 at 1.39.47 AM.png
发现没有端口在运行,觉得有点奇怪,感觉还是我对这一整体流程不太熟悉,按理来说6000和7000端口应该也有程序运行的?不然怎么样bind呢?希望有有缘人来帮忙答疑解惑一下。

3.4 最终结果

成功通过荷兰ip登陆转发,而不是国内的转发,速度明显加快=。 =!
Screen Shot 20220309 at 1.42.05 AM.png

4. 防火墙(2024年3月9日更新)

我发现之前并没有涉及到防火墙的问题,我们现在更新一波关于防火墙的问题。

4.1 Digital Ocean 防火墙

frps的服务器,我租界的是来自Digital Ocean的服务器,是一个Ubuntu,但是虽然说Digital Ocean可能默认开所有的端口,但是需要安装一个防火墙进行控制

sudo apt-get install ufw
sudo ufw enable
sudo ufw default deny %默认开启防火墙随系统启动并且同时关闭所有外部对本机的访问(本机访问外部正常)
sudo ufw allow 22     % ssh
sudo ufw allow 6000   $ frp
sudo ufw allow 7000   $ frp

然后Digital Ocean这边的防火墙设置好了

4.2 Raspberry Pi 4 Model B 防火墙和开启端口

apt-get install命令方面是一样的,一样是安装防火墙ufw

sudo apt-get install ufw
sudo ufw enable
sudo ufw default deny %默认开启防火墙随系统启动并且同时关闭所有外部对本机的访问(本机访问外部正常)
sudo ufw allow 22     % ssh
sudo ufw allow 6000   $ frp
sudo ufw allow 7000   $ frp

但是有一个不一样,是Raspberry Pi 4的Raspberry Pi OS是需要额外在Desktop UI上enable ssh的。

image.png

或者命令行sudo raspi-config

image.png

image.png

图片来自《How to SSH Into Your Raspberry Pi》

5. 如果服务无法启动

如果服务无法启动,尝试把UserNobody改为root或者seanzou之类有权限的用户名,如下:

[Unit]
Description=Frp Server Service
After=network.target

[Service]
Type=simple
User=root
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/frp/frpc -c /usr/local/frp/frpc.ini
ExceReload=/usr/local/frp/frpc -c /usr/local/frp/frpc.ini

[Install]
WantedBy=multi-user.target

更新

[1] 2024年3月9日,进行了关于新版本frp v0.54.0的更新
[2] 2024年4月24日,更新了关于服务无法启动的问题

参考

[1] 树莓派frp内网穿透
[2] 自己动手部署内网穿透:frp
[3] 查看Linux系统架构的命令,查看linux系统是哪种架构:AMD、ARM、x86、x86_64、pcc 或 查看Ubuntu的版本号
[4] arm64 、armhf 有什么区别
[5] SSH 连接、远程上传下载文件
[6] FRP内网穿透 SSH远程登录内网本地Linux教程
[7] ubuntu防火墙状态查看、开启和关闭
[8] How to SSH Into Your Raspberry Pi

Q.E.D.


立志做一个有趣的碳水化合物