内网穿透软件
约 3733 字大约 12 分钟
2025-04-09
1.frp 的安装运行
直接去 frp 官网获取其对应的二进制文件即可,而这里我以 Ubuntu
为例子,使用 wget
进行安装,并且只在 Ubuntu
的具有公网 ip
的机器上尝试运行。
警告
警告:我们这里只是尝试运行,不代表真正应用 frp
,因此下载好 frp
后,配置文件我暂时不修改,只是做个解读。
警告
警告:整个下载配置运行的过程,我都在具有公网 IP
服务器上进行了配置。
# 安装 frp
# 下载 frp 的二进制文件压缩包
$ wget https://github.com/fatedier/frp/releases/download/v0.60.0/frp_0.60.0_linux_amd64.tar.gz
# 解压 frp 的压缩包
$ tar -zxvf frp_0.60.0_linux_amd64.tar.gz
# 重命名解压文件夹
$ mv frp_0.60.0_linux_amd64 frp
# 打开解压文件夹
$ cd frp
# 查看当前目录下的文件
$ ls
frpc frpc.toml frps frps.toml LICENSE
# 查看 frp
# 查看当前服务端程序的配置文件
$ cat frps.toml # 不过我们先按照默认的即可, 我们只在本地稍微测试一下就行
bindPort = 7000 # frp 服务端程序在公网服务器中运行时所在的端口
# 查看当前客户端程序的配置文件
$ cat frpc.toml
serverAddr = "127.0.0.1" # 后续要改为公网服务器的公网 ip(后面是一定要修改的)
serverPort = 7000 # 就是前面的端口, 客户端通过 serverAddr+serverPort 才能找到公网机器中的 frp 服务端程序(因此要和前面 frps.toml 中的 bindPort 保持同步)
[[proxies]] # proxies 就是代理的意思
name = "test-tcp" # 客户端名称(可选修改)
type = "tcp" # 采用的代理协议(没有特殊需求无需修改)
localIP = "127.0.0.1" # 转发到这个 ip
localPort = 22 # 转发到这个 port
remotePort = 6000 # 公网机器上对外开放的端口, 用于支持外界穿透到内网(这样其他非内网主机就可以把对 "公网ip+remotePort" 的请求转发到 "localIP+localPort" 上进行处理)
# 运行 frp
$ ./frps -c ./frps.toml # 使用以下命令启动服务端程序
[1] 558528
2024-09-09 00:18:12.920 [I] [frps/root.go:105] frps uses config file: ./frps.toml
2024-09-09 00:18:13.171 [I] [server/service.go:237] frps tcp listen on 0.0.0.0:7000
2024-09-09 00:18:13.172 [I] [frps/root.go:114] frps started successfully
$ ./frpc -c ./frpc.toml # 使用以下命令启动客户端程序
2024-09-09 00:21:01.337 [I] [sub/root.go:142] start frpc service for config file [./frpc.toml]
2024-09-09 00:21:01.337 [I] [client/service.go:295] try to connect to server...
2024-09-09 00:21:01.342 [I] [server/service.go:576] [42307efebbdeb377] client login info: ip [127.0.0.1:48018] version [0.60.0] hostname [] os [linux] arch [amd64]
2024-09-09 00:21:01.342 [I] [client/service.go:287] [42307efebbdeb377] login to server success, get run id [42307efebbdeb377]
2024-09-09 00:21:01.342 [I] [proxy/proxy_manager.go:173] [42307efebbdeb377] proxy added: [test-tcp]
2024-09-09 00:21:01.343 [I] [proxy/tcp.go:82] [42307efebbdeb377] [test-tcp] tcp proxy listen port [6000]
2024-09-09 00:21:01.343 [I] [server/control.go:399] [42307efebbdeb377] new proxy [test-tcp] type [tcp] success
2024-09-09 00:21:01.343 [I] [client/control.go:168] [42307efebbdeb377] [test-tcp] start proxy success
可以看到没有什么明显的报错,这代表我们安装成功了。
2.frp 的工作原理
frp
主要由两个组件组成:客户端(frpc)
和 服务端(frps)
。通常情况下,服务端部署在具有公网 IP
地址的机器上,而客户端部署在需要穿透的内网服务所在的机器上。
由于内网服务缺乏公网 IP
地址,因此无法直接被非局域网内的用户访问。用户通过访问服务端的 frps
,frp
负责根据请求的端口或其他信息将请求路由到相应的内网机器,从而实现从局域网外的计算机向局域网进行通信。
在 frp
中,一个代理对应一个需要公开访问的内网服务。一个客户端可以同时配置多个代理,以满足不同的需求。
frp
支持多种代理类型,以适应不同的使用场景。以下是一些常见的代理类型:
- TCP:提供纯粹的
TCP
端口映射,使服务端能够根据不同的端口将请求路由到不同的内网服务 - UDP:提供纯粹的
UDP
端口映射,与TCP
代理类似,但用于UDP
流量 - HTTP:专为
HTTP
应用设计,支持修改Host Header
和增加鉴权等额外功能 - HTTPS:类似于
HTTP
代理,但专门用于处理HTTPS
流量 - STCP:提供安全的
TCP
内网代理,要求在被访问者和访问者的机器上都部署frpc
,不需要在服务端暴露端口 - SUDP:提供安全的
UDP
内网代理,与STCP
类似,需要在被访问者和访问者的机器上都部署frpc
,不需要在服务端暴露端口 - XTCP:点对点内网穿透代理,与
STCP
类似,但流量不需要经过服务器中转 - TCPMUX:支持服务端
TCP
端口的多路复用,允许通过同一端口访问不同的内网服务
每种代理类型适用于不同的使用情境,您可以根据需求选择合适的代理类型来配置 frp
,这里我尽可能追寻默认。
3.frp 的实践过程
3.1.代理单个 ssh 服务访问一台内网机器
3.1.1.准备环境
注意
注意:当然,前提是内网机器已经部署了 ssh
连接,否则后面都是空谈...
首先需要准备三台机器,我这里以及有:
- 一台具有公网
ip
的Ubuntu20
服务器public_server
,分配公网IP
假设为x.x.x.x
- 一台我自己组件子网的
Ubuntu24
电脑private_server
- 一台直连运行商
4G
网络的本地apple
电脑self_server
此时 private_server
和 self_server
都可以访问 public_server
,但是 self_server
无法访问到 private_server
。
我们此时要做到的就是 self_server
可以成功借助 public_server
访问到 private_server
。
3.1.2.编写 frp 配置文件
此时我们先把之前在 public_server
的 frp/
文件夹及其内部的内容全部复制到 private_server
中。然后接下来记住:
public_server
持有文件frps, frps.toml, frps.service
private_server
持有文件frpc, frpc.toml, frpc.service
根据我之前的提示,修改配置文件。
# public_server
$ vim frps.toml
$ cat frps.toml
bindPort = 7000 # 保持不变即可, 不过注意 public_server 服务器需要开启这个端口
# private_server
$ vim frpc.toml
$ cat frpc.toml
serverAddr = "x.x.x.x" # 公网机器
serverPort = 7000 # 一定要和上面的 bindPort 保持同步
[[proxies]]
name = "frp-tcp" # 这里我换了一个名字
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000 # 这个端口也一定要在 public_server 上开放
3.1.3.编写 systemd 配置文件
然后再配置文件的基础上,配置服务文件,因为我们一般都是直接使用 systemd
来管理服务端或客户端的。
警告
警告:不过这里官方只配置了一服务端程序的配置文件,这里我把客户端程序的配置文件也给出了,为了方便您后续的使用。而且我还做了一些配置上的改动,增强这个 frp
服务,提高可用性。
# 在 public_server 上创建 frps.service 配置文件
# 编写配置文件
$ sudo vim /etc/systemd/system/frps.service
$ cat /etc/systemd/system/frps.service
[Unit]
Description = frp server # 服务名称,可自定义
After = network-online.target syslog.target # 定义启动顺序: 当前服务要等到系统的网络相关服务, 日志系统相关服务启动之后再启动
Wants = network-online.target # 定义软依赖关系: 尽可能启动网络服务
# Requires = ... # 定义硬依赖关系: ...
[Service]
Type = simple # 定义服务启动类型
ExecStart = <这里填入您的 frps 可执行程序的路径> -c <这里填入您的 frps.toml 配置文件的路径> # 启动 frps 的命令, 需修改为您的 frps 的安装路径
[Install] # 这个不再展开, 要细细研究 systemd 一系列的知识才能正确理解...
WantedBy = multi-user.target
# 在 private_server 上创建 frpc.service 配置文件
# 编写配置文件
$ sudo vim /etc/systemd/system/frpc.service
$ cat /etc/systemd/system/frpc.service
[Unit]
Description = frp client # 服务名称,可自定义
After = network-online.target syslog.target # 定义启动顺序: 当前服务要等到系统的网络相关服务, 日志系统相关服务启动之后再启动
Wants = network-online.target # 定义软依赖关系: 尽可能启动网络服务
# Requires = ... # 定义硬依赖关系: ...
[Service]
Type = simple # 定义服务启动类型
ExecStart = <这里填入您的 frpc 可执行程序的路径> -c <这里填入您的 frpc.toml 配置文件的路径> # 启动 frps 的命令, 需修改为您的 frpc 的安装路径
[Install] # 这个不再展开, 要细细研究 systemd 一系列的知识才能正确理解...
WantedBy = multi-user.target
提示
区别:软依赖和硬依赖的区别。
- 软依赖(Wants=):表示一种非强制性依赖关系,启动当前服务时,会尽可能尝试启动依赖的服务,但即使依赖的服务启动失败,当前服务也会继续启动。适合那些不强制要求依赖服务的场景,即使依赖的服务未成功启动,当前服务依旧可以独立运行。
- 硬依赖(Requires=):表示一种强制性依赖关系,启动当前服务时,要求依赖的服务必须成功启动,否则当前服务也会启动失败。若依赖的服务在运行过程中失败并退出,当前服务也会因此被终止。
重要
补充:添加重启策略。
我所在的地方经常停电,因此我对于自动重启是强需求,因此我补充下面这个具有重启策略的文件供您参考。
# 在 private_server 上重新 frpc.service 配置文件
# 编写配置文件
$ sudo vim /etc/systemd/system/frpc.service
$ cat /etc/systemd/system/frpc.service
[Unit]
Description = frp client # 服务名称,可自定义
After = network-online.target syslog.target # 定义启动顺序: 当前服务要等到系统的网络相关服务, 日志系统相关服务启动之后再启动
Wants = network-online.target # 定义软依赖关系: 尽可能启动网络服务
# Requires = ... # 定义硬依赖关系: ...
[Service]
Type = simple # 定义服务启动类型
ExecStart = <这里填入您的 frpc 可执行程序的路径> -c <这里填入您的 frpc.toml 配置文件的路径> # 启动 frps 的命令, 需修改为您的 frpc 的安装路径
Restart=on-failure # 失败时自动重启
RestartSec=5s # 重启间隔时间(5秒)
[Install]
WantedBy=multi-user.target
3.1.4.管理服务
然后也是经典的 systemd
管理指令来进行管理。
# 管理 frps.service 服务
# 重载 frps.service 服务文件
$ sudo systemctl daemon-reload
# 启动 frps.service 服务
sudo systemctl start frps.service
# 设置 frps.service 服务为开机自启动
sudo systemctl enable frps.service
# 查看 frps.service 状态
sudo systemctl status frps.service
# 管理 frpc.service 服务
# 重载 frpc.service 服务文件
$ sudo systemctl daemon-reload
# 启动 frpc.service 服务
$ sudo systemctl start frpc.service
# 设置 frpc.service 服务为开机自启动
$ sudo systemctl enable frpc.service
# 查看 frpc.service 状态
$ sudo systemctl status frpc.service
3.1.5.使用内网穿透
然后使用 ssh -p 6001 private_server_user_name@x.x.x.x
在 self_server
上开始内网穿透,能输入密码并且访问到 bash
终端就说明穿透成功。
3.2.代理多个 ssh 服务访问多台内网机器
但是如果希望配置多个 ssh
服务怎么办呢?照葫芦画瓢。
3.2.1.准备环境
假设我现在有一台 public_server
,以及两台 private_server_1, private_server_2
和一台 self_server
,我们希望 self_server
可以通过 public_server
访问 private_server_1, private_server_2
。
这种做法可以,但是需要换一种协议,这种协议就是 tcpmux
,可以让我们只使用一个端口就可以连接多台服务器。
3.2.2.编写 frp 配置文件
# frps.toml
bindPort = 7000 # frps 服务的运行端口
tcpmuxHTTPConnectPort = 5002 # 多路复用代理端口, 通过一个 TCP 连接发送多个 HTTP 请求
# frpc.toml
serverAddr = "x.x.x.x" # frps 服务的运行地址
serverPort = 7000 # frps 服务的运行端口
[[proxies]]
name = "server_name" # 我改为了 private_server_1 和 private_server_2
type = "tcpmux" # 注意协议更换了
multiplexer = "httpconnect" # 允许多路复用
customDomains = ["server_name.com"] # 自定义域名, 我改为了 private_server_1.com 和 private_server_2.com
localIP = "127.0.0.1"
localPort = 22
注意
注意:多个 private_server
复用上面的 frpc.toml
即可,注意还是需要做些修改才能进行复用。
3.2.3.编写 systemd 配置文件
然后再配置文件的基础上,配置服务文件。
# 在 public_server 上创建 frps.service 配置文件
# 编写配置文件
$ sudo vim /etc/systemd/system/frps.service
$ cat /etc/systemd/system/frps.service
[Unit]
Description = frp server # 服务名称,可自定义
After = network-online.target syslog.target # 定义启动顺序: 当前服务要等到系统的网络相关服务, 日志系统相关服务启动之后再启动
Wants = network-online.target # 定义软依赖关系: 尽可能启动网络服务
# Requires = ... # 定义硬依赖关系: ...
[Service]
Type = simple # 定义服务启动类型
ExecStart = <这里填入您的 frps 可执行程序的路径> -c <这里填入您的 frps.toml 配置文件的路径> # 启动 frps 的命令, 需修改为您的 frps 的安装路径
[Install] # 这个不再展开, 要细细研究 systemd 一系列的知识才能正确理解...
WantedBy = multi-user.target
# 在 private_server 上都创建一样的 frpc.service 配置文件
# 编写配置文件
$ sudo vim /etc/systemd/system/frpc.service
$ cat /etc/systemd/system/frpc.service
[Unit]
Description = frp client # 服务名称,可自定义
After = network-online.target syslog.target # 定义启动顺序: 当前服务要等到系统的网络相关服务, 日志系统相关服务启动之后再启动
Wants = network-online.target # 定义软依赖关系: 尽可能启动网络服务
# Requires = ... # 定义硬依赖关系: ...
[Service]
Type = simple # 定义服务启动类型
ExecStart = <这里填入您的 frpc 可执行程序的路径> -c <这里填入您的 frpc.toml 配置文件的路径> # 启动 frps 的命令, 需修改为您的 frpc 的安装路径
[Install] # 这个不再展开, 要细细研究 systemd 一系列的知识才能正确理解...
WantedBy = multi-user.target
3.1.4.管理服务
然后也是经典的 systemd
管理指令来进行管理。
# 管理 frps.service 服务
# 重载 frps.service 服务文件
$ sudo systemctl daemon-reload
# 启动 frps.service 服务
sudo systemctl start frps.service
# 设置 frps.service 服务为开机自启动
sudo systemctl enable frps.service
# 查看 frps.service 状态
sudo systemctl status frps.service
# 管理 frpc.service 服务
# 重载 frpc.service 服务文件
$ sudo systemctl daemon-reload
# 启动 frpc.service 服务
$ sudo systemctl start frpc.service
# 设置 frpc.service 服务为开机自启动
$ sudo systemctl enable frpc.service
# 查看 frpc.service 状态
$ sudo systemctl status frpc.service
3.1.5.使用内网穿透
重要
补充:要使用还必须在本主机上下载 socat
...
使用 SSH ProxyCommand
访问内网机器 private_server_1
,假设用户名为 test
。使用以下命令:
ssh -o 'proxycommand socat - PROXY:x.x.x.x:%h:%p,proxyport=5002' test@private_server_1.com
要访问内网机器 B
,只需更改域名,假设用户名仍然为 test
:
ssh -o 'proxycommand socat - PROXY:x.x.x.x:%h:%p,proxyport=5002' test@private_server_2.com
通过按照以上步骤进行配置,您可以实现多个 SSH
服务复用同一端口,以便在具有公网 IP
的机器上进行访问。
重要
补充:不过这有一个麻烦,就是使用某些 ssh
连接软件的时候不太好配置,并且有时装发压力比较大...
注
结语:...
如果本系列文章对您有帮助,可以 star 一下我的 limou-learn-note,求求惹(๑> <)☆♡~
[Unit]
Description=Magic Service
After=network.target
[Service]
ExecStart=/home/ljp/.config/mihomo/clash-linux
Restart=on-failure
User=ljp
WorkingDirectory=/home/ljp/.config/mihomo/
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=clash-linux
[Install]
WantedBy=multi-user.target