FRP 内网穿透
内网穿透
本地电脑上起了服务,其他人是访问不到的,借助服务器的公网IP,服务端帮助转发消息,其他人才能访问到本地电脑上的服务。
具体可以用来做什么
1、本地计算机上启动 web 服务,通过端口映射,别人通过公网和端口就能访问。
2、Windows 远程桌面连接,比如,从住的地方连接公司的电脑。(有安全风险,需要和公司报备)
3、SSH 远程连接到开发板内的 linux 系统。
向日葵的免费账户的带宽有限
我有1台腾讯的轻量云服务器
frp 文件下载:https://www.123pan.com/s/Lwn8Vv-ul2x.html
提取码:FAIM
winsw 文件下载:https://www.123pan.com/s/Lwn8Vv-Sl2x.html
提取码:bYeZ
frp 中文文档
https://gofrp.org/zh-cn/docs/
https://github.com/fatedier/frp/blob/dev/README_zh.md
服务端
服务端下载 frps
下载frp软件:https://github.com/fatedier/frp
服务端下载安装
比如
在 /opt/
目录下
cd /opt/
下载64位0.44版本的,arm服务器要选arm版本,现在常见服务器都是amd64架构的,也就是x86的64位指令集架构。
wget https://github.com/fatedier/frp/releases/download/v0.44.0/frp_0.44.0_linux_amd64.tar.gz
服务端配置 frps
解压
tar -zxvf frp_0.44.0_linux_amd64.tar.gz
重命名,为了后面配置路径简单
mv frp_0.44.0_linux_amd64 frp
配置文件,服务端 frps 的 s
即 server,frpc 的 c
即 client。
vi frps.ini
frps.ini
文件内容,默认即可
[common]
bind_port = 7000
也可以设置token,相当于设置了一个密码,例如
[common]
bind_port = 7000
token = abc123
服务端防火墙,放行端口7000、7001、6000、8080等需要的端口
启动服务端
正常启动
./frps -c ./frps.ini
服务端设置程序开机启动
在frps.service里写入内容,有时候会提示system
目录不存在,那就先建目录
mkdir /usr/lib/systemd/system/
vi /usr/lib/systemd/system/frps.service
frps.service 内容
[Unit]
Description=frps service
After=network.target
[Service]
Type=simple
ExecStart=/opt/frp/frps -c /opt/frp/frps.ini
[Install]
WantedBy=multi-user.target
配置生效,启动,设置开机启动
systemctl daemon-reload
systemctl start frps
systemctl enable frps
查看状态
systemctl status frps
客户端
windows 客户端配置 frpc
Windows10 当然是amd64位架构的 frp_0.44.0_windows_amd64.zip
比如想在家远程公司电脑,在公司电脑上安装设置 frpc。
我喜欢在 C 盘下建一个sw
的文件夹来存自己安装的程序,sw 即 software 的意思。
解压到 C:\sw\
目录下,也就是现在 frp 目录是 C:\sw\frp
(需要把这个文件夹添加到病毒排除项)
修改 frp 客户端的配置文件frpc.ini
[common]
server_addr = 127.0.0.1
server_port = 7000
[rdp7001]
type = tcp
local_ip = 127.0.0.1
local_port = 3389
remote_port = 7001
修改第一句 server_addr
的127.0.0.1
为云服务器的 IP 地址
如果服务端配置了 token,那客户端也要配置。
windows一般也不用ssh,删除内容,增加远程桌面的协议 rdp 的设置
即现在是
[common]
server_addr = 云服务器地址
server_port = 7000
token = abc123
[rdp7001]
type = tcp
local_ip = 127.0.0.1
local_port = 3389
remote_port = 7001
🟢 “server_addr”是服务端 IP 地址,填入即可,
🟢 “server_port”为服务器端口,即 bind_port 的值,
🟢 “token”是你在服务器上设置的连接口令。
🟢 [rdp]:这个 rdp 是给服务起的名字,名字当然随意设置,就是服务名字不能重复(从服务端看来,一个端口一个名字),如果有多个远程桌面需要端口转发,可以起:[rdp7001]、[rdp7002]
这里用到了 2 个自定义规则,一个是 rdp,一个是 smb:
🍑RDP,即 Remote Desktop 远程桌面,Windows 的 RDP 默认端口是 3389,协议为 TCP,本条规则可以实现远程桌面连接。
🍑SMB,即 Windows 文件共享所使用的协议,默认端口号 445,协议 TCP,本条规则可实现远程文件访问。
在 window10 上启动 frpc 程序
注意:Microsoft Defender 会给 frpc.exe 软件报病毒,会给移除,需要还原。
打开 cmd 程序,比如 win + R,输入 cmd
,我一般按 win 键,输入 cmd,右键“以管理员身份运行”
切换到 frpc 的目录
cd C:\sw\frp
frpc.exe -c frpc.ini
就启动了
win10 启动远程桌面:【设置】,【系统】,【远程桌面】,启动远程桌面
Windows 远程连接:
按 win 键,输入“远程桌面连接”
计算机:服务端公网IP地址:7001
用户名和密码,是 window 电脑的用户名和密码。
当然也可以把本地 web 服务通过云服务器访问
增加 web 配置即可
[webxxx]
type = tcp
local_ip = 127.0.0.1
local_port = 本地端口
remote_port = 映射到的服务器端口
现在完整的配置如下
[common]
server_addr = 云服务器地址
server_port = 7000
token = abc123
[rdp7001]
type = tcp
local_ip = 127.0.0.1
local_port = 3389
remote_port = 7001
[web9090]
type = tcp
local_ip = 127.0.0.1
local_port = 8080
remote_port = 9090
windows 客户端设置程序开机启动
需要一个软件 winsw
https://github.com/winsw/winsw
Windows 服务包装器,WinSW 将任何应用程序作为一个 Windows 服务进行包装和管理。
WinSW 3可以在安装了 .NET Framework 4.6.1 或更高版本的Windows平台上运行。
对于没有 .NET 框架的系统,该项目提供基于 .NET 核心的本地64位和32位可执行文件。
因为 win11 自带 .Net 环境
所以下载 WinSW.NET461.exe
配置文件
WinSW.NET461.xml
<service>
<!-- 服务ID,整个 window 系统中唯一-->
<id>frpc</id>
<!-- 服务的显示名字 -->
<name>frpc</name>
<!-- 服务描述 -->
<description>FRP 客户端,用来实现内网穿透</description>
<!-- Path to the executable, which should be started -->
<!-- 想要启动的可执行程序的路径 -->
<executable>C:\SW\frp\frpc.exe</executable>
<!-- 携带的参数 -->
<arguments>-c C:\SW\frp\frpc.ini</arguments>
<!-- 第一次启动失败 60秒重启 -->
<onfailure action="restart" delay="60 sec"/>
<!-- 第二次启动失败 120秒后重启 -->
<onfailure action="restart" delay="120 sec"/>
<!-- 日志模式 -->
<logmode>append</logmode>
<!-- 指定日志文件目录(相对于WinSW.exe配置的路径) -->
<logpath>C:\SW\frp\log</logpath>
</service>
将 exe 和 xml 文件放到同一个文件夹下
命令行运行,使用 WinSW-x64.exe
// 安装服务
WinSW-x64.exe install
// 卸载服务
WinSW-x64.exe uninstall
// 启动服务
WinSW-x64.exe start
// 停止服务
WinSW-x64.exe stop
// 重启服务
WinSW-x64.exe restart
// 查看状态
WinSW-x64.exe status
命令行运行,使用 WinSW.NET461.exe
// 安装服务
WinSW.NET461.exe install
// 卸载服务
WinSW.NET461.exe uninstall
// 启动服务
WinSW.NET461.exe start
// 停止服务
WinSW.NET461.exe stop
// 重启服务
WinSW.NET461.exe restart
// 查看状态
WinSW.NET461.exe status
按 win 键,输入“服务”,找到 frpc 服务,第一次要手动启动
启动失败,就去看看 frpc 的配置文件 frpc.ini
内容是否不匹配。
linux 客户端配置 frpc
注意版本
开发板一般是arm架构系统32/64位的linux系统,frp_0.44.0_linux_arm.tar.gz,frp_0.44.0_linux_arm64.tar.gz
比如
在 /opt/
目录下
cd /opt/
下载
wget https://github.com/fatedier/frp/releases/download/v0.44.0/frp_0.44.0_linux_arm.tar.gz
解压
tar -zxvf frp_0.44.0_linux_arm.tar.gz
重命名,为了后面配置路径简单
mv frp_0.44.0_linux_arm frp
配置文件
修改配置文件 frpc.ini
[common]
server_addr = 服务端公网IP地址
server_port = 7000
token = abc123
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
运行客户端程序
./frpc -c ./frpc.ini
如果还有开发板客户端要连接,也就是服务端要用不同的端口帮忙转发,一个客户端用一个端口,比如新增加的开发板用 6001 端口,注意段端放开 6001 端口。
linux 客户端设置程序开机启动
为 frpc 配置 systemd
的service文件,有时候会提示system
目录不存在,那就先建目录
mkdir /usr/lib/systemd/system/
vi /usr/lib/systemd/system/frpc.service
frpc.service
文件内容
[Unit]
Description=frpc
Wants=network-online.target
After=network.target network-online.target
Requires=network-online.target
[Service]
ExecStart=/opt/frp/frpc -c /opt/frp/frpc.ini
ExecStop=/bin/kill $MAINPID
Restart=always
RestartSec=5
StartLimitInterval=0
[Install]
WantedBy=multi-user.target
解释一下上面文件内容
- Wants:本单元启动了,它“想要”的单元也会被启动。但是这个单元若启动不成功,对本单元没有影响。
- Requires: 这个单元启动了,那么它“需要”的单元也会被启动; 它“需要”的单元被停止了,它自己也活不了。但是请注意,这个设定并不能控制启动顺序,因为它“需要”的单元启动也需要时间,若它“需要”的单元启动还未完成,就开始启动本单元,则本单元也无法启动,所以不建议使用这个字段。
- OnFailure:若本单元启动失败了,那么启动这个单元作为折衷。
- Before/After:指定启动顺序。
Wants=network-online.target #其中network.target代表有网路,network-online.target代表一个连通着的网络。
ExecStart=/opt/frp/frpc -c /opt/frp/frpc.ini #是要运行的命令,文件要绝对地址。
Restart=always #总是重启
RestartSec=5 #自动重启当前服务间隔的秒数
StartLimitInterval=0 #无限次重启,默认是10秒内如果重启超过5次则不再重启,设置为0表示不限次数重启
使frpc服务生效
systemctl daemon-reload
systemctl enable frpc
systemctl start frpc
查看状态
systemctl status frpc
远程 SSH 连接开发板就是:
使用SSH工具登录
- 用户名,密码:就是开发板上的用户名和密码
- IP地址:公网IP
- 端口:6000
frp配置http
type = tcp 的配置
服务端不修改
客户端增加
frpc.ini
[common]
server_addr = 49.235.114.132
server_port = 7000
token = abc123
[web]
type = tcp
local_ip = 127.0.0.1
local_port = 48080
remote_port = 8080
type = http 的配置
服务端配置
frps.ini
[common]
bind_port = 7000
token = abc123
vhost_http_port = 8080
客户端配置
frpc.ini
[common]
server_addr = 49.235.114.132
server_port = 7000
token = abc123
[web-48080]
type = http
local_port = 48080
local_ip = 127.0.0.1
服务起名字
服务名字是随便取的,要求是不能重复。
当然一般可以起有意义的简短名字加上端口号
比如 rdp7002、web-48080
比如 kepserver 上的 OPCUA server 服务,我只知道本地端口 49320 转到服务端端口 49320
类似这样
[OPCUA-49320]
type = http
local_port = 49320
local_ip = 127.0.0.1
remote_port = 49320
内网服务外网访问
比如在内网服务器 192.168.10.8 上部署了一个服务 hello,端口 8080
想要能从外网通过公网 IP 访问
可以在客户端
[hello-8080]
type = tcp
local_ip = 192.168.10.8
local_port = 8080
remote_port = 8080
hello 相当于服务端的服务名字,不能重复,懒得起名可以使用 UUID
访问地址:外网IP:8080
Docker 启动和 toml 格式
Docker 启动服务端实践
文件夹
/app/frps
├── docker
│ ├── Dockerfile
│ └── frp
│ ├── frps
│ └── frps.toml
├── frps.toml
└── startup.sh
frps.toml
bindPort = 7000 #服务端监听端口
auth.method = "token" #服务端连接身份认证,默认token
auth.token = "mytoken" #服务端token密码
Dockerfile
FROM alpine:3.8
ENV VERSION 0.59.0
ENV TZ=Asia/Shanghai
ENV APP_DIR=/frp
WORKDIR $APP_DIR
COPY ./frp $APP_DIR
RUN apk add --no-cache tzdata \
&& ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime \
&& echo ${TZ} > /etc/timezone
VOLUME /frp
CMD /frp/frps -c /frp/frps.toml
构建
cd /app/frps/docker
docker build -t frps:1.0 .
启动命令 startup
docker run -d \
--name frps \
--restart always \
-v /app/frps/frps.toml:/frp/frps.toml \
--log-opt max-size=1m \
--log-opt max-file=3 \
frps:1.0
重启
docker restart frps
查看日志
docker logs -f frps
Docker 启动客户端实践
内网,所以先下载了对应文件,然后使用 Dockerfile 制作镜像。
优点:不使用 systemd 管理了,修改了 frpc.toml 后,docker 重启服务即可。
文件夹,只保留 frpc 和 frpc.toml 文件
/app/frpc/docker/frp
|-- frpc
-- frpc.toml
Dockerfile
FROM alpine:3.8
ENV VERSION 0.59.0
ENV TZ=Asia/Shanghai
ENV APP_DIR=/frp
WORKDIR $APP_DIR
COPY ./frp $APP_DIR
RUN apk add --no-cache tzdata \
&& ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime \
&& echo ${TZ} > /etc/timezone
VOLUME /frp
CMD /frp/frpc -c /frp/frpc.toml
构建
cd /app/frpc/docker
docker build -t frpc:1.0 .
启动
docker run -d \
--name frpc \
--restart always \
-v /app/frpc/frpc.toml:/frp/frpc.toml \
--log-opt max-size=1m \
--log-opt max-file=3 \
frpc:1.0
重启
docker restart frpc
docker logs -f frpc
toml 格式配置文件
服务端 frpc.toml
serverPort = 7000
auth.method = "token"
auth.token = "服务端设置的token值"
客户端 frpc.toml
serverAddr = "公网IP"
serverPort = 7000
auth.method = "token"
auth.token = "服务端设置的token值"
[[proxies]]
name = "redis-36379"
type = "tcp"
localIP = "192.168.10.8"
localPort = 36379
remotePort = 36379
[[proxies]]
name = "redis-26379"
type = "tcp"
localIP = "192.168.10.8"
localPort = 26379
remotePort = 26379
上面配置是将内网的一个 Redis 服务映射出去,测试用的。
客户端和服务端版本,最好一致,不一致也能用。