1
2
3
4
5
作者:李晓辉

微信联系:lxh_chat

联系邮箱: 939958092@qq.com

FRP 是啥玩意儿?

先来说说 FRP。这玩意儿全名叫 Fast Reverse Proxy,翻译过来就是“快速反向代理”。听起来是不是有点高大上?其实它就是一个简单又强大的工具,能帮我们穿透内网,让外部设备能访问到内网里的服务。就像给你的内网设备开了个“专属通道”,但又很安全哦!

为啥要用 FRP 做 SSH?

SSH 是啥?就是那个用来远程登录服务器的协议呀!你是不是也有过这样的烦恼:在外面想远程操作家里的电脑,但因为内网限制,根本连不上。这时候,FRP 就派上大用场啦!它能让你轻松地从外面访问内网里的 SSH 服务,就像在本地操作一样简单。

FRP角色说明

  • 服务端(FRPS):位于公网,负责中转客户端之间的数据,所以它需要具有公网IP地址。
  • 客户端A(FRPC):内网中的设备,需要被外部访问(如 SSH 服务),不需要具有公网IP。
  • 客户端B(FRPC):外部设备,用于访问内网中的服务,也不需要有公网IP。
角色IP地址作用描述
服务端xxxxxx监听来自客户端的连接请求,中转数据
客户端A192.168.1.100内网设备,提供本地服务(如 SSH)
客户端B动态分配外部设备,访问内网服务

既然搞明白了角色,那我们开始动手做起来~

下载FRP

点此从FRP官网下载最新版

以上的GitHub链接,可以下载最新版

需要注意的是,由于FRP反向代理、P2P打洞等特性,Windows极有可能报告有病毒,可自行甄别,不过一般来说,从官方下载的都没问题,其他地方下载的就不好说了。

看看安装包里都有什么?

1
[root@frp-server ~]# tar xf frp_0.62.0_linux_amd64.tar.gz
1
2
3
[root@frp-server ~]# cd frp_0.62.0_linux_amd64/
[root@frp-server frp_0.62.0_linux_amd64]# ls
frpc frpc.toml frps frps.toml LICENSE

安装包里,同时带有服务器端和客户端版本,以下是压缩包里的文件作用介绍:

  • frpc:FRP 客户端程序,用于运行客户端功能,连接到服务端并转发本地服务。
  • frpc.toml:FRP 客户端的配置文件,包含客户端连接到服务端的参数和本地服务的映射规则。
  • frps:FRP 服务端程序,用于运行服务端功能,中转客户端之间的数据。
  • frps.toml:FRP 服务端的配置文件,包含服务端的监听端口、认证信息等参数。
  • LICENSE:许可证文件,说明该软件的使用许可和版权信息。

动手吧!用 FRP 实现内网 SSH

配置服务器端

在服务器上解压文件后,请打开frps.toml进行配置,以下是我本地用的案例

1
2
3
4
5
6
bindPort = 7000
auth.token = "lixiaohui"
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "admin"

来让我介绍一下服务器的参数

  • bindPort = 7000:服务端监听的端口是 7000,客户端通过这个端口连接到服务端。
  • auth.token = "lixiaohui":设置了一个认证令牌,客户端和服务端通过这个令牌来验证身份,就像一把钥匙,只有匹配的才能连上。
  • webServer.addr = "0.0.0.0":Web 服务监听所有网络接口,方便从任何地方访问。
  • webServer.port = 7500:Web 服务的端口是 7500,可以通过这个端口访问 FRP 的管理界面。
  • webServer.user = "admin"webServer.password = "admin":Web 服务的用户名和密码,登录管理界面时要用到。

将含有安装包和配置文件的文件夹,拷贝到/usr/local/bin下面去,配置一下systemd,这样我们就能实现开启自启动了,棒棒哒~

1
2
3
[root@frp-server ~]# mv frp_0.62.0_linux_amd64 /usr/local/bin/frp
[root@frp-server ~]# ls /usr/local/bin/frp
frpc frpc.toml frps frps.toml LICENSE

ok,文件准备就绪,我们来创建systemd的服务单元

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat > /etc/systemd/system/frps.service <<-'EOF'
[Unit]
Description=FRP Server Service
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/frp/frps -c /usr/local/bin/frp/frps.toml
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

