利用 Frp 实现内网穿透

Frp 项目官方地址:https://github.com/fatedier/frp/

◇ 服务端

▷ 安装

使用以下命令查看服务端架构:

1
2
$ arch
x86_64

根据架构不同,选择相应版本并进行下载:

1
2
3
4
5
cd
mkdir -p project/frp
cd project/frp

wget https://github.com/fatedier/frp/releases/download/v0.52.3/frp_0.52.3_linux_amd64.tar.gz

然后解压文件:

1
2
3
4
# 解压到当前目录
tar -zxvf frp_0.22.0_linux_amd64.tar.gz
# 重命名文件夹
mv frp_0.22.0_linux_amd64 program

tar 用于压缩和解压文件和目录:

  • -z: 表示使用 gzip 来解压缩文件。.tar.gz 文件通常是经过 gzip 压缩的。
  • -x: 表示解压缩操作,即从 .tar.gz 文件中提取文件和目录。
  • -v: 用于启用详细的输出,以便查看解压缩过程中提取的文件。
  • -f: 指定要解压缩的 .tar.gz 文件的文件名。

如果要将文件提取到不同目录,可以使用 -C 指定目标目录,例如:

1
tar -zxvf <file_name>.tar.gz -C <folder_name>

▷ 配置

打开目录,发现有多个文件:

1
2
3
$ cd program
$ ls
frpc frpc.toml frps frps.toml LICENSE

其中 frpcfrpc.toml 是客户端文件,可以删除。

打开 frps.toml 配置文件:

1
vim frps.toml

填写以下内容:
(详细说明解释见官方文档:链接)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
bindPort = 7000
kcpBindPort = 7000

bindAddr = "0.0.0.0"
allowPorts = [
{ start = 1001, end = 1500 },
{ start = 10001, end = 22500 },
{ single = 3333 }
]

auth.method = "token"
auth.token = "abc"

tls.force = true

webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "user"
webServer.password = "123"

旧版 frps.ini 写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[common]
bind_port = 7000
bind_udp_port = 7000

bind_addr = 0.0.0.0
allow_ports = 1001-1500,10001-22500,3333

token = abc

tls_only = true

dashboard_port = 7500
dashboard_user = user
dashboard_pwd = 123

▷ 后台自启

使用以下命令前台运行:

1
./frps -c frps.toml

或者使用 systemctl 来后台自启。

创建文件:

1
2
cd
sudo vim /lib/systemd/system/frps.service

填入以下内容:

1
2
3
4
5
6
7
8
9
10
11
[Unit]
Description=frps service
After=network.target syslog.target
Wants=network.target

[Service]
Type=simple
ExecStart=/home/<user_name>/project/frp/program/frps -c /home/<user_name>/project/frp/program/frps.toml

[Install]
WantedBy=multi-user.target

[Unit]:包含有关服务单元的基本信息。

Description:服务的描述,简要说明服务的目的。

After:指定服务应该在哪些服务之后启动。

  • network.target 是一个 Systemd 目标,用于表示网络子系统的启动状态。

    当系统进入 network.target 时,表示网络子系统已准备就绪,包括网络接口的配置、网络连接等。这通常发生在系统引导过程中。

    许多网络相关的服务和单元文件会依赖于 network.target,以确保它们在网络可用时才会启动。这有助于避免服务在没有网络连接的情况下启动,从而提高了系统的稳定性。

  • syslog.target 也是一个 Systemd 目标,用于表示系统日志服务的启动状态。

    当系统进入 syslog.target 时,表示系统日志服务已准备就绪,可以记录系统事件、错误和日志信息。

    通常,各种系统日志服务 (如 rsyslog、systemd-journald 等) 会依赖于 syslog.target,以确保它们在系统启动时或在运行时能够正确地记录和处理系统日志。

Wants:指定了服务所依赖的其他服务。

===
[Service]:这个部分包含有关服务运行方式的信息。

Type:指定服务的启动类型。“simple” 表示是一个简单的启动类型,通常用于单个进程的服务。

ExecStart:指定服务启动时要运行的命令。

===
[Install]:这个部分指定了服务的安装信息。

WantedBy:指定了服务在哪个目标 (target) 下安装。“multi-user.target” 表示当系统进入多用户模式时,这个服务会被安装并启动。

后台自启,需要 root 权限:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 启动应用
systemctl start frps
# 重启应用
systemctl restart frps
# 停止应用
systemctl stop frps

# 打开自启动
systemctl enable frps
# 关闭自启动
systemctl disable frps

# 查看应用日志
systemctl status frps

💡 如果只希望特定用户登陆后启动一些服务,可以使用 Systemd 的用户单元文件而不是系统单元文件。

首先登录到特定用户的帐户,在用户的家目录中创建 .config/systemd/user/

1
mkdir -p ~/.config/systemd/user/

进入该目录创建一个名为 <name>.service 的用户单元文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
[Unit]
Description=
After=
Wants=

[Service]
Type=
ExecStart=

[Install]
WantedBy=default.target

这个用户单元文件的配置与之前的系统单元文件基本相同。唯一的不同之处在于 WantedBy 设置为 default.target,这将使该服务在用户登录时启动。

保存用户单元文件,使用以下命令来启用用户单元文件并启动服务:

