
frp 实现内网穿透
最近购买了阿里云的 99 元/年的 ECS,正好可以作为跳板将部署在内网的一些服务穿透到公网访问。本文将展示 frp 实现内网穿透的操作过程,供参考。
前提
- 一台随意服务商的具备公网 IP 的服务器。
我这里使用的服务器是阿里云的 ECS 实例。最好是方便远程 SSH 连接!
阿里云的服务器在网络与安全分组中的密钥对中可以添加自己常用的密钥,然后绑定到 ECS 实例,实例重启后就可以 SSH 免密登录了。
什么是 frp
frp 采用 C/S 模式,将服务端部署在具有公网 IP 的机器上,客户端部署在内网或防火墙内的机器上,通过访问暴露在服务器上的端口,反向代理到处于内网的服务。 在此基础上,frp 支持 TCP, UDP, HTTP, HTTPS 等多种协议,提供了加密、压缩,身份认证,代理限速,负载均衡等众多能力。此外,还可以通过 xtcp 实现 P2P 通信。
更多详情阅读 https://gofrp.org/zh-cn/
下载 frp
https://github.com/fatedier/frp/releases
需要根据服务器和内网机器的情况对应下载,比如我的服务器安装的是 64 位 ubuntu,内网机器是 Intel 芯片的 mac mini 安装的是 macOS,所以我需要下载:
每一个包中均包含四个关键文件:
部署 frp 测试
frp 大体的工作原理如下,我们只需要在服务器端按照指定配置文件启动 frps,在内网机器按照自定义客户端配置文件启动 frpc 即可完成内网服务穿透。
服务端启动 frps
把本地下载的 frp_0.56.0_linux_amd64.tar.gz 发送到服务器中:
1 2# aliyun 是我的服务器的 ssh 配置名称 scp frp_0.56.0_linux_amd64.tar.gz aliyun
ssh 连接服务器
1ssh aliyun
解压文件并重命名目录为 frp 进入 frp 目录
1tar -xzvf frp_0.56.0_linux_amd64.tar.gz && mv frp_0.56.0_linux_amd64 frp && cd frp
配置文件
可以执行以下命令修改配置文件内容(示例文件)
1 2 3 4cat <<EOF > frps.toml bindPort = 7000 authentication_timeout = 0 EOF
- bindPort 就是 frps 要运行在的端口,供客户端准确连接。
- authentication_timeout 指的是不限制认证超时时间。
启动服务
1./frps -c frps.toml
内网机器启动 frpc
解压文件并进入目录
1tar -xzvf frp_0.56.0_darwin_amd64.tar.gz && mv frp_0.56.0_darwin_amd64 frp && cd frp
配置文件
示例配置如下(示例文件)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16serverAddr = "xxx.xxx.xxx.xxx" serverPort = 7000 [[proxies]] name = "mysql" type = "tcp" localIP = "127.0.0.1" localPort = 3306 remotePort = 6000 [[proxies]] name = "ssh" type = "tcp" localIP = "127.0.0.1" localPort = 22 remotePort = 221
- serverAddr 是 frps 运行的IP 地址,也就是服务器的公网 IP
- serverPort 是 frps 运行的端口,对应 frps.toml 中的端口,也就是 7000
- 可以添加多个 proxy,形如
1 2 3 4 5 6[[proxies]] name = "mysql" type = "tcp" localIP = "127.0.0.1" localPort = 3306 remotePort = 6000
- name 为自定义的名称,方便自己区分代理穿透的是哪个服务
- type 为代理协议类型,支持 TCP、UDP、HTTP、HTTPS 等协议,TCP 最常用,需要根据自己的需求选择
- localIP 为本地服务运行机器的 IP 地址,可以是局域网内任何可访问的服务
- localPort 为本地服务运行端口
- remotePort 为服务器端的代理端口,这样就可以使用服务器
IP:remotePort访问到代理的本地服务,比如xxx.xxx.xxx.xxx:6000对应就能访问到内网机器的127.0.0.1:3306对应的服务
按照我的描述,自行修改你个人的客户端配置,我的配置中添加了 SSH 的代理,如果成功的话,我将可以通过 xxx.xxx.xxx.xxx:221 SSH 连接到内网机器。
启动客户端
1./frpc -c frpc.toml
测试连通性
使用穿透的 SSH 服务测试即可,祝愿你成功。
生产部署
CTRL+C停掉上面启动的 frps 和 frpc 服务。
服务端
在服务端可以通过 systemctl 托管 frps 部署。
确定 frps 和 frps.toml 的路径,后面会用到,在 frp目录中执行命令:
1printf "$(pwd)/%s\n" frps frps.toml
新建文件 /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=/root/frp/frps -c /root/frp/frps.toml [Install] WantedBy=multi-user.target
/root/frp/frps替换为第一步中获取的 frps 的路径/root/frp/frps.toml替换为第一步中获取的 frps.toml 的路径
开启服务的自启动
1 2# frps 对应的就是 frps.service 名字 systemctl enable frps
启动服务
1 2# frps 对应的就是 frps.service 名字 systemctl start frps
可以使用 systemctl status frps 命令查看服务运行状态,类似这样:
注:按 Q 键可退出状态查看。
客户端
Linux
如果你的内网机器是 linux ,恭喜你同样可以使用 systemctl 托管 frpc 的运行,步骤与上面的一致,无非就是换一下文件名称和路径。
/lib/systemd/system/frpc.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=/root/frp/frpc -c /root/frp/frpc.toml [Install] WantedBy=multi-user.target
macOS
因为我的是 macOS,需要使用 launchctl 达到同样的效果。
确定 frpc 和 frpc.toml 的路径,后面会用到,在 frp目录中执行命令:
1printf "$(pwd)/%s\n" frpc frpc.toml
新建文件 ~/Library/LaunchAgents/frpc.plist,内容如下(示例文件):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd > <plist version="1.0"> <dict> <key>Label</key> <string>frpc</string> <key>ProgramArguments</key> <array> <string>/Users/5km/frp/frpc</string> <string>-c</string> <string>/Users/5km/frp/frpc.toml</string> </array> <key>KeepAlive</key> <true/> <key>RunAtLoad</key> <true/> </dict> </plist>
/Users/5km/frp/frpc替换为第一步中获取的 frpc 的路径/Users/5km/frp/frpc.toml替换为第一步中获取的 frpc.toml 的路径
启动服务
1sudo launchctl load -w ~/Library/LaunchAgents/frpc.plist
停止服务
1sudo launchctl unload -w ~/Library/LaunchAgents/frpc.plist
启动服务后,就可以测试效果了,顺利的话就完成了内网穿透。
在上面的 frpc 的配置中我添加了数据库 MYSQL 服务的代理,所以我就可以使用 服务器 6000 端口访问内网机器上的数据库了。