ok,参数配好了,那我们来启动看看吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@frp-server ~]# systemctl daemon-reload
[root@frp-server ~]# systemctl enable frps.service --now
Created symlink /etc/systemd/system/multi-user.target.wants/frps.service → /etc/systemd/system/frps.service.
[root@frp-server ~]# systemctl status frps.service
● frps.service - FRP Server Service
Loaded: loaded (/etc/systemd/system/frps.service; enabled; preset: disabled)
Active: active (running) since Fri 2025-04-25 16:06:45 CST; 4s ago
Main PID: 355286 (frps)
Tasks: 5 (limit: 12344)
Memory: 9.0M
CPU: 324ms
CGroup: /system.slice/frps.service
└─355286 /usr/local/bin/frp/frps -c /usr/local/bin/frp/frps.toml

Apr 25 16:06:45 frp-server systemd[1]: Started FRP Server Service.
Apr 25 16:06:45 frp-server frps[355286]: 2025-04-25 16:06:45.952 [I] [frps/root.go:105] frps uses config file: /usr/local/bin/frp/frps.toml
Apr 25 16:06:46 frp-server frps[355286]: 2025-04-25 16:06:46.270 [I] [server/service.go:237] frps tcp listen on 0.0.0.0:7000
Apr 25 16:06:46 frp-server frps[355286]: 2025-04-25 16:06:46.271 [I] [frps/root.go:114] frps started successfully
Apr 25 16:06:46 frp-server frps[355286]: 2025-04-25 16:06:46.271 [I] [server/service.go:351] dashboard listen on 0.0.0.0:7500

ok,万事大吉,我们的服务起来了,登陆一下web的7500看看,请使用你服务器的公网ip打开它的7500,浏览器输入http://公网ip:7500

frp-dashboard

从图上可以看到流量和连接信息,点击左侧可以看到不同类型的代理信息

到此,我们的服务器就部署好了,它只是负责给不同的客户端牵线搭桥用的,我们来转战内网服务器吧,把它暴露到公网去

暴露内网ssh服务

和刚才一样,完成frp下载,拷贝到/usr/local/bin/frp的步骤,现在来配置内网服务器上的frp客户端吧

1
2
3
4
5
[root@internal-sshserver ~]# mv frp_0.62.0_linux_amd64 /usr/local/bin/frp
[root@internal-sshserver ~]# ls /usr/local/bin/frp
frpc frpc.toml frps frps.toml LICENSE
[root@internal-sshserver ~]# cd /usr/local/bin/frp
[root@internal-sshserver frp]# vim frpc.toml

注意,我们配置的是frpc.toml,而不是frps.toml,内网服务和最终的访问者,都是以客户端的身份连接到FRP服务器沟通的

1
2
3
4
5
6
7
8
9
serverAddr = "x.x.x.x"      # 服务端的公网 IP 地址
serverPort = 7000 # 服务端监听的端口
auth.token = "lixiaohui" # 这里要和服务器上配置的token一致
[[proxies]]
name = "ssh" # 代理名称
type = "tcp" # 代理类型,表示这是一个 TCP 代理
localIP = "127.0.0.1" # 本地服务的 IP 地址
localPort = 22 # 本地服务的端口(如 SSH 服务)
remotePort = 6000 # 在服务端上暴露的端口,用于外部访问

这段配置表示客户端通过 x.x.x.x:7000 连接到服务端,并将本地的 SSH 服务(127.0.0.1:22)映射到服务端的 6000 端口,从而可以从外部访问内网的 SSH 服务。

ok,配置好了之后,也创建systemd服务作为开机自启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat > /etc/systemd/system/frpc.service <<-'EOF'
[Unit]
Description=FRP Client Service
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/frp/frpc -c /usr/local/bin/frp/frpc.toml
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