1
2
systemctl --user enable <name>.service
systemctl --user start <name>.service

▷ 开放端口

登录云服务器账户,开放 7000 (tcp/udp) 和 7500 (tcp) 端口。

▷ 服务端仪表盘

浏览器访问 http://ip:7500 输入前面设置的用户名和密码,可以登录仪表盘查看信息:
dashboard

◇ 客户端

▷ 安装

官网地址下载对应版本并解压:https://github.com/fatedier/frp/releases

▷ 配置

打开 frpc.toml 配置文件,填写以下内容:
(详细说明解释见官方文档:链接)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
serverAddr = "111.111.111.111"
serverPort = 7000

auth.method = "token"
auth.token = "abc"

transport.tls.enable = true

transport.protocol = "websocket"

[[proxies]]
name = "remote_desktop"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3389
remotePort = 3333

旧版 frps=c.ini 写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[common]
server_addr = 111.111.111.111
server_port = 7000

token = abc

tls_enable = true

protocol = websocket

[remote_desktop]
type = tcp
local_ip = 127.0.0.1
local_port = 3389
remote_port = 3333

▷ 后台自启

使用以下命令前台运行:

1
./frps.exe -c frps.toml

或者使用 vbs 实现开机自启后台运行。

在程序文件夹创建名为 RUN-hide.vbs 的文件,填入以下内容:

1
CreateObject("WScript.Shell").Run "frpc.exe -c frpc.toml", 0

开机自启方式:

win + R 输入:

1
2
3
4
5
# 所有用户开机自启
shell:Common Startup

# 当前用户开机自启
shell:Startup

在打开的文件夹里添加一个 RUN-hide.vbs 文件的快捷方式即可。

▷ 开放端口

按照前面配置文件中的内容开放云服务器相应的端口。

◇ 使用场景

▷ 远程桌面

使用微软自带的远程桌面,输入服务器 IP 和设置的端口号,如:111.111.111.111:3333,即可连接。

▷ BT 加速

- Frp

客户端配置添加以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
[[proxies]]
name = "BT Listen TCP"
type = "tcp"
localIP = "127.0.0.1"
localPort = 5555
remotePort = 5555

[[proxies]]
name = "BT Listen UDP"
type = "udp"
localIP = "127.0.0.1"
localPort = 5555
remotePort = 5555

检查远程服务器 Frp 配置文件里是否允许该端口,没有的话记得添加一条。

然后开放云服务器相应的端口。

- Gost

除上面步骤之外需要为 BT 客户端设置一个代理。这里使用 Gost。

官方地址:https://github.com/ginuerzh/gost

使用 Docker 部署:

1
2
3
4
cd
mkdir -p project/gost/docker
cd project/gost/docker
vim docker-compose.yml

输入以下内容:

1
2
3
4
5
6
7
8
9
version: '3.3'
services:
gost:
restart: always
network_mode: host
container_name: gost
image: 'ginuerzh/gost:latest'
command:
- "-L=<user_name>:<password>@:6666"

为什么 command 字段不用输入命令 gost

查看项目源码 Dockerfile 文件的最后几行:

1
2
3
4
FROM alpine:latest
WORKDIR /bin/
COPY --from=builder /src/cmd/gost/gost .
ENTRYPOINT ["/bin/gost"]

可以看到一个 ENTRYPOINT 字段,它定义容器的默认启动命令,即 /bin/gost,所以无需输入 gost 命令。

进阶:

可以将 CMDENTRYPOINT 结合使用,以允许用户在运行容器时提供额外的命令参数。两个指令都可以在部署时通过特定参数覆盖 Dockerfile 中的默认命令。

例如,如果 Dockerfile 包含以下 ENTRYPOINTCMD 指令:

1
2
ENTRYPOINT ["python", "app.py"]
CMD ["--debug"]

当运行容器时,可以如下覆盖 CMD 中的 --debug 参数:

1
docker run my-image --production

这将执行 python app.py --production

覆盖格式:

docker run

1
docker run -d --entrypoint custom-entrypoint my-image --arg1 value1

docker compose

1
2
3
4
5
services:
my-service:
image: my-image
entrypoint: ["custom-entrypoint"]
command: ["--arg1", "value1"]

启动 Docker 容器:

1
2
# 后台运行
docker-compose up -d

开放对应端口,在 BT 客户端中填入 sockes5 代理即可。

◇ 参考内容

  1. 使用frp进行内网穿透. https://sspai.com/post/52523
  2. 利用内网穿透和代理获取公网 IP 地址解决比特彗星黄灯. https://blog.arisa.moe/blog/2022/220413-Intranet-penetration-bitcomit/
  3. 利用Frp和Gost打通比特彗星堵塞端口. https://zhuanlan.zhihu.com/p/543712091
  4. 各种踩坑后终于实现使用frp完成远程桌面连接. https://zhuanlan.zhihu.com/p/385162671
  5. 如何实现外网 RDP 远控(frp). https://wiki-power.com/%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E5%A4%96%E7%BD%91RDP%E8%BF%9C%E6%8E%A7%EF%BC%88frp%EF%BC%89/
  6. docker版Gost的打包解决方案:隧道、ss和socks5. https://www.isir.xyz/134