启动服务看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@internal-sshserver ~]# systemctl daemon-reload
[root@internal-sshserver ~]# systemctl restart frpc.service
[root@internal-sshserver ~]# systemctl status frpc.service
● frpc.service - FRP Client Service
Loaded: loaded (/etc/systemd/system/frps.service; disabled; preset: disabled)
Active: active (running) since Fri 2025-04-25 16:29:13 CST; 14s ago
Main PID: 94421 (frpc)
Tasks: 4 (limit: 12140)
Memory: 4.6M
CPU: 7ms
CGroup: /system.slice/frpc.service
└─94421 /usr/local/bin/frp/frpc -c /usr/local/bin/frp/frpc.toml

Apr 25 16:29:13 internal-sshserver systemd[1]: Started FRP Client Service.
Apr 25 16:29:13 internal-sshserver frpc[94421]: 2025-04-25 16:29:13.467 [I] [sub/root.go:149] start frpc service for config file [/usr/local/bin/frp/frpc.toml]
Apr 25 16:29:13 internal-sshserver frpc[94421]: 2025-04-25 16:29:13.467 [I] [client/service.go:314] try to connect to server...
Apr 25 16:29:13 internal-sshserver frpc[94421]: 2025-04-25 16:29:13.472 [I] [client/service.go:306] [66f9a7e320b717cd] login to server success, get run id [66f9a7e320b717cd]
Apr 25 16:29:13 internal-sshserver frpc[94421]: 2025-04-25 16:29:13.472 [I] [proxy/proxy_manager.go:177] [66f9a7e320b717cd] proxy added: [ssh]
Apr 25 16:29:13 internal-sshserver frpc[94421]: 2025-04-25 16:29:13.473 [I] [client/control.go:172] [66f9a7e320b717cd] [ssh] start proxy success

ok,从下面的输出看,和服务器连接成功了

如果token和服务器不一致,将报告以下错误

1
2
3
4
5
6
2025-04-25 16:31:36.210 [I] [sub/root.go:149] start frpc service for config file [./frpc.toml]
2025-04-25 16:31:36.210 [I] [client/service.go:314] try to connect to server...
2025-04-25 16:31:36.216 [E] [client/service.go:299] token in login doesn't match token from configuration
2025-04-25 16:31:36.216 [W] [client/service.go:317] connect to server error: token in login doesn't match token from configuration
2025-04-25 16:31:36.216 [I] [sub/root.go:167] frpc service for config file [./frpc.toml] stopped
login to the server failed: token in login doesn't match token from configuration. With loginFailExit enabled, no additional retries will be attempted

ok,我们的内网ssh服务也已经配置完成,现在就该我们的访问者登场了,访问者只需要访问frp服务器的remotePort端口即可,这个remotePort端口是内网服务器的配置文件中,通知服务器开启的,我们可以在服务器上看一下端口开启情况

1
2
3
4
[root@frp-server ~]# ss -tunlp | grep frp
tcp LISTEN 0 4096 *:6000 *:* users:(("frps",pid=355286,fd=9))
tcp LISTEN 0 4096 *:7000 *:* users:(("frps",pid=355286,fd=6))
tcp LISTEN 0 4096 *:7500 *:* users:(("frps",pid=355286,fd=3))

一旦有内网服务器和frp服务器沟通成功,我们就可以在frp的dashboard上看到了

frp-ssh-server

现在访问者可以通过互联网来访问了,我们来试试吧

远程访问内网ssh服务

1
2
3
4
5
6
7
8
9
10
11
PS C:\Users\Xiaohui> ssh root@你的frp公网IP -p 6000
The authenticity of host '你的frp公网IP (你的frp公网IP)' can't be established.
ED25519 key fingerprint is SHA256:D2EEPcJ8l2BhE6E/V9qNCUriU/njD2jPZMxl7GNMuYs.
This host key is known by the following other names/addresses:
C:\Users\Xiaohui/.ssh/known_hosts:11: [你的frp公网IP]:6000
Are you sure you want to continue connecting (yes/no/[fingerprint])?
root@你的frp公网IP's password:
Activate the web console with: systemctl enable --now cockpit.socket

Last login: Fri Apr 25 15:34:40 2025 from 144.34.235.12
[root@internal-sshserver ~]#

very good,从登录后的主机看,我们已经成功登录了内网服务器,成功了~

这个其实还挺安全的,理由如下:

  1. frp服务器和内网服务器之间经过强token加密

  2. 访问者和内网服务器之间只能通过特定的端口进行密码或密钥交互